@backstage/core-components 0.18.10-next.1 → 0.18.11-next.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 CHANGED
@@ -1,5 +1,25 @@
1
1
  # @backstage/core-components
2
2
 
3
+ ## 0.18.11-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - e0889a3: chore(deps): bump `qs` from 6.15.1 to 6.15.2
8
+ - a07e6a3: Added the correctly-spelled `'header'` literal to the `TableFiltersClassKey` union type and deprecated the previous typoed `'heder'` literal. The generated CSS class with the old key is preserved for backwards compatibility; switch to `'header'` to avoid future removal.
9
+ - 8add9b9: Fixed the proxy-based sign-in page failing to read the session token when the proxy issues a token whose payload is encoded using the URL-safe base64 alphabet. Such tokens are now decoded correctly so sign-in no longer breaks.
10
+
11
+ ## 0.18.10
12
+
13
+ ### Patch Changes
14
+
15
+ - 3846774: Added missing dependencies that were previously only available transitively.
16
+ - 021b368: Added stable DOM markers to the legacy Page and Header so adjacent layout components can coordinate spacing without relying on generated class names.
17
+ - 0c5e41f: Removed unused dependencies that had no imports in source code.
18
+ - Updated dependencies
19
+ - @backstage/errors@1.3.1
20
+ - @backstage/core-plugin-api@1.12.6
21
+ - @backstage/config@1.3.8
22
+
3
23
  ## 0.18.10-next.1
4
24
 
5
25
  ### Patch Changes
