@axis-backstage/plugin-readme 0.11.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,107 @@
1
+ # @axis-backstage/plugin-readme
2
+
3
+ ## 0.13.0
4
+
5
+ ### Minor Changes
6
+
7
+ - ede8341: Updated to Backstage v1.36.1.
8
+
9
+ ## 0.12.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 0726c03: Created the isReadmeAvailable function that returns false if no README content is found due to 404-error. If it returns false, no ReadmeCard is rendered in EntityPage. Also updated the error response from backend to be a NotFoundError.
14
+
15
+ ## 0.11.0
16
+
17
+ ### Minor Changes
18
+
19
+ - 3d15d61: Add new maxHeight property to ReadmeCard component
20
+
21
+ ## 0.10.0
22
+
23
+ ### Minor Changes
24
+
25
+ - 6fd284d: Updated to Backstage v1.30.1.
26
+
27
+ ## 0.9.0
28
+
29
+ ### Minor Changes
30
+
31
+ - 0b948ea: Generate pluginIds for plugins and bumping @backstage/cli
32
+
33
+ ## 0.8.0
34
+
35
+ ### Minor Changes
36
+
37
+ - 916589b: Bumped Backstage to v.27.7 and removed the TechRadar plugin since it was not used and caused problems with the new version.
38
+
39
+ ## 0.7.1
40
+
41
+ ### Patch Changes
42
+
43
+ - 0535af4: Bumped backstage dependencies to match 1.26.0
44
+
45
+ ## 0.7.0
46
+
47
+ ### Minor Changes
48
+
49
+ - 371f5fd: Readme backend APIs adjusted to consume entityRef as /:kind/:namespace/:name. Fixes a 404 routing issue where a proxy like oauth2Proxy could decode the URI encoded path parameter /:entityRef known to contain the reserved path delimiter '/'.
50
+
51
+ ## 0.6.0
52
+
53
+ ### Minor Changes
54
+
55
+ - 603304b: Updated the max height in case of variant `fullHeight` to be `none` by default. That is needed to really occupy the full height of the container.
56
+
57
+ ## 0.5.4
58
+
59
+ ### Patch Changes
60
+
61
+ - ae965c0: Fix broken workspace dependencies
62
+
63
+ ## 0.5.3
64
+
65
+ ### Patch Changes
66
+
67
+ - e6a9982: Troubleshooting "no readme file" error
68
+ - f09fe96: Added fullpage support
69
+ - b3faeda: Fixed so that Readme Dialog always have a min width. In that case, if it is not smuch markdown content, the dialog wont be weirdly small.
70
+
71
+ ## 0.5.2
72
+
73
+ ### Patch Changes
74
+
75
+ - 050e48d: Replace all Mui Grid v1 with v2
76
+
77
+ ## 0.5.1
78
+
79
+ ### Patch Changes
80
+
81
+ - 0613d84: Updated the notes in the README.md about backend installation and setup in Jira Dashboard plugin and README plugin
82
+ - b445aaa: Update @mui & @emotion dependencies
83
+
84
+ ## 0.5.0
85
+
86
+ ### Minor Changes
87
+
88
+ - 08961a1: Bump to react v.18 in app and plugins, and updated dependencies. "peer" is now react 18 + 17. Removed react v. 16.13.1
89
+
90
+ ## 0.4.0
91
+
92
+ ### Minor Changes
93
+
94
+ - 864d983: Bumped Backstage version to v.1.22.0
95
+
96
+ ## 0.3.0
97
+
98
+ ### Minor Changes
99
+
100
+ - 23ff76a: Bumped Backstage version to v.1.21.0 in whole monorepo
101
+ - 7d79c04: Bumped Readme frontend plugin to use Material UI v.5 components. Made necessary changes to the code.
102
+
103
+ ## 0.2.0
104
+
105
+ ### Minor Changes
106
+
107
+ - a67c963: Bumped Backstage to version 1.20.3
package/README.md CHANGED
@@ -48,6 +48,24 @@ const overviewContent = (
48
48
  )
49
49
  ```
50
50
 
51
+ If you wish to only render the ReadmeCard if a README file can be found for the entity, you can use the exported function **isReadmeAvailable**. See example below:
52
+
53
+ ```tsx
54
+ import { ReadmeCard, isReadmeAvailable } from '@axis-backstage/plugin-readme';
55
+
56
+ const defaultEntityPage = (
57
+ ...
58
+ <EntitySwitch>
59
+ <EntitySwitch.Case if={isReadmeAvailable}>
60
+ <Grid md={6} xs={12}>
61
+ <ReadmeCard maxHeight={350} />
62
+ </Grid>
63
+ </EntitySwitch.Case>
64
+ </EntitySwitch>
65
+ ...
66
+ )
67
+ ```
68
+
51
69
  To use `ReadmeCard` in a seperate page with full height:
52
70
 
53
71
  ```tsx
