@nospt/backstage-plugin-apigee 0.1.1 → 0.1.3

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.
@@ -0,0 +1,35 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { Sidebar, SidebarItem, SidebarSubmenu, SidebarSubmenuItem } from '@backstage/core-components';
3
+ import LayersIcon from '@material-ui/icons/Layers';
4
+
5
+ const ApigeeNavContent = ({ navItems }) => {
6
+ const allItems = navItems.rest();
7
+ const apigeeItems = allItems.filter(
8
+ (item) => item.node.spec.plugin.pluginId === "apigee"
9
+ );
10
+ const otherItems = allItems.filter(
11
+ (item) => item.node.spec.plugin.pluginId !== "apigee"
12
+ );
13
+ return /* @__PURE__ */ jsxs(Sidebar, { children: [
14
+ otherItems.map((item) => /* @__PURE__ */ jsx(
15
+ SidebarItem,
16
+ {
17
+ to: item.href,
18
+ icon: (_props) => item.icon,
19
+ text: item.title
20
+ },
21
+ item.node.spec.id
22
+ )),
23
+ apigeeItems.length > 0 && /* @__PURE__ */ jsx(SidebarItem, { icon: LayersIcon, text: "API Hub", children: /* @__PURE__ */ jsx(SidebarSubmenu, { title: "API Hub", children: apigeeItems.map((item) => /* @__PURE__ */ jsx(
24
+ SidebarSubmenuItem,
25
+ {
26
+ title: item.title,
27
+ to: item.href
28
+ },
29
+ item.node.spec.id
30
+ )) }) })
31
+ ] });
32
+ };
33
+
34
+ export { ApigeeNavContent };
35
+ //# sourceMappingURL=ApigeeNavContent.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApigeeNavContent.esm.js","sources":["../../src/components/ApigeeNavContent.tsx"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\nimport {\n Sidebar,\n SidebarItem,\n SidebarSubmenu,\n SidebarSubmenuItem,\n} from '@backstage/core-components';\nimport type {\n NavContentComponent,\n NavContentNavItem,\n} from '@backstage/plugin-app-react';\nimport LayersIcon from '@material-ui/icons/Layers';\nimport React from 'react';\n\n/**\n * Renders the app nav bar with an expandable \"API Hub\" group for all apigee\n * plugin pages, while rendering any other plugins' pages as flat sidebar items.\n *\n * To activate, add `apigeeNavModule` to your app's `createApp({ features })`.\n */\nexport const ApigeeNavContent: NavContentComponent = ({ navItems }) => {\n const allItems = navItems.rest();\n const apigeeItems = allItems.filter(\n (item: NavContentNavItem) =>\n item.node.spec.plugin.pluginId === 'apigee',\n );\n const otherItems = allItems.filter(\n (item: NavContentNavItem) =>\n item.node.spec.plugin.pluginId !== 'apigee',\n );\n\n return (\n <Sidebar>\n {otherItems.map((item: NavContentNavItem) => (\n <SidebarItem\n key={item.node.spec.id}\n to={item.href}\n // item.icon is IconElement (JSX); SidebarItem.icon is IconComponent.\n // Wrapping in a render-prop is the documented pattern from AppNav.\n icon={(_props: object) => item.icon as React.ReactElement}\n text={item.title}\n />\n ))}\n {apigeeItems.length > 0 && (\n <SidebarItem icon={LayersIcon} text=\"API Hub\">\n <SidebarSubmenu title=\"API Hub\">\n {apigeeItems.map((item: NavContentNavItem) => (\n <SidebarSubmenuItem\n key={item.node.spec.id}\n title={item.title}\n to={item.href}\n />\n ))}\n </SidebarSubmenu>\n </SidebarItem>\n )}\n </Sidebar>\n );\n};\n"],"names":[],"mappings":";;;;AAoBO,MAAM,gBAAA,GAAwC,CAAC,EAAE,QAAA,EAAS,KAAM;AACrE,EAAA,MAAM,QAAA,GAAW,SAAS,IAAA,EAAK;AAC/B,EAAA,MAAM,cAAc,QAAA,CAAS,MAAA;AAAA,IAC3B,CAAC,IAAA,KACC,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,OAAO,QAAA,KAAa;AAAA,GACvC;AACA,EAAA,MAAM,aAAa,QAAA,CAAS,MAAA;AAAA,IAC1B,CAAC,IAAA,KACC,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,OAAO,QAAA,KAAa;AAAA,GACvC;AAEA,EAAA,4BACG,OAAA,EAAA,EACE,QAAA,EAAA;AAAA,IAAA,UAAA,CAAW,GAAA,CAAI,CAAC,IAAA,qBACf,GAAA;AAAA,MAAC,WAAA;AAAA,MAAA;AAAA,QAEC,IAAI,IAAA,CAAK,IAAA;AAAA,QAGT,IAAA,EAAM,CAAC,MAAA,KAAmB,IAAA,CAAK,IAAA;AAAA,QAC/B,MAAM,IAAA,CAAK;AAAA,OAAA;AAAA,MALN,IAAA,CAAK,KAAK,IAAA,CAAK;AAAA,KAOvB,CAAA;AAAA,IACA,YAAY,MAAA,GAAS,CAAA,oBACpB,GAAA,CAAC,WAAA,EAAA,EAAY,MAAM,UAAA,EAAY,IAAA,EAAK,SAAA,EAClC,QAAA,kBAAA,GAAA,CAAC,kBAAe,KAAA,EAAM,SAAA,EACnB,QAAA,EAAA,WAAA,CAAY,GAAA,CAAI,CAAC,IAAA,qBAChB,GAAA;AAAA,MAAC,kBAAA;AAAA,MAAA;AAAA,QAEC,OAAO,IAAA,CAAK,KAAA;AAAA,QACZ,IAAI,IAAA,CAAK;AAAA,OAAA;AAAA,MAFJ,IAAA,CAAK,KAAK,IAAA,CAAK;AAAA,KAIvB,GACH,CAAA,EACF;AAAA,GAAA,EAEJ,CAAA;AAEJ;;;;"}
@@ -51,7 +51,7 @@ class ApiSearchFilter {
51
51
  }