@@ -84,7 +84,7 @@ const gfmRehypePlugins = [
84
84
  [
85
85
  rehypeRaw,
86
86
  {
87
- tagFiter: true
87
+ tagfilter: true
88
88
  }
89
89
  ],
90
90
  [
@@ -1 +1 @@
1
- {"version":3,"file":"MarkdownContent.esm.js","sources":["../../../src/components/MarkdownContent/MarkdownContent.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { makeStyles } from '@material-ui/core/styles';\nimport ReactMarkdown, { Options } from 'react-markdown';\nimport gfm from 'remark-gfm';\nimport { Children, createElement } from 'react';\nimport { CodeSnippet } from '../CodeSnippet';\nimport { HeadingProps } from 'react-markdown/lib/ast-to-react';\nimport rehypeRaw from 'rehype-raw';\nimport rehypeSanitize, { defaultSchema } from 'rehype-sanitize';\nimport type { PluggableList } from 'react-markdown/lib/react-markdown';\nimport { Link } from '../Link';\n\nexport type MarkdownContentClassKey = 'markdown';\n\nconst useStyles = makeStyles(\n theme => ({\n markdown: {\n '& table': {\n borderCollapse: 'collapse',\n border: `1px solid ${theme.palette.border}`,\n },\n '& th, & td': {\n border: `1px solid ${theme.palette.border}`,\n padding: theme.spacing(1),\n },\n '& td': {\n wordBreak: 'break-word',\n overflow: 'hidden',\n verticalAlign: 'middle',\n lineHeight: '1',\n margin: 0,\n padding: theme.spacing(3, 2, 3, 2.5),\n borderBottom: 0,\n },\n '& th': {\n backgroundColor: theme.palette.background.paper,\n },\n '& tr': {\n backgroundColor: theme.palette.background.paper,\n },\n '& tr:nth-child(odd)': {\n backgroundColor: theme.palette.background.default,\n },\n\n '& a': {\n color: theme.palette.link,\n },\n '& img': {\n maxWidth: '100%',\n },\n },\n }),\n { name: 'BackstageMarkdownContent' },\n);\n\ntype Props = {\n content: string;\n dialect?: 'gfm' | 'common-mark';\n linkTarget?: Options['linkTarget'];\n transformLinkUri?: (href: string) => string;\n transformImageUri?: (href: string) => string;\n className?: string;\n};\n\nconst flatten = (text: string, child: any): string => {\n if (!child) return text;\n\n return typeof child === 'string'\n ? text + child\n : Children.toArray(child.props.children).reduce(flatten, text);\n};\n\nconst headingRenderer = ({ level, children }: HeadingProps) => {\n const childrenArray = Children.toArray(children);\n const text = childrenArray.reduce(flatten, '');\n const slug = text.toLocaleLowerCase('en-US').replace(/\\W/g, '-');\n return createElement(`h${level}`, { id: slug }, children);\n};\n\nconst components: Options['components'] = {\n code: ({ inline, className, children, ...props }) => {\n const text = String(children).replace(/\\n+$/, '');\n const match = /language-(\\w+)/.exec(className || '');\n return !inline && match ? (\n <CodeSnippet language={match[1]} text={text} />\n ) : (\n <code className={className} {...props}>\n {children}\n </code>\n );\n },\n h1: headingRenderer,\n h2: headingRenderer,\n h3: headingRenderer,\n h4: headingRenderer,\n h5: headingRenderer,\n h6: headingRenderer,\n\n a: ({ href, children, title, target, rel }) =>\n href ? (\n <Link\n to={href}\n title={title}\n {...(target ? { target } : {})}\n {...(rel ? { rel } : {})}\n >\n {children}\n </Link>\n ) : (\n <>{children}</>\n ),\n};\n\nconst gfmRehypePlugins: PluggableList = [\n [\n rehypeRaw,\n {\n tagFiter: true,\n },\n ],\n [\n rehypeSanitize,\n {\n ...defaultSchema,\n attributes: {\n ...defaultSchema.attributes,\n code: [\n ...(defaultSchema.attributes?.code ?? []),\n // for syntax highlighting classes in code blocks\n // breaks the codesnippet component override above if omitted\n ['className'],\n ],\n },\n },\n ],\n];\n\n/**\n * Renders markdown with the default dialect {@link https://github.github.com/gfm/ | gfm - GitHub flavored Markdown} to backstage theme styled HTML.\n *\n * @remarks\n * If you just want to render to plain {@link https://commonmark.org/ | CommonMark}, set the dialect to `'common-mark'`\n */\nexport function MarkdownContent(props: Props) {\n const {\n content,\n dialect = 'gfm',\n linkTarget,\n transformLinkUri,\n transformImageUri,\n className,\n } = props;\n const classes = useStyles();\n return (\n <ReactMarkdown\n remarkPlugins={dialect === 'gfm' ? [gfm] : []}\n rehypePlugins={dialect === 'gfm' ? gfmRehypePlugins : []}\n className={`${classes.markdown} ${className ?? ''}`.trim()}\n children={content}\n components={components}\n linkTarget={linkTarget}\n transformLinkUri={transformLinkUri}\n transformImageUri={transformImageUri}\n />\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MarkdownContent.esm.js","sources":["../../../src/components/MarkdownContent/MarkdownContent.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { makeStyles } from '@material-ui/core/styles';\nimport ReactMarkdown, { Options } from 'react-markdown';\nimport gfm from 'remark-gfm';\nimport { Children, createElement } from 'react';\nimport { CodeSnippet } from '../CodeSnippet';\nimport { HeadingProps } from 'react-markdown/lib/ast-to-react';\nimport rehypeRaw from 'rehype-raw';\nimport rehypeSanitize, { defaultSchema } from 'rehype-sanitize';\nimport type { PluggableList } from 'react-markdown/lib/react-markdown';\nimport { Link } from '../Link';\n\nexport type MarkdownContentClassKey = 'markdown';\n\nconst useStyles = makeStyles(\n theme => ({\n markdown: {\n '& table': {\n borderCollapse: 'collapse',\n border: `1px solid ${theme.palette.border}`,\n },\n '& th, & td': {\n border: `1px solid ${theme.palette.border}`,\n padding: theme.spacing(1),\n },\n '& td': {\n wordBreak: 'break-word',\n overflow: 'hidden',\n verticalAlign: 'middle',\n lineHeight: '1',\n margin: 0,\n padding: theme.spacing(3, 2, 3, 2.5),\n borderBottom: 0,\n },\n '& th': {\n backgroundColor: theme.palette.background.paper,\n },\n '& tr': {\n backgroundColor: theme.palette.background.paper,\n },\n '& tr:nth-child(odd)': {\n backgroundColor: theme.palette.background.default,\n },\n\n '& a': {\n color: theme.palette.link,\n },\n '& img': {\n maxWidth: '100%',\n },\n },\n }),\n { name: 'BackstageMarkdownContent' },\n);\n\ntype Props = {\n content: string;\n dialect?: 'gfm' | 'common-mark';\n linkTarget?: Options['linkTarget'];\n transformLinkUri?: (href: string) => string;\n transformImageUri?: (href: string) => string;\n className?: string;\n};\n\nconst flatten = (text: string, child: any): string => {\n if (!child) return text;\n\n return typeof child === 'string'\n ? text + child\n : Children.toArray(child.props.children).reduce(flatten, text);\n};\n\nconst headingRenderer = ({ level, children }: HeadingProps) => {\n const childrenArray = Children.toArray(children);\n const text = childrenArray.reduce(flatten, '');\n const slug = text.toLocaleLowerCase('en-US').replace(/\\W/g, '-');\n return createElement(`h${level}`, { id: slug }, children);\n};\n\nconst components: Options['components'] = {\n code: ({ inline, className, children, ...props }) => {\n const text = String(children).replace(/\\n+$/, '');\n const match = /language-(\\w+)/.exec(className || '');\n return !inline && match ? (\n <CodeSnippet language={match[1]} text={text} />\n ) : (\n <code className={className} {...props}>\n {children}\n </code>\n );\n },\n h1: headingRenderer,\n h2: headingRenderer,\n h3: headingRenderer,\n h4: headingRenderer,\n h5: headingRenderer,\n h6: headingRenderer,\n\n a: ({ href, children, title, target, rel }) =>\n href ? (\n <Link\n to={href}\n title={title}\n {...(target ? { target } : {})}\n {...(rel ? { rel } : {})}\n >\n {children}\n </Link>\n ) : (\n <>{children}</>\n ),\n};\n\nconst gfmRehypePlugins: PluggableList = [\n [\n rehypeRaw,\n {\n tagfilter: true,\n },\n ],\n [\n rehypeSanitize,\n {\n ...defaultSchema,\n attributes: {\n ...defaultSchema.attributes,\n code: [\n ...(defaultSchema.attributes?.code ?? []),\n // for syntax highlighting classes in code blocks\n // breaks the codesnippet component override above if omitted\n ['className'],\n ],\n },\n },\n ],\n];\n\n/**\n * Renders markdown with the default dialect {@link https://github.github.com/gfm/ | gfm - GitHub flavored Markdown} to backstage theme styled HTML.\n *\n * @remarks\n * If you just want to render to plain {@link https://commonmark.org/ | CommonMark}, set the dialect to `'common-mark'`\n */\nexport function MarkdownContent(props: Props) {\n const {\n content,\n dialect = 'gfm',\n linkTarget,\n transformLinkUri,\n transformImageUri,\n className,\n } = props;\n const classes = useStyles();\n return (\n <ReactMarkdown\n remarkPlugins={dialect === 'gfm' ? [gfm] : []}\n rehypePlugins={dialect === 'gfm' ? gfmRehypePlugins : []}\n className={`${classes.markdown} ${className ?? ''}`.trim()}\n children={content}\n components={components}\n linkTarget={linkTarget}\n transformLinkUri={transformLinkUri}\n transformImageUri={transformImageUri}\n />\n );\n}\n"],"names":[],"mappings":"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"}
@@ -27,6 +27,13 @@ const useFilterStyles = makeStyles(
27
27
  justifyContent: "space-between",
28
28
  borderBottom: `1px solid ${theme.palette.grey[500]}`
29
29
  },
30
+ // Intentionally empty: the deprecated `heder` class is still applied to
31
+ // the same element as `header` so legacy theme overrides on
32
+ // `BackstageTableFilters.heder` continue to work. Keeping this rule empty
33
+ // (rather than duplicating `header`'s styles) avoids clobbering overrides
34
+ // on the canonical `header` key — JSS injects rules in key order, so an
35
+ // empty `heder` defined after `header` has no properties to override.
36
+ heder: {},
30
37
  filters: {
31
38
  display: "flex",
32
39
  flexDirection: "column",
@@ -53,7 +60,7 @@ const Filters = (props) => {
53
60
  onChangeFilters(selectedFilters);
54
61
  }, [selectedFilters, onChangeFilters]);
55
62
  return /* @__PURE__ */ jsxs(Box, { className: classes.root, children: [
56
- /* @__PURE__ */ jsxs(Box, { className: classes.header, children: [
63
+ /* @__PURE__ */ jsxs(Box, { className: `${classes.header} ${classes.heder}`, children: [
57
64
  /* @__PURE__ */ jsx(Box, { className: classes.value, children: t("table.filter.title") }),
58
65
  /* @__PURE__ */ jsx(Button, { color: "primary", onClick: handleClick, children: t("table.filter.clearAll") })
59
66
  ] }),
@@ -1 +1 @@
1
- {"version":3,"file":"Filters.esm.js","sources":["../../../src/components/Table/Filters.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport Box from '@material-ui/core/Box';\nimport Button from '@material-ui/core/Button';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { useEffect, useState } from 'react';\n\nimport { Select } from '../Select';\nimport { SelectProps } from '../Select/Select';\nimport { coreComponentsTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\nexport type TableFiltersClassKey = 'root' | 'value' | 'heder' | 'filters';\n\nconst useFilterStyles = makeStyles(\n theme => ({\n root: {\n height: '100%',\n width: '315px',\n display: 'flex',\n flexDirection: 'column',\n marginRight: theme.spacing(3),\n },\n value: {\n fontWeight: 'bold',\n fontSize: 18,\n },\n header: {\n display: 'flex',\n alignItems: 'center',\n height: theme.spacing(7.5),\n justifyContent: 'space-between',\n borderBottom: `1px solid ${theme.palette.grey[500]}`,\n },\n filters: {\n display: 'flex',\n flexDirection: 'column',\n '& > *': {\n marginTop: theme.spacing(2),\n },\n },\n }),\n { name: 'BackstageTableFilters' },\n);\n\nexport type Without<T, K> = Pick<T, Exclude<keyof T, K>>;\n\nexport type Filter = {\n type: 'select' | 'multiple-select';\n element: Without<SelectProps, 'onChange'>;\n};\n\nexport type SelectedFilters = {\n [key: string]: string | string[];\n};\n\ntype Props = {\n filters: Filter[];\n selectedFilters?: SelectedFilters;\n onChangeFilters: (arg: any) => any;\n};\n\nexport const Filters = (props: Props) => {\n const classes = useFilterStyles();\n\n const { onChangeFilters } = props;\n const { t } = useTranslationRef(coreComponentsTranslationRef);\n\n const [selectedFilters, setSelectedFilters] = useState<SelectedFilters>({\n ...props.selectedFilters,\n });\n const [reset, triggerReset] = useState(false);\n\n // Trigger re-rendering\n const handleClick = () => {\n setSelectedFilters({});\n triggerReset(el => !el);\n };\n\n useEffect(() => {\n onChangeFilters(selectedFilters);\n }, [selectedFilters, onChangeFilters]);\n\n // As material table doesn't provide a way to add a column filter tab we will make our own filter logic\n return (\n <Box className={classes.root}>\n <Box className={classes.header}>\n <Box className={classes.value}>{t('table.filter.title')}</Box>\n <Button color=\"primary\" onClick={handleClick}>\n {t('table.filter.clearAll')}\n </Button>\n </Box>\n <Box className={classes.filters}>\n {props.filters?.length &&\n props.filters.map(filter => (\n <Select\n triggerReset={reset}\n key={filter.element.label}\n {...(filter.element as SelectProps)}\n selected={selectedFilters[filter.element.label]}\n onChange={el =>\n setSelectedFilters({\n ...selectedFilters,\n [filter.element.label]: el as any,\n })\n }\n />\n ))}\n </Box>\n </Box>\n );\n};\n"],"names":["Select"],"mappings":"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"}
1
+ {"version":3,"file":"Filters.esm.js","sources":["../../../src/components/Table/Filters.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport Box from '@material-ui/core/Box';\nimport Button from '@material-ui/core/Button';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { useEffect, useState } from 'react';\n\nimport { Select } from '../Select';\nimport { SelectProps } from '../Select/Select';\nimport { coreComponentsTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\nexport type TableFiltersClassKey =\n | 'root'\n | 'value'\n | 'header'\n /**\n * @deprecated Use `'header'` instead. This was a typo in the original class key.\n */\n | 'heder'\n | 'filters';\n\nconst useFilterStyles = makeStyles(\n theme => ({\n root: {\n height: '100%',\n width: '315px',\n display: 'flex',\n flexDirection: 'column',\n marginRight: theme.spacing(3),\n },\n value: {\n fontWeight: 'bold',\n fontSize: 18,\n },\n header: {\n display: 'flex',\n alignItems: 'center',\n height: theme.spacing(7.5),\n justifyContent: 'space-between',\n borderBottom: `1px solid ${theme.palette.grey[500]}`,\n },\n // Intentionally empty: the deprecated `heder` class is still applied to\n // the same element as `header` so legacy theme overrides on\n // `BackstageTableFilters.heder` continue to work. Keeping this rule empty\n // (rather than duplicating `header`'s styles) avoids clobbering overrides\n // on the canonical `header` key — JSS injects rules in key order, so an\n // empty `heder` defined after `header` has no properties to override.\n heder: {},\n filters: {\n display: 'flex',\n flexDirection: 'column',\n '& > *': {\n marginTop: theme.spacing(2),\n },\n },\n }),\n { name: 'BackstageTableFilters' },\n);\n\nexport type Without<T, K> = Pick<T, Exclude<keyof T, K>>;\n\nexport type Filter = {\n type: 'select' | 'multiple-select';\n element: Without<SelectProps, 'onChange'>;\n};\n\nexport type SelectedFilters = {\n [key: string]: string | string[];\n};\n\ntype Props = {\n filters: Filter[];\n selectedFilters?: SelectedFilters;\n onChangeFilters: (arg: any) => any;\n};\n\nexport const Filters = (props: Props) => {\n const classes = useFilterStyles();\n\n const { onChangeFilters } = props;\n const { t } = useTranslationRef(coreComponentsTranslationRef);\n\n const [selectedFilters, setSelectedFilters] = useState<SelectedFilters>({\n ...props.selectedFilters,\n });\n const [reset, triggerReset] = useState(false);\n\n // Trigger re-rendering\n const handleClick = () => {\n setSelectedFilters({});\n triggerReset(el => !el);\n };\n\n useEffect(() => {\n onChangeFilters(selectedFilters);\n }, [selectedFilters, onChangeFilters]);\n\n // As material table doesn't provide a way to add a column filter tab we will make our own filter logic\n return (\n <Box className={classes.root}>\n <Box className={`${classes.header} ${classes.heder}`}>\n <Box className={classes.value}>{t('table.filter.title')}</Box>\n <Button color=\"primary\" onClick={handleClick}>\n {t('table.filter.clearAll')}\n </Button>\n </Box>\n <Box className={classes.filters}>\n {props.filters?.length &&\n props.filters.map(filter => (\n <Select\n triggerReset={reset}\n key={filter.element.label}\n {...(filter.element as SelectProps)}\n selected={selectedFilters[filter.element.label]}\n onChange={el =>\n setSelectedFilters({\n ...selectedFilters,\n [filter.element.label]: el as any,\n })\n }\n />\n ))}\n </Box>\n </Box>\n );\n};\n"],"names":["Select"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1312,7 +1312,11 @@ declare function RoutedTabs(props: {
1312
1312
  routes: SubRoute[];
1313
1313
  }): react_jsx_runtime.JSX.Element;
1314
1314
 
1315
- type TableFiltersClassKey = 'root' | 'value' | 'heder' | 'filters';
1315
+ type TableFiltersClassKey = 'root' | 'value' | 'header'
1316
+ /**
1317
+ * @deprecated Use `'header'` instead. This was a typo in the original class key.
1318
+ */
1319
+ | 'heder' | 'filters';
1316
1320
  type SelectedFilters = {
1317
1321
  [key: string]: string | string[];
1318
1322
  };
@@ -9,13 +9,18 @@ const DEFAULTS = {
9
9
  // shall start trying to get a new one
10
10
  tokenExpiryMarginMillis: 5 * 60 * 1e3
11
11
  };
12
+ function decodeBase64Url(value) {
13
+ const base64 = value.replace(/-/g, "+").replace(/_/g, "/");
14
+ const padded = base64.padEnd(Math.ceil(base64.length / 4) * 4, "=");
15
+ return window.atob(padded);
16
+ }
12
17
  function tokenToExpiry(jwtToken) {
13
18
  const fallback = new Date(Date.now() + DEFAULTS.defaultTokenExpiryMillis);
14
19
  if (!jwtToken) {
15
20
  return fallback;
16
21
  }
17
22
  const [_header, rawPayload, _signature] = jwtToken.split(".");
18
- const payload = JSON.parse(window.atob(rawPayload));
23
+ const payload = JSON.parse(decodeBase64Url(rawPayload));
19
24
  if (typeof payload.exp !== "number") {
20
25
  return fallback;
21
26
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ProxiedSignInIdentity.esm.js","sources":["../../../src/layout/ProxiedSignInPage/ProxiedSignInIdentity.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n BackstageUserIdentity,\n discoveryApiRef,\n IdentityApi,\n ProfileInfo,\n} from '@backstage/core-plugin-api';\nimport { ResponseError } from '@backstage/errors';\nimport { ProxiedSession, proxiedSessionSchema } from './types';\n\nexport const DEFAULTS = {\n // The amount of time between token refreshes, if we fail to get an actual\n // value out of the exp claim\n defaultTokenExpiryMillis: 5 * 60 * 1000,\n // The amount of time before the actual expiry of the Backstage token, that we\n // shall start trying to get a new one\n tokenExpiryMarginMillis: 5 * 60 * 1000,\n} as const;\n\n// When the token expires, with some margin\nexport function tokenToExpiry(jwtToken: string | undefined): Date {\n const fallback = new Date(Date.now() + DEFAULTS.defaultTokenExpiryMillis);\n if (!jwtToken) {\n return fallback;\n }\n\n const [_header, rawPayload, _signature] = jwtToken.split('.');\n const payload = JSON.parse(window.atob(rawPayload));\n if (typeof payload.exp !== 'number') {\n return fallback;\n }\n\n return new Date(payload.exp * 1000 - DEFAULTS.tokenExpiryMarginMillis);\n}\n\ntype ProxiedSignInIdentityOptions = {\n provider: string;\n discoveryApi: typeof discoveryApiRef.T;\n headers?: HeadersInit | (() => HeadersInit) | (() => Promise<HeadersInit>);\n};\n\ntype State =\n | {\n type: 'empty';\n }\n | {\n type: 'fetching';\n promise: Promise<ProxiedSession>;\n previous: ProxiedSession | undefined;\n }\n | {\n type: 'active';\n session: ProxiedSession;\n expiresAt: Date;\n }\n | {\n type: 'failed';\n error: Error;\n };\n\n/**\n * An identity API that gets the user auth information solely based on a\n * provider's `/refresh` endpoint.\n */\nexport class ProxiedSignInIdentity implements IdentityApi {\n private readonly options: ProxiedSignInIdentityOptions;\n private readonly abortController: AbortController;\n private state: State;\n\n constructor(options: ProxiedSignInIdentityOptions) {\n this.options = options;\n this.abortController = new AbortController();\n this.state = { type: 'empty' };\n }\n\n async start() {\n // Try to make a first fetch, bubble up any errors to the caller\n await this.getSessionAsync();\n }\n\n /** {@inheritdoc @backstage/core-plugin-api#IdentityApi.getUserId} */\n getUserId(): string {\n const { backstageIdentity } = this.getSessionSync();\n const ref = backstageIdentity.identity.userEntityRef;\n const match = /^([^:/]+:)?([^:/]+\\/)?([^:/]+)$/.exec(ref);\n if (!match) {\n throw new TypeError(`Invalid user entity reference \"${ref}\"`);\n }\n\n return match[3];\n }\n\n /** {@inheritdoc @backstage/core-plugin-api#IdentityApi.getIdToken} */\n async getIdToken(): Promise<string | undefined> {\n const session = await this.getSessionAsync();\n return session.backstageIdentity.token;\n }\n\n /** {@inheritdoc @backstage/core-plugin-api#IdentityApi.getProfile} */\n getProfile(): ProfileInfo {\n const session = this.getSessionSync();\n return session.profile;\n }\n\n /** {@inheritdoc @backstage/core-plugin-api#IdentityApi.getProfileInfo} */\n async getProfileInfo(): Promise<ProfileInfo> {\n const session = await this.getSessionAsync();\n return session.profile;\n }\n\n /** {@inheritdoc @backstage/core-plugin-api#IdentityApi.getBackstageIdentity} */\n async getBackstageIdentity(): Promise<BackstageUserIdentity> {\n const session = await this.getSessionAsync();\n return session.backstageIdentity.identity;\n }\n\n /** {@inheritdoc @backstage/core-plugin-api#IdentityApi.getCredentials} */\n async getCredentials(): Promise<{ token?: string | undefined }> {\n const session = await this.getSessionAsync();\n return {\n token: session.backstageIdentity.token,\n };\n }\n\n /** {@inheritdoc @backstage/core-plugin-api#IdentityApi.signOut} */\n async signOut(): Promise<void> {\n this.abortController.abort();\n }\n\n getSessionSync(): ProxiedSession {\n if (this.state.type === 'active') {\n return this.state.session;\n } else if (this.state.type === 'fetching' && this.state.previous) {\n return this.state.previous;\n }\n throw new Error('No session available. Try reloading your browser page.');\n }\n\n async getSessionAsync(): Promise<ProxiedSession> {\n if (this.state.type === 'fetching') {\n return this.state.promise;\n } else if (\n this.state.type === 'active' &&\n new Date() < this.state.expiresAt\n ) {\n return this.state.session;\n }\n\n const previous =\n this.state.type === 'active' ? this.state.session : undefined;\n\n const promise = this.fetchSession().then(\n session => {\n this.state = {\n type: 'active',\n session,\n expiresAt: tokenToExpiry(session.backstageIdentity.token),\n };\n return session;\n },\n error => {\n this.state = {\n type: 'failed',\n error,\n };\n throw error;\n },\n );\n\n this.state = {\n type: 'fetching',\n promise,\n previous,\n };\n\n return promise;\n }\n\n async fetchSession(): Promise<ProxiedSession> {\n const baseUrl = await this.options.discoveryApi.getBaseUrl('auth');\n\n const headers =\n typeof this.options.headers === 'function'\n ? await this.options.headers()\n : this.options.headers;\n const mergedHeaders = new Headers(headers);\n mergedHeaders.set('X-Requested-With', 'XMLHttpRequest');\n\n // Note that we do not use the fetchApi here, since this all happens before\n // sign-in completes so there can be no automatic token injection and\n // similar.\n const response = await fetch(\n `${baseUrl}/${this.options.provider}/refresh`,\n {\n signal: this.abortController.signal,\n headers: mergedHeaders,\n credentials: 'include',\n },\n );\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return proxiedSessionSchema.parse(await response.json());\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ProxiedSignInIdentity.esm.js","sources":["../../../src/layout/ProxiedSignInPage/ProxiedSignInIdentity.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n BackstageUserIdentity,\n discoveryApiRef,\n IdentityApi,\n ProfileInfo,\n} from '@backstage/core-plugin-api';\nimport { ResponseError } from '@backstage/errors';\nimport { ProxiedSession, proxiedSessionSchema } from './types';\n\nexport const DEFAULTS = {\n // The amount of time between token refreshes, if we fail to get an actual\n // value out of the exp claim\n defaultTokenExpiryMillis: 5 * 60 * 1000,\n // The amount of time before the actual expiry of the Backstage token, that we\n // shall start trying to get a new one\n tokenExpiryMarginMillis: 5 * 60 * 1000,\n} as const;\n\n// Decodes a base64url-encoded string. JWTs encode their segments using base64url\n// (RFC 7515), which substitutes '-' and '_' for '+' and '/' and omits padding.\n// `window.atob` only accepts standard base64, so translate back to that alphabet\n// and restore the padding before decoding.\nfunction decodeBase64Url(value: string): string {\n const base64 = value.replace(/-/g, '+').replace(/_/g, '/');\n const padded = base64.padEnd(Math.ceil(base64.length / 4) * 4, '=');\n return window.atob(padded);\n}\n\n// When the token expires, with some margin\nexport function tokenToExpiry(jwtToken: string | undefined): Date {\n const fallback = new Date(Date.now() + DEFAULTS.defaultTokenExpiryMillis);\n if (!jwtToken) {\n return fallback;\n }\n\n const [_header, rawPayload, _signature] = jwtToken.split('.');\n const payload = JSON.parse(decodeBase64Url(rawPayload));\n if (typeof payload.exp !== 'number') {\n return fallback;\n }\n\n return new Date(payload.exp * 1000 - DEFAULTS.tokenExpiryMarginMillis);\n}\n\ntype ProxiedSignInIdentityOptions = {\n provider: string;\n discoveryApi: typeof discoveryApiRef.T;\n headers?: HeadersInit | (() => HeadersInit) | (() => Promise<HeadersInit>);\n};\n\ntype State =\n | {\n type: 'empty';\n }\n | {\n type: 'fetching';\n promise: Promise<ProxiedSession>;\n previous: ProxiedSession | undefined;\n }\n | {\n type: 'active';\n session: ProxiedSession;\n expiresAt: Date;\n }\n | {\n type: 'failed';\n error: Error;\n };\n\n/**\n * An identity API that gets the user auth information solely based on a\n * provider's `/refresh` endpoint.\n */\nexport class ProxiedSignInIdentity implements IdentityApi {\n private readonly options: ProxiedSignInIdentityOptions;\n private readonly abortController: AbortController;\n private state: State;\n\n constructor(options: ProxiedSignInIdentityOptions) {\n this.options = options;\n this.abortController = new AbortController();\n this.state = { type: 'empty' };\n }\n\n async start() {\n // Try to make a first fetch, bubble up any errors to the caller\n await this.getSessionAsync();\n }\n\n /** {@inheritdoc @backstage/core-plugin-api#IdentityApi.getUserId} */\n getUserId(): string {\n const { backstageIdentity } = this.getSessionSync();\n const ref = backstageIdentity.identity.userEntityRef;\n const match = /^([^:/]+:)?([^:/]+\\/)?([^:/]+)$/.exec(ref);\n if (!match) {\n throw new TypeError(`Invalid user entity reference \"${ref}\"`);\n }\n\n return match[3];\n }\n\n /** {@inheritdoc @backstage/core-plugin-api#IdentityApi.getIdToken} */\n async getIdToken(): Promise<string | undefined> {\n const session = await this.getSessionAsync();\n return session.backstageIdentity.token;\n }\n\n /** {@inheritdoc @backstage/core-plugin-api#IdentityApi.getProfile} */\n getProfile(): ProfileInfo {\n const session = this.getSessionSync();\n return session.profile;\n }\n\n /** {@inheritdoc @backstage/core-plugin-api#IdentityApi.getProfileInfo} */\n async getProfileInfo(): Promise<ProfileInfo> {\n const session = await this.getSessionAsync();\n return session.profile;\n }\n\n /** {@inheritdoc @backstage/core-plugin-api#IdentityApi.getBackstageIdentity} */\n async getBackstageIdentity(): Promise<BackstageUserIdentity> {\n const session = await this.getSessionAsync();\n return session.backstageIdentity.identity;\n }\n\n /** {@inheritdoc @backstage/core-plugin-api#IdentityApi.getCredentials} */\n async getCredentials(): Promise<{ token?: string | undefined }> {\n const session = await this.getSessionAsync();\n return {\n token: session.backstageIdentity.token,\n };\n }\n\n /** {@inheritdoc @backstage/core-plugin-api#IdentityApi.signOut} */\n async signOut(): Promise<void> {\n this.abortController.abort();\n }\n\n getSessionSync(): ProxiedSession {\n if (this.state.type === 'active') {\n return this.state.session;\n } else if (this.state.type === 'fetching' && this.state.previous) {\n return this.state.previous;\n }\n throw new Error('No session available. Try reloading your browser page.');\n }\n\n async getSessionAsync(): Promise<ProxiedSession> {\n if (this.state.type === 'fetching') {\n return this.state.promise;\n } else if (\n this.state.type === 'active' &&\n new Date() < this.state.expiresAt\n ) {\n return this.state.session;\n }\n\n const previous =\n this.state.type === 'active' ? this.state.session : undefined;\n\n const promise = this.fetchSession().then(\n session => {\n this.state = {\n type: 'active',\n session,\n expiresAt: tokenToExpiry(session.backstageIdentity.token),\n };\n return session;\n },\n error => {\n this.state = {\n type: 'failed',\n error,\n };\n throw error;\n },\n );\n\n this.state = {\n type: 'fetching',\n promise,\n previous,\n };\n\n return promise;\n }\n\n async fetchSession(): Promise<ProxiedSession> {\n const baseUrl = await this.options.discoveryApi.getBaseUrl('auth');\n\n const headers =\n typeof this.options.headers === 'function'\n ? await this.options.headers()\n : this.options.headers;\n const mergedHeaders = new Headers(headers);\n mergedHeaders.set('X-Requested-With', 'XMLHttpRequest');\n\n // Note that we do not use the fetchApi here, since this all happens before\n // sign-in completes so there can be no automatic token injection and\n // similar.\n const response = await fetch(\n `${baseUrl}/${this.options.provider}/refresh`,\n {\n signal: this.abortController.signal,\n headers: mergedHeaders,\n credentials: 'include',\n },\n );\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return proxiedSessionSchema.parse(await response.json());\n }\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/core-components",
3
- "version": "0.18.10-next.1",
3
+ "version": "0.18.11-next.0",
4
4
  "description": "Core components used by Backstage plugins and apps",
5
5
  "backstage": {
6
6
  "role": "web-library"
@@ -66,9 +66,9 @@
66
66
  "test": "backstage-cli package test"
67
67
  },
68
68
  "dependencies": {
69
- "@backstage/config": "1.3.8-next.0",
70
- "@backstage/core-plugin-api": "1.12.6-next.1",
71
- "@backstage/errors": "1.3.1-next.0",
69
+ "@backstage/config": "1.3.8",
70
+ "@backstage/core-plugin-api": "1.12.6",
71
+ "@backstage/errors": "1.3.1",
72
72
  "@backstage/theme": "0.7.3",
73
73
  "@backstage/version-bridge": "1.0.12",
74
74
  "@dagrejs/dagre": "^1.1.4",
@@ -91,7 +91,7 @@
91
91
  "linkifyjs": "4.3.2",
92
92
  "lodash": "^4.17.21",
93
93
  "parse5": "^6.0.0",
94
- "qs": "^6.9.4",
94
+ "qs": "^6.15.2",
95
95
  "rc-progress": "3.5.1",
96
96
  "react-full-screen": "^1.1.1",
97
97
  "react-helmet": "6.1.0",
@@ -110,10 +110,10 @@
110
110
  "zod": "^3.25.76 || ^4.0.0"
111
111
  },
112
112
  "devDependencies": {
113
- "@backstage/app-defaults": "1.7.8-next.0",
114
- "@backstage/cli": "0.36.2-next.1",
115
- "@backstage/core-app-api": "1.20.1-next.0",
116
- "@backstage/test-utils": "1.7.18-next.0",
113
+ "@backstage/app-defaults": "1.7.9-next.0",
114
+ "@backstage/cli": "0.36.3-next.0",
115
+ "@backstage/core-app-api": "1.20.1",
116
+ "@backstage/test-utils": "1.7.18",
117
117
  "@testing-library/dom": "^10.0.0",
118
118
  "@testing-library/jest-dom": "^6.0.0",
119
119
  "@testing-library/user-event": "^14.0.0",