@@ -59,6 +77,7 @@ const defaultEntityPage = (
59
77
  <ReadmeCard variant="fullHeight" />
60
78
  </EntityLayout.Route>
61
79
  ...
80
+ )
62
81
  ```
63
82
 
64
83
  ## Layout
@@ -1 +1 @@
1
- {"version":3,"file":"ReadmeApi.esm.js","sources":["../../src/api/ReadmeApi.tsx"],"sourcesContent":["import { createApiRef } from '@backstage/core-plugin-api';\n\nexport const readmeApiRef = createApiRef<ReadmeApi>({\n id: 'plugin.readme',\n});\n\nexport type ReadmeApi = {\n getReadmeContent(entityRef: string): Promise<[string, string]>;\n};\n"],"names":[],"mappings":";;AAEO,MAAM,eAAe,YAAwB,CAAA;AAAA,EAClD,EAAI,EAAA,eAAA;AACN,CAAC;;;;"}
1
+ {"version":3,"file":"ReadmeApi.esm.js","sources":["../../src/api/ReadmeApi.tsx"],"sourcesContent":["import { createApiRef } from '@backstage/core-plugin-api';\n\nexport const readmeApiRef = createApiRef<ReadmeApi>({\n id: 'plugin.readme',\n});\n\nexport type ReadmeApi = {\n getReadmeContent(entityRef: string): Promise<[string, string]>;\n};\n"],"names":[],"mappings":";;AAEO,MAAM,eAAe,YAAwB,CAAA;AAAA,EAClD,EAAI,EAAA;AACN,CAAC;;;;"}
@@ -1,5 +1,21 @@
1
- import { parseEntityRef, DEFAULT_NAMESPACE } from '@backstage/catalog-model';
1
+ import { parseEntityRef, DEFAULT_NAMESPACE, stringifyEntityRef } from '@backstage/catalog-model';
2
+ import { ResponseError } from '@backstage/errors';
3
+ import { readmeApiRef } from './ReadmeApi.esm.js';
2
4
 
5
+ const isReadmeAvailable = async (entity, context) => {
6
+ const readmeClient = context.apis.get(readmeApiRef);
7
+ if (readmeClient === void 0) {
8
+ return false;
9
+ }
10
+ try {
11
+ await readmeClient.getReadmeContent(stringifyEntityRef(entity));
12
+ } catch (error) {
13
+ if (error instanceof ResponseError && error.statusCode === 404) {
14
+ return false;
15
+ }
16
+ }
17
+ return true;
18
+ };
3
19
  class ReadmeClient {
4
20
  discoveryApi;
5
21
  fetchApi;
@@ -28,12 +44,9 @@ class ReadmeClient {
28
44
  resp.headers.get("Content-Type") || "text/plain"
29
45
  ];
30
46
  }
31
- if (resp.status === 404) {
32
- throw new Error("404");
33
- }
34
- throw new Error(`${resp.status}: ${resp.statusText}`);
47
+ throw await ResponseError.fromResponse(resp);
35
48
  }
36
49
  }
37
50
 
38
- export { ReadmeClient };
51
+ export { ReadmeClient, isReadmeAvailable };
39
52
  //# sourceMappingURL=ReadmeClient.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ReadmeClient.esm.js","sources":["../../src/api/ReadmeClient.tsx"],"sourcesContent":["import {\n DiscoveryApi,\n FetchApi,\n IdentityApi,\n} from '@backstage/core-plugin-api';\nimport { DEFAULT_NAMESPACE, parseEntityRef } from '@backstage/catalog-model';\nimport { ReadmeApi } from './ReadmeApi';\n\nexport class ReadmeClient implements ReadmeApi {\n private readonly discoveryApi: DiscoveryApi;\n private readonly fetchApi: FetchApi;\n private readonly identityApi: IdentityApi;\n\n constructor(options: {\n discoveryApi: DiscoveryApi;\n fetchApi: FetchApi;\n identityApi: IdentityApi;\n }) {\n this.discoveryApi = options.discoveryApi;\n this.fetchApi = options.fetchApi;\n this.identityApi = options.identityApi;\n }\n\n async getReadmeContent(entityRef: string): Promise<[string, string]> {\n const { token } = await this.identityApi.getCredentials();\n const baseUrl = await this.discoveryApi.getBaseUrl('readme');\n\n const { kind, name, namespace } = parseEntityRef(entityRef, {\n defaultNamespace: DEFAULT_NAMESPACE,\n });\n\n const resp = await this.fetchApi.fetch(\n `${baseUrl}/${kind}/${namespace}/${name}`,\n {\n method: 'GET',\n headers: { Authorization: `Bearer ${token}` },\n },\n );\n if (resp.ok) {\n return [\n await resp.text(),\n resp.headers.get('Content-Type') || 'text/plain',\n ];\n }\n if (resp.status === 404) {\n throw new Error('404');\n }\n throw new Error(`${resp.status}: ${resp.statusText}`);\n }\n}\n"],"names":[],"mappings":";;AAQO,MAAM,YAAkC,CAAA;AAAA,EAC5B,YAAA,CAAA;AAAA,EACA,QAAA,CAAA;AAAA,EACA,WAAA,CAAA;AAAA,EAEjB,YAAY,OAIT,EAAA;AACD,IAAA,IAAA,CAAK,eAAe,OAAQ,CAAA,YAAA,CAAA;AAC5B,IAAA,IAAA,CAAK,WAAW,OAAQ,CAAA,QAAA,CAAA;AACxB,IAAA,IAAA,CAAK,cAAc,OAAQ,CAAA,WAAA,CAAA;AAAA,GAC7B;AAAA,EAEA,MAAM,iBAAiB,SAA8C,EAAA;AACnE,IAAA,MAAM,EAAE,KAAM,EAAA,GAAI,MAAM,IAAA,CAAK,YAAY,cAAe,EAAA,CAAA;AACxD,IAAA,MAAM,OAAU,GAAA,MAAM,IAAK,CAAA,YAAA,CAAa,WAAW,QAAQ,CAAA,CAAA;AAE3D,IAAA,MAAM,EAAE,IAAM,EAAA,IAAA,EAAM,SAAU,EAAA,GAAI,eAAe,SAAW,EAAA;AAAA,MAC1D,gBAAkB,EAAA,iBAAA;AAAA,KACnB,CAAA,CAAA;AAED,IAAM,MAAA,IAAA,GAAO,MAAM,IAAA,CAAK,QAAS,CAAA,KAAA;AAAA,MAC/B,GAAG,OAAO,CAAA,CAAA,EAAI,IAAI,CAAI,CAAA,EAAA,SAAS,IAAI,IAAI,CAAA,CAAA;AAAA,MACvC;AAAA,QACE,MAAQ,EAAA,KAAA;AAAA,QACR,OAAS,EAAA,EAAE,aAAe,EAAA,CAAA,OAAA,EAAU,KAAK,CAAG,CAAA,EAAA;AAAA,OAC9C;AAAA,KACF,CAAA;AACA,IAAA,IAAI,KAAK,EAAI,EAAA;AACX,MAAO,OAAA;AAAA,QACL,MAAM,KAAK,IAAK,EAAA;AAAA,QAChB,IAAK,CAAA,OAAA,CAAQ,GAAI,CAAA,cAAc,CAAK,IAAA,YAAA;AAAA,OACtC,CAAA;AAAA,KACF;AACA,IAAI,IAAA,IAAA,CAAK,WAAW,GAAK,EAAA;AACvB,MAAM,MAAA,IAAI,MAAM,KAAK,CAAA,CAAA;AAAA,KACvB;AACA,IAAM,MAAA,IAAI,MAAM,CAAG,EAAA,IAAA,CAAK,MAAM,CAAK,EAAA,EAAA,IAAA,CAAK,UAAU,CAAE,CAAA,CAAA,CAAA;AAAA,GACtD;AACF;;;;"}
1
+ {"version":3,"file":"ReadmeClient.esm.js","sources":["../../src/api/ReadmeClient.tsx"],"sourcesContent":["import {\n ApiHolder,\n DiscoveryApi,\n FetchApi,\n IdentityApi,\n} from '@backstage/core-plugin-api';\nimport {\n DEFAULT_NAMESPACE,\n Entity,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { ResponseError } from '@backstage/errors';\nimport { ReadmeApi, readmeApiRef } from './ReadmeApi';\n\n/**\n * Checks if a README is available for the given entity by making a request to the backend.\nIf the backend returns a 404 NotFound error, it indicates that no README is available for the entity.\n@param entity - The entity for which to check the README availability.\n@param context - The context providing access to the API holder.\n@returns A promise that resolves to true if the README is available, or false if not found (404).\n * @public\n */\nexport const isReadmeAvailable = async (\n entity: Entity,\n context: { apis: ApiHolder },\n): Promise<boolean> => {\n const readmeClient = context.apis.get(readmeApiRef);\n\n if (readmeClient === undefined) {\n return false;\n }\n\n try {\n await readmeClient.getReadmeContent(stringifyEntityRef(entity));\n } catch (error) {\n if (error instanceof ResponseError && error.statusCode === 404) {\n return false;\n }\n }\n return true;\n};\n\nexport class ReadmeClient implements ReadmeApi {\n private readonly discoveryApi: DiscoveryApi;\n private readonly fetchApi: FetchApi;\n private readonly identityApi: IdentityApi;\n\n constructor(options: {\n discoveryApi: DiscoveryApi;\n fetchApi: FetchApi;\n identityApi: IdentityApi;\n }) {\n this.discoveryApi = options.discoveryApi;\n this.fetchApi = options.fetchApi;\n this.identityApi = options.identityApi;\n }\n\n async getReadmeContent(entityRef: string): Promise<[string, string]> {\n const { token } = await this.identityApi.getCredentials();\n const baseUrl = await this.discoveryApi.getBaseUrl('readme');\n\n const { kind, name, namespace } = parseEntityRef(entityRef, {\n defaultNamespace: DEFAULT_NAMESPACE,\n });\n\n const resp = await this.fetchApi.fetch(\n `${baseUrl}/${kind}/${namespace}/${name}`,\n {\n method: 'GET',\n headers: { Authorization: `Bearer ${token}` },\n },\n );\n\n if (resp.ok) {\n return [\n await resp.text(),\n resp.headers.get('Content-Type') || 'text/plain',\n ];\n }\n\n throw await ResponseError.fromResponse(resp);\n }\n}\n"],"names":[],"mappings":";;;;AAuBa,MAAA,iBAAA,GAAoB,OAC/B,MAAA,EACA,OACqB,KAAA;AACrB,EAAA,MAAM,YAAe,GAAA,OAAA,CAAQ,IAAK,CAAA,GAAA,CAAI,YAAY,CAAA;AAElD,EAAA,IAAI,iBAAiB,MAAW,EAAA;AAC9B,IAAO,OAAA,KAAA;AAAA;AAGT,EAAI,IAAA;AACF,IAAA,MAAM,YAAa,CAAA,gBAAA,CAAiB,kBAAmB,CAAA,MAAM,CAAC,CAAA;AAAA,WACvD,KAAO,EAAA;AACd,IAAA,IAAI,KAAiB,YAAA,aAAA,IAAiB,KAAM,CAAA,UAAA,KAAe,GAAK,EAAA;AAC9D,MAAO,OAAA,KAAA;AAAA;AACT;AAEF,EAAO,OAAA,IAAA;AACT;AAEO,MAAM,YAAkC,CAAA;AAAA,EAC5B,YAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA;AAAA,EAEjB,YAAY,OAIT,EAAA;AACD,IAAA,IAAA,CAAK,eAAe,OAAQ,CAAA,YAAA;AAC5B,IAAA,IAAA,CAAK,WAAW,OAAQ,CAAA,QAAA;AACxB,IAAA,IAAA,CAAK,cAAc,OAAQ,CAAA,WAAA;AAAA;AAC7B,EAEA,MAAM,iBAAiB,SAA8C,EAAA;AACnE,IAAA,MAAM,EAAE,KAAM,EAAA,GAAI,MAAM,IAAA,CAAK,YAAY,cAAe,EAAA;AACxD,IAAA,MAAM,OAAU,GAAA,MAAM,IAAK,CAAA,YAAA,CAAa,WAAW,QAAQ,CAAA;AAE3D,IAAA,MAAM,EAAE,IAAM,EAAA,IAAA,EAAM,SAAU,EAAA,GAAI,eAAe,SAAW,EAAA;AAAA,MAC1D,gBAAkB,EAAA;AAAA,KACnB,CAAA;AAED,IAAM,MAAA,IAAA,GAAO,MAAM,IAAA,CAAK,QAAS,CAAA,KAAA;AAAA,MAC/B,GAAG,OAAO,CAAA,CAAA,EAAI,IAAI,CAAI,CAAA,EAAA,SAAS,IAAI,IAAI,CAAA,CAAA;AAAA,MACvC;AAAA,QACE,MAAQ,EAAA,KAAA;AAAA,QACR,OAAS,EAAA,EAAE,aAAe,EAAA,CAAA,OAAA,EAAU,KAAK,CAAG,CAAA;AAAA;AAC9C,KACF;AAEA,IAAA,IAAI,KAAK,EAAI,EAAA;AACX,MAAO,OAAA;AAAA,QACL,MAAM,KAAK,IAAK,EAAA;AAAA,QAChB,IAAK,CAAA,OAAA,CAAQ,GAAI,CAAA,cAAc,CAAK,IAAA;AAAA,OACtC;AAAA;AAGF,IAAM,MAAA,MAAM,aAAc,CAAA,YAAA,CAAa,IAAI,CAAA;AAAA;AAE/C;;;;"}
@@ -1,12 +1,13 @@
1
1
  import React from 'react';
2
2
  import { useEntity } from '@backstage/plugin-catalog-react';
3
3
  import { useApi } from '@backstage/core-plugin-api';
4
- import { Progress, Link, ErrorPanel, MarkdownContent, CodeSnippet } from '@backstage/core-components';
4
+ import { Progress, Link, ResponseErrorPanel, ErrorPanel, MarkdownContent, CodeSnippet } from '@backstage/core-components';
5
5
  import useAsync from 'react-use/lib/useAsync';
6
6
  import { readmeApiRef } from '../../api/ReadmeApi.esm.js';
7
7
  import { getEntitySourceLocation, stringifyEntityRef } from '@backstage/catalog-model';
8
8
  import Box from '@mui/material/Box';
9
9
  import Typography from '@mui/material/Typography';
10
+ import { ResponseError } from '@backstage/errors';
10
11
 
11
12
  const FetchComponent = () => {
12
13
  const { entity } = useEntity();
@@ -29,8 +30,11 @@ const FetchComponent = () => {
29
30
  if (loading) {
30
31
  return /* @__PURE__ */ React.createElement(Progress, null);
31
32
  }
32
- if (error?.message === "404") {
33
- return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Typography, { pb: 2, variant: "body2" }, "No README.md file found at source location:", " ", location && /* @__PURE__ */ React.createElement("strong", null, location)), /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, "Need help? Go to our", " ", /* @__PURE__ */ React.createElement(Link, { to: "https://github.com/AxisCommunications/backstage-plugins/blob/main/plugins/readme/README.md" }, "documentation")));
33
+ if (error instanceof ResponseError) {
34
+ if (error.statusCode === 404) {
35
+ return /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Typography, { pb: 2, variant: "body2" }, "No README.md file found at source location:", " ", location && /* @__PURE__ */ React.createElement("strong", null, location)), /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, "Need help? Go to our", " ", /* @__PURE__ */ React.createElement(Link, { to: "https://github.com/AxisCommunications/backstage-plugins/blob/main/plugins/readme/README.md" }, "documentation")));
36
+ }
37
+ return /* @__PURE__ */ React.createElement(ResponseErrorPanel, { error });
34
38
  }
35
39
  if (error) {
36
40
  return /* @__PURE__ */ React.createElement(ErrorPanel, { error });
@@ -1 +1 @@
1
- {"version":3,"file":"FetchComponent.esm.js","sources":["../../../src/components/FetchComponent/FetchComponent.tsx"],"sourcesContent":["import React from 'react';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { useApi } from '@backstage/core-plugin-api';\nimport {\n CodeSnippet,\n ErrorPanel,\n Link,\n MarkdownContent,\n Progress,\n} from '@backstage/core-components';\nimport useAsync from 'react-use/lib/useAsync';\nimport { readmeApiRef } from '../../api/ReadmeApi';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\nimport { getEntitySourceLocation } from '@backstage/catalog-model';\nimport Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\n\nexport const FetchComponent = () => {\n const { entity } = useEntity();\n const readmeApi = useApi(readmeApiRef);\n let location;\n\n try {\n const { target } = getEntitySourceLocation(entity);\n location = target ?? target;\n } catch (err) {\n location = ': Unknown';\n }\n\n const {\n value: content,\n loading,\n error,\n } = useAsync(\n async (): Promise<string[]> =>\n await readmeApi.getReadmeContent(stringifyEntityRef(entity)),\n [entity],\n );\n\n if (loading) {\n return <Progress />;\n }\n if (error?.message === '404') {\n return (\n <Box>\n <Typography pb={2} variant=\"body2\">\n No README.md file found at source location:{' '}\n {location && <strong>{location}</strong>}\n </Typography>\n <Typography variant=\"body2\">\n Need help? Go to our{' '}\n <Link to=\"https://github.com/AxisCommunications/backstage-plugins/blob/main/plugins/readme/README.md\">\n documentation\n </Link>\n </Typography>\n </Box>\n );\n }\n\n if (error) {\n return <ErrorPanel error={error} />;\n }\n if (!content) {\n return <ErrorPanel error={Error('Unknown error')} />;\n }\n if (!content[1] || content[1] === 'error') {\n return <ErrorPanel error={Error(content[1] ?? 'Unknown error')} />;\n } else if (content[1].startsWith('text/markdown')) {\n return <MarkdownContent content={content[0]} />;\n }\n // probably text/plain\n return (\n <div data-testid=\"readme-content\">\n <CodeSnippet text={content[0]} language=\"plaintext\" />\n </div>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;AAiBO,MAAM,iBAAiB,MAAM;AAClC,EAAM,MAAA,EAAE,MAAO,EAAA,GAAI,SAAU,EAAA,CAAA;AAC7B,EAAM,MAAA,SAAA,GAAY,OAAO,YAAY,CAAA,CAAA;AACrC,EAAI,IAAA,QAAA,CAAA;AAEJ,EAAI,IAAA;AACF,IAAA,MAAM,EAAE,MAAA,EAAW,GAAA,uBAAA,CAAwB,MAAM,CAAA,CAAA;AACjD,IAAA,QAAA,GAAW,MAAU,IAAA,MAAA,CAAA;AAAA,WACd,GAAK,EAAA;AACZ,IAAW,QAAA,GAAA,WAAA,CAAA;AAAA,GACb;AAEA,EAAM,MAAA;AAAA,IACJ,KAAO,EAAA,OAAA;AAAA,IACP,OAAA;AAAA,IACA,KAAA;AAAA,GACE,GAAA,QAAA;AAAA,IACF,YACE,MAAM,SAAA,CAAU,gBAAiB,CAAA,kBAAA,CAAmB,MAAM,CAAC,CAAA;AAAA,IAC7D,CAAC,MAAM,CAAA;AAAA,GACT,CAAA;AAEA,EAAA,IAAI,OAAS,EAAA;AACX,IAAA,2CAAQ,QAAS,EAAA,IAAA,CAAA,CAAA;AAAA,GACnB;AACA,EAAI,IAAA,KAAA,EAAO,YAAY,KAAO,EAAA;AAC5B,IAAA,uBACG,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,IAAA,kBACE,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,EAAI,EAAA,CAAA,EAAG,OAAQ,EAAA,OAAA,EAAA,EAAQ,6CACW,EAAA,GAAA,EAC3C,QAAY,oBAAA,KAAA,CAAA,aAAA,CAAC,QAAQ,EAAA,IAAA,EAAA,QAAS,CACjC,CAAA,kBACC,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAQ,EAAA,OAAA,EAAA,EAAQ,sBACL,EAAA,GAAA,kBACpB,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,EAAG,EAAA,4FAAA,EAAA,EAA6F,eAEtG,CACF,CACF,CAAA,CAAA;AAAA,GAEJ;AAEA,EAAA,IAAI,KAAO,EAAA;AACT,IAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,KAAc,EAAA,CAAA,CAAA;AAAA,GACnC;AACA,EAAA,IAAI,CAAC,OAAS,EAAA;AACZ,IAAA,uBAAQ,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,KAAO,EAAA,KAAA,CAAM,eAAe,CAAG,EAAA,CAAA,CAAA;AAAA,GACpD;AACA,EAAA,IAAI,CAAC,OAAQ,CAAA,CAAC,KAAK,OAAQ,CAAA,CAAC,MAAM,OAAS,EAAA;AACzC,IAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,KAAO,EAAA,KAAA,CAAM,QAAQ,CAAC,CAAA,IAAK,eAAe,CAAG,EAAA,CAAA,CAAA;AAAA,aACvD,OAAQ,CAAA,CAAC,CAAE,CAAA,UAAA,CAAW,eAAe,CAAG,EAAA;AACjD,IAAA,uBAAQ,KAAA,CAAA,aAAA,CAAA,eAAA,EAAA,EAAgB,OAAS,EAAA,OAAA,CAAQ,CAAC,CAAG,EAAA,CAAA,CAAA;AAAA,GAC/C;AAEA,EAAA,uBACG,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAI,aAAY,EAAA,gBAAA,EAAA,kBACd,KAAA,CAAA,aAAA,CAAA,WAAA,EAAA,EAAY,IAAM,EAAA,OAAA,CAAQ,CAAC,CAAA,EAAG,QAAS,EAAA,WAAA,EAAY,CACtD,CAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"FetchComponent.esm.js","sources":["../../../src/components/FetchComponent/FetchComponent.tsx"],"sourcesContent":["import React from 'react';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { useApi } from '@backstage/core-plugin-api';\nimport {\n CodeSnippet,\n ErrorPanel,\n Link,\n MarkdownContent,\n Progress,\n ResponseErrorPanel,\n} from '@backstage/core-components';\nimport useAsync from 'react-use/lib/useAsync';\nimport { readmeApiRef } from '../../api/ReadmeApi';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\nimport { getEntitySourceLocation } from '@backstage/catalog-model';\nimport Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\nimport { ResponseError } from '@backstage/errors';\n\nexport const FetchComponent = () => {\n const { entity } = useEntity();\n const readmeApi = useApi(readmeApiRef);\n let location;\n\n try {\n const { target } = getEntitySourceLocation(entity);\n location = target ?? target;\n } catch (err) {\n location = ': Unknown';\n }\n\n const {\n value: content,\n loading,\n error,\n } = useAsync(\n async (): Promise<string[]> =>\n await readmeApi.getReadmeContent(stringifyEntityRef(entity)),\n [entity],\n );\n\n if (loading) {\n return <Progress />;\n }\n\n if (error instanceof ResponseError) {\n if (error.statusCode === 404) {\n return (\n <Box>\n <Typography pb={2} variant=\"body2\">\n No README.md file found at source location:{' '}\n {location && <strong>{location}</strong>}\n </Typography>\n <Typography variant=\"body2\">\n Need help? Go to our{' '}\n <Link to=\"https://github.com/AxisCommunications/backstage-plugins/blob/main/plugins/readme/README.md\">\n documentation\n </Link>\n </Typography>\n </Box>\n );\n }\n return <ResponseErrorPanel error={error} />;\n }\n\n if (error) {\n return <ErrorPanel error={error} />;\n }\n if (!content) {\n return <ErrorPanel error={Error('Unknown error')} />;\n }\n if (!content[1] || content[1] === 'error') {\n return <ErrorPanel error={Error(content[1] ?? 'Unknown error')} />;\n } else if (content[1].startsWith('text/markdown')) {\n return <MarkdownContent content={content[0]} />;\n }\n // probably text/plain\n return (\n <div data-testid=\"readme-content\">\n <CodeSnippet text={content[0]} language=\"plaintext\" />\n </div>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;AAmBO,MAAM,iBAAiB,MAAM;AAClC,EAAM,MAAA,EAAE,MAAO,EAAA,GAAI,SAAU,EAAA;AAC7B,EAAM,MAAA,SAAA,GAAY,OAAO,YAAY,CAAA;AACrC,EAAI,IAAA,QAAA;AAEJ,EAAI,IAAA;AACF,IAAA,MAAM,EAAE,MAAA,EAAW,GAAA,uBAAA,CAAwB,MAAM,CAAA;AACjD,IAAA,QAAA,GAAW,MAAU,IAAA,MAAA;AAAA,WACd,GAAK,EAAA;AACZ,IAAW,QAAA,GAAA,WAAA;AAAA;AAGb,EAAM,MAAA;AAAA,IACJ,KAAO,EAAA,OAAA;AAAA,IACP,OAAA;AAAA,IACA;AAAA,GACE,GAAA,QAAA;AAAA,IACF,YACE,MAAM,SAAA,CAAU,gBAAiB,CAAA,kBAAA,CAAmB,MAAM,CAAC,CAAA;AAAA,IAC7D,CAAC,MAAM;AAAA,GACT;AAEA,EAAA,IAAI,OAAS,EAAA;AACX,IAAA,2CAAQ,QAAS,EAAA,IAAA,CAAA;AAAA;AAGnB,EAAA,IAAI,iBAAiB,aAAe,EAAA;AAClC,IAAI,IAAA,KAAA,CAAM,eAAe,GAAK,EAAA;AAC5B,MAAA,uBACG,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,IAAA,kBACE,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,EAAI,EAAA,CAAA,EAAG,OAAQ,EAAA,OAAA,EAAA,EAAQ,6CACW,EAAA,GAAA,EAC3C,QAAY,oBAAA,KAAA,CAAA,aAAA,CAAC,QAAQ,EAAA,IAAA,EAAA,QAAS,CACjC,CAAA,kBACC,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAQ,EAAA,OAAA,EAAA,EAAQ,sBACL,EAAA,GAAA,kBACpB,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,EAAG,EAAA,4FAAA,EAAA,EAA6F,eAEtG,CACF,CACF,CAAA;AAAA;AAGJ,IAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,sBAAmB,KAAc,EAAA,CAAA;AAAA;AAG3C,EAAA,IAAI,KAAO,EAAA;AACT,IAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,KAAc,EAAA,CAAA;AAAA;AAEnC,EAAA,IAAI,CAAC,OAAS,EAAA;AACZ,IAAA,uBAAQ,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,KAAO,EAAA,KAAA,CAAM,eAAe,CAAG,EAAA,CAAA;AAAA;AAEpD,EAAA,IAAI,CAAC,OAAQ,CAAA,CAAC,KAAK,OAAQ,CAAA,CAAC,MAAM,OAAS,EAAA;AACzC,IAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,KAAO,EAAA,KAAA,CAAM,QAAQ,CAAC,CAAA,IAAK,eAAe,CAAG,EAAA,CAAA;AAAA,aACvD,OAAQ,CAAA,CAAC,CAAE,CAAA,UAAA,CAAW,eAAe,CAAG,EAAA;AACjD,IAAA,uBAAQ,KAAA,CAAA,aAAA,CAAA,eAAA,EAAA,EAAgB,OAAS,EAAA,OAAA,CAAQ,CAAC,CAAG,EAAA,CAAA;AAAA;AAG/C,EAAA,uBACG,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAI,aAAY,EAAA,gBAAA,EAAA,kBACd,KAAA,CAAA,aAAA,CAAA,WAAA,EAAA,EAAY,IAAM,EAAA,OAAA,CAAQ,CAAC,CAAA,EAAG,QAAS,EAAA,WAAA,EAAY,CACtD,CAAA;AAEJ;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ReadmeCard.esm.js","sources":["../../../src/components/ReadmeCard/ReadmeCard.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport IconButton from '@mui/material/IconButton';\nimport Box from '@mui/material/Box';\nimport { InfoCard, InfoCardVariants } from '@backstage/core-components';\nimport { FetchComponent } from '../FetchComponent';\nimport OpenInNewIcon from '@mui/icons-material/OpenInNew';\nimport { ReadmeDialog } from '../ReadmeDialog/ReadmeDialog';\n\n/**\n * ReadmeCardProps props.\n *\n * @public\n */\n\nexport type ReadmeCardProps = {\n variant?: InfoCardVariants;\n maxHeight?: string | number;\n};\n\nexport const ReadmeCard = (props: ReadmeCardProps) => {\n const { variant = 'gridItem', maxHeight: propMaxHeight } = props;\n const maxHeight =\n variant === 'fullHeight' ? 'none' : propMaxHeight ?? '235px';\n\n const [displayDialog, setDisplayDialog] = useState(false);\n\n return (\n <>\n <InfoCard\n title=\"README\"\n variant={variant}\n action={\n variant !== 'fullHeight' ? (\n <IconButton\n onClick={() => setDisplayDialog(true)}\n aria-label=\"open dialog\"\n role=\"button\"\n title=\"Open in dialog\"\n size=\"large\"\n >\n <OpenInNewIcon />\n </IconButton>\n ) : undefined\n }\n >\n <div style={{ overflow: 'auto' }}>\n <Box maxHeight={maxHeight}>\n <FetchComponent />\n </Box>\n </div>\n </InfoCard>\n\n <ReadmeDialog\n open={displayDialog}\n onClose={() => setDisplayDialog(false)}\n />\n </>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AAmBa,MAAA,UAAA,GAAa,CAAC,KAA2B,KAAA;AACpD,EAAA,MAAM,EAAE,OAAA,GAAU,UAAY,EAAA,SAAA,EAAW,eAAkB,GAAA,KAAA,CAAA;AAC3D,EAAA,MAAM,SACJ,GAAA,OAAA,KAAY,YAAe,GAAA,MAAA,GAAS,aAAiB,IAAA,OAAA,CAAA;AAEvD,EAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAAI,SAAS,KAAK,CAAA,CAAA;AAExD,EAAA,uBAEI,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,KAAM,EAAA,QAAA;AAAA,MACN,OAAA;AAAA,MACA,MAAA,EACE,YAAY,YACV,mBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,UAAA;AAAA,QAAA;AAAA,UACC,OAAA,EAAS,MAAM,gBAAA,CAAiB,IAAI,CAAA;AAAA,UACpC,YAAW,EAAA,aAAA;AAAA,UACX,IAAK,EAAA,QAAA;AAAA,UACL,KAAM,EAAA,gBAAA;AAAA,UACN,IAAK,EAAA,OAAA;AAAA,SAAA;AAAA,4CAEJ,aAAc,EAAA,IAAA,CAAA;AAAA,OAEf,GAAA,KAAA,CAAA;AAAA,KAAA;AAAA,oBAGL,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAI,KAAO,EAAA,EAAE,QAAU,EAAA,MAAA,EACtB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,SAAA,EAAA,kBACF,KAAA,CAAA,aAAA,CAAA,cAAA,EAAA,IAAe,CAClB,CACF,CAAA;AAAA,GAGF,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,YAAA;AAAA,IAAA;AAAA,MACC,IAAM,EAAA,aAAA;AAAA,MACN,OAAA,EAAS,MAAM,gBAAA,CAAiB,KAAK,CAAA;AAAA,KAAA;AAAA,GAEzC,CAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"ReadmeCard.esm.js","sources":["../../../src/components/ReadmeCard/ReadmeCard.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport IconButton from '@mui/material/IconButton';\nimport Box from '@mui/material/Box';\nimport { InfoCard, InfoCardVariants } from '@backstage/core-components';\nimport { FetchComponent } from '../FetchComponent';\nimport OpenInNewIcon from '@mui/icons-material/OpenInNew';\nimport { ReadmeDialog } from '../ReadmeDialog/ReadmeDialog';\n\n/**\n * ReadmeCardProps props.\n *\n * @public\n */\n\nexport type ReadmeCardProps = {\n variant?: InfoCardVariants;\n maxHeight?: string | number;\n};\n\nexport const ReadmeCard = (props: ReadmeCardProps) => {\n const { variant = 'gridItem', maxHeight: propMaxHeight } = props;\n const maxHeight =\n variant === 'fullHeight' ? 'none' : propMaxHeight ?? '235px';\n\n const [displayDialog, setDisplayDialog] = useState(false);\n\n return (\n <>\n <InfoCard\n title=\"README\"\n variant={variant}\n action={\n variant !== 'fullHeight' ? (\n <IconButton\n onClick={() => setDisplayDialog(true)}\n aria-label=\"open dialog\"\n role=\"button\"\n title=\"Open in dialog\"\n size=\"large\"\n >\n <OpenInNewIcon />\n </IconButton>\n ) : undefined\n }\n >\n <div style={{ overflow: 'auto' }}>\n <Box maxHeight={maxHeight}>\n <FetchComponent />\n </Box>\n </div>\n </InfoCard>\n\n <ReadmeDialog\n open={displayDialog}\n onClose={() => setDisplayDialog(false)}\n />\n </>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AAmBa,MAAA,UAAA,GAAa,CAAC,KAA2B,KAAA;AACpD,EAAA,MAAM,EAAE,OAAA,GAAU,UAAY,EAAA,SAAA,EAAW,eAAkB,GAAA,KAAA;AAC3D,EAAA,MAAM,SACJ,GAAA,OAAA,KAAY,YAAe,GAAA,MAAA,GAAS,aAAiB,IAAA,OAAA;AAEvD,EAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAAI,SAAS,KAAK,CAAA;AAExD,EAAA,uBAEI,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,KAAM,EAAA,QAAA;AAAA,MACN,OAAA;AAAA,MACA,MAAA,EACE,YAAY,YACV,mBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,UAAA;AAAA,QAAA;AAAA,UACC,OAAA,EAAS,MAAM,gBAAA,CAAiB,IAAI,CAAA;AAAA,UACpC,YAAW,EAAA,aAAA;AAAA,UACX,IAAK,EAAA,QAAA;AAAA,UACL,KAAM,EAAA,gBAAA;AAAA,UACN,IAAK,EAAA;AAAA,SAAA;AAAA,4CAEJ,aAAc,EAAA,IAAA;AAAA,OAEf,GAAA;AAAA,KAAA;AAAA,oBAGL,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAI,KAAO,EAAA,EAAE,QAAU,EAAA,MAAA,EACtB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,SAAA,EAAA,kBACF,KAAA,CAAA,aAAA,CAAA,cAAA,EAAA,IAAe,CAClB,CACF;AAAA,GAGF,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,YAAA;AAAA,IAAA;AAAA,MACC,IAAM,EAAA,aAAA;AAAA,MACN,OAAA,EAAS,MAAM,gBAAA,CAAiB,KAAK;AAAA;AAAA,GAEzC,CAAA;AAEJ;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ReadmeDialog.esm.js","sources":["../../../src/components/ReadmeDialog/ReadmeDialog.tsx"],"sourcesContent":["import React from 'react';\nimport Button from '@mui/material/Button';\nimport Dialog from '@mui/material/Dialog';\nimport DialogActions from '@mui/material/DialogActions';\nimport DialogContent from '@mui/material/DialogContent';\nimport DialogTitle from '@mui/material/DialogTitle';\nimport Box from '@mui/material/Box';\nimport { FetchComponent } from '../FetchComponent';\n\ntype Props = {\n open: boolean;\n onClose: () => void;\n};\n\nexport const ReadmeDialog = ({ open, onClose }: Props) => {\n return (\n <Dialog\n maxWidth=\"md\"\n open={open}\n onClose={onClose}\n data-testid=\"content-dialog\"\n >\n <DialogTitle>README</DialogTitle>\n <DialogContent dividers>\n <Box minWidth={650}>\n <FetchComponent />\n </Box>\n </DialogContent>\n <DialogActions>\n <Button\n variant=\"contained\"\n color=\"primary\"\n aria-label=\"close\"\n onClick={onClose}\n >\n Close\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AAcO,MAAM,YAAe,GAAA,CAAC,EAAE,IAAA,EAAM,SAAqB,KAAA;AACxD,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,QAAS,EAAA,IAAA;AAAA,MACT,IAAA;AAAA,MACA,OAAA;AAAA,MACA,aAAY,EAAA,gBAAA;AAAA,KAAA;AAAA,oBAEZ,KAAA,CAAA,aAAA,CAAC,mBAAY,QAAM,CAAA;AAAA,oBACnB,KAAA,CAAA,aAAA,CAAC,aAAc,EAAA,EAAA,QAAA,EAAQ,IACrB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,QAAA,EAAU,GACb,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAe,EAAA,IAAA,CAClB,CACF,CAAA;AAAA,wCACC,aACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,OAAQ,EAAA,WAAA;AAAA,QACR,KAAM,EAAA,SAAA;AAAA,QACN,YAAW,EAAA,OAAA;AAAA,QACX,OAAS,EAAA,OAAA;AAAA,OAAA;AAAA,MACV,OAAA;AAAA,KAGH,CAAA;AAAA,GACF,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"ReadmeDialog.esm.js","sources":["../../../src/components/ReadmeDialog/ReadmeDialog.tsx"],"sourcesContent":["import React from 'react';\nimport Button from '@mui/material/Button';\nimport Dialog from '@mui/material/Dialog';\nimport DialogActions from '@mui/material/DialogActions';\nimport DialogContent from '@mui/material/DialogContent';\nimport DialogTitle from '@mui/material/DialogTitle';\nimport Box from '@mui/material/Box';\nimport { FetchComponent } from '../FetchComponent';\n\ntype Props = {\n open: boolean;\n onClose: () => void;\n};\n\nexport const ReadmeDialog = ({ open, onClose }: Props) => {\n return (\n <Dialog\n maxWidth=\"md\"\n open={open}\n onClose={onClose}\n data-testid=\"content-dialog\"\n >\n <DialogTitle>README</DialogTitle>\n <DialogContent dividers>\n <Box minWidth={650}>\n <FetchComponent />\n </Box>\n </DialogContent>\n <DialogActions>\n <Button\n variant=\"contained\"\n color=\"primary\"\n aria-label=\"close\"\n onClick={onClose}\n >\n Close\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AAcO,MAAM,YAAe,GAAA,CAAC,EAAE,IAAA,EAAM,SAAqB,KAAA;AACxD,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,QAAS,EAAA,IAAA;AAAA,MACT,IAAA;AAAA,MACA,OAAA;AAAA,MACA,aAAY,EAAA;AAAA,KAAA;AAAA,oBAEZ,KAAA,CAAA,aAAA,CAAC,mBAAY,QAAM,CAAA;AAAA,oBACnB,KAAA,CAAA,aAAA,CAAC,aAAc,EAAA,EAAA,QAAA,EAAQ,IACrB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,QAAA,EAAU,GACb,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAe,EAAA,IAAA,CAClB,CACF,CAAA;AAAA,wCACC,aACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,OAAQ,EAAA,WAAA;AAAA,QACR,KAAM,EAAA,SAAA;AAAA,QACN,YAAW,EAAA,OAAA;AAAA,QACX,OAAS,EAAA;AAAA,OAAA;AAAA,MACV;AAAA,KAGH;AAAA,GACF;AAEJ;;;;"}
package/dist/index.d.ts CHANGED
@@ -2,6 +2,8 @@
2
2
  import * as React from 'react';
3
3
  import { InfoCardVariants } from '@backstage/core-components';
4
4
  import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
5
+ import { ApiHolder } from '@backstage/core-plugin-api';
6
+ import { Entity } from '@backstage/catalog-model';
5
7
 
6
8
  /**
7
9
  * ReadmeCardProps props.
@@ -24,4 +26,16 @@ declare const readmePlugin: _backstage_core_plugin_api.BackstagePlugin<{
24
26
  * @public */
25
27
  declare const ReadmeCard: (props: ReadmeCardProps) => React.JSX.Element;
26
28
 
27
- export { ReadmeCard, type ReadmeCardProps, readmePlugin };
29
+ /**
30
+ * Checks if a README is available for the given entity by making a request to the backend.
31
+ If the backend returns a 404 NotFound error, it indicates that no README is available for the entity.
32
+ @param entity - The entity for which to check the README availability.
33
+ @param context - The context providing access to the API holder.
34
+ @returns A promise that resolves to true if the README is available, or false if not found (404).
35
+ * @public
36
+ */
37
+ declare const isReadmeAvailable: (entity: Entity, context: {
38
+ apis: ApiHolder;
39
+ }) => Promise<boolean>;
40
+
41
+ export { ReadmeCard, type ReadmeCardProps, isReadmeAvailable, readmePlugin };
package/dist/index.esm.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export { ReadmeCard, readmePlugin } from './plugin.esm.js';
2
+ export { isReadmeAvailable } from './api/ReadmeClient.esm.js';
2
3
  //# sourceMappingURL=index.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
1
+ {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -1,4 +1,4 @@
1
- import { createPlugin, createApiFactory, discoveryApiRef, fetchApiRef, identityApiRef, createRoutableExtension } from '@backstage/core-plugin-api';
1
+ import { createPlugin, createApiFactory, identityApiRef, fetchApiRef, discoveryApiRef, createRoutableExtension } from '@backstage/core-plugin-api';
2
2
  import { rootRouteRef } from './routes.esm.js';
3
3
  import { readmeApiRef } from './api/ReadmeApi.esm.js';
4
4
  import { ReadmeClient } from './api/ReadmeClient.esm.js';
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.esm.js","sources":["../src/plugin.ts"],"sourcesContent":["import {\n createApiFactory,\n createPlugin,\n createRoutableExtension,\n discoveryApiRef,\n fetchApiRef,\n identityApiRef,\n} from '@backstage/core-plugin-api';\n\nimport { rootRouteRef } from './routes';\nimport { readmeApiRef } from './api/ReadmeApi';\nimport { ReadmeClient } from './api/ReadmeClient';\n\n/**\n * Plugin that provides the Readme api\n * @public */\nexport const readmePlugin = createPlugin({\n id: 'readme',\n apis: [\n createApiFactory({\n api: readmeApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n identityApi: identityApiRef,\n },\n factory: ({ discoveryApi, fetchApi, identityApi }) =>\n new ReadmeClient({ discoveryApi, fetchApi, identityApi }),\n }),\n ],\n routes: {\n root: rootRouteRef,\n },\n});\n\n/**\n * Readme card exported from the Readme plugin\n * @public */\nexport const ReadmeCard = readmePlugin.provide(\n createRoutableExtension({\n name: 'ReadmeCard',\n component: () => import('./components/ReadmeCard').then(m => m.ReadmeCard),\n mountPoint: rootRouteRef,\n }),\n);\n"],"names":[],"mappings":";;;;;AAgBO,MAAM,eAAe,YAAa,CAAA;AAAA,EACvC,EAAI,EAAA,QAAA;AAAA,EACJ,IAAM,EAAA;AAAA,IACJ,gBAAiB,CAAA;AAAA,MACf,GAAK,EAAA,YAAA;AAAA,MACL,IAAM,EAAA;AAAA,QACJ,YAAc,EAAA,eAAA;AAAA,QACd,QAAU,EAAA,WAAA;AAAA,QACV,WAAa,EAAA,cAAA;AAAA,OACf;AAAA,MACA,OAAS,EAAA,CAAC,EAAE,YAAA,EAAc,QAAU,EAAA,WAAA,EAClC,KAAA,IAAI,YAAa,CAAA,EAAE,YAAc,EAAA,QAAA,EAAU,aAAa,CAAA;AAAA,KAC3D,CAAA;AAAA,GACH;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA,YAAA;AAAA,GACR;AACF,CAAC,EAAA;AAKM,MAAM,aAAa,YAAa,CAAA,OAAA;AAAA,EACrC,uBAAwB,CAAA;AAAA,IACtB,IAAM,EAAA,YAAA;AAAA,IACN,SAAA,EAAW,MAAM,OAAO,sCAAyB,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,UAAU,CAAA;AAAA,IACzE,UAAY,EAAA,YAAA;AAAA,GACb,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"plugin.esm.js","sources":["../src/plugin.ts"],"sourcesContent":["import {\n createApiFactory,\n createPlugin,\n createRoutableExtension,\n discoveryApiRef,\n fetchApiRef,\n identityApiRef,\n} from '@backstage/core-plugin-api';\n\nimport { rootRouteRef } from './routes';\nimport { readmeApiRef } from './api/ReadmeApi';\nimport { ReadmeClient } from './api/ReadmeClient';\n\n/**\n * Plugin that provides the Readme api\n * @public */\nexport const readmePlugin = createPlugin({\n id: 'readme',\n apis: [\n createApiFactory({\n api: readmeApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n identityApi: identityApiRef,\n },\n factory: ({ discoveryApi, fetchApi, identityApi }) =>\n new ReadmeClient({ discoveryApi, fetchApi, identityApi }),\n }),\n ],\n routes: {\n root: rootRouteRef,\n },\n});\n\n/**\n * Readme card exported from the Readme plugin\n * @public */\nexport const ReadmeCard = readmePlugin.provide(\n createRoutableExtension({\n name: 'ReadmeCard',\n component: () => import('./components/ReadmeCard').then(m => m.ReadmeCard),\n mountPoint: rootRouteRef,\n }),\n);\n"],"names":[],"mappings":";;;;;AAgBO,MAAM,eAAe,YAAa,CAAA;AAAA,EACvC,EAAI,EAAA,QAAA;AAAA,EACJ,IAAM,EAAA;AAAA,IACJ,gBAAiB,CAAA;AAAA,MACf,GAAK,EAAA,YAAA;AAAA,MACL,IAAM,EAAA;AAAA,QACJ,YAAc,EAAA,eAAA;AAAA,QACd,QAAU,EAAA,WAAA;AAAA,QACV,WAAa,EAAA;AAAA,OACf;AAAA,MACA,OAAS,EAAA,CAAC,EAAE,YAAA,EAAc,QAAU,EAAA,WAAA,EAClC,KAAA,IAAI,YAAa,CAAA,EAAE,YAAc,EAAA,QAAA,EAAU,aAAa;AAAA,KAC3D;AAAA,GACH;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA;AAAA;AAEV,CAAC;AAKM,MAAM,aAAa,YAAa,CAAA,OAAA;AAAA,EACrC,uBAAwB,CAAA;AAAA,IACtB,IAAM,EAAA,YAAA;AAAA,IACN,SAAA,EAAW,MAAM,OAAO,sCAAyB,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,UAAU,CAAA;AAAA,IACzE,UAAY,EAAA;AAAA,GACb;AACH;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"routes.esm.js","sources":["../src/routes.ts"],"sourcesContent":["import { createRouteRef } from '@backstage/core-plugin-api';\n\nexport const rootRouteRef = createRouteRef({\n id: 'readme',\n});\n"],"names":[],"mappings":";;AAEO,MAAM,eAAe,cAAe,CAAA;AAAA,EACzC,EAAI,EAAA,QAAA;AACN,CAAC;;;;"}
1
+ {"version":3,"file":"routes.esm.js","sources":["../src/routes.ts"],"sourcesContent":["import { createRouteRef } from '@backstage/core-plugin-api';\n\nexport const rootRouteRef = createRouteRef({\n id: 'readme',\n});\n"],"names":[],"mappings":";;AAEO,MAAM,eAAe,cAAe,CAAA;AAAA,EACzC,EAAI,EAAA;AACN,CAAC;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axis-backstage/plugin-readme",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "main": "dist/index.esm.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "license": "Apache-2.0",
@@ -29,11 +29,12 @@
29
29
  "postpack": "backstage-cli package postpack"
30
30
  },
31
31
  "dependencies": {
32
- "@backstage/catalog-model": "^1.6.0",
33
- "@backstage/core-components": "^0.14.10",
34
- "@backstage/core-plugin-api": "^1.9.3",
35
- "@backstage/plugin-catalog-react": "^1.12.3",
36
- "@backstage/theme": "^0.5.6",
32
+ "@backstage/catalog-model": "^1.7.3",
33
+ "@backstage/core-components": "^0.16.4",
34
+ "@backstage/core-plugin-api": "^1.10.4",
35
+ "@backstage/errors": "^1.2.7",
36
+ "@backstage/plugin-catalog-react": "^1.15.2",
37
+ "@backstage/theme": "^0.6.4",
37
38
  "@mui/icons-material": "^5.15.7",
38
39
  "@mui/material": "^5.15.7",
39
40
  "react-use": "^17.2.4"
@@ -44,10 +45,10 @@
44
45
  "react": "^17.0.0 || ^18.0.0"
45
46
  },
46
47
  "devDependencies": {
47
- "@backstage/cli": "^0.27.0",
48
- "@backstage/core-app-api": "^1.14.2",
49
- "@backstage/dev-utils": "^1.0.37",
50
- "@backstage/test-utils": "^1.5.10",
48
+ "@backstage/cli": "^0.30.0",
49
+ "@backstage/core-app-api": "^1.15.5",
50
+ "@backstage/dev-utils": "^1.1.7",
51
+ "@backstage/test-utils": "^1.7.5",
51
52
  "@testing-library/jest-dom": "6.0.0",
52
53
  "@testing-library/react": "^14.0.0",
53
54
  "@testing-library/user-event": "^14.0.0",
@@ -56,6 +57,13 @@
56
57
  "files": [
57
58
  "dist"
58
59
  ],
60
+ "typesVersions": {
61
+ "*": {
62
+ "index": [
63
+ "dist/index.d.ts"
64
+ ]
65
+ }
66
+ },
59
67
  "module": "./dist/index.esm.js",
60
68
  "directory": "_release/package"
61
- }
69
+ }