@backstage/plugin-catalog-react 0.6.9 → 0.6.12

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,63 @@
1
1
  # @backstage/plugin-catalog-react
2
2
 
3
+ ## 0.6.12
4
+
5
+ ### Patch Changes
6
+
7
+ - 3d87019269: The `entityRouteRef` is now a well-known route that should be imported directly from `@backstage/plugin-catalog-react`. It is guaranteed to be globally unique across duplicate installations of the `@backstage/plugin-catalog-react`, starting at this version.
8
+
9
+ Deprecated `entityRoute` in favor of `entityRouteRef`.
10
+
11
+ Deprecated `rootRoute` and `catalogRouteRef`. If you want to refer to the catalog index page from a public plugin you now need to use an `ExternalRouteRef` instead. For private plugins it is possible to take the shortcut of referring directly to `catalogPlugin.routes.indexPage` instead.
12
+
13
+ - 2916a83b9c: Deprecated `loadIdentityOwnerRefs`, since they can now be retrieved as `ownershipEntityRefs` from `identityApi.getBackstageIdentity()` instead.
14
+ - 51fbedc445: Migrated usage of deprecated `IdentityApi` methods.
15
+ - c54c0d9d10: Add useEntityPermission hook
16
+ - Updated dependencies
17
+ - @backstage/plugin-permission-react@0.3.0
18
+ - @backstage/core-components@0.8.5
19
+ - @backstage/integration@0.7.2
20
+ - @backstage/plugin-permission-common@0.4.0
21
+ - @backstage/core-plugin-api@0.6.0
22
+ - @backstage/catalog-model@0.9.10
23
+ - @backstage/catalog-client@0.5.5
24
+
25
+ ## 0.6.12-next.0
26
+
27
+ ### Patch Changes
28
+
29
+ - 2916a83b9c: Deprecated `loadIdentityOwnerRefs`, since they can now be retrieved as `ownershipEntityRefs` from `identityApi.getBackstageIdentity()` instead.
30
+ - 51fbedc445: Migrated usage of deprecated `IdentityApi` methods.
31
+ - Updated dependencies
32
+ - @backstage/core-components@0.8.5-next.0
33
+ - @backstage/core-plugin-api@0.6.0-next.0
34
+ - @backstage/catalog-model@0.9.10-next.0
35
+ - @backstage/catalog-client@0.5.5-next.0
36
+ - @backstage/integration@0.7.2-next.0
37
+
38
+ ## 0.6.11
39
+
40
+ ### Patch Changes
41
+
42
+ - 5333451def: Cleaned up API exports
43
+ - Updated dependencies
44
+ - @backstage/integration@0.7.1
45
+ - @backstage/core-components@0.8.4
46
+ - @backstage/core-plugin-api@0.5.0
47
+ - @backstage/errors@0.2.0
48
+ - @backstage/catalog-client@0.5.4
49
+ - @backstage/catalog-model@0.9.9
50
+
51
+ ## 0.6.10
52
+
53
+ ### Patch Changes
54
+
55
+ - fe2a6532ff: Add Override Components for Components in @backstage/plugin-catalog-react
56
+ - 4ce51ab0f1: Internal refactor of the `react-use` imports to use `react-use/lib/*` instead.
57
+ - Updated dependencies
58
+ - @backstage/core-plugin-api@0.4.1
59
+ - @backstage/core-components@0.8.3
60
+
3
61
  ## 0.6.9
4
62
 
5
63
  ### Patch Changes
package/dist/index.cjs.js CHANGED
@@ -11,12 +11,17 @@ var React = require('react');
11
11
  var lab = require('@material-ui/lab');
12
12
  var versionBridge = require('@backstage/version-bridge');
13
13
  var reactRouter = require('react-router');
14
- var reactUse = require('react-use');
14
+ var useAsyncRetry = require('react-use/lib/useAsyncRetry');
15
15
  var qs = require('qs');
16
+ var useAsyncFn = require('react-use/lib/useAsyncFn');
17
+ var useDebounce = require('react-use/lib/useDebounce');
18
+ var useMountedState = require('react-use/lib/useMountedState');
19
+ var useAsync = require('react-use/lib/useAsync');
16
20
  var isEqual = require('lodash/isEqual');
17
21
  var coreComponents = require('@backstage/core-components');
18
22
  var core = require('@material-ui/core');
19
- var jwtDecoder = require('jwt-decode');
23
+ var useObservable = require('react-use/lib/useObservable');
24
+ var pluginPermissionReact = require('@backstage/plugin-permission-react');
20
25
  var CheckBoxIcon = require('@material-ui/icons/CheckBox');
21
26
  var CheckBoxOutlineBlankIcon = require('@material-ui/icons/CheckBoxOutlineBlank');
