@backstage/plugin-catalog 2.0.7-next.0 → 2.0.7

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,38 @@
1
1
  # @backstage/plugin-catalog
2
2
 
3
+ ## 2.0.7
4
+
5
+ ### Patch Changes
6
+
7
+ - ba49e37: Migrated the new frontend system Catalog entity context menu to BUI and switched its built-in action icons to Remix icons. The old frontend system Catalog context menu remains unchanged.
8
+
9
+ **BREAKING ALPHA**: The new frontend system Catalog entity page now consumes data-driven context menu item extensions. Its `contextMenuItems` input expects the `EntityContextMenuItemBlueprint` data output rather than a rendered React element.
10
+
11
+ The default English value of the `entityContextMenu.moreButtonAriaLabel` translation changed from `more` to `More actions`. If you provide localized Catalog messages, update this label as appropriate for your locale.
12
+
13
+ - 15719cc: **BREAKING ALPHA**: Migrated the new frontend system Catalog entity page to the automatic Catalog plugin header and a BUI page header with entity tags, title, metadata, favorite and context-menu actions, and Catalog-composed navigation.
14
+
15
+ Existing alpha opaque entity header customizations continue to render through a temporary per-entity legacy fallback with the previous MUI tabs and page shell. Migrate those customizations to the new BUI-ready entity header layout extension point to receive composed tabs and the active tab ID. The new extension point wins when both customization types match an entity.
16
+
17
+ The default BUI navigation does not render entity-content tab icons because the BUI Header tab API does not expose an icon slot. Legacy fallback pages retain their existing tab-icon behavior.
18
+
19
+ Added the translation keys `entityLabels.systemLabel`, `entityLabels.domainLabel`, and `entityLabels.partOfLabel`. Apps that provide Catalog translations should add translations for these new messages.
20
+
21
+ - a00547f: Fix crash when exporting the catalog with unset filters.
22
+ - 1217673: Fixed a crash in the catalog export when an entity list filter is `undefined`, which could occur if optional filters were not set.
23
+ - Updated dependencies
24
+ - @backstage/frontend-plugin-api@0.17.3
25
+ - @backstage/ui@0.17.0
26
+ - @backstage/plugin-catalog-react@3.2.0
27
+ - @backstage/core-components@0.18.12
28
+ - @backstage/plugin-techdocs-react@1.3.13
29
+ - @backstage/catalog-client@1.16.1
30
+ - @backstage/core-compat-api@0.5.13
31
+ - @backstage/core-plugin-api@1.12.8
32
+ - @backstage/integration-react@1.2.20
33
+ - @backstage/plugin-permission-react@0.5.3
34
+ - @backstage/plugin-search-react@1.11.6
35
+
3
36
  ## 2.0.7-next.0
4
37
 
5
38
  ### Patch Changes
@@ -7,23 +7,23 @@ import { entityRouteRef, useAsyncEntity } from '@backstage/plugin-catalog-react'
7
7
  import { catalogTranslationRef } from '../../translation.esm.js';
8
8
  import { EntityHeader } from '../EntityHeader/EntityHeader.esm.js';
9
9
  import { EntityTabs } from '../EntityTabs/EntityTabs.esm.js';
10
- import { useEntityLayoutRoutes, EntityLayoutRoute } from './entityLayoutRoutes.esm.js';
10
+ import { filterEntityLayoutRoutes } from './entityLayoutRoutes.esm.js';
11
11
 
12
- const EntityLayout = (props) => {
12
+ function EntityLayout(props) {
13
13
  const {
14
14
  UNSTABLE_extraContextMenuItems,
15
15
  contextMenuItems,
16
- children,
17
16
  header,
18
17
  NotFoundComponent,
19
18
  parentEntityRelations,
20
19
  groupDefinitions,
21
20
  defaultContentOrder,
22
- showNavItemIcons
21
+ showNavItemIcons,
22
+ routes
23
23
  } = props;
24
24
  const { kind } = useRouteRefParams(entityRouteRef);
25
25
  const { entity, loading, error } = useAsyncEntity();
26
- const routes = useEntityLayoutRoutes(children, entity);
26
+ const visibleRoutes = filterEntityLayoutRoutes(routes, entity);
27
27
  const { t } = useTranslationRef(catalogTranslationRef);
28
28
  return /* @__PURE__ */ jsxs(Page, { themeId: entity?.spec?.type?.toString() ?? "home", children: [
29
29
  header ?? /* @__PURE__ */ jsx(
@@ -38,7 +38,7 @@ const EntityLayout = (props) => {
38
38
  entity && /* @__PURE__ */ jsx(
39
39
  EntityTabs,
40
40
  {
41
- routes,
41
+ routes: visibleRoutes,
42
42
  groupDefinitions,
43
43
  defaultContentOrder,
44
44
  showIcons: showNavItemIcons
@@ -50,8 +50,7 @@ const EntityLayout = (props) => {
50
50
  link: /* @__PURE__ */ jsx(Link, { to: "https://backstage.io/docs/features/software-catalog/references", children: t("entityPage.notFoundLinkText") })
51
51
  }) }) })
52
52
  ] });
53
- };
54
- EntityLayout.Route = EntityLayoutRoute;
53
+ }
55
54
 
56
55
  export { EntityLayout };
57
56
  //# sourceMappingURL=EntityLayout.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"EntityLayout.esm.js","sources":["../../../../src/alpha/components/EntityLayout/EntityLayout.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 { ComponentProps, ReactNode } from 'react';\n\nimport Alert from '@material-ui/lab/Alert';\n\nimport { useRouteRefParams } from '@backstage/core-plugin-api';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport {\n Content,\n Link,\n Page,\n Progress,\n WarningPanel,\n} from '@backstage/core-components';\nimport {\n entityRouteRef,\n useAsyncEntity,\n} from '@backstage/plugin-catalog-react';\n\nimport { catalogTranslationRef } from '../../translation';\nimport { EntityHeader } from '../EntityHeader';\nimport { EntityTabs } from '../EntityTabs';\nimport { EntityContentGroupDefinitions } from '@backstage/plugin-catalog-react/alpha';\nimport { EntityLayoutRoute, useEntityLayoutRoutes } from './entityLayoutRoutes';\n\nexport type { EntityLayoutRouteProps } from './entityLayoutRoutes';\n\n/** @public */\nexport interface EntityLayoutProps {\n UNSTABLE_extraContextMenuItems?: ComponentProps<\n typeof EntityHeader\n >['UNSTABLE_extraContextMenuItems'];\n contextMenuItems?: ComponentProps<typeof EntityHeader>['contextMenuItems'];\n children?: ReactNode;\n header?: JSX.Element;\n NotFoundComponent?: ReactNode;\n /**\n * An array of relation types used to determine the parent entities in the hierarchy.\n * These relations are prioritized in the order provided, allowing for flexible\n * navigation through entity relationships.\n *\n * For example, use relation types like `[\"partOf\", \"memberOf\", \"ownedBy\"]` to define how the entity is related to\n * its parents in the Entity Catalog.\n *\n * It adds breadcrumbs in the Entity page to enhance user navigation and context awareness.\n */\n parentEntityRelations?: string[];\n groupDefinitions: EntityContentGroupDefinitions;\n defaultContentOrder?: 'title' | 'natural';\n showNavItemIcons?: boolean;\n}\n\n/**\n * EntityLayout is a compound component, which allows you to define a layout for\n * entities using a sub-navigation mechanism.\n *\n * Consists of two parts: EntityLayout and EntityLayout.Route\n *\n * @example\n * ```jsx\n * <EntityLayout>\n * <EntityLayout.Route path=\"/example\" title=\"Example tab\">\n * <div>This is rendered under /example/anything-here route</div>\n * </EntityLayout.Route>\n * </EntityLayout>\n * ```\n *\n * @public\n */\nexport const EntityLayout = (props: EntityLayoutProps) => {\n const {\n UNSTABLE_extraContextMenuItems,\n contextMenuItems,\n children,\n header,\n NotFoundComponent,\n parentEntityRelations,\n groupDefinitions,\n defaultContentOrder,\n showNavItemIcons,\n } = props;\n const { kind } = useRouteRefParams(entityRouteRef);\n const { entity, loading, error } = useAsyncEntity();\n\n const routes = useEntityLayoutRoutes(children, entity);\n\n const { t } = useTranslationRef(catalogTranslationRef);\n\n return (\n <Page themeId={entity?.spec?.type?.toString() ?? 'home'}>\n {header ?? (\n <EntityHeader\n parentEntityRelations={parentEntityRelations}\n UNSTABLE_extraContextMenuItems={UNSTABLE_extraContextMenuItems}\n contextMenuItems={contextMenuItems}\n />\n )}\n\n {loading && <Progress />}\n\n {entity && (\n <EntityTabs\n routes={routes}\n groupDefinitions={groupDefinitions}\n defaultContentOrder={defaultContentOrder}\n showIcons={showNavItemIcons}\n />\n )}\n\n {error && (\n <Content>\n <Alert severity=\"error\">{error.toString()}</Alert>\n </Content>\n )}\n\n {!loading && !error && !entity && (\n <Content>\n {NotFoundComponent ? (\n NotFoundComponent\n ) : (\n <WarningPanel title={t('entityLabels.warningPanelTitle')}>\n {t('entityPage.notFoundMessage', {\n kind,\n link: (\n <Link to=\"https://backstage.io/docs/features/software-catalog/references\">\n {t('entityPage.notFoundLinkText')}\n </Link>\n ),\n })}\n </WarningPanel>\n )}\n </Content>\n )}\n </Page>\n );\n};\n\nEntityLayout.Route = EntityLayoutRoute;\n"],"names":[],"mappings":";;;;;;;;;;;AAoFO,MAAM,YAAA,GAAe,CAAC,KAAA,KAA6B;AACxD,EAAA,MAAM;AAAA,IACJ,8BAAA;AAAA,IACA,gBAAA;AAAA,IACA,QAAA;AAAA,IACA,MAAA;AAAA,IACA,iBAAA;AAAA,IACA,qBAAA;AAAA,IACA,gBAAA;AAAA,IACA,mBAAA;AAAA,IACA;AAAA,GACF,GAAI,KAAA;AACJ,EAAA,MAAM,EAAE,IAAA,EAAK,GAAI,iBAAA,CAAkB,cAAc,CAAA;AACjD,EAAA,MAAM,EAAE,MAAA,EAAQ,OAAA,EAAS,KAAA,KAAU,cAAA,EAAe;AAElD,EAAA,MAAM,MAAA,GAAS,qBAAA,CAAsB,QAAA,EAAU,MAAM,CAAA;AAErD,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,iBAAA,CAAkB,qBAAqB,CAAA;AAErD,EAAA,uBACE,IAAA,CAAC,QAAK,OAAA,EAAS,MAAA,EAAQ,MAAM,IAAA,EAAM,QAAA,MAAc,MAAA,EAC9C,QAAA,EAAA;AAAA,IAAA,MAAA,oBACC,GAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,qBAAA;AAAA,QACA,8BAAA;AAAA,QACA;AAAA;AAAA,KACF;AAAA,IAGD,OAAA,wBAAY,QAAA,EAAA,EAAS,CAAA;AAAA,IAErB,MAAA,oBACC,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,MAAA;AAAA,QACA,gBAAA;AAAA,QACA,mBAAA;AAAA,QACA,SAAA,EAAW;AAAA;AAAA,KACb;AAAA,IAGD,KAAA,oBACC,GAAA,CAAC,OAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,KAAA,EAAA,EAAM,UAAS,OAAA,EAAS,QAAA,EAAA,KAAA,CAAM,QAAA,EAAS,EAAE,CAAA,EAC5C,CAAA;AAAA,IAGD,CAAC,OAAA,IAAW,CAAC,KAAA,IAAS,CAAC,0BACtB,GAAA,CAAC,OAAA,EAAA,EACE,QAAA,EAAA,iBAAA,GACC,iBAAA,uBAEC,YAAA,EAAA,EAAa,KAAA,EAAO,EAAE,gCAAgC,CAAA,EACpD,YAAE,4BAAA,EAA8B;AAAA,MAC/B,IAAA;AAAA,MACA,sBACE,GAAA,CAAC,IAAA,EAAA,EAAK,IAAG,gEAAA,EACN,QAAA,EAAA,CAAA,CAAE,6BAA6B,CAAA,EAClC;AAAA,KAEH,GACH,CAAA,EAEJ;AAAA,GAAA,EAEJ,CAAA;AAEJ;AAEA,YAAA,CAAa,KAAA,GAAQ,iBAAA;;;;"}
