@backstage/plugin-catalog-react 1.9.2-next.0 → 1.9.2-next.2

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,52 @@
1
1
  # @backstage/plugin-catalog-react
2
2
 
3
+ ## 1.9.2-next.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 8f5d6c1: Updates to the `/alpha` exports to match the extension input wrapping change.
8
+ - 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed.
9
+ - Updated dependencies
10
+ - @backstage/frontend-plugin-api@0.4.0-next.2
11
+ - @backstage/theme@0.5.0-next.1
12
+ - @backstage/catalog-client@1.5.0-next.1
13
+ - @backstage/catalog-model@1.4.3
14
+ - @backstage/core-components@0.13.9-next.2
15
+ - @backstage/core-plugin-api@1.8.1-next.1
16
+ - @backstage/errors@1.2.3
17
+ - @backstage/integration-react@1.1.22-next.1
18
+ - @backstage/types@1.1.1
19
+ - @backstage/version-bridge@1.0.7
20
+ - @backstage/plugin-catalog-common@1.0.18
21
+ - @backstage/plugin-permission-common@0.7.10
22
+ - @backstage/plugin-permission-react@0.4.18-next.1
23
+
24
+ ## 1.9.2-next.1
25
+
26
+ ### Patch Changes
27
+
28
+ - 53600976bb: Ensure that passed-in icons are taken advantage of in the presentation API
29
+ - 08d9e67199: Add default icon for kind resource.
30
+ - a5a04739e1: Internal refactor of alpha exports due to a change in how extension factories are defined.
31
+ - e223f2264d: Breaking alpha-API change to entity visibility filter functions to accept a bare entity as their first argument, instead of an object with an entity property.
32
+
33
+ Functions that accept such filters now also support the string expression form of filters.
34
+
35
+ - Updated dependencies
36
+ - @backstage/frontend-plugin-api@0.4.0-next.1
37
+ - @backstage/core-components@0.13.9-next.1
38
+ - @backstage/core-plugin-api@1.8.1-next.1
39
+ - @backstage/catalog-client@1.5.0-next.0
40
+ - @backstage/integration-react@1.1.22-next.1
41
+ - @backstage/plugin-permission-react@0.4.18-next.1
42
+ - @backstage/catalog-model@1.4.3
43
+ - @backstage/errors@1.2.3
44
+ - @backstage/theme@0.5.0-next.0
45
+ - @backstage/types@1.1.1
46
+ - @backstage/version-bridge@1.0.7
47
+ - @backstage/plugin-catalog-common@1.0.18
48
+ - @backstage/plugin-permission-common@0.7.10
49
+
3
50
  ## 1.9.2-next.0
4
51
 
5
52
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-catalog-react",
3
- "version": "1.9.2-next.0",
3
+ "version": "1.9.2-next.2",
4
4
  "main": "../dist/alpha.esm.js",
5
5
  "module": "../dist/alpha.esm.js",
6
6
  "types": "../dist/alpha.d.ts"
package/dist/alpha.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
3
- import { AnyExtensionInputMap, ExtensionInputValues, RouteRef } from '@backstage/frontend-plugin-api';
3
+ import { AnyExtensionInputMap, ResolvedExtensionInputs, RouteRef } from '@backstage/frontend-plugin-api';
4
4
  import { Entity } from '@backstage/catalog-model';
5
5
  import { ResourcePermission } from '@backstage/plugin-permission-common';
6
6
 
@@ -43,33 +43,30 @@ declare function useEntityPermission(permission: ResourcePermission<'catalog-ent
43
43
  /** @alpha */
44
44
  declare const entityContentTitleExtensionDataRef: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, {}>;
45
45
  /** @alpha */
46
- declare const entityFilterExtensionDataRef: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(ctx: {
47
- entity: Entity;
48
- }) => boolean, {}>;
46
+ declare const entityFilterFunctionExtensionDataRef: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: Entity) => boolean, {}>;
47
+ /** @alpha */
48
+ declare const entityFilterExpressionExtensionDataRef: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, {}>;
49
49
  /** @alpha */