22
27
  var ExpandMoreIcon = require('@material-ui/icons/ExpandMore');
@@ -33,9 +38,14 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
33
38
 
34
39
  var ObservableImpl__default = /*#__PURE__*/_interopDefaultLegacy(ObservableImpl);
35
40
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
41
+ var useAsyncRetry__default = /*#__PURE__*/_interopDefaultLegacy(useAsyncRetry);
36
42
  var qs__default = /*#__PURE__*/_interopDefaultLegacy(qs);
43
+ var useAsyncFn__default = /*#__PURE__*/_interopDefaultLegacy(useAsyncFn);
44
+ var useDebounce__default = /*#__PURE__*/_interopDefaultLegacy(useDebounce);
45
+ var useMountedState__default = /*#__PURE__*/_interopDefaultLegacy(useMountedState);
46
+ var useAsync__default = /*#__PURE__*/_interopDefaultLegacy(useAsync);
37
47
  var isEqual__default = /*#__PURE__*/_interopDefaultLegacy(isEqual);
38
- var jwtDecoder__default = /*#__PURE__*/_interopDefaultLegacy(jwtDecoder);
48
+ var useObservable__default = /*#__PURE__*/_interopDefaultLegacy(useObservable);
39
49
  var CheckBoxIcon__default = /*#__PURE__*/_interopDefaultLegacy(CheckBoxIcon);
40
50
  var CheckBoxOutlineBlankIcon__default = /*#__PURE__*/_interopDefaultLegacy(CheckBoxOutlineBlankIcon);
41
51
  var ExpandMoreIcon__default = /*#__PURE__*/_interopDefaultLegacy(ExpandMoreIcon);
@@ -118,11 +128,11 @@ const rootRoute = corePluginApi.createRouteRef({
118
128
  id: "catalog"
119
129
  });
120
130
  const catalogRouteRef = rootRoute;