1
+ {"version":3,"file":"EntityLayout.esm.js","sources":["../../../../src/alpha/components/EntityLayout/EntityLayout.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 { ComponentProps, ReactNode } from 'react';\n\nimport Alert from '@material-ui/lab/Alert';\n\nimport { useRouteRefParams } from '@backstage/core-plugin-api';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport {\n Content,\n Link,\n Page,\n Progress,\n WarningPanel,\n} from '@backstage/core-components';\nimport {\n entityRouteRef,\n useAsyncEntity,\n} from '@backstage/plugin-catalog-react';\n\nimport { catalogTranslationRef } from '../../translation';\nimport { EntityHeader } from '../EntityHeader';\nimport { EntityTabs } from '../EntityTabs';\nimport { EntityContentGroupDefinitions } from '@backstage/plugin-catalog-react/alpha';\nimport {\n EntityLayoutRoute,\n filterEntityLayoutRoutes,\n} from './entityLayoutRoutes';\n\ninterface EntityLayoutProps {\n UNSTABLE_extraContextMenuItems?: ComponentProps<\n typeof EntityHeader\n >['UNSTABLE_extraContextMenuItems'];\n contextMenuItems?: ComponentProps<typeof EntityHeader>['contextMenuItems'];\n header?: JSX.Element;\n NotFoundComponent?: ReactNode;\n /**\n * An array of relation types used to determine the parent entities in the hierarchy.\n * These relations are prioritized in the order provided, allowing for flexible\n * navigation through entity relationships.\n *\n * For example, use relation types like `[\"partOf\", \"memberOf\", \"ownedBy\"]` to define how the entity is related to\n * its parents in the Entity Catalog.\n *\n * It adds breadcrumbs in the Entity page to enhance user navigation and context awareness.\n */\n parentEntityRelations?: string[];\n groupDefinitions: EntityContentGroupDefinitions;\n defaultContentOrder?: 'title' | 'natural';\n showNavItemIcons?: boolean;\n routes: EntityLayoutRoute[];\n}\n\nexport function EntityLayout(props: EntityLayoutProps) {\n const {\n UNSTABLE_extraContextMenuItems,\n contextMenuItems,\n header,\n NotFoundComponent,\n parentEntityRelations,\n groupDefinitions,\n defaultContentOrder,\n showNavItemIcons,\n routes,\n } = props;\n const { kind } = useRouteRefParams(entityRouteRef);\n const { entity, loading, error } = useAsyncEntity();\n\n const visibleRoutes = filterEntityLayoutRoutes(routes, entity);\n\n const { t } = useTranslationRef(catalogTranslationRef);\n\n return (\n <Page themeId={entity?.spec?.type?.toString() ?? 'home'}>\n {header ?? (\n <EntityHeader\n parentEntityRelations={parentEntityRelations}\n UNSTABLE_extraContextMenuItems={UNSTABLE_extraContextMenuItems}\n contextMenuItems={contextMenuItems}\n />\n )}\n\n {loading && <Progress />}\n\n {entity && (\n <EntityTabs\n routes={visibleRoutes}\n groupDefinitions={groupDefinitions}\n defaultContentOrder={defaultContentOrder}\n showIcons={showNavItemIcons}\n />\n )}\n\n {error && (\n <Content>\n <Alert severity=\"error\">{error.toString()}</Alert>\n </Content>\n )}\n\n {!loading && !error && !entity && (\n <Content>\n {NotFoundComponent ? (\n NotFoundComponent\n ) : (\n <WarningPanel title={t('entityLabels.warningPanelTitle')}>\n {t('entityPage.notFoundMessage', {\n kind,\n link: (\n <Link to=\"https://backstage.io/docs/features/software-catalog/references\">\n {t('entityPage.notFoundLinkText')}\n </Link>\n ),\n })}\n </WarningPanel>\n )}\n </Content>\n )}\n </Page>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;AAmEO,SAAS,aAAa,KAAA,EAA0B;AACrD,EAAA,MAAM;AAAA,IACJ,8BAAA;AAAA,IACA,gBAAA;AAAA,IACA,MAAA;AAAA,IACA,iBAAA;AAAA,IACA,qBAAA;AAAA,IACA,gBAAA;AAAA,IACA,mBAAA;AAAA,IACA,gBAAA;AAAA,IACA;AAAA,GACF,GAAI,KAAA;AACJ,EAAA,MAAM,EAAE,IAAA,EAAK,GAAI,iBAAA,CAAkB,cAAc,CAAA;AACjD,EAAA,MAAM,EAAE,MAAA,EAAQ,OAAA,EAAS,KAAA,KAAU,cAAA,EAAe;AAElD,EAAA,MAAM,aAAA,GAAgB,wBAAA,CAAyB,MAAA,EAAQ,MAAM,CAAA;AAE7D,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,iBAAA,CAAkB,qBAAqB,CAAA;AAErD,EAAA,uBACE,IAAA,CAAC,QAAK,OAAA,EAAS,MAAA,EAAQ,MAAM,IAAA,EAAM,QAAA,MAAc,MAAA,EAC9C,QAAA,EAAA;AAAA,IAAA,MAAA,oBACC,GAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,qBAAA;AAAA,QACA,8BAAA;AAAA,QACA;AAAA;AAAA,KACF;AAAA,IAGD,OAAA,wBAAY,QAAA,EAAA,EAAS,CAAA;AAAA,IAErB,MAAA,oBACC,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,MAAA,EAAQ,aAAA;AAAA,QACR,gBAAA;AAAA,QACA,mBAAA;AAAA,QACA,SAAA,EAAW;AAAA;AAAA,KACb;AAAA,IAGD,KAAA,oBACC,GAAA,CAAC,OAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,KAAA,EAAA,EAAM,UAAS,OAAA,EAAS,QAAA,EAAA,KAAA,CAAM,QAAA,EAAS,EAAE,CAAA,EAC5C,CAAA;AAAA,IAGD,CAAC,OAAA,IAAW,CAAC,KAAA,IAAS,CAAC,0BACtB,GAAA,CAAC,OAAA,EAAA,EACE,QAAA,EAAA,iBAAA,GACC,iBAAA,uBAEC,YAAA,EAAA,EAAa,KAAA,EAAO,EAAE,gCAAgC,CAAA,EACpD,YAAE,4BAAA,EAA8B;AAAA,MAC/B,IAAA;AAAA,MACA,sBACE,GAAA,CAAC,IAAA,EAAA,EAAK,IAAG,gEAAA,EACN,QAAA,EAAA,CAAA,CAAE,6BAA6B,CAAA,EAClC;AAAA,KAEH,GACH,CAAA,EAEJ;AAAA,GAAA,EAEJ,CAAA;AAEJ;;;;"}
@@ -11,7 +11,7 @@ import { useAsyncEntity, entityRouteRef, useEntityPresentation, InspectEntityDia
11
11
  import { catalogTranslationRef } from '../../translation.esm.js';
12
12
  import { EntityHeaderBui } from '../EntityHeader/EntityHeaderBui.esm.js';
13
13
  import { useEntityTabs } from '../EntityTabs/useEntityTabs.esm.js';
14
- import { useEntityLayoutRoutes } from './entityLayoutRoutes.esm.js';
14
+ import { filterEntityLayoutRoutes } from './entityLayoutRoutes.esm.js';
15
15
 
16
16
  function EntityDocumentTitle(props) {
17
17
  const configApi = useApi(configApiRef);
@@ -91,7 +91,7 @@ function EntityLayoutContent(props) {
91
91
  }
92
92
  function EntityLayoutBui(props) {
93
93
  const {
94
- children,
94
+ routes,
95
95
  NotFoundComponent,
96
96
  groupDefinitions,
97
97
  defaultContentOrder,
@@ -99,8 +99,12 @@ function EntityLayoutBui(props) {
99
99
  HeaderComponent
100
100
  } = props;
101
101
  const { entity } = useAsyncEntity();
102
- const routes = useEntityLayoutRoutes(children, entity);
103
- const tabs = useEntityTabs({ routes, groupDefinitions, defaultContentOrder });
102
+ const visibleRoutes = filterEntityLayoutRoutes(routes, entity);
103
+ const tabs = useEntityTabs({
104
+ routes: visibleRoutes,
105
+ groupDefinitions,
106
+ defaultContentOrder
107
+ });
104
108
  return /* @__PURE__ */ jsxs("main", { children: [
105
109
  /* @__PURE__ */ jsx(EntityDocumentTitle, { activeContentTitle: tabs.title }),
106
110
  HeaderComponent ? /* @__PURE__ */ jsx(HeaderComponent, { tabs: tabs.tabs, activeTabId: tabs.activeTabId }) : /* @__PURE__ */ jsx(
@@ -1 +1 @@
1
- {"version":3,"file":"EntityLayoutBui.esm.js","sources":["../../../../src/alpha/components/EntityLayout/EntityLayoutBui.tsx"],"sourcesContent":["/*\n * Copyright 2026 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 { ComponentProps, ComponentType, ReactNode, useCallback } from 'react';\nimport { Helmet } from 'react-helmet';\nimport { useSearchParams } from 'react-router-dom';\nimport { Alert, Container } from '@backstage/ui';\nimport {\n configApiRef,\n useApi,\n useRouteRefParams,\n} from '@backstage/core-plugin-api';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { Link, Progress } from '@backstage/core-components';\nimport { NotFoundErrorPage } from '@backstage/frontend-plugin-api';\nimport {\n entityRouteRef,\n InspectEntityDialog,\n useAsyncEntity,\n useEntityPresentation,\n} from '@backstage/plugin-catalog-react';\nimport {\n type EntityContentGroupDefinitions,\n type EntityHeaderLayoutProps,\n} from '@backstage/plugin-catalog-react/alpha';\nimport { catalogTranslationRef } from '../../translation';\nimport { EntityHeaderBui } from '../EntityHeader/EntityHeaderBui';\nimport { useEntityTabs } from '../EntityTabs/useEntityTabs';\nimport { useEntityLayoutRoutes } from './entityLayoutRoutes';\n\nfunction EntityDocumentTitle(props: { activeContentTitle?: string }) {\n const configApi = useApi(configApiRef);\n const routeParams = useRouteRefParams(entityRouteRef);\n const { entity } = useAsyncEntity();\n const presentation = useEntityPresentation(entity ?? routeParams);\n const appTitle = configApi.getOptionalString('app.title') || 'Backstage';\n return (\n <>\n <Helmet\n titleTemplate={`${presentation.primaryTitle} | %s | ${appTitle}`}\n defaultTitle={`${presentation.primaryTitle} | ${appTitle}`}\n />\n {props.activeContentTitle && <Helmet title={props.activeContentTitle} />}\n </>\n );\n}\n\nfunction InspectEntityDialogHost() {\n const { entity } = useAsyncEntity();\n const [searchParams, setSearchParams] = useSearchParams();\n const selectedTab = searchParams.get('inspect');\n const setSelectedTab = useCallback(\n (tab: string) =>\n setSearchParams(params => {\n const next = new URLSearchParams(params);\n next.set('inspect', tab);\n return next;\n }),\n [setSearchParams],\n );\n const close = useCallback(\n () =>\n setSearchParams(params => {\n const next = new URLSearchParams(params);\n next.delete('inspect');\n return next;\n }),\n [setSearchParams],\n );\n if (!entity) return null;\n return (\n <InspectEntityDialog\n entity={entity}\n initialTab={\n (selectedTab as ComponentProps<\n typeof InspectEntityDialog\n >['initialTab']) || undefined\n }\n open={typeof selectedTab === 'string'}\n onClose={close}\n onSelect={setSelectedTab}\n />\n );\n}\n\nfunction EntityLayoutContent(props: {\n content?: React.JSX.Element;\n NotFoundComponent?: ReactNode;\n}) {\n const { kind } = useRouteRefParams(entityRouteRef);\n const { entity, loading, error } = useAsyncEntity();\n const { t } = useTranslationRef(catalogTranslationRef);\n\n let content: ReactNode;\n if (error) {\n content = (\n <Container>\n <Alert status=\"danger\" title={error.toString()} />\n </Container>\n );\n } else if (entity) {\n content = <Container>{props.content ?? <NotFoundErrorPage />}</Container>;\n } else if (!loading) {\n content = (\n <Container>\n {props.NotFoundComponent ?? (\n <Alert\n status=\"warning\"\n title={t('entityLabels.warningPanelTitle')}\n description={t('entityPage.notFoundMessage', {\n kind,\n link: (\n <Link to=\"https://backstage.io/docs/features/software-catalog/references\">\n {t('entityPage.notFoundLinkText')}\n </Link>\n ),\n })}\n />\n )}\n </Container>\n );\n }\n\n return (\n <>\n {loading && <Progress />}\n {content}\n </>\n );\n}\n\nexport function EntityLayoutBui(props: {\n children?: ReactNode;\n NotFoundComponent?: ReactNode;\n groupDefinitions: EntityContentGroupDefinitions;\n defaultContentOrder: 'title' | 'natural';\n contextMenuItems?: ComponentProps<typeof EntityHeaderBui>['contextMenuItems'];\n HeaderComponent?: ComponentType<EntityHeaderLayoutProps>;\n}) {\n const {\n children,\n NotFoundComponent,\n groupDefinitions,\n defaultContentOrder,\n contextMenuItems,\n HeaderComponent,\n } = props;\n const { entity } = useAsyncEntity();\n const routes = useEntityLayoutRoutes(children, entity);\n const tabs = useEntityTabs({ routes, groupDefinitions, defaultContentOrder });\n\n return (\n <main>\n <EntityDocumentTitle activeContentTitle={tabs.title} />\n {HeaderComponent ? (\n <HeaderComponent tabs={tabs.tabs} activeTabId={tabs.activeTabId} />\n ) : (\n <EntityHeaderBui\n tabs={tabs.tabs}\n activeTabId={tabs.activeTabId}\n contextMenuItems={contextMenuItems}\n />\n )}\n <EntityLayoutContent\n content={tabs.content}\n NotFoundComponent={NotFoundComponent}\n />\n <InspectEntityDialogHost />\n </main>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EntityLayoutBui.esm.js","sources":["../../../../src/alpha/components/EntityLayout/EntityLayoutBui.tsx"],"sourcesContent":["/*\n * Copyright 2026 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 { ComponentProps, ComponentType, ReactNode, useCallback } from 'react';\nimport { Helmet } from 'react-helmet';\nimport { useSearchParams } from 'react-router-dom';\nimport { Alert, Container } from '@backstage/ui';\nimport {\n configApiRef,\n useApi,\n useRouteRefParams,\n} from '@backstage/core-plugin-api';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { Link, Progress } from '@backstage/core-components';\nimport { NotFoundErrorPage } from '@backstage/frontend-plugin-api';\nimport {\n entityRouteRef,\n InspectEntityDialog,\n useAsyncEntity,\n useEntityPresentation,\n} from '@backstage/plugin-catalog-react';\nimport {\n type EntityContentGroupDefinitions,\n type EntityHeaderLayoutProps,\n} from '@backstage/plugin-catalog-react/alpha';\nimport { catalogTranslationRef } from '../../translation';\nimport { EntityHeaderBui } from '../EntityHeader/EntityHeaderBui';\nimport { useEntityTabs } from '../EntityTabs/useEntityTabs';\nimport {\n EntityLayoutRoute,\n filterEntityLayoutRoutes,\n} from './entityLayoutRoutes';\n\nfunction EntityDocumentTitle(props: { activeContentTitle?: string }) {\n const configApi = useApi(configApiRef);\n const routeParams = useRouteRefParams(entityRouteRef);\n const { entity } = useAsyncEntity();\n const presentation = useEntityPresentation(entity ?? routeParams);\n const appTitle = configApi.getOptionalString('app.title') || 'Backstage';\n return (\n <>\n <Helmet\n titleTemplate={`${presentation.primaryTitle} | %s | ${appTitle}`}\n defaultTitle={`${presentation.primaryTitle} | ${appTitle}`}\n />\n {props.activeContentTitle && <Helmet title={props.activeContentTitle} />}\n </>\n );\n}\n\nfunction InspectEntityDialogHost() {\n const { entity } = useAsyncEntity();\n const [searchParams, setSearchParams] = useSearchParams();\n const selectedTab = searchParams.get('inspect');\n const setSelectedTab = useCallback(\n (tab: string) =>\n setSearchParams(params => {\n const next = new URLSearchParams(params);\n next.set('inspect', tab);\n return next;\n }),\n [setSearchParams],\n );\n const close = useCallback(\n () =>\n setSearchParams(params => {\n const next = new URLSearchParams(params);\n next.delete('inspect');\n return next;\n }),\n [setSearchParams],\n );\n if (!entity) return null;\n return (\n <InspectEntityDialog\n entity={entity}\n initialTab={\n (selectedTab as ComponentProps<\n typeof InspectEntityDialog\n >['initialTab']) || undefined\n }\n open={typeof selectedTab === 'string'}\n onClose={close}\n onSelect={setSelectedTab}\n />\n );\n}\n\nfunction EntityLayoutContent(props: {\n content?: React.JSX.Element;\n NotFoundComponent?: ReactNode;\n}) {\n const { kind } = useRouteRefParams(entityRouteRef);\n const { entity, loading, error } = useAsyncEntity();\n const { t } = useTranslationRef(catalogTranslationRef);\n\n let content: ReactNode;\n if (error) {\n content = (\n <Container>\n <Alert status=\"danger\" title={error.toString()} />\n </Container>\n );\n } else if (entity) {\n content = <Container>{props.content ?? <NotFoundErrorPage />}</Container>;\n } else if (!loading) {\n content = (\n <Container>\n {props.NotFoundComponent ?? (\n <Alert\n status=\"warning\"\n title={t('entityLabels.warningPanelTitle')}\n description={t('entityPage.notFoundMessage', {\n kind,\n link: (\n <Link to=\"https://backstage.io/docs/features/software-catalog/references\">\n {t('entityPage.notFoundLinkText')}\n </Link>\n ),\n })}\n />\n )}\n </Container>\n );\n }\n\n return (\n <>\n {loading && <Progress />}\n {content}\n </>\n );\n}\n\nexport function EntityLayoutBui(props: {\n routes: EntityLayoutRoute[];\n NotFoundComponent?: ReactNode;\n groupDefinitions: EntityContentGroupDefinitions;\n defaultContentOrder: 'title' | 'natural';\n contextMenuItems?: ComponentProps<typeof EntityHeaderBui>['contextMenuItems'];\n HeaderComponent?: ComponentType<EntityHeaderLayoutProps>;\n}) {\n const {\n routes,\n NotFoundComponent,\n groupDefinitions,\n defaultContentOrder,\n contextMenuItems,\n HeaderComponent,\n } = props;\n const { entity } = useAsyncEntity();\n const visibleRoutes = filterEntityLayoutRoutes(routes, entity);\n const tabs = useEntityTabs({\n routes: visibleRoutes,\n groupDefinitions,\n defaultContentOrder,\n });\n\n return (\n <main>\n <EntityDocumentTitle activeContentTitle={tabs.title} />\n {HeaderComponent ? (\n <HeaderComponent tabs={tabs.tabs} activeTabId={tabs.activeTabId} />\n ) : (\n <EntityHeaderBui\n tabs={tabs.tabs}\n activeTabId={tabs.activeTabId}\n contextMenuItems={contextMenuItems}\n />\n )}\n <EntityLayoutContent\n content={tabs.content}\n NotFoundComponent={NotFoundComponent}\n />\n <InspectEntityDialogHost />\n </main>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -1,30 +1,9 @@
1
- import { useElementFilter, attachComponentData } from '@backstage/core-plugin-api';
2
-
3
- const dataKey = "plugin.catalog.entityLayoutRoute";
4
- const EntityLayoutRoute = () => null;
5
- attachComponentData(EntityLayoutRoute, dataKey, true);
6
- attachComponentData(EntityLayoutRoute, "core.gatherMountPoints", true);
7
- function useEntityLayoutRoutes(children, entity) {
8
- return useElementFilter(
9
- children,
10
- (elements) => elements.selectByComponentData({
11
- key: dataKey,
12
- withStrictError: "Child of EntityLayout must be an EntityLayout.Route"
13
- }).getElements().flatMap(({ props }) => {
14
- if (!entity || props.if && !props.if(entity)) return [];
15
- return [
16
- {
17
- path: props.path,
18
- title: props.title,
19
- group: props.group,
20
- icon: props.icon,
21
- children: props.children
22
- }
23
- ];
24
- }),
25
- [entity]
26
- );
1
+ function filterEntityLayoutRoutes(routes, entity) {
2
+ if (!entity) {
3
+ return [];
4
+ }
5
+ return routes.filter((route) => !route.if || route.if(entity));
27
6
  }
28
7
 
29
- export { EntityLayoutRoute, useEntityLayoutRoutes };
8
+ export { filterEntityLayoutRoutes };
30
9
  //# sourceMappingURL=entityLayoutRoutes.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"entityLayoutRoutes.esm.js","sources":["../../../../src/alpha/components/EntityLayout/entityLayoutRoutes.tsx"],"sourcesContent":["/*\n * Copyright 2026 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 { Entity } from '@backstage/catalog-model';\nimport {\n attachComponentData,\n useElementFilter,\n} from '@backstage/core-plugin-api';\nimport { ReactElement, ReactNode } from 'react';\n\nexport type EntityLayoutRouteProps = {\n path: string;\n title: string;\n group?: string;\n icon?: string | ReactElement;\n children: JSX.Element;\n if?: (entity: Entity) => boolean;\n};\n\nconst dataKey = 'plugin.catalog.entityLayoutRoute';\n\nexport const EntityLayoutRoute: (props: EntityLayoutRouteProps) => null = () =>\n null;\nattachComponentData(EntityLayoutRoute, dataKey, true);\n// Ensures mount points discovered within a route use the route's own path.\nattachComponentData(EntityLayoutRoute, 'core.gatherMountPoints', true);\n\nexport function useEntityLayoutRoutes(\n children: ReactNode,\n entity: Entity | undefined,\n) {\n return useElementFilter(\n children,\n elements =>\n elements\n .selectByComponentData({\n key: dataKey,\n withStrictError:\n 'Child of EntityLayout must be an EntityLayout.Route',\n })\n .getElements<EntityLayoutRouteProps>()\n .flatMap(({ props }) => {\n if (!entity || (props.if && !props.if(entity))) return [];\n return [\n {\n path: props.path,\n title: props.title,\n group: props.group,\n icon: props.icon,\n children: props.children,\n },\n ];\n }),\n [entity],\n );\n}\n"],"names":[],"mappings":";;AAgCA,MAAM,OAAA,GAAU,kCAAA;AAET,MAAM,oBAA6D,MACxE;AACF,mBAAA,CAAoB,iBAAA,EAAmB,SAAS,IAAI,CAAA;AAEpD,mBAAA,CAAoB,iBAAA,EAAmB,0BAA0B,IAAI,CAAA;AAE9D,SAAS,qBAAA,CACd,UACA,MAAA,EACA;AACA,EAAA,OAAO,gBAAA;AAAA,IACL,QAAA;AAAA,IACA,CAAA,QAAA,KACE,SACG,qBAAA,CAAsB;AAAA,MACrB,GAAA,EAAK,OAAA;AAAA,MACL,eAAA,EACE;AAAA,KACH,EACA,WAAA,EAAoC,CACpC,QAAQ,CAAC,EAAE,OAAM,KAAM;AACtB,MAAA,IAAI,CAAC,MAAA,IAAW,KAAA,CAAM,EAAA,IAAM,CAAC,MAAM,EAAA,CAAG,MAAM,CAAA,EAAI,OAAO,EAAC;AACxD,MAAA,OAAO;AAAA,QACL;AAAA,UACE,MAAM,KAAA,CAAM,IAAA;AAAA,UACZ,OAAO,KAAA,CAAM,KAAA;AAAA,UACb,OAAO,KAAA,CAAM,KAAA;AAAA,UACb,MAAM,KAAA,CAAM,IAAA;AAAA,UACZ,UAAU,KAAA,CAAM;AAAA;AAClB,OACF;AAAA,IACF,CAAC,CAAA;AAAA,IACL,CAAC,MAAM;AAAA,GACT;AACF;;;;"}
1
+ {"version":3,"file":"entityLayoutRoutes.esm.js","sources":["../../../../src/alpha/components/EntityLayout/entityLayoutRoutes.tsx"],"sourcesContent":["/*\n * Copyright 2026 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 { Entity } from '@backstage/catalog-model';\nimport { ReactElement } from 'react';\n\nexport type EntityLayoutRoute = {\n path: string;\n title: string;\n group?: string;\n icon?: string | ReactElement;\n children: JSX.Element;\n if?: (entity: Entity) => boolean;\n};\n\nexport function filterEntityLayoutRoutes(\n routes: EntityLayoutRoute[],\n entity: Entity | undefined,\n) {\n if (!entity) {\n return [];\n }\n return routes.filter(route => !route.if || route.if(entity));\n}\n"],"names":[],"mappings":"AA4BO,SAAS,wBAAA,CACd,QACA,MAAA,EACA;AACA,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,EAAC;AAAA,EACV;AACA,EAAA,OAAO,MAAA,CAAO,OAAO,CAAA,KAAA,KAAS,CAAC,MAAM,EAAA,IAAM,KAAA,CAAM,EAAA,CAAG,MAAM,CAAC,CAAA;AAC7D;;;;"}
@@ -180,21 +180,17 @@ const catalogEntityPage = PageBlueprint.makeWithOverrides({
180
180
  (rest, group) => ({ ...rest, ...group }),
181
181
  {}
182
182
  ) ?? defaultEntityContentGroupDefinitions;
183
- const routes = inputs.contents.map((output) => /* @__PURE__ */ jsx(
184
- EntityLayout.Route,
185
- {
186
- group: output.get(EntityContentBlueprint.dataRefs.group),
187
- path: output.get(coreExtensionData.routePath),
188
- title: output.get(EntityContentBlueprint.dataRefs.title),
189
- icon: output.get(EntityContentBlueprint.dataRefs.icon),
190
- if: buildFilterFn(
191
- output.get(EntityContentBlueprint.dataRefs.filterFunction),
192
- output.get(EntityContentBlueprint.dataRefs.filterExpression)
193
- ),
194
- children: output.get(coreExtensionData.reactElement)
195
- },
196
- output.get(coreExtensionData.routePath)
197
- ));
183
+ const routes = inputs.contents.map((output) => ({
184
+ group: output.get(EntityContentBlueprint.dataRefs.group),
185
+ path: output.get(coreExtensionData.routePath),
186
+ title: output.get(EntityContentBlueprint.dataRefs.title),
187
+ icon: output.get(EntityContentBlueprint.dataRefs.icon),
188
+ if: buildFilterFn(
189
+ output.get(EntityContentBlueprint.dataRefs.filterFunction),
190
+ output.get(EntityContentBlueprint.dataRefs.filterExpression)
191
+ ),
192
+ children: output.get(coreExtensionData.reactElement)
193
+ }));
198
194
  const Component = () => {
199
195
  const routeParams = useRouteRefParams(entityRouteRef);
200
196
  const entityFromUrl = useEntityFromUrl();
@@ -206,21 +202,21 @@ const catalogEntityPage = PageBlueprint.makeWithOverrides({
206
202
  const layout = HeaderComponent || !legacyHeader ? /* @__PURE__ */ jsx(
207
203
  EntityLayoutBui,
208
204
  {
205
+ routes,
209
206
  HeaderComponent,
210
207
  contextMenuItems: filteredMenuItems,
211
208
  groupDefinitions,
212
- defaultContentOrder: config.defaultContentOrder,
213
- children: routes
209
+ defaultContentOrder: config.defaultContentOrder
214
210
  }
215
211
  ) : /* @__PURE__ */ jsx(
216
212
  EntityLayout,
217
213
  {
214
+ routes,
218
215
  header: legacyHeader,
219
216
  contextMenuItems: filteredMenuItems,
220
217
  groupDefinitions,
221
218
  defaultContentOrder: config.defaultContentOrder,
222
- showNavItemIcons: config.showNavItemIcons,
223
- children: routes
219
+ showNavItemIcons: config.showNavItemIcons
224
220
  }
225
221
  );
226
222
  return /* @__PURE__ */ jsx(AsyncEntityProvider, { ...entityProviderProps, children: layout });
@@ -1 +1 @@
1
- {"version":3,"file":"pages.esm.js","sources":["../../src/alpha/pages.tsx"],"sourcesContent":["/*\n * Copyright 2023 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 { convertLegacyRouteRef } from '@backstage/core-compat-api';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\nimport { useRouteRefParams } from '@backstage/core-plugin-api';\nimport {\n coreExtensionData,\n createExtensionInput,\n createExtensionDataRef,\n createExtensionBlueprint,\n PageBlueprint,\n} from '@backstage/frontend-plugin-api';\nimport { z } from 'zod/v4';\nimport {\n AsyncEntityProvider,\n entityRouteRef,\n} from '@backstage/plugin-catalog-react';\nimport {\n defaultEntityContentGroupDefinitions,\n EntityContentBlueprint,\n EntityContextMenuItemBlueprint,\n EntityHeaderBlueprint,\n EntityHeaderLayoutBlueprint,\n EntityContentGroupDefinitions,\n} from '@backstage/plugin-catalog-react/alpha';\nimport CategoryIcon from '@material-ui/icons/Category';\nimport { rootRouteRef } from '../routes';\nimport { useEntityFromUrl } from '../components/CatalogEntityPage/useEntityFromUrl';\nimport { buildFilterFn } from './filter/FilterWrapper';\nimport type { CatalogExportSettings } from '../components/CatalogExportButton';\n\nconst catalogExportConfigDataRef = createExtensionDataRef<{\n exporters?: CatalogExportSettings['exporters'];\n columns?: CatalogExportSettings['columns'];\n onSuccess?: CatalogExportSettings['onSuccess'];\n onError?: CatalogExportSettings['onError'];\n}>().with({\n id: 'catalog.export-customization',\n});\n\n/**\n * Blueprint for creating catalog export configuration extensions.\n * @public\n */\nexport const CatalogExportConfigBlueprint = createExtensionBlueprint({\n kind: 'catalog-export-config',\n attachTo: { id: 'page:catalog', input: 'exportConfig' },\n output: [catalogExportConfigDataRef],\n factory(params: {\n exporters?: CatalogExportSettings['exporters'];\n columns?: CatalogExportSettings['columns'];\n onSuccess?: CatalogExportSettings['onSuccess'];\n onError?: CatalogExportSettings['onError'];\n }) {\n return [catalogExportConfigDataRef(params)];\n },\n});\n\nexport const catalogPage = PageBlueprint.makeWithOverrides({\n inputs: {\n filters: createExtensionInput([coreExtensionData.reactElement]),\n exportConfig: createExtensionInput([catalogExportConfigDataRef.optional()]),\n },\n configSchema: {\n pagination: z\n .union([\n z.boolean(),\n z.object({\n mode: z.enum(['cursor', 'offset']),\n limit: z.number().optional(),\n offset: z.number().optional(),\n }),\n ])\n .default(true),\n exportSettings: z\n .object({\n /** When true, displays the export button in the catalog interface. */\n enabled: z.boolean().optional(),\n /**\n * When true, hides the built-in CSV and JSON export options.\n * Useful when only custom exporters (provided via extensions) should be available.\n */\n disableBuiltinExporters: z.boolean().optional(),\n })\n .optional(),\n },\n factory(originalFactory, { inputs, config }) {\n return originalFactory({\n path: '/catalog',\n routeRef: rootRouteRef,\n icon: <CategoryIcon fontSize=\"inherit\" />,\n title: 'Catalog',\n loader: async () => {\n const { NfsDefaultCatalogPage } = await import(\n '../components/CatalogPage/DefaultCatalogPage'\n );\n const filters = inputs.filters.map(filter =>\n filter.get(coreExtensionData.reactElement),\n );\n\n // Merge export customizers from all attached extensions\n const mergedExportSettings: CatalogExportSettings = {\n ...config.exportSettings,\n };\n\n for (const exportConfigInput of inputs.exportConfig) {\n const data = exportConfigInput.get(catalogExportConfigDataRef);\n if (data) {\n if (data.exporters) {\n mergedExportSettings.exporters = {\n ...mergedExportSettings.exporters,\n ...data.exporters,\n };\n }\n if (data.columns && !mergedExportSettings.columns) {\n mergedExportSettings.columns = data.columns;\n }\n if (data.onSuccess && !mergedExportSettings.onSuccess) {\n mergedExportSettings.onSuccess = data.onSuccess;\n }\n if (data.onError && !mergedExportSettings.onError) {\n mergedExportSettings.onError = data.onError;\n }\n }\n }\n\n return (\n <NfsDefaultCatalogPage\n filters={<>{filters}</>}\n pagination={config.pagination}\n exportSettings={\n mergedExportSettings.enabled ? mergedExportSettings : undefined\n }\n />\n );\n },\n });\n },\n});\n\nexport const catalogEntityPage = PageBlueprint.makeWithOverrides({\n name: 'entity',\n inputs: {\n headerLayouts: createExtensionInput([\n EntityHeaderLayoutBlueprint.dataRefs.component,\n EntityHeaderLayoutBlueprint.dataRefs.filterFunction.optional(),\n ]),\n headers: createExtensionInput([\n EntityHeaderBlueprint.dataRefs.element.optional(),\n EntityHeaderBlueprint.dataRefs.filterFunction.optional(),\n ]),\n contents: createExtensionInput([\n coreExtensionData.reactElement,\n coreExtensionData.routePath,\n coreExtensionData.routeRef.optional(),\n EntityContentBlueprint.dataRefs.title,\n EntityContentBlueprint.dataRefs.filterFunction.optional(),\n EntityContentBlueprint.dataRefs.filterExpression.optional(),\n EntityContentBlueprint.dataRefs.group.optional(),\n EntityContentBlueprint.dataRefs.icon.optional(),\n ]),\n contextMenuItems: createExtensionInput([\n EntityContextMenuItemBlueprint.dataRefs.data,\n EntityContextMenuItemBlueprint.dataRefs.filterFunction.optional(),\n ]),\n },\n configSchema: {\n groups: z\n .array(\n z.record(\n z.string(),\n z.object({\n title: z.string(),\n icon: z.string().optional(),\n aliases: z.array(z.string()).optional(),\n contentOrder: z.enum(['title', 'natural']).optional(),\n }),\n ),\n )\n .optional(),\n defaultContentOrder: z\n .enum(['title', 'natural'])\n .optional()\n .default('title'),\n showNavItemIcons: z.boolean().optional().default(false),\n },\n factory(originalFactory, { config, inputs }) {\n return originalFactory({\n path: '/catalog/:namespace/:kind/:name',\n // NOTE: The `convertLegacyRouteRef` call here ensures that this route ref\n // is mutated to support the new frontend system. Removing this conversion\n // is a potentially breaking change since this is a singleton and the\n // route refs from `core-plugin-api` used to not support the new format.\n // This shouldn't be removed until we completely deprecate the\n // `core-compat-api` package.\n routeRef: convertLegacyRouteRef(entityRouteRef), // READ THE ABOVE\n loader: async () => {\n const [{ EntityLayout }, { EntityLayoutBui }] = await Promise.all([\n import('./components/EntityLayout'),\n import('./components/EntityLayout/EntityLayoutBui'),\n ]);\n\n const menuItems = inputs.contextMenuItems.map(item => ({\n data: item.get(EntityContextMenuItemBlueprint.dataRefs.data),\n node: item.node,\n filter:\n item.get(EntityContextMenuItemBlueprint.dataRefs.filterFunction) ??\n (() => true),\n }));\n\n // Get available headers, sorted by if they have a filter function or not.\n // TODO(blam): we should really have priority or some specificity here which can be used to sort the headers.\n // That can be done with embedding the priority in the dataRef alongside the filter function.\n const headerLayouts = inputs.headerLayouts\n .map(layout => {\n const filterFunction = layout.get(\n EntityHeaderLayoutBlueprint.dataRefs.filterFunction,\n );\n return {\n Component: layout.get(\n EntityHeaderLayoutBlueprint.dataRefs.component,\n ),\n filter: filterFunction ?? (() => true),\n hasFilter: Boolean(filterFunction),\n };\n })\n .sort((a, b) => Number(b.hasFilter) - Number(a.hasFilter));\n\n const headers = inputs.headers\n .map(header => {\n const filterFunction = header.get(\n EntityHeaderBlueprint.dataRefs.filterFunction,\n );\n return {\n element: header.get(EntityHeaderBlueprint.dataRefs.element),\n filter: filterFunction ?? (() => true),\n hasFilter: Boolean(filterFunction),\n };\n })\n .sort((a, b) => Number(b.hasFilter) - Number(a.hasFilter));\n\n const groupDefinitions =\n config.groups?.reduce(\n (rest, group) => ({ ...rest, ...group }),\n {} as EntityContentGroupDefinitions,\n ) ?? defaultEntityContentGroupDefinitions;\n\n const routes = inputs.contents.map(output => (\n <EntityLayout.Route\n group={output.get(EntityContentBlueprint.dataRefs.group)}\n key={output.get(coreExtensionData.routePath)}\n path={output.get(coreExtensionData.routePath)}\n title={output.get(EntityContentBlueprint.dataRefs.title)}\n icon={output.get(EntityContentBlueprint.dataRefs.icon)}\n if={buildFilterFn(\n output.get(EntityContentBlueprint.dataRefs.filterFunction),\n output.get(EntityContentBlueprint.dataRefs.filterExpression),\n )}\n >\n {output.get(coreExtensionData.reactElement)}\n </EntityLayout.Route>\n ));\n\n const Component = () => {\n const routeParams = useRouteRefParams(entityRouteRef);\n const entityFromUrl = useEntityFromUrl();\n const entity =\n entityFromUrl.entity &&\n stringifyEntityRef(entityFromUrl.entity) ===\n stringifyEntityRef(routeParams)\n ? entityFromUrl.entity\n : undefined;\n const entityProviderProps = { ...entityFromUrl, entity };\n const filteredMenuItems = entity\n ? menuItems\n .filter(i => i.filter(entity))\n .map(({ data, node }) => ({ data, node }))\n : [];\n\n const HeaderComponent = entity\n ? headerLayouts.find(layout => layout.filter(entity))?.Component\n : undefined;\n const legacyHeader = entity\n ? headers.find(header => header.filter(entity))?.element\n : undefined;\n\n const layout =\n HeaderComponent || !legacyHeader ? (\n <EntityLayoutBui\n HeaderComponent={HeaderComponent}\n contextMenuItems={filteredMenuItems}\n groupDefinitions={groupDefinitions}\n defaultContentOrder={config.defaultContentOrder}\n >\n {routes}\n </EntityLayoutBui>\n ) : (\n <EntityLayout\n header={legacyHeader}\n contextMenuItems={filteredMenuItems}\n groupDefinitions={groupDefinitions}\n defaultContentOrder={config.defaultContentOrder}\n showNavItemIcons={config.showNavItemIcons}\n >\n {routes}\n </EntityLayout>\n );\n\n return (\n <AsyncEntityProvider {...entityProviderProps}>\n {layout}\n </AsyncEntityProvider>\n );\n };\n\n return <Component />;\n },\n });\n },\n});\n\nexport default [catalogPage, catalogEntityPage];\n"],"names":["layout"],"mappings":"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"}
1
+ {"version":3,"file":"pages.esm.js","sources":["../../src/alpha/pages.tsx"],"sourcesContent":["/*\n * Copyright 2023 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 { convertLegacyRouteRef } from '@backstage/core-compat-api';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\nimport { useRouteRefParams } from '@backstage/core-plugin-api';\nimport {\n coreExtensionData,\n createExtensionInput,\n createExtensionDataRef,\n createExtensionBlueprint,\n PageBlueprint,\n} from '@backstage/frontend-plugin-api';\nimport { z } from 'zod/v4';\nimport {\n AsyncEntityProvider,\n entityRouteRef,\n} from '@backstage/plugin-catalog-react';\nimport {\n defaultEntityContentGroupDefinitions,\n EntityContentBlueprint,\n EntityContextMenuItemBlueprint,\n EntityHeaderBlueprint,\n EntityHeaderLayoutBlueprint,\n EntityContentGroupDefinitions,\n} from '@backstage/plugin-catalog-react/alpha';\nimport CategoryIcon from '@material-ui/icons/Category';\nimport { rootRouteRef } from '../routes';\nimport { useEntityFromUrl } from '../components/CatalogEntityPage/useEntityFromUrl';\nimport { buildFilterFn } from './filter/FilterWrapper';\nimport type { CatalogExportSettings } from '../components/CatalogExportButton';\n\nconst catalogExportConfigDataRef = createExtensionDataRef<{\n exporters?: CatalogExportSettings['exporters'];\n columns?: CatalogExportSettings['columns'];\n onSuccess?: CatalogExportSettings['onSuccess'];\n onError?: CatalogExportSettings['onError'];\n}>().with({\n id: 'catalog.export-customization',\n});\n\n/**\n * Blueprint for creating catalog export configuration extensions.\n * @public\n */\nexport const CatalogExportConfigBlueprint = createExtensionBlueprint({\n kind: 'catalog-export-config',\n attachTo: { id: 'page:catalog', input: 'exportConfig' },\n output: [catalogExportConfigDataRef],\n factory(params: {\n exporters?: CatalogExportSettings['exporters'];\n columns?: CatalogExportSettings['columns'];\n onSuccess?: CatalogExportSettings['onSuccess'];\n onError?: CatalogExportSettings['onError'];\n }) {\n return [catalogExportConfigDataRef(params)];\n },\n});\n\nexport const catalogPage = PageBlueprint.makeWithOverrides({\n inputs: {\n filters: createExtensionInput([coreExtensionData.reactElement]),\n exportConfig: createExtensionInput([catalogExportConfigDataRef.optional()]),\n },\n configSchema: {\n pagination: z\n .union([\n z.boolean(),\n z.object({\n mode: z.enum(['cursor', 'offset']),\n limit: z.number().optional(),\n offset: z.number().optional(),\n }),\n ])\n .default(true),\n exportSettings: z\n .object({\n /** When true, displays the export button in the catalog interface. */\n enabled: z.boolean().optional(),\n /**\n * When true, hides the built-in CSV and JSON export options.\n * Useful when only custom exporters (provided via extensions) should be available.\n */\n disableBuiltinExporters: z.boolean().optional(),\n })\n .optional(),\n },\n factory(originalFactory, { inputs, config }) {\n return originalFactory({\n path: '/catalog',\n routeRef: rootRouteRef,\n icon: <CategoryIcon fontSize=\"inherit\" />,\n title: 'Catalog',\n loader: async () => {\n const { NfsDefaultCatalogPage } = await import(\n '../components/CatalogPage/DefaultCatalogPage'\n );\n const filters = inputs.filters.map(filter =>\n filter.get(coreExtensionData.reactElement),\n );\n\n // Merge export customizers from all attached extensions\n const mergedExportSettings: CatalogExportSettings = {\n ...config.exportSettings,\n };\n\n for (const exportConfigInput of inputs.exportConfig) {\n const data = exportConfigInput.get(catalogExportConfigDataRef);\n if (data) {\n if (data.exporters) {\n mergedExportSettings.exporters = {\n ...mergedExportSettings.exporters,\n ...data.exporters,\n };\n }\n if (data.columns && !mergedExportSettings.columns) {\n mergedExportSettings.columns = data.columns;\n }\n if (data.onSuccess && !mergedExportSettings.onSuccess) {\n mergedExportSettings.onSuccess = data.onSuccess;\n }\n if (data.onError && !mergedExportSettings.onError) {\n mergedExportSettings.onError = data.onError;\n }\n }\n }\n\n return (\n <NfsDefaultCatalogPage\n filters={<>{filters}</>}\n pagination={config.pagination}\n exportSettings={\n mergedExportSettings.enabled ? mergedExportSettings : undefined\n }\n />\n );\n },\n });\n },\n});\n\nexport const catalogEntityPage = PageBlueprint.makeWithOverrides({\n name: 'entity',\n inputs: {\n headerLayouts: createExtensionInput([\n EntityHeaderLayoutBlueprint.dataRefs.component,\n EntityHeaderLayoutBlueprint.dataRefs.filterFunction.optional(),\n ]),\n headers: createExtensionInput([\n EntityHeaderBlueprint.dataRefs.element.optional(),\n EntityHeaderBlueprint.dataRefs.filterFunction.optional(),\n ]),\n contents: createExtensionInput([\n coreExtensionData.reactElement,\n coreExtensionData.routePath,\n coreExtensionData.routeRef.optional(),\n EntityContentBlueprint.dataRefs.title,\n EntityContentBlueprint.dataRefs.filterFunction.optional(),\n EntityContentBlueprint.dataRefs.filterExpression.optional(),\n EntityContentBlueprint.dataRefs.group.optional(),\n EntityContentBlueprint.dataRefs.icon.optional(),\n ]),\n contextMenuItems: createExtensionInput([\n EntityContextMenuItemBlueprint.dataRefs.data,\n EntityContextMenuItemBlueprint.dataRefs.filterFunction.optional(),\n ]),\n },\n configSchema: {\n groups: z\n .array(\n z.record(\n z.string(),\n z.object({\n title: z.string(),\n icon: z.string().optional(),\n aliases: z.array(z.string()).optional(),\n contentOrder: z.enum(['title', 'natural']).optional(),\n }),\n ),\n )\n .optional(),\n defaultContentOrder: z\n .enum(['title', 'natural'])\n .optional()\n .default('title'),\n showNavItemIcons: z.boolean().optional().default(false),\n },\n factory(originalFactory, { config, inputs }) {\n return originalFactory({\n path: '/catalog/:namespace/:kind/:name',\n // NOTE: The `convertLegacyRouteRef` call here ensures that this route ref\n // is mutated to support the new frontend system. Removing this conversion\n // is a potentially breaking change since this is a singleton and the\n // route refs from `core-plugin-api` used to not support the new format.\n // This shouldn't be removed until we completely deprecate the\n // `core-compat-api` package.\n routeRef: convertLegacyRouteRef(entityRouteRef), // READ THE ABOVE\n loader: async () => {\n const [{ EntityLayout }, { EntityLayoutBui }] = await Promise.all([\n import('./components/EntityLayout'),\n import('./components/EntityLayout/EntityLayoutBui'),\n ]);\n\n const menuItems = inputs.contextMenuItems.map(item => ({\n data: item.get(EntityContextMenuItemBlueprint.dataRefs.data),\n node: item.node,\n filter:\n item.get(EntityContextMenuItemBlueprint.dataRefs.filterFunction) ??\n (() => true),\n }));\n\n // Get available headers, sorted by if they have a filter function or not.\n // TODO(blam): we should really have priority or some specificity here which can be used to sort the headers.\n // That can be done with embedding the priority in the dataRef alongside the filter function.\n const headerLayouts = inputs.headerLayouts\n .map(layout => {\n const filterFunction = layout.get(\n EntityHeaderLayoutBlueprint.dataRefs.filterFunction,\n );\n return {\n Component: layout.get(\n EntityHeaderLayoutBlueprint.dataRefs.component,\n ),\n filter: filterFunction ?? (() => true),\n hasFilter: Boolean(filterFunction),\n };\n })\n .sort((a, b) => Number(b.hasFilter) - Number(a.hasFilter));\n\n const headers = inputs.headers\n .map(header => {\n const filterFunction = header.get(\n EntityHeaderBlueprint.dataRefs.filterFunction,\n );\n return {\n element: header.get(EntityHeaderBlueprint.dataRefs.element),\n filter: filterFunction ?? (() => true),\n hasFilter: Boolean(filterFunction),\n };\n })\n .sort((a, b) => Number(b.hasFilter) - Number(a.hasFilter));\n\n const groupDefinitions =\n config.groups?.reduce(\n (rest, group) => ({ ...rest, ...group }),\n {} as EntityContentGroupDefinitions,\n ) ?? defaultEntityContentGroupDefinitions;\n\n const routes = inputs.contents.map(output => ({\n group: output.get(EntityContentBlueprint.dataRefs.group),\n path: output.get(coreExtensionData.routePath),\n title: output.get(EntityContentBlueprint.dataRefs.title),\n icon: output.get(EntityContentBlueprint.dataRefs.icon),\n if: buildFilterFn(\n output.get(EntityContentBlueprint.dataRefs.filterFunction),\n output.get(EntityContentBlueprint.dataRefs.filterExpression),\n ),\n children: output.get(coreExtensionData.reactElement),\n }));\n\n const Component = () => {\n const routeParams = useRouteRefParams(entityRouteRef);\n const entityFromUrl = useEntityFromUrl();\n const entity =\n entityFromUrl.entity &&\n stringifyEntityRef(entityFromUrl.entity) ===\n stringifyEntityRef(routeParams)\n ? entityFromUrl.entity\n : undefined;\n const entityProviderProps = { ...entityFromUrl, entity };\n const filteredMenuItems = entity\n ? menuItems\n .filter(i => i.filter(entity))\n .map(({ data, node }) => ({ data, node }))\n : [];\n\n const HeaderComponent = entity\n ? headerLayouts.find(layout => layout.filter(entity))?.Component\n : undefined;\n const legacyHeader = entity\n ? headers.find(header => header.filter(entity))?.element\n : undefined;\n\n const layout =\n HeaderComponent || !legacyHeader ? (\n <EntityLayoutBui\n routes={routes}\n HeaderComponent={HeaderComponent}\n contextMenuItems={filteredMenuItems}\n groupDefinitions={groupDefinitions}\n defaultContentOrder={config.defaultContentOrder}\n />\n ) : (\n <EntityLayout\n routes={routes}\n header={legacyHeader}\n contextMenuItems={filteredMenuItems}\n groupDefinitions={groupDefinitions}\n defaultContentOrder={config.defaultContentOrder}\n showNavItemIcons={config.showNavItemIcons}\n />\n );\n\n return (\n <AsyncEntityProvider {...entityProviderProps}>\n {layout}\n </AsyncEntityProvider>\n );\n };\n\n return <Component />;\n },\n });\n },\n});\n\nexport default [catalogPage, catalogEntityPage];\n"],"names":["layout"],"mappings":"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"}
@@ -2,10 +2,10 @@ function isBackendFilter(f) {
2
2
  return typeof f?.getCatalogFilters === "function";
3
3
  }
4
4
  function isEntityTextFilter(f) {
5
- return !!f.getFullTextFilters;
5
+ return typeof f?.getFullTextFilters === "function";
6
6
  }
7
7
  function isEntityOrderFilter(f) {
8
- return !!f.getOrderFilters;
8
+ return typeof f?.getOrderFilters === "function";
9
9
  }
10
10
  function getBackendFilterObject(backendFilter) {
11
11
  const result = {};
@@ -23,7 +23,10 @@ function getBackendFilterObject(backendFilter) {
23
23
  return result;
24
24
  }
25
25
  const toStreamRequest = (filters) => {
26
- const backendFilters = Object.values(filters).flatMap((f) => {
26
+ const filterValues = Object.values(filters).filter(
27
+ (f) => f !== null && f !== void 0
28
+ );
29
+ const backendFilters = filterValues.flatMap((f) => {
27
30
  if (isBackendFilter(f)) {
28
31
  const backendFilter = f.getCatalogFilters();
29
32
  return backendFilter ? [backendFilter] : [];
@@ -32,8 +35,8 @@ const toStreamRequest = (filters) => {
32
35
  }).reduce((acc, f) => {
33
36
  return { ...acc, ...getBackendFilterObject(f) };
34
37
  }, {});
35
- const fullTextFilter = Object.values(filters).find(isEntityTextFilter)?.getFullTextFilters();
36
- const orderFieldsFilter = Object.values(filters).find(isEntityOrderFilter);
38
+ const fullTextFilter = filterValues.find(isEntityTextFilter)?.getFullTextFilters();
39
+ const orderFieldsFilter = filterValues.find(isEntityOrderFilter);
37
40
  const orderFields = orderFieldsFilter ? orderFieldsFilter.getOrderFilters() : void 0;
38
41
  const request = {};
39
42
  if (Object.keys(backendFilters).length > 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"toStreamRequest.esm.js","sources":["../../../../src/components/CatalogExportButton/file-download/toStreamRequest.ts"],"sourcesContent":["/*\n * Copyright 2025 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 */\nimport {\n DefaultEntityFilters,\n EntityTextFilter,\n EntityOrderFilter,\n} from '@backstage/plugin-catalog-react';\nimport type {\n StreamEntitiesRequest,\n EntityOrderQuery,\n} from '@backstage/catalog-client';\n\nfunction isBackendFilter(f: any): f is { getCatalogFilters: () => any } {\n return typeof f?.getCatalogFilters === 'function';\n}\n\nfunction isEntityTextFilter(f: any): f is EntityTextFilter {\n return !!(f as EntityTextFilter).getFullTextFilters;\n}\n\nfunction isEntityOrderFilter(f: any): f is EntityOrderFilter {\n return !!(f as EntityOrderFilter).getOrderFilters;\n}\n\nfunction getBackendFilterObject(\n backendFilter: Record<string, any>,\n): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n\n for (const [backendFilterName, backendFilterValue] of Object.entries(\n backendFilter,\n )) {\n if (Array.isArray(backendFilterValue)) {\n if (backendFilterValue.length > 0) {\n result[backendFilterName] = backendFilterValue;\n }\n } else if (\n backendFilterValue !== undefined &&\n backendFilterValue !== null\n ) {\n result[backendFilterName] = backendFilterValue;\n }\n }\n\n return result;\n}\n\n/**\n * Converts entity filters to a StreamEntitiesRequest that can be used\n * with the catalogApi.streamEntities method.\n *\n * This extracts all enabled backend filters, full text filters, and order filters\n * and converts them to the appropriate format for streaming.\n *\n * @param filters - The entity filters from useEntityList\n * @returns A StreamEntitiesRequest object, or undefined if no filters are enabled\n */\nexport const toStreamRequest = (\n filters: DefaultEntityFilters,\n): StreamEntitiesRequest | undefined => {\n const backendFilters = Object.values(filters)\n .flatMap(f => {\n if (isBackendFilter(f)) {\n const backendFilter = f.getCatalogFilters();\n return backendFilter ? [backendFilter] : [];\n }\n return [];\n })\n .reduce((acc, f) => {\n return { ...acc, ...getBackendFilterObject(f) };\n }, {} as Record<string, string | string[]>);\n\n const fullTextFilter = Object.values(filters)\n .find(isEntityTextFilter)\n ?.getFullTextFilters();\n\n const orderFieldsFilter = Object.values(filters).find(isEntityOrderFilter);\n const orderFields = orderFieldsFilter\n ? (orderFieldsFilter.getOrderFilters() as EntityOrderQuery)\n : undefined;\n\n const request: StreamEntitiesRequest = {};\n\n if (Object.keys(backendFilters).length > 0) {\n request.filter = backendFilters;\n }\n\n if (fullTextFilter) {\n request.fullTextFilter = fullTextFilter;\n }\n\n if (orderFields) {\n request.orderFields = orderFields;\n }\n\n // Return undefined if no filters, which means stream all entities\n return Object.keys(request).length > 0 ? request : undefined;\n};\n"],"names":[],"mappings":"AAyBA,SAAS,gBAAgB,CAAA,EAA+C;AACtE,EAAA,OAAO,OAAO,GAAG,iBAAA,KAAsB,UAAA;AACzC;AAEA,SAAS,mBAAmB,CAAA,EAA+B;AACzD,EAAA,OAAO,CAAC,CAAE,CAAA,CAAuB,kBAAA;AACnC;AAEA,SAAS,oBAAoB,CAAA,EAAgC;AAC3D,EAAA,OAAO,CAAC,CAAE,CAAA,CAAwB,eAAA;AACpC;AAEA,SAAS,uBACP,aAAA,EACmC;AACnC,EAAA,MAAM,SAA4C,EAAC;AAEnD,EAAA,KAAA,MAAW,CAAC,iBAAA,EAAmB,kBAAkB,CAAA,IAAK,MAAA,CAAO,OAAA;AAAA,IAC3D;AAAA,GACF,EAAG;AACD,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,kBAAkB,CAAA,EAAG;AACrC,MAAA,IAAI,kBAAA,CAAmB,SAAS,CAAA,EAAG;AACjC,QAAA,MAAA,CAAO,iBAAiB,CAAA,GAAI,kBAAA;AAAA,MAC9B;AAAA,IACF,CAAA,MAAA,IACE,kBAAA,KAAuB,MAAA,IACvB,kBAAA,KAAuB,IAAA,EACvB;AACA,MAAA,MAAA,CAAO,iBAAiB,CAAA,GAAI,kBAAA;AAAA,IAC9B;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAYO,MAAM,eAAA,GAAkB,CAC7B,OAAA,KACsC;AACtC,EAAA,MAAM,iBAAiB,MAAA,CAAO,MAAA,CAAO,OAAO,CAAA,CACzC,QAAQ,CAAA,CAAA,KAAK;AACZ,IAAA,IAAI,eAAA,CAAgB,CAAC,CAAA,EAAG;AACtB,MAAA,MAAM,aAAA,GAAgB,EAAE,iBAAA,EAAkB;AAC1C,MAAA,OAAO,aAAA,GAAgB,CAAC,aAAa,CAAA,GAAI,EAAC;AAAA,IAC5C;AACA,IAAA,OAAO,EAAC;AAAA,EACV,CAAC,CAAA,CACA,MAAA,CAAO,CAAC,KAAK,CAAA,KAAM;AAClB,IAAA,OAAO,EAAE,GAAG,GAAA,EAAK,GAAG,sBAAA,CAAuB,CAAC,CAAA,EAAE;AAAA,EAChD,CAAA,EAAG,EAAuC,CAAA;AAE5C,EAAA,MAAM,cAAA,GAAiB,OAAO,MAAA,CAAO,OAAO,EACzC,IAAA,CAAK,kBAAkB,GACtB,kBAAA,EAAmB;AAEvB,EAAA,MAAM,oBAAoB,MAAA,CAAO,MAAA,CAAO,OAAO,CAAA,CAAE,KAAK,mBAAmB,CAAA;AACzE,EAAA,MAAM,WAAA,GAAc,iBAAA,GACf,iBAAA,CAAkB,eAAA,EAAgB,GACnC,MAAA;AAEJ,EAAA,MAAM,UAAiC,EAAC;AAExC,EAAA,IAAI,MAAA,CAAO,IAAA,CAAK,cAAc,CAAA,CAAE,SAAS,CAAA,EAAG;AAC1C,IAAA,OAAA,CAAQ,MAAA,GAAS,cAAA;AAAA,EACnB;AAEA,EAAA,IAAI,cAAA,EAAgB;AAClB,IAAA,OAAA,CAAQ,cAAA,GAAiB,cAAA;AAAA,EAC3B;AAEA,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,OAAA,CAAQ,WAAA,GAAc,WAAA;AAAA,EACxB;AAGA,EAAA,OAAO,OAAO,IAAA,CAAK,OAAO,CAAA,CAAE,MAAA,GAAS,IAAI,OAAA,GAAU,MAAA;AACrD;;;;"}
1
+ {"version":3,"file":"toStreamRequest.esm.js","sources":["../../../../src/components/CatalogExportButton/file-download/toStreamRequest.ts"],"sourcesContent":["/*\n * Copyright 2025 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 */\nimport {\n DefaultEntityFilters,\n EntityTextFilter,\n EntityOrderFilter,\n} from '@backstage/plugin-catalog-react';\nimport type {\n StreamEntitiesRequest,\n EntityOrderQuery,\n} from '@backstage/catalog-client';\n\nfunction isBackendFilter(f: any): f is { getCatalogFilters: () => any } {\n return typeof f?.getCatalogFilters === 'function';\n}\n\nfunction isEntityTextFilter(f: any): f is EntityTextFilter {\n return typeof f?.getFullTextFilters === 'function';\n}\n\nfunction isEntityOrderFilter(f: any): f is EntityOrderFilter {\n return typeof f?.getOrderFilters === 'function';\n}\n\nfunction getBackendFilterObject(\n backendFilter: Record<string, any>,\n): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n\n for (const [backendFilterName, backendFilterValue] of Object.entries(\n backendFilter,\n )) {\n if (Array.isArray(backendFilterValue)) {\n if (backendFilterValue.length > 0) {\n result[backendFilterName] = backendFilterValue;\n }\n } else if (\n backendFilterValue !== undefined &&\n backendFilterValue !== null\n ) {\n result[backendFilterName] = backendFilterValue;\n }\n }\n\n return result;\n}\n\n/**\n * Converts entity filters to a StreamEntitiesRequest that can be used\n * with the catalogApi.streamEntities method.\n *\n * This extracts all enabled backend filters, full text filters, and order filters\n * and converts them to the appropriate format for streaming.\n *\n * @param filters - The entity filters from useEntityList\n * @returns A StreamEntitiesRequest object, or undefined if no filters are enabled\n */\nexport const toStreamRequest = (\n filters: DefaultEntityFilters,\n): StreamEntitiesRequest | undefined => {\n const filterValues = Object.values(filters).filter(\n (f): f is NonNullable<typeof f> => f !== null && f !== undefined,\n );\n\n const backendFilters = filterValues\n .flatMap(f => {\n if (isBackendFilter(f)) {\n const backendFilter = f.getCatalogFilters();\n return backendFilter ? [backendFilter] : [];\n }\n return [];\n })\n .reduce((acc, f) => {\n return { ...acc, ...getBackendFilterObject(f) };\n }, {} as Record<string, string | string[]>);\n\n const fullTextFilter = filterValues\n .find(isEntityTextFilter)\n ?.getFullTextFilters();\n\n const orderFieldsFilter = filterValues.find(isEntityOrderFilter);\n const orderFields = orderFieldsFilter\n ? (orderFieldsFilter.getOrderFilters() as EntityOrderQuery)\n : undefined;\n\n const request: StreamEntitiesRequest = {};\n\n if (Object.keys(backendFilters).length > 0) {\n request.filter = backendFilters;\n }\n\n if (fullTextFilter) {\n request.fullTextFilter = fullTextFilter;\n }\n\n if (orderFields) {\n request.orderFields = orderFields;\n }\n\n // Return undefined if no filters, which means stream all entities\n return Object.keys(request).length > 0 ? request : undefined;\n};\n"],"names":[],"mappings":"AAyBA,SAAS,gBAAgB,CAAA,EAA+C;AACtE,EAAA,OAAO,OAAO,GAAG,iBAAA,KAAsB,UAAA;AACzC;AAEA,SAAS,mBAAmB,CAAA,EAA+B;AACzD,EAAA,OAAO,OAAO,GAAG,kBAAA,KAAuB,UAAA;AAC1C;AAEA,SAAS,oBAAoB,CAAA,EAAgC;AAC3D,EAAA,OAAO,OAAO,GAAG,eAAA,KAAoB,UAAA;AACvC;AAEA,SAAS,uBACP,aAAA,EACmC;AACnC,EAAA,MAAM,SAA4C,EAAC;AAEnD,EAAA,KAAA,MAAW,CAAC,iBAAA,EAAmB,kBAAkB,CAAA,IAAK,MAAA,CAAO,OAAA;AAAA,IAC3D;AAAA,GACF,EAAG;AACD,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,kBAAkB,CAAA,EAAG;AACrC,MAAA,IAAI,kBAAA,CAAmB,SAAS,CAAA,EAAG;AACjC,QAAA,MAAA,CAAO,iBAAiB,CAAA,GAAI,kBAAA;AAAA,MAC9B;AAAA,IACF,CAAA,MAAA,IACE,kBAAA,KAAuB,MAAA,IACvB,kBAAA,KAAuB,IAAA,EACvB;AACA,MAAA,MAAA,CAAO,iBAAiB,CAAA,GAAI,kBAAA;AAAA,IAC9B;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAYO,MAAM,eAAA,GAAkB,CAC7B,OAAA,KACsC;AACtC,EAAA,MAAM,YAAA,GAAe,MAAA,CAAO,MAAA,CAAO,OAAO,CAAA,CAAE,MAAA;AAAA,IAC1C,CAAC,CAAA,KAAkC,CAAA,KAAM,IAAA,IAAQ,CAAA,KAAM;AAAA,GACzD;AAEA,EAAA,MAAM,cAAA,GAAiB,YAAA,CACpB,OAAA,CAAQ,CAAA,CAAA,KAAK;AACZ,IAAA,IAAI,eAAA,CAAgB,CAAC,CAAA,EAAG;AACtB,MAAA,MAAM,aAAA,GAAgB,EAAE,iBAAA,EAAkB;AAC1C,MAAA,OAAO,aAAA,GAAgB,CAAC,aAAa,CAAA,GAAI,EAAC;AAAA,IAC5C;AACA,IAAA,OAAO,EAAC;AAAA,EACV,CAAC,CAAA,CACA,MAAA,CAAO,CAAC,KAAK,CAAA,KAAM;AAClB,IAAA,OAAO,EAAE,GAAG,GAAA,EAAK,GAAG,sBAAA,CAAuB,CAAC,CAAA,EAAE;AAAA,EAChD,CAAA,EAAG,EAAuC,CAAA;AAE5C,EAAA,MAAM,cAAA,GAAiB,YAAA,CACpB,IAAA,CAAK,kBAAkB,GACtB,kBAAA,EAAmB;AAEvB,EAAA,MAAM,iBAAA,GAAoB,YAAA,CAAa,IAAA,CAAK,mBAAmB,CAAA;AAC/D,EAAA,MAAM,WAAA,GAAc,iBAAA,GACf,iBAAA,CAAkB,eAAA,EAAgB,GACnC,MAAA;AAEJ,EAAA,MAAM,UAAiC,EAAC;AAExC,EAAA,IAAI,MAAA,CAAO,IAAA,CAAK,cAAc,CAAA,CAAE,SAAS,CAAA,EAAG;AAC1C,IAAA,OAAA,CAAQ,MAAA,GAAS,cAAA;AAAA,EACnB;AAEA,EAAA,IAAI,cAAA,EAAgB;AAClB,IAAA,OAAA,CAAQ,cAAA,GAAiB,cAAA;AAAA,EAC3B;AAEA,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,OAAA,CAAQ,WAAA,GAAc,WAAA;AAAA,EACxB;AAGA,EAAA,OAAO,OAAO,IAAA,CAAK,OAAO,CAAA,CAAE,MAAA,GAAS,IAAI,OAAA,GAAU,MAAA;AACrD;;;;"}
@@ -1,5 +1,5 @@
1
1
  var name = "@backstage/plugin-catalog";
2
- var version = "2.0.7-next.0";
2
+ var version = "2.0.7";
3
3
  var description = "The Backstage plugin for browsing the Backstage catalog";
4
4
  var backstage = {
5
5
  role: "frontend-plugin",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-catalog",
3
- "version": "2.0.7-next.0",
3
+ "version": "2.0.7",
4
4
  "description": "The Backstage plugin for browsing the Backstage catalog",
5
5
  "backstage": {
6
6
  "role": "frontend-plugin",
@@ -70,25 +70,25 @@
70
70
  "test": "backstage-cli package test"
71
71
  },
72
72
  "dependencies": {
73
- "@backstage/catalog-client": "1.16.1-next.0",
74
- "@backstage/catalog-model": "1.9.0",
75
- "@backstage/core-compat-api": "0.5.13-next.0",
76
- "@backstage/core-components": "0.18.12-next.0",
77
- "@backstage/core-plugin-api": "1.12.8-next.0",
78
- "@backstage/errors": "1.3.1",
79
- "@backstage/frontend-plugin-api": "0.17.3-next.0",
80
- "@backstage/integration-react": "1.2.20-next.0",
81
- "@backstage/plugin-catalog-common": "1.1.10",
82
- "@backstage/plugin-catalog-react": "3.2.0-next.0",
83
- "@backstage/plugin-permission-react": "0.5.3-next.0",
84
- "@backstage/plugin-scaffolder-common": "2.2.1",
85
- "@backstage/plugin-search-common": "1.2.24",
86
- "@backstage/plugin-search-react": "1.11.6-next.0",
87
- "@backstage/plugin-techdocs-common": "0.1.1",
88
- "@backstage/plugin-techdocs-react": "1.3.13-next.0",
89
- "@backstage/types": "1.2.2",
90
- "@backstage/ui": "0.17.0-next.0",
91
- "@backstage/version-bridge": "1.0.12",
73
+ "@backstage/catalog-client": "^1.16.1",
74
+ "@backstage/catalog-model": "^1.9.0",
75
+ "@backstage/core-compat-api": "^0.5.13",
76
+ "@backstage/core-components": "^0.18.12",
77
+ "@backstage/core-plugin-api": "^1.12.8",
78
+ "@backstage/errors": "^1.3.1",
79
+ "@backstage/frontend-plugin-api": "^0.17.3",
80
+ "@backstage/integration-react": "^1.2.20",
81
+ "@backstage/plugin-catalog-common": "^1.1.10",
82
+ "@backstage/plugin-catalog-react": "^3.2.0",
83
+ "@backstage/plugin-permission-react": "^0.5.3",
84
+ "@backstage/plugin-scaffolder-common": "^2.2.1",
85
+ "@backstage/plugin-search-common": "^1.2.24",
86
+ "@backstage/plugin-search-react": "^1.11.6",
87
+ "@backstage/plugin-techdocs-common": "^0.1.1",
88
+ "@backstage/plugin-techdocs-react": "^1.3.13",
89
+ "@backstage/types": "^1.2.2",
90
+ "@backstage/ui": "^0.17.0",
91
+ "@backstage/version-bridge": "^1.0.12",
92
92
  "@material-ui/core": "^4.12.2",
93
93
  "@material-ui/icons": "^4.9.1",
94
94
  "@material-ui/lab": "4.0.0-alpha.61",
@@ -105,12 +105,12 @@
105
105
  "zod": "^4.0.0"
106
106
  },
107
107
  "devDependencies": {
108
- "@backstage/cli": "0.36.4-next.0",
109
- "@backstage/core-app-api": "1.20.3-next.0",
110
- "@backstage/dev-utils": "1.1.25-next.0",
111
- "@backstage/frontend-test-utils": "0.6.2-next.0",
112
- "@backstage/plugin-permission-common": "0.9.9",
113
- "@backstage/test-utils": "1.7.20-next.0",
108
+ "@backstage/cli": "^0.36.4",
109
+ "@backstage/core-app-api": "^1.20.3",
110
+ "@backstage/dev-utils": "^1.1.25",
111
+ "@backstage/frontend-test-utils": "^0.6.2",
112
+ "@backstage/plugin-permission-common": "^0.9.9",
113
+ "@backstage/test-utils": "^1.7.20",
114
114
  "@testing-library/dom": "^10.0.0",
115
115
  "@testing-library/jest-dom": "^6.0.0",
116
116
  "@testing-library/react": "^16.0.0",