50
50
  declare function createEntityCardExtension<TInputs extends AnyExtensionInputMap>(options: {
51
- id: string;
51
+ namespace?: string;
52
+ name?: string;
52
53
  attachTo?: {
53
54
  id: string;
54
55
  input: string;
55
56
  };
56
57
  disabled?: boolean;
57
58
  inputs?: TInputs;
58
- filter?: (ctx: {
59
- entity: Entity;
60
- }) => boolean;
59
+ filter?: typeof entityFilterFunctionExtensionDataRef.T | typeof entityFilterExpressionExtensionDataRef.T;
61
60
  loader: (options: {
62
- inputs: Expand<ExtensionInputValues<TInputs>>;
61
+ inputs: Expand<ResolvedExtensionInputs<TInputs>>;
63
62
  }) => Promise<JSX.Element>;
64
- }): _backstage_frontend_plugin_api.Extension<{
65
- filter?: {
66
- isKind?: string | undefined;
67
- isType?: string | undefined;
68
- }[] | undefined;
63
+ }): _backstage_frontend_plugin_api.ExtensionDefinition<{
64
+ filter?: string | undefined;
69
65
  }>;
70
66
  /** @alpha */
71
67
  declare function createEntityContentExtension<TInputs extends AnyExtensionInputMap>(options: {
72
- id: string;
68
+ namespace?: string;
69
+ name?: string;
73
70
  attachTo?: {
74
71
  id: string;
75
72
  input: string;
@@ -79,19 +76,14 @@ declare function createEntityContentExtension<TInputs extends AnyExtensionInputM
79
76
  routeRef?: RouteRef;
80
77
  defaultPath: string;
81
78
  defaultTitle: string;
82
- filter?: (ctx: {
83
- entity: Entity;
84
- }) => boolean;
79
+ filter?: typeof entityFilterFunctionExtensionDataRef.T | typeof entityFilterExpressionExtensionDataRef.T;
85
80
  loader: (options: {
86
- inputs: Expand<ExtensionInputValues<TInputs>>;
81
+ inputs: Expand<ResolvedExtensionInputs<TInputs>>;
87
82
  }) => Promise<JSX.Element>;
88
- }): _backstage_frontend_plugin_api.Extension<{
83
+ }): _backstage_frontend_plugin_api.ExtensionDefinition<{
89
84
  title: string;
90
85
  path: string;
91
- filter?: {
92
- isKind?: string | undefined;
93
- isType?: string | undefined;
94
- }[] | undefined;
86
+ filter?: string | undefined;
95
87
  }>;
96
88
 
97
- export { createEntityCardExtension, createEntityContentExtension, entityContentTitleExtensionDataRef, entityFilterExtensionDataRef, isOwnerOf, useEntityPermission };
89
+ export { createEntityCardExtension, createEntityContentExtension, entityContentTitleExtensionDataRef, entityFilterExpressionExtensionDataRef, entityFilterFunctionExtensionDataRef, isOwnerOf, useEntityPermission };
package/dist/alpha.esm.js CHANGED
@@ -1,8 +1,8 @@
1
- import React, { lazy } from 'react';
2
1
  import { createExtensionDataRef, createExtension, coreExtensionData, createSchemaFromZod, ExtensionBoundary } from '@backstage/frontend-plugin-api';
2
+ import React, { lazy } from 'react';
3
3
  import { RELATION_MEMBER_OF, getCompoundEntityRef, stringifyEntityRef, RELATION_OWNED_BY } from '@backstage/catalog-model';
4
- import { g as getEntityRelations, a as useAsyncEntity } from './esm/useEntity-de64059a.esm.js';
5
4
  import { usePermission } from '@backstage/plugin-permission-react';
5
+ import { g as getEntityRelations, a as useAsyncEntity } from './esm/useEntity-de64059a.esm.js';
6
6
  import '@backstage/core-plugin-api';
7
7
  import '@backstage/version-bridge';
8
8
 
@@ -48,77 +48,49 @@ function useEntityPermission(permission) {
48
48
  }
49
49
 
50
50
  const entityContentTitleExtensionDataRef = createExtensionDataRef("plugin.catalog.entity.content.title");
