@backstage/frontend-app-api 0.5.0 → 0.6.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,46 @@
1
1
  # @backstage/frontend-app-api
2
2
 
3
+ ## 0.6.0-next.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 86346c2: **BREAKING**: The `app.routes.bindings` app-config mapping has been simplified. You now only need to specify the plugin ID and route ID on both sides of the mapping.
8
+
9
+ Old form:
10
+
11
+ ```yaml
12
+ app:
13
+ routes:
14
+ bindings:
15
+ plugin.catalog.externalRoutes.viewTechDoc: plugin.techdocs.routes.docRoot
16
+ plugin.catalog.externalRoutes.createComponent: plugin.catalog-import.routes.importPage
17
+ ```
18
+
19
+ New form:
20
+
21
+ ```yaml
22
+ app:
23
+ routes:
24
+ bindings:
25
+ catalog.viewTechDoc: techdocs.docRoot
26
+ catalog.createComponent: catalog-import.importPage
27
+ ```
28
+
29
+ ### Patch Changes
30
+
31
+ - 42ebf27: Added `IconsApi` implementation and the ability to configure icons through the `icons` option for `createApp` and `createSpecializedApp`. This is not a long-term solution as icons should be installable via extensions instead. This is just a stop-gap to make sure there is feature parity with the existing frontend system.
32
+ - e0a4dd1: Improved the error message when data input/output shapes do not match
33
+ - Updated dependencies
34
+ - @backstage/frontend-plugin-api@0.5.1-next.0
35
+ - @backstage/core-components@0.13.10
36
+ - @backstage/config@1.1.1
37
+ - @backstage/core-app-api@1.11.3
38
+ - @backstage/core-plugin-api@1.8.2
39
+ - @backstage/errors@1.2.3
40
+ - @backstage/theme@0.5.0
41
+ - @backstage/types@1.1.1
42
+ - @backstage/version-bridge@1.0.7
43
+
3
44
  ## 0.5.0
4
45
 
5
46
  ### Minor Changes
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ExternalRouteRef, RouteRef, SubRouteRef, ExtensionDataRef, FrontendFeature } from '@backstage/frontend-plugin-api';
2
2
  import { JSX } from 'react';
3
3
  import { Config } from '@backstage/config';
4
- import { ConfigApi } from '@backstage/core-plugin-api';
4
+ import { ConfigApi, IconComponent } from '@backstage/core-plugin-api';
5
5
 
6
6
  /**
7
7
  * Extracts a union of the keys in a map whose value extends the given type
@@ -78,6 +78,9 @@ interface CreateAppFeatureLoader {
78
78
  }
79
79
  /** @public */