52
52
  }
53
53
  class ApiKindFilter {
54
- value = "api";
54
+ value = "API";
55
55
  getCatalogFilters() {
56
56
  return { kind: this.value };
57
57
  }
@@ -1 +1 @@
1
- {"version":3,"file":"apigeeFacetFilters.esm.js","sources":["../../src/components/apigeeFacetFilters.ts"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\nimport { type Entity, parseEntityRef } from '@backstage/catalog-model';\nimport type { EntityFilter } from '@backstage/plugin-catalog-react';\nimport { humanizeEntityRef } from '@backstage/plugin-catalog-react';\nimport {\n ANNOTATION_APIGEE_ORGS,\n ANNOTATION_APIGEE_ORG,\n ANNOTATION_CATEGORY,\n} from '../constants';\n\n/** Dual-key is-Apigee gate (same rule as the existing ApigeeOrgFilter). */\nexport function isApigeeEntity(e: Entity): boolean {\n const a = e.metadata.annotations ?? {};\n return ANNOTATION_APIGEE_ORGS in a || ANNOTATION_APIGEE_ORG in a;\n}\n\n// --- Pure field extractors: the ONE place each facet's value is defined. Reused by\n// deriveFacets(), the facet predicates, and the search haystack. Unit-testable. ---\nexport const entityLifecycle = (e: Entity): string | undefined =>\n (e.spec?.lifecycle as string | undefined)?.trim() || undefined;\n\nexport const entityOwnerLabel = (e: Entity): string | undefined => {\n const owner = e.spec?.owner as string | undefined;\n return owner\n ? humanizeEntityRef(\n parseEntityRef(owner, { defaultKind: 'group', defaultNamespace: 'default' }),\n { defaultKind: 'group' },\n ) // 'group:default/payments-team' -> 'payments-team'\n : undefined;\n};\n\nexport const entityOrg = (e: Entity): string | undefined => {\n const a = e.metadata.annotations ?? {};\n return (\n (a[ANNOTATION_APIGEE_ORGS] ?? a[ANNOTATION_APIGEE_ORG])?.split(',')[0]?.trim() ||\n undefined\n );\n};\n\nexport const entityCategory = (e: Entity): string | undefined =>\n (e.metadata.annotations ?? {})[ANNOTATION_CATEGORY]?.split(',')[0]?.trim() ||\n undefined;\n\n/**\n * Facet-only category value: maps an uncategorised entity to the 'other' bucket\n * (LOCKED UI-SPEC Facet Data). Search uses `entityCategory` (the REAL slug) instead,\n * so a search for \"other\" does not match uncategorised APIs.\n */\nexport const entityCategoryFacet = (e: Entity): string =>\n entityCategory(e) ?? 'other';\n\n/** Generic single-field multi-value facet. Within-facet OR. No URL seam / getCatalogFilters. */\nexport class FieldFacetFilter implements EntityFilter {\n constructor(\n private readonly extract: (e: Entity) => string | undefined,\n public readonly values: string[],\n ) {}\n filterEntity(entity: Entity): boolean {\n const v = this.extract(entity);\n return v !== undefined && this.values.includes(v); // OR across selected values\n }\n}\n\n/** Broad \"find anything\" search: name + description + owner + org + category (D-09). */\nexport function apiSearchHaystack(e: Entity): string {\n return [\n e.metadata.title ?? e.metadata.name,\n e.metadata.description ?? '',\n entityOwnerLabel(e) ?? '',\n entityOrg(e) ?? '',\n entityCategory(e) ?? '',\n ]\n .join(' ')\n .toLowerCase();\n}\n\nexport class ApiSearchFilter implements EntityFilter {\n private readonly needle: string;\n constructor(query: string) {\n this.needle = query.trim().toLowerCase();\n }\n filterEntity(entity: Entity): boolean {\n // String.includes ONLY — never build a RegExp from user input (ReDoS guard).\n return this.needle === '' || apiSearchHaystack(entity).includes(this.needle);\n }\n}\n\n/**\n * Replaces EntityKindFilter('api','API'): keeps the backend kind=api filter but exposes no\n * URL seam, so the provider does not serialize `filters[kind]=api` into the URL (D-06).\n */\nexport class ApiKindFilter implements EntityFilter {\n readonly value = 'api';\n getCatalogFilters(): Record<string, string> {\n return { kind: this.value };\n }\n}\n"],"names":[],"mappings":";;;;AAWO,SAAS,eAAe,CAAA,EAAoB;AACjD,EAAA,MAAM,CAAA,GAAI,CAAA,CAAE,QAAA,CAAS,WAAA,IAAe,EAAC;AACrC,EAAA,OAAO,sBAAA,IAA0B,KAAK,qBAAA,IAAyB,CAAA;AACjE;AAIO,MAAM,kBAAkB,CAAC,CAAA,KAC7B,EAAE,IAAA,EAAM,SAAA,EAAkC,MAAK,IAAK;AAEhD,MAAM,gBAAA,GAAmB,CAAC,CAAA,KAAkC;AACjE,EAAA,MAAM,KAAA,GAAQ,EAAE,IAAA,EAAM,KAAA;AACtB,EAAA,OAAO,KAAA,GACH,iBAAA;AAAA,IACE,eAAe,KAAA,EAAO,EAAE,aAAa,OAAA,EAAS,gBAAA,EAAkB,WAAW,CAAA;AAAA,IAC3E,EAAE,aAAa,OAAA;AAAQ,GACzB,GACA,MAAA;AACN;AAEO,MAAM,SAAA,GAAY,CAAC,CAAA,KAAkC;AAC1D,EAAA,MAAM,CAAA,GAAI,CAAA,CAAE,QAAA,CAAS,WAAA,IAAe,EAAC;AACrC,EAAA,OAAA,CACG,CAAA,CAAE,sBAAsB,CAAA,IAAK,CAAA,CAAE,qBAAqB,CAAA,GAAI,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,EAAG,IAAA,EAAK,IAC7E,MAAA;AAEJ;AAEO,MAAM,iBAAiB,CAAC,CAAA,KAAA,CAC5B,CAAA,CAAE,QAAA,CAAS,eAAe,EAAC,EAAG,mBAAmB,CAAA,EAAG,MAAM,GAAG,CAAA,CAAE,CAAC,CAAA,EAAG,MAAK,IACzE;AAOK,MAAM,mBAAA,GAAsB,CAAC,CAAA,KAClC,cAAA,CAAe,CAAC,CAAA,IAAK;AAGhB,MAAM,gBAAA,CAAyC;AAAA,EACpD,WAAA,CACmB,SACD,MAAA,EAChB;AAFiB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACD,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EACf;AAAA,EAFgB,OAAA;AAAA,EACD,MAAA;AAAA,EAElB,aAAa,MAAA,EAAyB;AACpC,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,OAAA,CAAQ,MAAM,CAAA;AAC7B,IAAA,OAAO,CAAA,KAAM,MAAA,IAAa,IAAA,CAAK,MAAA,CAAO,SAAS,CAAC,CAAA;AAAA,EAClD;AACF;AAGO,SAAS,kBAAkB,CAAA,EAAmB;AACnD,EAAA,OAAO;AAAA,IACL,CAAA,CAAE,QAAA,CAAS,KAAA,IAAS,CAAA,CAAE,QAAA,CAAS,IAAA;AAAA,IAC/B,CAAA,CAAE,SAAS,WAAA,IAAe,EAAA;AAAA,IAC1B,gBAAA,CAAiB,CAAC,CAAA,IAAK,EAAA;AAAA,IACvB,SAAA,CAAU,CAAC,CAAA,IAAK,EAAA;AAAA,IAChB,cAAA,CAAe,CAAC,CAAA,IAAK;AAAA,GACvB,CACG,IAAA,CAAK,GAAG,CAAA,CACR,WAAA,EAAY;AACjB;AAEO,MAAM,eAAA,CAAwC;AAAA,EAClC,MAAA;AAAA,EACjB,YAAY,KAAA,EAAe;AACzB,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA,CAAM,IAAA,EAAK,CAAE,WAAA,EAAY;AAAA,EACzC;AAAA,EACA,aAAa,MAAA,EAAyB;AAEpC,IAAA,OAAO,IAAA,CAAK,WAAW,EAAA,IAAM,iBAAA,CAAkB,MAAM,CAAA,CAAE,QAAA,CAAS,KAAK,MAAM,CAAA;AAAA,EAC7E;AACF;AAMO,MAAM,aAAA,CAAsC;AAAA,EACxC,KAAA,GAAQ,KAAA;AAAA,EACjB,iBAAA,GAA4C;AAC1C,IAAA,OAAO,EAAE,IAAA,EAAM,IAAA,CAAK,KAAA,EAAM;AAAA,EAC5B;AACF;;;;"}
1
+ {"version":3,"file":"apigeeFacetFilters.esm.js","sources":["../../src/components/apigeeFacetFilters.ts"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\nimport { type Entity, parseEntityRef } from '@backstage/catalog-model';\nimport type { EntityFilter } from '@backstage/plugin-catalog-react';\nimport { humanizeEntityRef } from '@backstage/plugin-catalog-react';\nimport {\n ANNOTATION_APIGEE_ORGS,\n ANNOTATION_APIGEE_ORG,\n ANNOTATION_CATEGORY,\n} from '../constants';\n\n/** Dual-key is-Apigee gate (same rule as the existing ApigeeOrgFilter). */\nexport function isApigeeEntity(e: Entity): boolean {\n const a = e.metadata.annotations ?? {};\n return ANNOTATION_APIGEE_ORGS in a || ANNOTATION_APIGEE_ORG in a;\n}\n\n// --- Pure field extractors: the ONE place each facet's value is defined. Reused by\n// deriveFacets(), the facet predicates, and the search haystack. Unit-testable. ---\nexport const entityLifecycle = (e: Entity): string | undefined =>\n (e.spec?.lifecycle as string | undefined)?.trim() || undefined;\n\nexport const entityOwnerLabel = (e: Entity): string | undefined => {\n const owner = e.spec?.owner as string | undefined;\n return owner\n ? humanizeEntityRef(\n parseEntityRef(owner, { defaultKind: 'group', defaultNamespace: 'default' }),\n { defaultKind: 'group' },\n ) // 'group:default/payments-team' -> 'payments-team'\n : undefined;\n};\n\nexport const entityOrg = (e: Entity): string | undefined => {\n const a = e.metadata.annotations ?? {};\n return (\n (a[ANNOTATION_APIGEE_ORGS] ?? a[ANNOTATION_APIGEE_ORG])?.split(',')[0]?.trim() ||\n undefined\n );\n};\n\nexport const entityCategory = (e: Entity): string | undefined =>\n (e.metadata.annotations ?? {})[ANNOTATION_CATEGORY]?.split(',')[0]?.trim() ||\n undefined;\n\n/**\n * Facet-only category value: maps an uncategorised entity to the 'other' bucket\n * (LOCKED UI-SPEC Facet Data). Search uses `entityCategory` (the REAL slug) instead,\n * so a search for \"other\" does not match uncategorised APIs.\n */\nexport const entityCategoryFacet = (e: Entity): string =>\n entityCategory(e) ?? 'other';\n\n/** Generic single-field multi-value facet. Within-facet OR. No URL seam / getCatalogFilters. */\nexport class FieldFacetFilter implements EntityFilter {\n constructor(\n private readonly extract: (e: Entity) => string | undefined,\n public readonly values: string[],\n ) {}\n filterEntity(entity: Entity): boolean {\n const v = this.extract(entity);\n return v !== undefined && this.values.includes(v); // OR across selected values\n }\n}\n\n/** Broad \"find anything\" search: name + description + owner + org + category (D-09). */\nexport function apiSearchHaystack(e: Entity): string {\n return [\n e.metadata.title ?? e.metadata.name,\n e.metadata.description ?? '',\n entityOwnerLabel(e) ?? '',\n entityOrg(e) ?? '',\n entityCategory(e) ?? '',\n ]\n .join(' ')\n .toLowerCase();\n}\n\nexport class ApiSearchFilter implements EntityFilter {\n private readonly needle: string;\n constructor(query: string) {\n this.needle = query.trim().toLowerCase();\n }\n filterEntity(entity: Entity): boolean {\n // String.includes ONLY — never build a RegExp from user input (ReDoS guard).\n return this.needle === '' || apiSearchHaystack(entity).includes(this.needle);\n }\n}\n\n/**\n * Replaces EntityKindFilter('api','API'): keeps the backend kind=API filter but exposes no\n * URL seam, so the provider does not serialize `filters[kind]=API` into the URL (D-06).\n */\nexport class ApiKindFilter implements EntityFilter {\n readonly value = 'API';\n getCatalogFilters(): Record<string, string> {\n return { kind: this.value };\n }\n}\n"],"names":[],"mappings":";;;;AAWO,SAAS,eAAe,CAAA,EAAoB;AACjD,EAAA,MAAM,CAAA,GAAI,CAAA,CAAE,QAAA,CAAS,WAAA,IAAe,EAAC;AACrC,EAAA,OAAO,sBAAA,IAA0B,KAAK,qBAAA,IAAyB,CAAA;AACjE;AAIO,MAAM,kBAAkB,CAAC,CAAA,KAC7B,EAAE,IAAA,EAAM,SAAA,EAAkC,MAAK,IAAK;AAEhD,MAAM,gBAAA,GAAmB,CAAC,CAAA,KAAkC;AACjE,EAAA,MAAM,KAAA,GAAQ,EAAE,IAAA,EAAM,KAAA;AACtB,EAAA,OAAO,KAAA,GACH,iBAAA;AAAA,IACE,eAAe,KAAA,EAAO,EAAE,aAAa,OAAA,EAAS,gBAAA,EAAkB,WAAW,CAAA;AAAA,IAC3E,EAAE,aAAa,OAAA;AAAQ,GACzB,GACA,MAAA;AACN;AAEO,MAAM,SAAA,GAAY,CAAC,CAAA,KAAkC;AAC1D,EAAA,MAAM,CAAA,GAAI,CAAA,CAAE,QAAA,CAAS,WAAA,IAAe,EAAC;AACrC,EAAA,OAAA,CACG,CAAA,CAAE,sBAAsB,CAAA,IAAK,CAAA,CAAE,qBAAqB,CAAA,GAAI,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,EAAG,IAAA,EAAK,IAC7E,MAAA;AAEJ;AAEO,MAAM,iBAAiB,CAAC,CAAA,KAAA,CAC5B,CAAA,CAAE,QAAA,CAAS,eAAe,EAAC,EAAG,mBAAmB,CAAA,EAAG,MAAM,GAAG,CAAA,CAAE,CAAC,CAAA,EAAG,MAAK,IACzE;AAOK,MAAM,mBAAA,GAAsB,CAAC,CAAA,KAClC,cAAA,CAAe,CAAC,CAAA,IAAK;AAGhB,MAAM,gBAAA,CAAyC;AAAA,EACpD,WAAA,CACmB,SACD,MAAA,EAChB;AAFiB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACD,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EACf;AAAA,EAFgB,OAAA;AAAA,EACD,MAAA;AAAA,EAElB,aAAa,MAAA,EAAyB;AACpC,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,OAAA,CAAQ,MAAM,CAAA;AAC7B,IAAA,OAAO,CAAA,KAAM,MAAA,IAAa,IAAA,CAAK,MAAA,CAAO,SAAS,CAAC,CAAA;AAAA,EAClD;AACF;AAGO,SAAS,kBAAkB,CAAA,EAAmB;AACnD,EAAA,OAAO;AAAA,IACL,CAAA,CAAE,QAAA,CAAS,KAAA,IAAS,CAAA,CAAE,QAAA,CAAS,IAAA;AAAA,IAC/B,CAAA,CAAE,SAAS,WAAA,IAAe,EAAA;AAAA,IAC1B,gBAAA,CAAiB,CAAC,CAAA,IAAK,EAAA;AAAA,IACvB,SAAA,CAAU,CAAC,CAAA,IAAK,EAAA;AAAA,IAChB,cAAA,CAAe,CAAC,CAAA,IAAK;AAAA,GACvB,CACG,IAAA,CAAK,GAAG,CAAA,CACR,WAAA,EAAY;AACjB;AAEO,MAAM,eAAA,CAAwC;AAAA,EAClC,MAAA;AAAA,EACjB,YAAY,KAAA,EAAe;AACzB,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA,CAAM,IAAA,EAAK,CAAE,WAAA,EAAY;AAAA,EACzC;AAAA,EACA,aAAa,MAAA,EAAyB;AAEpC,IAAA,OAAO,IAAA,CAAK,WAAW,EAAA,IAAM,iBAAA,CAAkB,MAAM,CAAA,CAAE,QAAA,CAAS,KAAK,MAAM,CAAA;AAAA,EAC7E;AACF;AAMO,MAAM,aAAA,CAAsC;AAAA,EACxC,KAAA,GAAQ,KAAA;AAAA,EACjB,iBAAA,GAA4C;AAC1C,IAAA,OAAO,EAAE,IAAA,EAAM,IAAA,CAAK,KAAA,EAAM;AAAA,EAC5B;AACF;;;;"}
package/dist/index.d.ts CHANGED
@@ -1,26 +1,61 @@
1
1
  import * as react from 'react';
2
2
  import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
3
3
 
4
+ declare const apigeePage: _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
5
+ kind: "page";
6
+ name: undefined;
7
+ config: {
8
+ path: string | undefined;
9
+ title: string | undefined;
10
+ };
11
+ configInput: {
12
+ title?: string | undefined;
13
+ path?: string | undefined;
14
+ };
15
+ output: _backstage_frontend_plugin_api.ExtensionDataRef<string, "core.routing.path", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams>, "core.routing.ref", {
16
+ optional: true;
17
+ }> | _backstage_frontend_plugin_api.ExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "core.title", {
18
+ optional: true;
19
+ }> | _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.IconElement, "core.icon", {
20
+ optional: true;
21
+ }>;
22
+ inputs: {
23
+ pages: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.ConfigurableExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "core.routing.path", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<_backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams>, "core.routing.ref", {
24
+ optional: true;
25
+ }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "core.title", {
26
+ optional: true;
27
+ }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<_backstage_frontend_plugin_api.IconElement, "core.icon", {
28
+ optional: true;
29
+ }>, {
30
+ singleton: false;
31
+ optional: false;
32
+ internal: false;
33
+ }>;
34
+ };
35
+ params: {
36
+ path: string;
37
+ title?: string;
38
+ icon?: _backstage_frontend_plugin_api.IconElement;
39
+ loader?: () => Promise<react.JSX.Element>;
40
+ routeRef?: _backstage_frontend_plugin_api.RouteRef;
41
+ noHeader?: boolean;
42
+ };
43
+ }>;
44
+ /**
45
+ * Frontend module that overrides the app nav bar to show an expandable
46
+ * "API Hub" group containing all apigee plugin pages as sub-items.
47
+ *
48
+ * Add this to your app's `createApp({ features })` to activate the grouped nav.
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * createApp({ features: [apigeePlugin, apigeeNavModule] });
53
+ * ```
54
+ */
55
+ declare const apigeeNavModule: _backstage_frontend_plugin_api.FrontendModule;
4
56
  declare const apigeePlugin: _backstage_frontend_plugin_api.OverridableFrontendPlugin<{
5
57
  root: _backstage_frontend_plugin_api.RouteRef<undefined>;
6
58
  }, {}, {
7
- "nav-item:apigee": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
8
- kind: "nav-item";
9
- name: undefined;
10
- config: {};
11
- configInput: {};
12
- output: _backstage_frontend_plugin_api.ExtensionDataRef<{
13
- title: string;
14
- icon: _backstage_frontend_plugin_api.IconComponent;
15
- routeRef: _backstage_frontend_plugin_api.RouteRef<undefined>;
16
- }, "core.nav-item.target", {}>;
17
- inputs: {};
18
- params: {
19
- title: string;
20
- icon: _backstage_frontend_plugin_api.IconComponent;
21
- routeRef: _backstage_frontend_plugin_api.RouteRef<undefined>;
22
- };
23
- }>;
24
59
  "page:apigee": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
25
60
  kind: "page";
26
61
  name: undefined;
@@ -63,4 +98,4 @@ declare const apigeePlugin: _backstage_frontend_plugin_api.OverridableFrontendPl
63
98
  }>;
64
99
  }>;
65
100
 
66
- export { apigeePlugin as default };
101
+ export { apigeeNavModule, apigeePage, apigeePlugin, apigeePlugin as default };
package/dist/index.esm.js CHANGED
@@ -1,2 +1,2 @@
1
- export { apigeePlugin as default } from './plugin.esm.js';
1
+ export { apigeeNavModule, apigeePage, apigeePlugin, apigeePlugin as default } from './plugin.esm.js';
2
2
  //# sourceMappingURL=index.esm.js.map
@@ -1,11 +1,14 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { PageBlueprint, NavItemBlueprint, createFrontendPlugin } from '@backstage/frontend-plugin-api';
2
+ import { PageBlueprint, createFrontendModule, createFrontendPlugin } from '@backstage/frontend-plugin-api';
3
+ import { NavContentBlueprint } from '@backstage/plugin-app-react';
3
4
  import LayersIcon from '@material-ui/icons/Layers';
4
5
  import { rootRouteRef } from './routes.esm.js';
6
+ import { ApigeeNavContent } from './components/ApigeeNavContent.esm.js';
5
7
 
6
8
  const apigeePage = PageBlueprint.make({
7
9
  params: {
8
10
  title: "API Catalog",
11
+ icon: /* @__PURE__ */ jsx(LayersIcon, {}),
9
12
  routeRef: rootRouteRef,
10
13
  path: "/apigee",
11
14
  loader: () => import('./components/ApigeeApiCatalogPage.esm.js').then(
@@ -13,21 +16,24 @@ const apigeePage = PageBlueprint.make({
13
16
  )
14
17
  }
15
18
  });
16
- const apigeeNavItem = NavItemBlueprint.make({
17
- params: {
18
- title: "API Catalog",
19
- icon: LayersIcon,
20
- routeRef: rootRouteRef
21
- }
19
+ const apigeeNavModule = createFrontendModule({
20
+ pluginId: "app",
21
+ extensions: [
22
+ NavContentBlueprint.make({
23
+ params: {
24
+ component: ApigeeNavContent
25
+ }
26
+ })
27
+ ]
22
28
  });
23
29
  const apigeePlugin = createFrontendPlugin({
24
30
  pluginId: "apigee",
25
- title: "API Catalog",
26
- extensions: [apigeePage, apigeeNavItem],
31
+ title: "API Hub",
32
+ extensions: [apigeePage],
27
33
  routes: {
28
34
  root: rootRouteRef
29
35
  }
30
36
  });
31
37
 
32
- export { apigeeNavItem, apigeePage, apigeePlugin };
38
+ export { apigeeNavModule, apigeePage, apigeePlugin };
33
39
  //# sourceMappingURL=plugin.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.esm.js","sources":["../src/plugin.tsx"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\nimport {\n createFrontendPlugin,\n NavItemBlueprint,\n PageBlueprint,\n} from '@backstage/frontend-plugin-api';\nimport LayersIcon from '@material-ui/icons/Layers';\nimport { rootRouteRef } from './routes';\n\nexport const apigeePage = PageBlueprint.make({\n params: {\n title: 'API Catalog',\n routeRef: rootRouteRef,\n path: '/apigee',\n loader: () =>\n import('./components/ApigeeApiCatalogPage').then(\n ({ ApigeeApiCatalogPage }) => <ApigeeApiCatalogPage />,\n ),\n },\n});\n\nexport const apigeeNavItem = NavItemBlueprint.make({\n params: {\n title: 'API Catalog',\n icon: LayersIcon,\n routeRef: rootRouteRef,\n },\n});\n\nexport const apigeePlugin = createFrontendPlugin({\n pluginId: 'apigee',\n title: 'API Catalog',\n extensions: [apigeePage, apigeeNavItem],\n routes: {\n root: rootRouteRef,\n },\n});\n"],"names":[],"mappings":";;;;;AASO,MAAM,UAAA,GAAa,cAAc,IAAA,CAAK;AAAA,EAC3C,MAAA,EAAQ;AAAA,IACN,KAAA,EAAO,aAAA;AAAA,IACP,QAAA,EAAU,YAAA;AAAA,IACV,IAAA,EAAM,SAAA;AAAA,IACN,MAAA,EAAQ,MACN,OAAO,0CAAmC,CAAA,CAAE,IAAA;AAAA,MAC1C,CAAC,EAAE,oBAAA,EAAqB,yBAAO,oBAAA,EAAA,EAAqB;AAAA;AACtD;AAEN,CAAC;AAEM,MAAM,aAAA,GAAgB,iBAAiB,IAAA,CAAK;AAAA,EACjD,MAAA,EAAQ;AAAA,IACN,KAAA,EAAO,aAAA;AAAA,IACP,IAAA,EAAM,UAAA;AAAA,IACN,QAAA,EAAU;AAAA;AAEd,CAAC;AAEM,MAAM,eAAe,oBAAA,CAAqB;AAAA,EAC/C,QAAA,EAAU,QAAA;AAAA,EACV,KAAA,EAAO,aAAA;AAAA,EACP,UAAA,EAAY,CAAC,UAAA,EAAY,aAAa,CAAA;AAAA,EACtC,MAAA,EAAQ;AAAA,IACN,IAAA,EAAM;AAAA;AAEV,CAAC;;;;"}
1
+ {"version":3,"file":"plugin.esm.js","sources":["../src/plugin.tsx"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\nimport {\n createFrontendModule,\n createFrontendPlugin,\n PageBlueprint,\n} from '@backstage/frontend-plugin-api';\nimport { NavContentBlueprint } from '@backstage/plugin-app-react';\nimport LayersIcon from '@material-ui/icons/Layers';\nimport { rootRouteRef } from './routes';\nimport { ApigeeNavContent } from './components/ApigeeNavContent';\n\nexport const apigeePage = PageBlueprint.make({\n params: {\n title: 'API Catalog',\n icon: <LayersIcon />,\n routeRef: rootRouteRef,\n path: '/apigee',\n loader: () =>\n import('./components/ApigeeApiCatalogPage').then(\n ({ ApigeeApiCatalogPage }) => <ApigeeApiCatalogPage />,\n ),\n },\n});\n\n/**\n * Frontend module that overrides the app nav bar to show an expandable\n * \"API Hub\" group containing all apigee plugin pages as sub-items.\n *\n * Add this to your app's `createApp({ features })` to activate the grouped nav.\n *\n * @example\n * ```ts\n * createApp({ features: [apigeePlugin, apigeeNavModule] });\n * ```\n */\nexport const apigeeNavModule = createFrontendModule({\n pluginId: 'app',\n extensions: [\n NavContentBlueprint.make({\n params: {\n component: ApigeeNavContent,\n },\n }),\n ],\n});\n\nexport const apigeePlugin = createFrontendPlugin({\n pluginId: 'apigee',\n title: 'API Hub',\n extensions: [apigeePage],\n routes: {\n root: rootRouteRef,\n },\n});\n"],"names":[],"mappings":";;;;;;;AAWO,MAAM,UAAA,GAAa,cAAc,IAAA,CAAK;AAAA,EAC3C,MAAA,EAAQ;AAAA,IACN,KAAA,EAAO,aAAA;AAAA,IACP,IAAA,sBAAO,UAAA,EAAA,EAAW,CAAA;AAAA,IAClB,QAAA,EAAU,YAAA;AAAA,IACV,IAAA,EAAM,SAAA;AAAA,IACN,MAAA,EAAQ,MACN,OAAO,0CAAmC,CAAA,CAAE,IAAA;AAAA,MAC1C,CAAC,EAAE,oBAAA,EAAqB,yBAAO,oBAAA,EAAA,EAAqB;AAAA;AACtD;AAEN,CAAC;AAaM,MAAM,kBAAkB,oBAAA,CAAqB;AAAA,EAClD,QAAA,EAAU,KAAA;AAAA,EACV,UAAA,EAAY;AAAA,IACV,oBAAoB,IAAA,CAAK;AAAA,MACvB,MAAA,EAAQ;AAAA,QACN,SAAA,EAAW;AAAA;AACb,KACD;AAAA;AAEL,CAAC;AAEM,MAAM,eAAe,oBAAA,CAAqB;AAAA,EAC/C,QAAA,EAAU,QAAA;AAAA,EACV,KAAA,EAAO,SAAA;AAAA,EACP,UAAA,EAAY,CAAC,UAAU,CAAA;AAAA,EACvB,MAAA,EAAQ;AAAA,IACN,IAAA,EAAM;AAAA;AAEV,CAAC;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nospt/backstage-plugin-apigee",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Backstage frontend plugin bootstrap for Apigee integration",
6
6
  "author": "NOS SGPS, S.A.",
@@ -53,7 +53,7 @@
53
53
  "@backstage/plugin-catalog-react": "^2.1.1",
54
54
  "@material-ui/core": "^4.9.13",
55
55
  "@material-ui/icons": "^4.9.1",
56
- "@nospt/backstage-plugin-apigee-common": "^0.1.1"
56
+ "@nospt/backstage-plugin-apigee-common": "^0.1.3"
57
57
  },
58
58
  "peerDependencies": {
59
59
  "react": "^16.13.1 || ^17.0.0 || ^18.0.0",