51
- const entityFilterExtensionDataRef = createExtensionDataRef("plugin.catalog.entity.filter");
52
- function applyFilter(a, b) {
53
- if (!a) {
54
- return true;
55
- }
56
- return a.toLocaleLowerCase("en-US") === (b == null ? void 0 : b.toLocaleLowerCase("en-US"));
57
- }
58
- function buildFilter(config, filterFunc) {
59
- return (ctx) => {
60
- var _a;
61
- const configuredFilterMatch = (_a = config.filter) == null ? void 0 : _a.some((filter) => {
62
- var _a2, _b;
63
- const kindMatch = applyFilter(filter.isKind, ctx.entity.kind);
64
- const typeMatch = applyFilter(
65
- filter.isType,
66
- (_b = (_a2 = ctx.entity.spec) == null ? void 0 : _a2.type) == null ? void 0 : _b.toString()
67
- );
68
- return kindMatch && typeMatch;
69
- });
70
- if (configuredFilterMatch) {
71
- return true;
72
- }
73
- if (filterFunc) {
74
- return filterFunc(ctx);
75
- }
76
- return true;
77
- };
78
- }
51
+ const entityFilterFunctionExtensionDataRef = createExtensionDataRef("plugin.catalog.entity.filter.fn");
52
+ const entityFilterExpressionExtensionDataRef = createExtensionDataRef("plugin.catalog.entity.filter.expression");
79
53
  function createEntityCardExtension(options) {
80
54
  var _a, _b;
81
- const id = `entity.cards.${options.id}`;
82
55
  return createExtension({
83
- id,
56
+ kind: "entity-card",
57
+ namespace: options.namespace,
58
+ name: options.name,
84
59
  attachTo: (_a = options.attachTo) != null ? _a : {
85
- id: "entity.content.overview",
60
+ id: "entity-content:catalog/overview",
86
61
  input: "cards"
87
62
  },
88
63
  disabled: (_b = options.disabled) != null ? _b : true,
89
64
  output: {
90
65
  element: coreExtensionData.reactElement,
91
- filter: entityFilterExtensionDataRef
66
+ filterFunction: entityFilterFunctionExtensionDataRef.optional(),
67
+ filterExpression: entityFilterExpressionExtensionDataRef.optional()
92
68
  },
93
69
  inputs: options.inputs,
94
70
  configSchema: createSchemaFromZod(
95
71
  (z) => z.object({
96
- filter: z.array(
97
- z.object({
98
- isKind: z.string().optional(),
99
- isType: z.string().optional()
100
- })
101
- ).optional()
72
+ filter: z.string().optional()
102
73
  })
103
74
  ),
104
- factory({ config, inputs, source }) {
75
+ factory({ config, inputs, node }) {
105
76
  const ExtensionComponent = lazy(
106
77
  () => options.loader({ inputs }).then((element) => ({ default: () => element }))
107
78
  );
108
79
  return {
109
- element: /* @__PURE__ */ React.createElement(ExtensionBoundary, { id, source }, /* @__PURE__ */ React.createElement(ExtensionComponent, null)),
110
- filter: buildFilter(config, options.filter)
80
+ element: /* @__PURE__ */ React.createElement(ExtensionBoundary, { node }, /* @__PURE__ */ React.createElement(ExtensionComponent, null)),
81
+ ...mergeFilters({ config, options })
111
82
  };
112
83
  }
113
84
  });
114
85
  }
115
86
  function createEntityContentExtension(options) {
116
87
  var _a, _b;
117
- const id = `entity.content.${options.id}`;
118
88
  return createExtension({
119
- id,
89
+ kind: "entity-content",
90
+ namespace: options.namespace,
91
+ name: options.name,
120
92
  attachTo: (_a = options.attachTo) != null ? _a : {
121
- id: "plugin.catalog.page.entity",
93
+ id: "page:catalog/entity",
122
94
  input: "contents"
123
95
  },
124
96
  disabled: (_b = options.disabled) != null ? _b : true,
@@ -127,22 +99,18 @@ function createEntityContentExtension(options) {
127
99
  path: coreExtensionData.routePath,
128
100
  routeRef: coreExtensionData.routeRef.optional(),
129
101
  title: entityContentTitleExtensionDataRef,
130
- filter: entityFilterExtensionDataRef
102
+ filterFunction: entityFilterFunctionExtensionDataRef.optional(),
103
+ filterExpression: entityFilterExpressionExtensionDataRef.optional()
131
104
  },
132
105
  inputs: options.inputs,
133
106
  configSchema: createSchemaFromZod(
134
107
  (z) => z.object({
135
108
  path: z.string().default(options.defaultPath),
136
109
  title: z.string().default(options.defaultTitle),
137
- filter: z.array(
138
- z.object({
139
- isKind: z.string().optional(),
140
- isType: z.string().optional()
141
- })
142
- ).optional()
110
+ filter: z.string().optional()
143
111
  })
144
112
  ),
145
- factory({ config, inputs, source }) {
113
+ factory({ config, inputs, node }) {
146
114
  const ExtensionComponent = lazy(
147
115
  () => options.loader({ inputs }).then((element) => ({ default: () => element }))
148
116
  );
@@ -150,12 +118,23 @@ function createEntityContentExtension(options) {
150
118
  path: config.path,
151
119
  title: config.title,
152
120
  routeRef: options.routeRef,
153
- element: /* @__PURE__ */ React.createElement(ExtensionBoundary, { id, source, routable: true }, /* @__PURE__ */ React.createElement(ExtensionComponent, null)),
154
- filter: buildFilter(config, options.filter)
121
+ element: /* @__PURE__ */ React.createElement(ExtensionBoundary, { node, routable: true }, /* @__PURE__ */ React.createElement(ExtensionComponent, null)),
122
+ ...mergeFilters({ config, options })
155
123
  };
156
124
  }
157
125
  });
158
126
  }
127
+ function mergeFilters(inputs) {
128
+ const { options, config } = inputs;
129
+ if (config.filter) {
130
+ return { filterExpression: config.filter };
131
+ } else if (typeof options.filter === "string") {
132
+ return { filterExpression: options.filter };
133
+ } else if (typeof options.filter === "function") {
134
+ return { filterFunction: options.filter };
135
+ }
136
+ return {};
137
+ }
159
138
 
160
- export { createEntityCardExtension, createEntityContentExtension, entityContentTitleExtensionDataRef, entityFilterExtensionDataRef, isOwnerOf, useEntityPermission };
139
+ export { createEntityCardExtension, createEntityContentExtension, entityContentTitleExtensionDataRef, entityFilterExpressionExtensionDataRef, entityFilterFunctionExtensionDataRef, isOwnerOf, useEntityPermission };
161
140
  //# sourceMappingURL=alpha.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"alpha.esm.js","sources":["../src/utils/isOwnerOf.ts","../src/hooks/useEntityPermission.ts","../src/alpha.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 {\n Entity,\n getCompoundEntityRef,\n RELATION_MEMBER_OF,\n RELATION_OWNED_BY,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { getEntityRelations } from './getEntityRelations';\n\n/**\n * Returns true if the `owner` argument is a direct owner on the `entity` argument.\n *\n * @alpha\n * @remarks\n *\n * Note that this ownership is not the same as using the claims in the auth-resolver, it only will take into account ownership as expressed by direct entity relations.\n * It doesn't know anything about the additional groups that a user might belong to which the claims contain.\n */\nexport function isOwnerOf(owner: Entity, entity: Entity) {\n const possibleOwners = new Set(\n [\n ...getEntityRelations(owner, RELATION_MEMBER_OF, { kind: 'group' }),\n ...(owner ? [getCompoundEntityRef(owner)] : []),\n ].map(stringifyEntityRef),\n );\n\n const owners = getEntityRelations(entity, RELATION_OWNED_BY).map(\n stringifyEntityRef,\n );\n\n for (const ownerItem of owners) {\n if (possibleOwners.has(ownerItem)) {\n return true;\n }\n }\n\n return false;\n}\n","/*\n * Copyright 2022 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 { stringifyEntityRef } from '@backstage/catalog-model';\nimport { ResourcePermission } from '@backstage/plugin-permission-common';\nimport { usePermission } from '@backstage/plugin-permission-react';\nimport { useAsyncEntity } from './useEntity';\n\n/**\n * A thin wrapper around the\n * {@link @backstage/plugin-permission-react#usePermission} hook which uses the\n * current entity in context to make an authorization request for the given\n * {@link @backstage/plugin-catalog-common#CatalogEntityPermission}.\n *\n * Note: this hook blocks the permission request until the entity has loaded in\n * context. If you have the entityRef and need concurrent requests, use the\n * `usePermission` hook directly.\n * @alpha\n */\nexport function useEntityPermission(\n // TODO(joeporpeglia) Replace with `CatalogEntityPermission` when the issue described in\n // https://github.com/backstage/backstage/pull/10128 is fixed.\n permission: ResourcePermission<'catalog-entity'>,\n): {\n loading: boolean;\n allowed: boolean;\n error?: Error;\n} {\n const {\n entity,\n loading: loadingEntity,\n error: entityError,\n } = useAsyncEntity();\n const {\n allowed,\n loading: loadingPermission,\n error: permissionError,\n } = usePermission({\n permission,\n resourceRef: entity ? stringifyEntityRef(entity) : undefined,\n });\n\n if (loadingEntity || loadingPermission) {\n return { loading: true, allowed: false };\n }\n if (entityError) {\n return { loading: false, allowed: false, error: entityError };\n }\n return { loading: false, allowed, error: permissionError };\n}\n","/*\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 React, { lazy } from 'react';\nimport {\n AnyExtensionInputMap,\n ExtensionBoundary,\n ExtensionInputValues,\n RouteRef,\n coreExtensionData,\n createExtension,\n createExtensionDataRef,\n createSchemaFromZod,\n} from '@backstage/frontend-plugin-api';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { Expand } from '../../../packages/frontend-plugin-api/src/types';\nimport { Entity } from '@backstage/catalog-model';\n\nexport { isOwnerOf } from './utils';\nexport { useEntityPermission } from './hooks/useEntityPermission';\n\n/** @alpha */\nexport const entityContentTitleExtensionDataRef =\n createExtensionDataRef<string>('plugin.catalog.entity.content.title');\n\n/** @alpha */\nexport const entityFilterExtensionDataRef = createExtensionDataRef<\n (ctx: { entity: Entity }) => boolean\n>('plugin.catalog.entity.filter');\n\nfunction applyFilter(a?: string, b?: string): boolean {\n if (!a) {\n return true;\n }\n return a.toLocaleLowerCase('en-US') === b?.toLocaleLowerCase('en-US');\n}\n\n// TODO: Only two hardcoded isKind and isType filters are available for now\n// This is just an initial config filter implementation and needs to be revisited\nfunction buildFilter(\n config: { filter?: { isKind?: string; isType?: string }[] },\n filterFunc?: (ctx: { entity: Entity }) => boolean,\n) {\n return (ctx: { entity: Entity }) => {\n const configuredFilterMatch = config.filter?.some(filter => {\n const kindMatch = applyFilter(filter.isKind, ctx.entity.kind);\n const typeMatch = applyFilter(\n filter.isType,\n ctx.entity.spec?.type?.toString(),\n );\n return kindMatch && typeMatch;\n });\n if (configuredFilterMatch) {\n return true;\n }\n if (filterFunc) {\n return filterFunc(ctx);\n }\n return true;\n };\n}\n\n// TODO: Figure out how to merge with provided config schema\n/** @alpha */\nexport function createEntityCardExtension<\n TInputs extends AnyExtensionInputMap,\n>(options: {\n id: string;\n attachTo?: { id: string; input: string };\n disabled?: boolean;\n inputs?: TInputs;\n filter?: (ctx: { entity: Entity }) => boolean;\n loader: (options: {\n inputs: Expand<ExtensionInputValues<TInputs>>;\n }) => Promise<JSX.Element>;\n}) {\n const id = `entity.cards.${options.id}`;\n\n return createExtension({\n id,\n attachTo: options.attachTo ?? {\n id: 'entity.content.overview',\n input: 'cards',\n },\n disabled: options.disabled ?? true,\n output: {\n element: coreExtensionData.reactElement,\n filter: entityFilterExtensionDataRef,\n },\n inputs: options.inputs,\n configSchema: createSchemaFromZod(z =>\n z.object({\n filter: z\n .array(\n z.object({\n isKind: z.string().optional(),\n isType: z.string().optional(),\n }),\n )\n .optional(),\n }),\n ),\n factory({ config, inputs, source }) {\n const ExtensionComponent = lazy(() =>\n options\n .loader({ inputs })\n .then(element => ({ default: () => element })),\n );\n\n return {\n element: (\n <ExtensionBoundary id={id} source={source}>\n <ExtensionComponent />\n </ExtensionBoundary>\n ),\n filter: buildFilter(config, options.filter),\n };\n },\n });\n}\n\n/** @alpha */\nexport function createEntityContentExtension<\n TInputs extends AnyExtensionInputMap,\n>(options: {\n id: string;\n attachTo?: { id: string; input: string };\n disabled?: boolean;\n inputs?: TInputs;\n routeRef?: RouteRef;\n defaultPath: string;\n defaultTitle: string;\n filter?: (ctx: { entity: Entity }) => boolean;\n loader: (options: {\n inputs: Expand<ExtensionInputValues<TInputs>>;\n }) => Promise<JSX.Element>;\n}) {\n const id = `entity.content.${options.id}`;\n\n return createExtension({\n id,\n attachTo: options.attachTo ?? {\n id: 'plugin.catalog.page.entity',\n input: 'contents',\n },\n disabled: options.disabled ?? true,\n output: {\n element: coreExtensionData.reactElement,\n path: coreExtensionData.routePath,\n routeRef: coreExtensionData.routeRef.optional(),\n title: entityContentTitleExtensionDataRef,\n filter: entityFilterExtensionDataRef,\n },\n inputs: options.inputs,\n configSchema: createSchemaFromZod(z =>\n z.object({\n path: z.string().default(options.defaultPath),\n title: z.string().default(options.defaultTitle),\n filter: z\n .array(\n z.object({\n isKind: z.string().optional(),\n isType: z.string().optional(),\n }),\n )\n .optional(),\n }),\n ),\n factory({ config, inputs, source }) {\n const ExtensionComponent = lazy(() =>\n options\n .loader({ inputs })\n .then(element => ({ default: () => element })),\n );\n\n return {\n path: config.path,\n title: config.title,\n routeRef: options.routeRef,\n element: (\n <ExtensionBoundary id={id} source={source} routable>\n <ExtensionComponent />\n </ExtensionBoundary>\n ),\n filter: buildFilter(config, options.filter),\n };\n },\n });\n}\n"],"names":["_a"],"mappings":"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"}
1
+ {"version":3,"file":"alpha.esm.js","sources":["../src/utils/isOwnerOf.ts","../src/hooks/useEntityPermission.ts","../src/alpha.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 {\n Entity,\n getCompoundEntityRef,\n RELATION_MEMBER_OF,\n RELATION_OWNED_BY,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { getEntityRelations } from './getEntityRelations';\n\n/**\n * Returns true if the `owner` argument is a direct owner on the `entity` argument.\n *\n * @alpha\n * @remarks\n *\n * Note that this ownership is not the same as using the claims in the auth-resolver, it only will take into account ownership as expressed by direct entity relations.\n * It doesn't know anything about the additional groups that a user might belong to which the claims contain.\n */\nexport function isOwnerOf(owner: Entity, entity: Entity) {\n const possibleOwners = new Set(\n [\n ...getEntityRelations(owner, RELATION_MEMBER_OF, { kind: 'group' }),\n ...(owner ? [getCompoundEntityRef(owner)] : []),\n ].map(stringifyEntityRef),\n );\n\n const owners = getEntityRelations(entity, RELATION_OWNED_BY).map(\n stringifyEntityRef,\n );\n\n for (const ownerItem of owners) {\n if (possibleOwners.has(ownerItem)) {\n return true;\n }\n }\n\n return false;\n}\n","/*\n * Copyright 2022 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 { stringifyEntityRef } from '@backstage/catalog-model';\nimport { ResourcePermission } from '@backstage/plugin-permission-common';\nimport { usePermission } from '@backstage/plugin-permission-react';\nimport { useAsyncEntity } from './useEntity';\n\n/**\n * A thin wrapper around the\n * {@link @backstage/plugin-permission-react#usePermission} hook which uses the\n * current entity in context to make an authorization request for the given\n * {@link @backstage/plugin-catalog-common#CatalogEntityPermission}.\n *\n * Note: this hook blocks the permission request until the entity has loaded in\n * context. If you have the entityRef and need concurrent requests, use the\n * `usePermission` hook directly.\n * @alpha\n */\nexport function useEntityPermission(\n // TODO(joeporpeglia) Replace with `CatalogEntityPermission` when the issue described in\n // https://github.com/backstage/backstage/pull/10128 is fixed.\n permission: ResourcePermission<'catalog-entity'>,\n): {\n loading: boolean;\n allowed: boolean;\n error?: Error;\n} {\n const {\n entity,\n loading: loadingEntity,\n error: entityError,\n } = useAsyncEntity();\n const {\n allowed,\n loading: loadingPermission,\n error: permissionError,\n } = usePermission({\n permission,\n resourceRef: entity ? stringifyEntityRef(entity) : undefined,\n });\n\n if (loadingEntity || loadingPermission) {\n return { loading: true, allowed: false };\n }\n if (entityError) {\n return { loading: false, allowed: false, error: entityError };\n }\n return { loading: false, allowed, error: permissionError };\n}\n","/*\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 {\n AnyExtensionInputMap,\n ExtensionBoundary,\n ResolvedExtensionInputs,\n RouteRef,\n coreExtensionData,\n createExtension,\n createExtensionDataRef,\n createSchemaFromZod,\n} from '@backstage/frontend-plugin-api';\nimport React, { lazy } from 'react';\nimport { Entity } from '@backstage/catalog-model';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { Expand } from '../../../packages/frontend-plugin-api/src/types';\n\nexport { useEntityPermission } from './hooks/useEntityPermission';\nexport { isOwnerOf } from './utils';\n\n/** @alpha */\nexport const entityContentTitleExtensionDataRef =\n createExtensionDataRef<string>('plugin.catalog.entity.content.title');\n\n/** @alpha */\nexport const entityFilterFunctionExtensionDataRef = createExtensionDataRef<\n (entity: Entity) => boolean\n>('plugin.catalog.entity.filter.fn');\n\n/** @alpha */\nexport const entityFilterExpressionExtensionDataRef =\n createExtensionDataRef<string>('plugin.catalog.entity.filter.expression');\n\n// TODO: Figure out how to merge with provided config schema\n/** @alpha */\nexport function createEntityCardExtension<\n TInputs extends AnyExtensionInputMap,\n>(options: {\n namespace?: string;\n name?: string;\n attachTo?: { id: string; input: string };\n disabled?: boolean;\n inputs?: TInputs;\n filter?:\n | typeof entityFilterFunctionExtensionDataRef.T\n | typeof entityFilterExpressionExtensionDataRef.T;\n loader: (options: {\n inputs: Expand<ResolvedExtensionInputs<TInputs>>;\n }) => Promise<JSX.Element>;\n}) {\n return createExtension({\n kind: 'entity-card',\n namespace: options.namespace,\n name: options.name,\n attachTo: options.attachTo ?? {\n id: 'entity-content:catalog/overview',\n input: 'cards',\n },\n disabled: options.disabled ?? true,\n output: {\n element: coreExtensionData.reactElement,\n filterFunction: entityFilterFunctionExtensionDataRef.optional(),\n filterExpression: entityFilterExpressionExtensionDataRef.optional(),\n },\n inputs: options.inputs,\n configSchema: createSchemaFromZod(z =>\n z.object({\n filter: z.string().optional(),\n }),\n ),\n factory({ config, inputs, node }) {\n const ExtensionComponent = lazy(() =>\n options\n .loader({ inputs })\n .then(element => ({ default: () => element })),\n );\n\n return {\n element: (\n <ExtensionBoundary node={node}>\n <ExtensionComponent />\n </ExtensionBoundary>\n ),\n ...mergeFilters({ config, options }),\n };\n },\n });\n}\n\n/** @alpha */\nexport function createEntityContentExtension<\n TInputs extends AnyExtensionInputMap,\n>(options: {\n namespace?: string;\n name?: string;\n attachTo?: { id: string; input: string };\n disabled?: boolean;\n inputs?: TInputs;\n routeRef?: RouteRef;\n defaultPath: string;\n defaultTitle: string;\n filter?:\n | typeof entityFilterFunctionExtensionDataRef.T\n | typeof entityFilterExpressionExtensionDataRef.T;\n loader: (options: {\n inputs: Expand<ResolvedExtensionInputs<TInputs>>;\n }) => Promise<JSX.Element>;\n}) {\n return createExtension({\n kind: 'entity-content',\n namespace: options.namespace,\n name: options.name,\n attachTo: options.attachTo ?? {\n id: 'page:catalog/entity',\n input: 'contents',\n },\n disabled: options.disabled ?? true,\n output: {\n element: coreExtensionData.reactElement,\n path: coreExtensionData.routePath,\n routeRef: coreExtensionData.routeRef.optional(),\n title: entityContentTitleExtensionDataRef,\n filterFunction: entityFilterFunctionExtensionDataRef.optional(),\n filterExpression: entityFilterExpressionExtensionDataRef.optional(),\n },\n inputs: options.inputs,\n configSchema: createSchemaFromZod(z =>\n z.object({\n path: z.string().default(options.defaultPath),\n title: z.string().default(options.defaultTitle),\n filter: z.string().optional(),\n }),\n ),\n factory({ config, inputs, node }) {\n const ExtensionComponent = lazy(() =>\n options\n .loader({ inputs })\n .then(element => ({ default: () => element })),\n );\n\n return {\n path: config.path,\n title: config.title,\n routeRef: options.routeRef,\n element: (\n <ExtensionBoundary node={node} routable>\n <ExtensionComponent />\n </ExtensionBoundary>\n ),\n ...mergeFilters({ config, options }),\n };\n },\n });\n}\n\n/**\n * Decides what filter outputs to produce, given some options and config\n */\nfunction mergeFilters(inputs: {\n options: {\n filter?:\n | typeof entityFilterFunctionExtensionDataRef.T\n | typeof entityFilterExpressionExtensionDataRef.T;\n };\n config: {\n filter?: string;\n };\n}): {\n filterFunction?: typeof entityFilterFunctionExtensionDataRef.T;\n filterExpression?: typeof entityFilterExpressionExtensionDataRef.T;\n} {\n const { options, config } = inputs;\n if (config.filter) {\n return { filterExpression: config.filter };\n } else if (typeof options.filter === 'string') {\n return { filterExpression: options.filter };\n } else if (typeof options.filter === 'function') {\n return { filterFunction: options.filter };\n }\n return {};\n}\n"],"names":[],"mappings":"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"}
package/dist/index.esm.js CHANGED
@@ -1,15 +1,6 @@
1
1
  export { CATALOG_FILTER_EXISTS } from '@backstage/catalog-client';
2
2
  import { createApiRef, useApiHolder, useApi, identityApiRef, alertApiRef, createRouteRef, useRouteRef, useApp, configApiRef } from '@backstage/core-plugin-api';
3
3
  import { stringifyEntityRef, DEFAULT_NAMESPACE, ANNOTATION_SOURCE_LOCATION, parseLocationRef, parseEntityRef, RELATION_OWNED_BY, getCompoundEntityRef, isUserEntity, isGroupEntity, RELATION_PART_OF, ANNOTATION_LOCATION, ANNOTATION_ORIGIN_LOCATION } from '@backstage/catalog-model';
4
- import ApartmentIcon from '@material-ui/icons/Apartment';
5
- import BusinessIcon from '@material-ui/icons/Business';
6
- import ExtensionIcon from '@material-ui/icons/Extension';
7
- import HelpIcon$1 from '@material-ui/icons/Help';
8
- import LibraryAddIcon from '@material-ui/icons/LibraryAdd';
9
- import LocationOnIcon from '@material-ui/icons/LocationOn';
10
- import MemoryIcon from '@material-ui/icons/Memory';
11
- import PeopleIcon from '@material-ui/icons/People';
12
- import PersonIcon from '@material-ui/icons/Person';
13
4
  import get from 'lodash/get';
14
5
  import React, { useState, useEffect, useMemo, createContext, useCallback, useContext, useRef, memo, forwardRef, useLayoutEffect, Fragment } from 'react';
15
6
  import ObservableImpl from 'zen-observable';
@@ -34,6 +25,7 @@ import CheckBoxIcon from '@material-ui/icons/CheckBox';
34
25
  import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';
35
26
  import classNames from 'classnames';
36
27
  import { useMountEffect, useDebouncedEffect } from '@react-hookz/web';
28
+ import PersonIcon from '@material-ui/icons/Person';
37
29
  import GroupIcon from '@material-ui/icons/Group';
38
30
  import { getOrCreateGlobalSingleton } from '@backstage/version-bridge';
39
31
  import HoverPopover from 'material-ui-popup-state/HoverPopover';
@@ -66,20 +58,8 @@ const entityPresentationApiRef = createApiRef({
66
58
  id: "plugin.catalog.entity-presentation"
67
59
  });
68
60
 
69
- const UNKNOWN_KIND_ICON = HelpIcon$1;
70
- const DEFAULT_ICONS = {
71
- api: ExtensionIcon,
72
- component: MemoryIcon,
73
- system: BusinessIcon,
74
- domain: ApartmentIcon,
75
- location: LocationOnIcon,
76
- user: PersonIcon,
77
- group: PeopleIcon,
78
- template: LibraryAddIcon
79
- };
80
61
  function defaultEntityPresentation(entityOrRef, context) {
81
62
  const { kind, namespace, name, title, description, displayName, type } = getParts(entityOrRef);
82
- const Icon = kind && DEFAULT_ICONS[kind.toLocaleLowerCase("en-US")] || UNKNOWN_KIND_ICON;
83
63
  const entityRef = stringifyEntityRef({
84
64
  kind: kind || "unknown",
85
65
  namespace: namespace || DEFAULT_NAMESPACE,
@@ -98,7 +78,8 @@ function defaultEntityPresentation(entityOrRef, context) {
98
78
  entityRef,
99
79
  primaryTitle: primary,
100
80
  secondaryTitle: secondary || void 0,
101
- Icon
81
+ Icon: void 0
82
+ // leave it up to the presentation API to handle
102
83
  };
103
84
  }
104
85
  function getParts(entityOrRef) {