121
- const entityRoute = corePluginApi.createRouteRef({
131
+ const entityRouteRef = versionBridge.getOrCreateGlobalSingleton("catalog:entity-route-ref", () => corePluginApi.createRouteRef({
122
132
  id: "catalog:entity",
123
133
  params: ["namespace", "kind", "name"]
124
- });
125
- const entityRouteRef = entityRoute;
134
+ }));
135
+ const entityRoute = entityRouteRef;
126
136
  function entityRouteParams(entity) {
127
137
  var _a, _b;
128
138
  return {
@@ -187,7 +197,7 @@ const useEntityFromUrl = () => {
187
197
  error,
188
198
  loading,
189
199
  retry: refresh
190
- } = reactUse.useAsyncRetry(() => catalogApi.getEntityByName({ kind, namespace, name }), [catalogApi, kind, namespace, name]);
200
+ } = useAsyncRetry__default["default"](() => catalogApi.getEntityByName({ kind, namespace, name }), [catalogApi, kind, namespace, name]);
191
201
  React.useEffect(() => {
192
202
  if (!name) {
193
203
  errorApi.post(new Error("No name provided!"));
@@ -281,7 +291,7 @@ const EntityListContext = React.createContext(void 0);
281
291
  const EntityListProvider = ({
282
292
  children
283
293
  }) => {
284
- const isMounted = reactUse.useMountedState();
294
+ const isMounted = useMountedState__default["default"]();
285
295
  const catalogApi = corePluginApi.useApi(catalogApiRef);
286
296
  const [requestedFilters, setRequestedFilters] = React.useState({});
287
297
  const [outputState, setOutputState] = React.useState(() => {
@@ -296,7 +306,7 @@ const EntityListProvider = ({
296
306
  queryParameters: (_a = query.filters) != null ? _a : {}
297
307
  };
298
308
  });
299
- const [{ loading, error }, refresh] = reactUse.useAsyncFn(async () => {
309
+ const [{ loading, error }, refresh] = useAsyncFn__default["default"](async () => {
300
310
  var _a;
301
311
  const compacted = lodash.compact(Object.values(requestedFilters));
302
312
  const entityFilter = reduceEntityFilters(compacted);
@@ -336,7 +346,7 @@ const EntityListProvider = ({
336
346
  (_a = window.history) == null ? void 0 : _a.replaceState(null, document.title, newUrl);
337
347
  }
338
348
  }, [catalogApi, requestedFilters, outputState], { loading: true });
339
- reactUse.useDebounce(refresh, 10, [requestedFilters]);
349
+ useDebounce__default["default"](refresh, 10, [requestedFilters]);
340
350
  const updateFilters = React.useCallback((update) => {
341
351
  setRequestedFilters((prevFilters) => {
342
352
  const newFilters = typeof update === "function" ? update(prevFilters) : update;
@@ -546,7 +556,7 @@ function useEntityTypeFilter() {
546
556
  error,
547
557
  loading,
548
558
  value: entities
549
- } = reactUse.useAsync(async () => {
559
+ } = useAsync__default["default"](async () => {
550
560
  if (kind) {
551
561
  const items = await catalogApi.getEntities({
552
562
  filter: { kind },
@@ -603,7 +613,7 @@ function useEntityKinds() {
603
613
  error,
604
614
  loading,
605
615
  value: kinds
606
- } = reactUse.useAsync(async () => {
616
+ } = useAsync__default["default"](async () => {
607
617
  const entities = await catalogApi.getEntities({ fields: ["kind"] }).then((response) => response.items);
608
618
  return [...new Set(entities.map((e) => e.kind))].sort();
609
619
  });
@@ -613,11 +623,13 @@ function useEntityKinds() {
613
623
  function useOwnUser() {
614
624
  const catalogApi = corePluginApi.useApi(catalogApiRef);
615
625
  const identityApi = corePluginApi.useApi(corePluginApi.identityApiRef);
616
- return reactUse.useAsync(() => catalogApi.getEntityByName({
617
- kind: "User",
618
- namespace: "default",
619
- name: identityApi.getUserId()
620
- }), [catalogApi, identityApi]);
626
+ return useAsync__default["default"](async () => {
627
+ const identity = await identityApi.getBackstageIdentity();
628
+ return catalogApi.getEntityByName(catalogModel.parseEntityRef(identity.userEntityRef, {
629
+ defaultKind: "User",
630
+ defaultNamespace: catalogModel.ENTITY_DEFAULT_NAMESPACE
631
+ }));
632
+ }, [catalogApi, identityApi]);
621
633
  }
622
634
 
623
635
  const BATCH_SIZE = 20;
@@ -627,7 +639,7 @@ function useRelatedEntities(entity, { type, kind }) {
627
639
  loading,
628
640
  value: entities,
629
641
  error
630
- } = reactUse.useAsync(async () => {
642
+ } = useAsync__default["default"](async () => {
631
643
  const relations = entity.relations && entity.relations.filter((r) => (!type || r.type.toLocaleLowerCase("en-US") === type.toLocaleLowerCase("en-US")) && (!kind || r.target.kind.toLocaleLowerCase("en-US") === kind.toLocaleLowerCase("en-US")));
632
644
  if (!relations) {
633
645
  return [];
@@ -668,7 +680,7 @@ function getEntityRef$1(entityOrRef) {
668
680
  }
669
681
  function useStarredEntities() {
670
682
  const starredEntitiesApi = corePluginApi.useApi(starredEntitiesApiRef);
671
- const starredEntities = reactUse.useObservable(starredEntitiesApi.starredEntitie$(), /* @__PURE__ */ new Set());
683
+ const starredEntities = useObservable__default["default"](starredEntitiesApi.starredEntitie$(), /* @__PURE__ */ new Set());
672
684
  const isStarredEntity = React.useCallback((entityOrRef) => starredEntities.has(getEntityRef$1(entityOrRef)), [starredEntities]);
673
685
  const toggleStarredEntity = React.useCallback((entityOrRef) => starredEntitiesApi.toggleStarred(getEntityRef$1(entityOrRef)).then(), [starredEntitiesApi]);
674
686
  return {
@@ -701,34 +713,9 @@ function useStarredEntity(entityOrRef) {
701
713
  };
702
714
  }
703
715
 
704
- function extendUserId(id) {
705
- try {
706
- const ref = catalogModel.parseEntityRef(id, {
707
- defaultKind: "User",
708
- defaultNamespace: "default"
709
- });
710
- return catalogModel.stringifyEntityRef(ref);
711
- } catch {
712
- return id;
713
- }
714
- }
715
716
  async function loadIdentityOwnerRefs(identityApi) {
716
- const id = identityApi.getUserId();
717
- const token = await identityApi.getIdToken();
718
- const result = [];
719
- if (id) {
720
- result.push(extendUserId(id));
721
- }
722
- if (token) {
723
- try {
724
- const decoded = jwtDecoder__default["default"](token);
725
- if (decoded == null ? void 0 : decoded.ent) {
726
- [decoded.ent].flat().filter((x) => typeof x === "string").map((x) => x.toLocaleLowerCase("en-US")).forEach((x) => result.push(x));
727
- }
728
- } catch {
729
- }
730
- }
731
- return result;
717
+ const identity = await identityApi.getBackstageIdentity();
718
+ return identity.ownershipEntityRefs;
732
719
  }
733
720
  async function loadCatalogOwnerRefs(catalogApi, identityOwnerRefs) {
734
721
  const result = new Array();
@@ -749,10 +736,10 @@ async function loadCatalogOwnerRefs(catalogApi, identityOwnerRefs) {
749
736
  function useEntityOwnership() {
750
737
  const identityApi = corePluginApi.useApi(corePluginApi.identityApiRef);
751
738
  const catalogApi = corePluginApi.useApi(catalogApiRef);
752
- const { loading, value: refs } = reactUse.useAsync(async () => {
753
- const identityRefs = await loadIdentityOwnerRefs(identityApi);
754
- const catalogRefs = await loadCatalogOwnerRefs(catalogApi, identityRefs);
755
- return /* @__PURE__ */ new Set([...identityRefs, ...catalogRefs]);
739
+ const { loading, value: refs } = useAsync__default["default"](async () => {
740
+ const { ownershipEntityRefs } = await identityApi.getBackstageIdentity();
741
+ const catalogRefs = await loadCatalogOwnerRefs(catalogApi, ownershipEntityRefs);
742
+ return /* @__PURE__ */ new Set([...ownershipEntityRefs, ...catalogRefs]);
756
743
  }, []);
757
744
  const isOwnedEntity = React.useMemo(() => {
758
745
  const myOwnerRefs = new Set(refs != null ? refs : []);
@@ -772,7 +759,7 @@ function useEntityOwnership() {
772
759
  function useOwnedEntities(allowedKinds) {
773
760
  const identityApi = corePluginApi.useApi(corePluginApi.identityApiRef);
774
761
  const catalogApi = corePluginApi.useApi(catalogApiRef);
775
- const { loading, value: refs } = reactUse.useAsync(async () => {
762
+ const { loading, value: refs } = useAsync__default["default"](async () => {
776
763
  const identityRefs = await loadIdentityOwnerRefs(identityApi);
777
764
  const catalogRefs = await loadCatalogOwnerRefs(catalogApi, identityRefs);
778
765
  const catalogs = await catalogApi.getEntities(allowedKinds ? {
@@ -793,6 +780,22 @@ function useOwnedEntities(allowedKinds) {
793
780
  return React.useMemo(() => ({ loading, ownedEntities }), [loading, ownedEntities]);
794
781
  }
795
782
 
783
+ function useEntityPermission(permission) {
784
+ const { entity, loading: loadingEntity, error: entityError } = useEntity();
785
+ const {
786
+ allowed,
787
+ loading: loadingPermission,
788
+ error: permissionError
789
+ } = pluginPermissionReact.usePermission(permission, entity ? catalogModel.stringifyEntityRef(entity) : void 0);
790
+ if (loadingEntity || loadingPermission) {
791
+ return { loading: true, allowed: false };
792
+ }
793
+ if (entityError) {
794
+ return { loading: false, allowed: false, error: entityError };
795
+ }
796
+ return { loading: false, allowed, error: permissionError };
797
+ }
798
+
796
799
  const EntityKindPicker = ({
797
800
  initialFilter,
798
801
  hidden
@@ -945,7 +948,7 @@ const EntitySearchBar = () => {
945
948
  const classes = useStyles$4();
946
949
  const { filters, updateFilters } = useEntityListProvider();
947
950
  const [search, setSearch] = React.useState((_b = (_a = filters.text) == null ? void 0 : _a.value) != null ? _b : "");
948
- reactUse.useDebounce(() => {
951
+ useDebounce__default["default"](() => {
949
952
  updateFilters({
950
953
  text: search.length ? new EntityTextFilter(search) : void 0
951
954
  });
@@ -1268,7 +1271,7 @@ function useUnregisterEntityDialogState(entity) {
1268
1271
  const locationRef = (_a = entity.metadata.annotations) == null ? void 0 : _a[catalogModel.ORIGIN_LOCATION_ANNOTATION];
1269
1272
  const uid = entity.metadata.uid;
1270
1273
  const isBootstrap = locationRef === "bootstrap:bootstrap";
1271
- const prerequisites = reactUse.useAsync(async () => {
1274
+ const prerequisites = useAsync__default["default"](async () => {
1272
1275
  const locationPromise = catalogApi.getOriginLocationByEntity(entity);
1273
1276
  let colocatedEntitiesPromise;
1274
1277
  if (!locationRef) {
@@ -1662,6 +1665,7 @@ exports.useEntityFromUrl = useEntityFromUrl;
1662
1665
  exports.useEntityKinds = useEntityKinds;
1663
1666
  exports.useEntityListProvider = useEntityListProvider;
1664
1667
  exports.useEntityOwnership = useEntityOwnership;
1668
+ exports.useEntityPermission = useEntityPermission;
1665
1669
  exports.useEntityTypeFilter = useEntityTypeFilter;
1666
1670
  exports.useOwnUser = useOwnUser;
1667
1671
  exports.useOwnedEntities = useOwnedEntities;