80
80
  declare function createApp(options?: {
81
+ icons?: {
82
+ [key in string]: IconComponent;
83
+ };
81
84
  features?: (FrontendFeature | CreateAppFeatureLoader)[];
82
85
  configLoader?: () => Promise<{
83
86
  config: ConfigApi;
@@ -95,6 +98,9 @@ declare function createApp(options?: {
95
98
  * @public
96
99
  */
97
100
  declare function createSpecializedApp(options?: {
101
+ icons?: {
102
+ [key in string]: IconComponent;
103
+ };
98
104
  features?: FrontendFeature[];
99
105
  config?: ConfigApi;
100
106
  bindRoutes?(context: {
package/dist/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import React, { useMemo, useState, useEffect, createContext, Fragment, useContext } from 'react';
2
2
  import { ConfigReader } from '@backstage/config';
3
- import { createExtension, createExtensionInput, createApiExtension, createThemeExtension, createComponentExtension, createTranslationExtension, coreExtensionData, useComponentRef, coreComponentRefs, createNavItemExtension, createNavLogoExtension, useRouteRef, createAppRootElementExtension, createSchemaFromZod, AnalyticsContext, useAnalytics, createRouterExtension, createSignInPageExtension, createAppRootWrapperExtension, appTreeApiRef, componentsApiRef } from '@backstage/frontend-plugin-api';
3
+ import { createExtension, createExtensionInput, createApiExtension, createThemeExtension, createComponentExtension, createTranslationExtension, coreExtensionData, useComponentRef, coreComponentRefs, createNavItemExtension, createNavLogoExtension, useRouteRef, createAppRootElementExtension, createSchemaFromZod, AnalyticsContext, useAnalytics, createRouterExtension, createSignInPageExtension, createAppRootWrapperExtension, appTreeApiRef, componentsApiRef, iconsApiRef } from '@backstage/frontend-plugin-api';
4
4
  import { useRoutes, BrowserRouter, useInRouterContext, MemoryRouter, matchRoutes, generatePath, useLocation, Route } from 'react-router-dom';
5
5
  import { SidebarPage, sidebarConfig, Sidebar, SidebarDivider, useSidebarOpenState, Link, SidebarItem, Progress, ErrorPage, ErrorPanel, OAuthRequestDialog, AlertDisplay } from '@backstage/core-components';
6
6
  import { makeStyles, Button as Button$1 } from '@material-ui/core';
@@ -11,27 +11,27 @@ import ObservableImpl from 'zen-observable';
11
11
  import { createInstance } from 'i18next';
12
12
  import { permissionApiRef, IdentityPermissionApi } from '@backstage/plugin-permission-react';
13
13
  import Button from '@material-ui/core/Button';
14
- import '@material-ui/icons/Apartment';
15
- import '@material-ui/icons/BrokenImage';
16
- import '@material-ui/icons/Category';
17
- import '@material-ui/icons/CreateNewFolder';
18
- import '@material-ui/icons/Subject';
19
- import '@material-ui/icons/Search';
20
- import '@material-ui/icons/Chat';
21
- import '@material-ui/icons/Dashboard';
22
- import '@material-ui/icons/Description';
23
- import '@material-ui/icons/Email';
24
- import '@material-ui/icons/Extension';
25
- import '@material-ui/icons/GitHub';
26
- import '@material-ui/icons/Help';
27
- import '@material-ui/icons/LocationOn';
28
- import '@material-ui/icons/Memory';
29
- import '@material-ui/icons/MenuBook';
30
- import '@material-ui/icons/People';
31
- import '@material-ui/icons/Person';
32
- import '@material-ui/icons/Warning';
33
- import '@material-ui/icons/Work';
34
- import '@material-ui/icons/FeaturedPlayList';
14
+ import MuiApartmentIcon from '@material-ui/icons/Apartment';
15
+ import MuiBrokenImageIcon from '@material-ui/icons/BrokenImage';
16
+ import MuiCategoryIcon from '@material-ui/icons/Category';
17
+ import MuiCreateNewFolderIcon from '@material-ui/icons/CreateNewFolder';
18
+ import MuiSubjectIcon from '@material-ui/icons/Subject';
19
+ import MuiSearchIcon from '@material-ui/icons/Search';
20
+ import MuiChatIcon from '@material-ui/icons/Chat';
21
+ import MuiDashboardIcon from '@material-ui/icons/Dashboard';
22
+ import MuiDocsIcon from '@material-ui/icons/Description';
23
+ import MuiEmailIcon from '@material-ui/icons/Email';
24
+ import MuiExtensionIcon from '@material-ui/icons/Extension';
25
+ import MuiGitHubIcon from '@material-ui/icons/GitHub';
26
+ import MuiHelpIcon from '@material-ui/icons/Help';
27
+ import MuiLocationOnIcon from '@material-ui/icons/LocationOn';
28
+ import MuiMemoryIcon from '@material-ui/icons/Memory';
29
+ import MuiMenuBookIcon from '@material-ui/icons/MenuBook';
30
+ import MuiPeopleIcon from '@material-ui/icons/People';
31
+ import MuiPersonIcon from '@material-ui/icons/Person';
32
+ import MuiWarningIcon from '@material-ui/icons/Warning';
33
+ import MuiStorageIcon from '@material-ui/icons/Storage';
34
+ import MuiFeaturedPlayListIcon from '@material-ui/icons/FeaturedPlayList';
35
35
  import { UnifiedThemeProvider, themes } from '@backstage/theme';
36
36
  import DarkIcon from '@material-ui/icons/Brightness2';
37
37
  import LightIcon from '@material-ui/icons/WbSunny';
@@ -668,21 +668,21 @@ class BehaviorSubject {
668
668
  }
669
669
  }
670
670
 
671
- var __accessCheck$2 = (obj, member, msg) => {
671
+ var __accessCheck$3 = (obj, member, msg) => {
672
672
  if (!member.has(obj))
673
673
  throw TypeError("Cannot " + msg);
674
674
  };
675
- var __privateGet$2 = (obj, member, getter) => {
676
- __accessCheck$2(obj, member, "read from private field");
675
+ var __privateGet$3 = (obj, member, getter) => {
676
+ __accessCheck$3(obj, member, "read from private field");
677
677
  return getter ? getter.call(obj) : member.get(obj);
678
678
  };
679
- var __privateAdd$2 = (obj, member, value) => {
679
+ var __privateAdd$3 = (obj, member, value) => {
680
680
  if (member.has(obj))
681
681
  throw TypeError("Cannot add the same private member more than once");
682
682
  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
683
683
  };
684
- var __privateSet$2 = (obj, member, value, setter) => {
685
- __accessCheck$2(obj, member, "write to private field");
684
+ var __privateSet$3 = (obj, member, value, setter) => {
685
+ __accessCheck$3(obj, member, "write to private field");
686
686
  setter ? setter.call(obj, value) : member.set(obj, value);
687
687
  return value;
688
688
  };
@@ -691,13 +691,13 @@ const STORAGE_KEY = "language";
691
691
  const DEFAULT_LANGUAGE = "en";
692
692
  const _AppLanguageSelector = class _AppLanguageSelector {
693
693
  constructor(languages, initialLanguage) {
694
- __privateAdd$2(this, _languages, void 0);
695
- __privateAdd$2(this, _language$1, void 0);
696
- __privateAdd$2(this, _subject, void 0);
697
- __privateSet$2(this, _languages, languages);
698
- __privateSet$2(this, _language$1, initialLanguage);
699
- __privateSet$2(this, _subject, new BehaviorSubject({
700
- language: __privateGet$2(this, _language$1)
694
+ __privateAdd$3(this, _languages, void 0);
695
+ __privateAdd$3(this, _language$1, void 0);
696
+ __privateAdd$3(this, _subject, void 0);
697
+ __privateSet$3(this, _languages, languages);
698
+ __privateSet$3(this, _language$1, initialLanguage);
699
+ __privateSet$3(this, _subject, new BehaviorSubject({
700
+ language: __privateGet$3(this, _language$1)
701
701
  }));
702
702
  }
703
703
  static create(options) {
@@ -748,28 +748,28 @@ const _AppLanguageSelector = class _AppLanguageSelector {
748
748
  return selector;
749
749
  }
750
750
  getAvailableLanguages() {
751
- return { languages: __privateGet$2(this, _languages).slice() };
751
+ return { languages: __privateGet$3(this, _languages).slice() };
752
752
  }
753
753
  setLanguage(language) {
754
754
  const lng = language != null ? language : DEFAULT_LANGUAGE;
755
- if (lng === __privateGet$2(this, _language$1)) {
755
+ if (lng === __privateGet$3(this, _language$1)) {
756
756
  return;
757
757
  }
758
- if (lng && !__privateGet$2(this, _languages).includes(lng)) {
758
+ if (lng && !__privateGet$3(this, _languages).includes(lng)) {
759
759
  throw new Error(
760
- `Failed to change language to '${lng}', available languages are '${__privateGet$2(this, _languages).join(
760
+ `Failed to change language to '${lng}', available languages are '${__privateGet$3(this, _languages).join(
761
761
  "', '"
762
762
  )}'`
763
763
  );
764
764
  }
765
- __privateSet$2(this, _language$1, lng);
766
- __privateGet$2(this, _subject).next({ language: lng });
765
+ __privateSet$3(this, _language$1, lng);
766
+ __privateGet$3(this, _subject).next({ language: lng });
767
767
  }
768
768
  getLanguage() {
769
- return { language: __privateGet$2(this, _language$1) };
769
+ return { language: __privateGet$3(this, _language$1) };
770
770
  }
771
771
  language$() {
772
- return __privateGet$2(this, _subject);
772
+ return __privateGet$3(this, _subject);
773
773
  }
774
774
  };
775
775
  _languages = new WeakMap();
@@ -799,26 +799,26 @@ function toInternalTranslationRef(ref) {
799
799
  return r;
800
800
  }
801
801
 
802
- var __accessCheck$1 = (obj, member, msg) => {
802
+ var __accessCheck$2 = (obj, member, msg) => {
803
803
  if (!member.has(obj))
804
804
  throw TypeError("Cannot " + msg);
805
805
  };
806
- var __privateGet$1 = (obj, member, getter) => {
807
- __accessCheck$1(obj, member, "read from private field");
806
+ var __privateGet$2 = (obj, member, getter) => {
807
+ __accessCheck$2(obj, member, "read from private field");
808
808
  return getter ? getter.call(obj) : member.get(obj);
809
809
  };
810
- var __privateAdd$1 = (obj, member, value) => {
810
+ var __privateAdd$2 = (obj, member, value) => {
811
811
  if (member.has(obj))
812
812
  throw TypeError("Cannot add the same private member more than once");
813
813
  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
814
814
  };
815
- var __privateSet$1 = (obj, member, value, setter) => {
816
- __accessCheck$1(obj, member, "write to private field");
815
+ var __privateSet$2 = (obj, member, value, setter) => {
816
+ __accessCheck$2(obj, member, "write to private field");
817
817
  setter ? setter.call(obj, value) : member.set(obj, value);
818
818
  return value;
819
819
  };
820
820
  var __privateMethod = (obj, member, method) => {
821
- __accessCheck$1(obj, member, "access private method");
821
+ __accessCheck$2(obj, member, "access private method");
822
822
  return method;
823
823
  };
824
824
  var _loaded, _loading, _loaders, _getLoaderKey, getLoaderKey_fn, _i18n, _loader, _language, _registeredRefs, _languageChangeListeners, _changeLanguage, changeLanguage_fn, _createSnapshot, createSnapshot_fn, _registerDefaults, registerDefaults_fn;
@@ -832,41 +832,41 @@ function removeNulls(messages) {
832
832
  class ResourceLoader {
833
833
  constructor(onLoad) {
834
834
  this.onLoad = onLoad;
835
- __privateAdd$1(this, _getLoaderKey);
835
+ __privateAdd$2(this, _getLoaderKey);
836
836
  /** Loaded resources by loader key */
837
- __privateAdd$1(this, _loaded, /* @__PURE__ */ new Set());
837
+ __privateAdd$2(this, _loaded, /* @__PURE__ */ new Set());
838
838
  /** Resource loading promises by loader key */
839
- __privateAdd$1(this, _loading, /* @__PURE__ */ new Map());
839
+ __privateAdd$2(this, _loading, /* @__PURE__ */ new Map());
840
840
  /** Loaders for each resource language */
841
- __privateAdd$1(this, _loaders, /* @__PURE__ */ new Map());
841
+ __privateAdd$2(this, _loaders, /* @__PURE__ */ new Map());
842
842
  }
843
843
  addTranslationResource(resource) {
844
844
  const internalResource = toInternalTranslationResource(resource);
845
845
  for (const entry of internalResource.resources) {
846
846
  const key = __privateMethod(this, _getLoaderKey, getLoaderKey_fn).call(this, entry.language, internalResource.id);
847
- if (!__privateGet$1(this, _loaders).has(key)) {
848
- __privateGet$1(this, _loaders).set(key, entry.loader);
847
+ if (!__privateGet$2(this, _loaders).has(key)) {
848
+ __privateGet$2(this, _loaders).set(key, entry.loader);
849
849
  }
850
850
  }
851
851
  }
852
852
  needsLoading(language, namespace) {
853
853
  const key = __privateMethod(this, _getLoaderKey, getLoaderKey_fn).call(this, language, namespace);
854
- const loader = __privateGet$1(this, _loaders).get(key);
854
+ const loader = __privateGet$2(this, _loaders).get(key);
855
855
  if (!loader) {
856
856
  return false;
857
857
  }
858
- return !__privateGet$1(this, _loaded).has(key);
858
+ return !__privateGet$2(this, _loaded).has(key);
859
859
  }
860
860
  async load(language, namespace) {
861
861
  const key = __privateMethod(this, _getLoaderKey, getLoaderKey_fn).call(this, language, namespace);
862
- const loader = __privateGet$1(this, _loaders).get(key);
862
+ const loader = __privateGet$2(this, _loaders).get(key);
863
863
  if (!loader) {
864
864
  return;
865
865
  }
866
- if (__privateGet$1(this, _loaded).has(key)) {
866
+ if (__privateGet$2(this, _loaded).has(key)) {
867
867
  return;
868
868
  }
869
- const loading = __privateGet$1(this, _loading).get(key);
869
+ const loading = __privateGet$2(this, _loading).get(key);
870
870
  if (loading) {
871
871
  await loading;
872
872
  return;
@@ -874,14 +874,14 @@ class ResourceLoader {
874
874
  const load = loader().then(
875
875
  (result) => {
876
876
  this.onLoad({ language, namespace, messages: result.messages });
877
- __privateGet$1(this, _loaded).add(key);
877
+ __privateGet$2(this, _loaded).add(key);
878
878
  },
879
879
  (error) => {
880
- __privateGet$1(this, _loaded).add(key);
880
+ __privateGet$2(this, _loaded).add(key);
881
881
  throw error;
882
882
  }
883
883
  );
884
- __privateGet$1(this, _loading).set(key, load);
884
+ __privateGet$2(this, _loading).set(key, load);
885
885
  await load;
886
886
  }
887
887
  }
@@ -894,19 +894,19 @@ getLoaderKey_fn = function(language, namespace) {
894
894
  };
895
895
  const _I18nextTranslationApi = class _I18nextTranslationApi {
896
896
  constructor(i18n, loader, language) {
897
- __privateAdd$1(this, _changeLanguage);
898
- __privateAdd$1(this, _createSnapshot);
899
- __privateAdd$1(this, _registerDefaults);
900
- __privateAdd$1(this, _i18n, void 0);
901
- __privateAdd$1(this, _loader, void 0);
902
- __privateAdd$1(this, _language, void 0);
897
+ __privateAdd$2(this, _changeLanguage);
898
+ __privateAdd$2(this, _createSnapshot);
899
+ __privateAdd$2(this, _registerDefaults);
900
+ __privateAdd$2(this, _i18n, void 0);
901
+ __privateAdd$2(this, _loader, void 0);
902
+ __privateAdd$2(this, _language, void 0);
903
903
  /** Keep track of which refs we have registered default resources for */
904
- __privateAdd$1(this, _registeredRefs, /* @__PURE__ */ new Set());
904
+ __privateAdd$2(this, _registeredRefs, /* @__PURE__ */ new Set());
905
905
  /** Notify observers when language changes */
906
- __privateAdd$1(this, _languageChangeListeners, /* @__PURE__ */ new Set());
907
- __privateSet$1(this, _i18n, i18n);
908
- __privateSet$1(this, _loader, loader);
909
- __privateSet$1(this, _language, language);
906
+ __privateAdd$2(this, _languageChangeListeners, /* @__PURE__ */ new Set());
907
+ __privateSet$2(this, _i18n, i18n);
908
+ __privateSet$2(this, _loader, loader);
909
+ __privateSet$2(this, _language, language);
910
910
  }
911
911
  static create(options) {
912
912
  const { languages } = options.languageApi.getAvailableLanguages();
@@ -982,7 +982,7 @@ const _I18nextTranslationApi = class _I18nextTranslationApi {
982
982
  const loadResource = () => {
983
983
  loadTicket = {};
984
984
  const ticket = loadTicket;
985
- __privateGet$1(this, _loader).load(__privateGet$1(this, _language), internalRef.id).then(
985
+ __privateGet$2(this, _loader).load(__privateGet$2(this, _language), internalRef.id).then(
986
986
  () => {
987
987
  if (ticket === loadTicket) {
988
988
  const snapshot = __privateMethod(this, _createSnapshot, createSnapshot_fn).call(this, internalRef);
@@ -1006,12 +1006,12 @@ const _I18nextTranslationApi = class _I18nextTranslationApi {
1006
1006
  loadResource();
1007
1007
  }
1008
1008
  };
1009
- if (__privateGet$1(this, _loader).needsLoading(__privateGet$1(this, _language), internalRef.id)) {
1009
+ if (__privateGet$2(this, _loader).needsLoading(__privateGet$2(this, _language), internalRef.id)) {
1010
1010
  loadResource();
1011
1011
  }
1012
- __privateGet$1(this, _languageChangeListeners).add(onChange);
1012
+ __privateGet$2(this, _languageChangeListeners).add(onChange);
1013
1013
  return () => {
1014
- __privateGet$1(this, _languageChangeListeners).delete(onChange);
1014
+ __privateGet$2(this, _languageChangeListeners).delete(onChange);
1015
1015
  };
1016
1016
  });
1017
1017
  }
@@ -1023,18 +1023,18 @@ _registeredRefs = new WeakMap();
1023
1023
  _languageChangeListeners = new WeakMap();
1024
1024
  _changeLanguage = new WeakSet();
1025
1025
  changeLanguage_fn = function(language) {
1026
- if (__privateGet$1(this, _language) !== language) {
1027
- __privateSet$1(this, _language, language);
1028
- __privateGet$1(this, _i18n).changeLanguage(language);
1029
- __privateGet$1(this, _languageChangeListeners).forEach((listener) => listener());
1026
+ if (__privateGet$2(this, _language) !== language) {
1027
+ __privateSet$2(this, _language, language);
1028
+ __privateGet$2(this, _i18n).changeLanguage(language);
1029
+ __privateGet$2(this, _languageChangeListeners).forEach((listener) => listener());
1030
1030
  }
1031
1031
  };
1032
1032
  _createSnapshot = new WeakSet();
1033
1033
  createSnapshot_fn = function(internalRef) {
1034
- if (__privateGet$1(this, _loader).needsLoading(__privateGet$1(this, _language), internalRef.id)) {
1034
+ if (__privateGet$2(this, _loader).needsLoading(__privateGet$2(this, _language), internalRef.id)) {
1035
1035
  return { ready: false };
1036
1036
  }
1037
- const t = __privateGet$1(this, _i18n).getFixedT(
1037
+ const t = __privateGet$2(this, _i18n).getFixedT(
1038
1038
  null,
1039
1039
  internalRef.id
1040
1040
  );
@@ -1045,12 +1045,12 @@ createSnapshot_fn = function(internalRef) {
1045
1045
  };
1046
1046
  _registerDefaults = new WeakSet();
1047
1047
  registerDefaults_fn = function(internalRef) {
1048
- if (__privateGet$1(this, _registeredRefs).has(internalRef.id)) {
1048
+ if (__privateGet$2(this, _registeredRefs).has(internalRef.id)) {
1049
1049
  return;
1050
1050
  }
1051
- __privateGet$1(this, _registeredRefs).add(internalRef.id);
1051
+ __privateGet$2(this, _registeredRefs).add(internalRef.id);
1052
1052
  const defaultMessages = internalRef.getDefaultMessages();
1053
- __privateGet$1(this, _i18n).addResourceBundle(
1053
+ __privateGet$2(this, _i18n).addResourceBundle(
1054
1054
  DEFAULT_LANGUAGE,
1055
1055
  internalRef.id,
1056
1056
  defaultMessages,
@@ -1061,7 +1061,7 @@ registerDefaults_fn = function(internalRef) {
1061
1061
  );
1062
1062
  const defaultResource = internalRef.getDefaultResource();
1063
1063
  if (defaultResource) {
1064
- __privateGet$1(this, _loader).addTranslationResource(defaultResource);
1064
+ __privateGet$2(this, _loader).addTranslationResource(defaultResource);
1065
1065
  }
1066
1066
  };
1067
1067
  let I18nextTranslationApi = _I18nextTranslationApi;
@@ -1356,6 +1356,33 @@ const components = {
1356
1356
  ErrorBoundaryFallback: DefaultErrorBoundaryFallback
1357
1357
  };
1358
1358
 
1359
+ const icons = {
1360
+ brokenImage: MuiBrokenImageIcon,
1361
+ // To be confirmed: see https://github.com/backstage/backstage/issues/4970
1362
+ catalog: MuiMenuBookIcon,
1363
+ scaffolder: MuiCreateNewFolderIcon,
1364
+ techdocs: MuiSubjectIcon,
1365
+ search: MuiSearchIcon,
1366
+ chat: MuiChatIcon,
1367
+ dashboard: MuiDashboardIcon,
1368
+ docs: MuiDocsIcon,
1369
+ email: MuiEmailIcon,
1370
+ github: MuiGitHubIcon,
1371
+ group: MuiPeopleIcon,
1372
+ help: MuiHelpIcon,
1373
+ "kind:api": MuiExtensionIcon,
1374
+ "kind:component": MuiMemoryIcon,
1375
+ "kind:domain": MuiApartmentIcon,
1376
+ "kind:group": MuiPeopleIcon,
1377
+ "kind:location": MuiLocationOnIcon,
1378
+ "kind:system": MuiCategoryIcon,
1379
+ "kind:user": MuiPersonIcon,
1380
+ "kind:resource": MuiStorageIcon,
1381
+ "kind:template": MuiFeaturedPlayListIcon,
1382
+ user: MuiPersonIcon,
1383
+ warning: MuiWarningIcon
1384
+ };
1385
+
1359
1386
  const LightTheme = createThemeExtension({
1360
1387
  id: "light",
1361
1388
  title: "Light Theme",
@@ -1751,7 +1778,7 @@ function collectRouteIds(features) {
1751
1778
  continue;
1752
1779
  }
1753
1780
  for (const [name, ref] of Object.entries(feature.routes)) {
1754
- const refId = `plugin.${feature.id}.routes.${name}`;
1781
+ const refId = `${feature.id}.${name}`;
1755
1782
  if (routesById.has(refId)) {
1756
1783
  throw new Error(`Unexpected duplicate route '${refId}'`);
1757
1784
  }
@@ -1765,7 +1792,7 @@ function collectRouteIds(features) {
1765
1792
  }
1766
1793
  }
1767
1794
  for (const [name, ref] of Object.entries(feature.externalRoutes)) {
1768
- const refId = `plugin.${feature.id}.externalRoutes.${name}`;
1795
+ const refId = `${feature.id}.${name}`;
1769
1796
  if (externalRoutesById.has(refId)) {
1770
1797
  throw new Error(`Unexpected duplicate external route '${refId}'`);
1771
1798
  }
@@ -2163,11 +2190,13 @@ function resolveAppNodeSpecs(options) {
2163
2190
 
2164
2191
  function resolveInputData(dataMap, attachment, inputName) {
2165
2192
  return mapValues(dataMap, (ref) => {
2166
- var _a;
2193
+ var _a, _b, _c;
2167
2194
  const value = (_a = attachment.instance) == null ? void 0 : _a.getData(ref);
2168
2195
  if (value === void 0 && !ref.config.optional) {
2196
+ const expected = Object.values(dataMap).filter((r) => !r.config.optional).map((r) => `'${r.id}'`).join(", ");
2197
+ const provided = [...(_c = (_b = attachment.instance) == null ? void 0 : _b.getDataRefs()) != null ? _c : []].map((r) => `'${r.id}'`).join(", ");
2169
2198
  throw new Error(
2170
- `input '${inputName}' did not receive required extension data '${ref.id}' from extension '${attachment.spec.id}'`
2199
+ `extension '${attachment.spec.id}' could not be attached because its output data (${provided}) does not match what the input '${inputName}' requires (${expected})`
2171
2200
  );
2172
2201
  }
2173
2202
  return value;
@@ -2527,32 +2556,32 @@ function AppRouter(props) {
2527
2556
  ));
2528
2557
  }
2529
2558
 
2530
- var __accessCheck = (obj, member, msg) => {
2559
+ var __accessCheck$1 = (obj, member, msg) => {
2531
2560
  if (!member.has(obj))
2532
2561
  throw TypeError("Cannot " + msg);
2533
2562
  };
2534
- var __privateGet = (obj, member, getter) => {
2535
- __accessCheck(obj, member, "read from private field");
2563
+ var __privateGet$1 = (obj, member, getter) => {
2564
+ __accessCheck$1(obj, member, "read from private field");
2536
2565
  return getter ? getter.call(obj) : member.get(obj);
2537
2566
  };
2538
- var __privateAdd = (obj, member, value) => {
2567
+ var __privateAdd$1 = (obj, member, value) => {
2539
2568
  if (member.has(obj))
2540
2569
  throw TypeError("Cannot add the same private member more than once");
2541
2570
  member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
2542
2571
  };
2543
- var __privateSet = (obj, member, value, setter) => {
2544
- __accessCheck(obj, member, "write to private field");
2572
+ var __privateSet$1 = (obj, member, value, setter) => {
2573
+ __accessCheck$1(obj, member, "write to private field");
2545
2574
  setter ? setter.call(obj, value) : member.set(obj, value);
2546
2575
  return value;
2547
2576
  };
2548
2577
  var _components;
2549
2578
  class DefaultComponentsApi {
2550
2579
  constructor(components) {
2551
- __privateAdd(this, _components, void 0);
2552
- __privateSet(this, _components, components);
2580
+ __privateAdd$1(this, _components, void 0);
2581
+ __privateSet$1(this, _components, components);
2553
2582
  }
2554
2583
  getComponent(ref) {
2555
- const impl = __privateGet(this, _components).get(ref);
2584
+ const impl = __privateGet$1(this, _components).get(ref);
2556
2585
  if (!impl) {
2557
2586
  throw new Error(`No implementation found for component ref ${ref}`);
2558
2587
  }
@@ -2561,6 +2590,39 @@ class DefaultComponentsApi {
2561
2590
  }
2562
2591
  _components = new WeakMap();
2563
2592
 
2593
+ var __accessCheck = (obj, member, msg) => {
2594
+ if (!member.has(obj))
2595
+ throw TypeError("Cannot " + msg);
2596
+ };
2597
+ var __privateGet = (obj, member, getter) => {
2598
+ __accessCheck(obj, member, "read from private field");
2599
+ return getter ? getter.call(obj) : member.get(obj);
2600
+ };
2601
+ var __privateAdd = (obj, member, value) => {
2602
+ if (member.has(obj))
2603
+ throw TypeError("Cannot add the same private member more than once");
2604
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
2605
+ };
2606
+ var __privateSet = (obj, member, value, setter) => {
2607
+ __accessCheck(obj, member, "write to private field");
2608
+ setter ? setter.call(obj, value) : member.set(obj, value);
2609
+ return value;
2610
+ };
2611
+ var _icons;
2612
+ class DefaultIconsApi {
2613
+ constructor(icons) {
2614
+ __privateAdd(this, _icons, void 0);
2615
+ __privateSet(this, _icons, new Map(Object.entries(icons)));
2616
+ }
2617
+ getIcon(key) {
2618
+ return __privateGet(this, _icons).get(key);
2619
+ }
2620
+ listIconKeys() {
2621
+ return Array.from(__privateGet(this, _icons).keys());
2622
+ }
2623
+ }
2624
+ _icons = new WeakMap();
2625
+
2564
2626
  const DefaultApis = apis.map((factory) => createApiExtension({ factory }));
2565
2627
  const builtinExtensions = [
2566
2628
  App,
@@ -2678,6 +2740,7 @@ function createApp(options) {
2678
2740
  }
2679
2741
  }
2680
2742
  const app = createSpecializedApp({
2743
+ icons: options == null ? void 0 : options.icons,
2681
2744
  config,
2682
2745
  features: [...discoveredFeatures, ...providedFeatures],
2683
2746
  bindRoutes: options == null ? void 0 : options.bindRoutes
@@ -2703,7 +2766,12 @@ function createSpecializedApp(options) {
2703
2766
  config
2704
2767
  });
2705
2768
  const appIdentityProxy = new AppIdentityProxy();
2706
- const apiHolder = createApiHolder(tree, config, appIdentityProxy);
2769
+ const apiHolder = createApiHolder(
2770
+ tree,
2771
+ config,
2772
+ appIdentityProxy,
2773
+ options == null ? void 0 : options.icons
2774
+ );
2707
2775
  const featureFlagApi = apiHolder.get(featureFlagsApiRef);
2708
2776
  if (featureFlagApi) {
2709
2777
  for (const feature of features) {
@@ -2742,7 +2810,7 @@ function createSpecializedApp(options) {
2742
2810
  }
2743
2811
  };
2744
2812
  }
2745
- function createApiHolder(tree, configApi, appIdentityProxy) {
2813
+ function createApiHolder(tree, configApi, appIdentityProxy, icons$1) {
2746
2814
  var _a, _b, _c, _d, _e, _f, _g, _h;
2747
2815
  const factoryRegistry = new ApiFactoryRegistry();
2748
2816
  const pluginApis = (_b = (_a = tree.root.edges.attachments.get("apis")) == null ? void 0 : _a.map((e) => {
@@ -2794,6 +2862,11 @@ function createApiHolder(tree, configApi, appIdentityProxy) {
2794
2862
  deps: {},
2795
2863
  factory: () => new DefaultComponentsApi(componentsMap)
2796
2864
  });
2865
+ factoryRegistry.register("static", {
2866
+ api: iconsApiRef,
2867
+ deps: {},
2868
+ factory: () => new DefaultIconsApi({ ...icons, ...icons$1 })
2869
+ });
2797
2870
  factoryRegistry.register("static", {
2798
2871
  api: appThemeApiRef,
2799
2872
  deps: {},