@backstage/plugin-catalog 1.22.0 → 1.22.1-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,29 @@
1
1
  # @backstage/plugin-catalog
2
2
 
3
+ ## 1.22.1-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - fec8b57: Updated exports to use the new type parameters for extensions and extension blueprints.
8
+ - 5446061: The `/alpha` export no longer export extension creators for the new frontend system, existing usage should be switched to use the equivalent extension blueprint instead. For more information see the [new frontend system 1.30 migration documentation](https://backstage.io/docs/frontend-system/architecture/migrations#130).
9
+ - 180a45f: Entity presentation api now only fetches fields that are required to display entity title
10
+ - Updated dependencies
11
+ - @backstage/frontend-plugin-api@0.8.0-next.0
12
+ - @backstage/core-compat-api@0.2.9-next.0
13
+ - @backstage/plugin-catalog-react@1.12.4-next.0
14
+ - @backstage/plugin-search-react@1.8.0-next.0
15
+ - @backstage/catalog-client@1.6.6
16
+ - @backstage/catalog-model@1.6.0
17
+ - @backstage/core-components@0.14.10
18
+ - @backstage/core-plugin-api@1.9.3
19
+ - @backstage/errors@1.2.4
20
+ - @backstage/integration-react@1.1.30
21
+ - @backstage/types@1.1.1
22
+ - @backstage/plugin-catalog-common@1.0.26
23
+ - @backstage/plugin-permission-react@0.4.25
24
+ - @backstage/plugin-scaffolder-common@1.5.5
25
+ - @backstage/plugin-search-common@1.2.14
26
+
3
27
  ## 1.22.0
4
28
 
5
29
  ### Minor Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-catalog__alpha",
3
- "version": "1.22.0",
3
+ "version": "1.22.1-next.0",
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
@@ -4,7 +4,6 @@ import * as _backstage_catalog_model from '@backstage/catalog-model';
4
4
  import * as React from 'react';
5
5
  import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
6
6
  import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
7
- import { AnyExtensionInputMap, PortableSchema } from '@backstage/frontend-plugin-api';
8
7
  import * as _backstage_core_plugin_api_alpha from '@backstage/core-plugin-api/alpha';
9
8
 
10
9
  /** @alpha */
@@ -28,332 +27,411 @@ declare const _default: _backstage_frontend_plugin_api.BackstagePlugin<{
28
27
  }>;
29
28
  unregisterRedirect: _backstage_frontend_plugin_api.ExternalRouteRef<undefined>;
30
29
  }, {
31
- "nav-item:catalog": _backstage_frontend_plugin_api.ExtensionDefinition<{}, {}, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<{
32
- title: string;
33
- icon: _backstage_core_plugin_api.IconComponent;
34
- routeRef: _backstage_frontend_plugin_api.RouteRef<undefined>;
35
- }, "core.nav-item.target", {}>, {}, {
30
+ "api:catalog": _backstage_frontend_plugin_api.ExtensionDefinition<{
31
+ kind: "api";
32
+ namespace: undefined;
33
+ name: undefined;
34
+ config: {};
35
+ configInput: {};
36
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<_backstage_frontend_plugin_api.AnyApiFactory, "core.api.factory", {}>;
37
+ inputs: {};
38
+ }>;
39
+ "nav-item:catalog": _backstage_frontend_plugin_api.ExtensionDefinition<{
36
40
  kind: "nav-item";
37
41
  namespace: undefined;
38
42
  name: undefined;
43
+ config: {};
44
+ configInput: {};
45
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<{
46
+ title: string;
47
+ icon: _backstage_core_plugin_api.IconComponent;
48
+ routeRef: _backstage_frontend_plugin_api.RouteRef<undefined>;
49
+ }, "core.nav-item.target", {}>;
50
+ inputs: {};
39
51
  }>;
40
- "api:catalog/starred-entities": _backstage_frontend_plugin_api.ExtensionDefinition<{}, {}, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<_backstage_frontend_plugin_api.AnyApiFactory, "core.api.factory", {}>, {}, {
52
+ "api:catalog/starred-entities": _backstage_frontend_plugin_api.ExtensionDefinition<{
41
53
  kind: "api";
42
54
  namespace: undefined;
43
55
  name: "starred-entities";
56
+ config: {};
57
+ configInput: {};
58
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<_backstage_frontend_plugin_api.AnyApiFactory, "core.api.factory", {}>;
59
+ inputs: {};
44
60
  }>;
45
- "api:catalog/entity-presentation": _backstage_frontend_plugin_api.ExtensionDefinition<{}, {}, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<_backstage_frontend_plugin_api.AnyApiFactory, "core.api.factory", {}>, {}, {
61
+ "api:catalog/entity-presentation": _backstage_frontend_plugin_api.ExtensionDefinition<{
46
62
  kind: "api";
47
63
  namespace: undefined;
48
64
  name: "entity-presentation";
65
+ config: {};
66
+ configInput: {};
67
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<_backstage_frontend_plugin_api.AnyApiFactory, "core.api.factory", {}>;
68
+ inputs: {};
49
69
  }>;
50
70
  "entity-card:catalog/about": _backstage_frontend_plugin_api.ExtensionDefinition<{
51
- filter: string | undefined;
52
- }, {
53
- filter?: string | undefined;
54
- }, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
55
- optional: true;
56
- }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
57
- optional: true;
58
- }>, {}, {
59
71
  kind: "entity-card";
60
72
  namespace: undefined;
61
73
  name: "about";
74
+ config: {
75
+ filter: string | undefined;
76
+ };
77
+ configInput: {
78
+ filter?: string | undefined;
79
+ };
80
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
81
+ optional: true;
82
+ }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
83
+ optional: true;
84
+ }>;
85
+ inputs: {};
62
86
  }>;
63
87
  "entity-card:catalog/links": _backstage_frontend_plugin_api.ExtensionDefinition<{
64
- filter: string | undefined;
65
- }, {
66
- filter?: string | undefined;
67
- }, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
68
- optional: true;
69
- }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
70
- optional: true;
71
- }>, {}, {
72
88
  kind: "entity-card";
73
89
  namespace: undefined;
74
90
  name: "links";
91
+ config: {
92
+ filter: string | undefined;
93
+ };
94
+ configInput: {
95
+ filter?: string | undefined;
96
+ };
97
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
98
+ optional: true;
99
+ }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
100
+ optional: true;
101
+ }>;
102
+ inputs: {};
75
103
  }>;
76
104
  "entity-card:catalog/labels": _backstage_frontend_plugin_api.ExtensionDefinition<{
77
- filter: string | undefined;
78
- }, {
79
- filter?: string | undefined;
80
- }, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
81
- optional: true;
82
- }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
83
- optional: true;
84
- }>, {}, {
85
105
  kind: "entity-card";
86
106
  namespace: undefined;
87
107
  name: "labels";
108
+ config: {
109
+ filter: string | undefined;
110
+ };
111
+ configInput: {
112
+ filter?: string | undefined;
113
+ };
114
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
115
+ optional: true;
116
+ }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
117
+ optional: true;
118
+ }>;
119
+ inputs: {};
88
120
  }>;
89
121
  "entity-card:catalog/depends-on-components": _backstage_frontend_plugin_api.ExtensionDefinition<{
90
- filter: string | undefined;
91
- }, {
92
- filter?: string | undefined;
93
- }, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
94
- optional: true;
95
- }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
96
- optional: true;
97
- }>, {}, {
98
122
  kind: "entity-card";
99
123
  namespace: undefined;
100
124
  name: "depends-on-components";
125
+ config: {
126
+ filter: string | undefined;
127
+ };
128
+ configInput: {
129
+ filter?: string | undefined;
130
+ };
131
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
132
+ optional: true;
133
+ }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
134
+ optional: true;
135
+ }>;
136
+ inputs: {};
101
137
  }>;
102
138
  "entity-card:catalog/depends-on-resources": _backstage_frontend_plugin_api.ExtensionDefinition<{
103
- filter: string | undefined;
104
- }, {
105
- filter?: string | undefined;
106
- }, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
107
- optional: true;
108
- }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
109
- optional: true;
110
- }>, {}, {
111
139
  kind: "entity-card";
112
140
  namespace: undefined;
113
141
  name: "depends-on-resources";
142
+ config: {
143
+ filter: string | undefined;
144
+ };
145
+ configInput: {
146
+ filter?: string | undefined;
147
+ };
148
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
149
+ optional: true;
150
+ }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
151
+ optional: true;
152
+ }>;
153
+ inputs: {};
114
154
  }>;
115
155
  "entity-card:catalog/has-components": _backstage_frontend_plugin_api.ExtensionDefinition<{
116
- filter: string | undefined;
117
- }, {
118
- filter?: string | undefined;
119
- }, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
120
- optional: true;
121
- }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
122
- optional: true;
123
- }>, {}, {
124
156
  kind: "entity-card";
125
157
  namespace: undefined;
126
158
  name: "has-components";
159
+ config: {
160
+ filter: string | undefined;
161
+ };
162
+ configInput: {
163
+ filter?: string | undefined;
164
+ };
165
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
166
+ optional: true;
167
+ }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
168
+ optional: true;
169
+ }>;
170
+ inputs: {};
127
171
  }>;
128
172
  "entity-card:catalog/has-resources": _backstage_frontend_plugin_api.ExtensionDefinition<{
129
- filter: string | undefined;
130
- }, {
131
- filter?: string | undefined;
132
- }, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
133
- optional: true;
134
- }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
135
- optional: true;
136
- }>, {}, {
137
173
  kind: "entity-card";
138
174
  namespace: undefined;
139
175
  name: "has-resources";
176
+ config: {
177
+ filter: string | undefined;
178
+ };
179
+ configInput: {
180
+ filter?: string | undefined;
181
+ };
182
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
183
+ optional: true;
184
+ }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
185
+ optional: true;
186
+ }>;
187
+ inputs: {};
140
188
  }>;
141
189
  "entity-card:catalog/has-subcomponents": _backstage_frontend_plugin_api.ExtensionDefinition<{
142
- filter: string | undefined;
143
- }, {
144
- filter?: string | undefined;
145
- }, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
146
- optional: true;
147
- }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
148
- optional: true;
149
- }>, {}, {
150
190
  kind: "entity-card";
151
191
  namespace: undefined;
152
192
  name: "has-subcomponents";
193
+ config: {
194
+ filter: string | undefined;
195
+ };
196
+ configInput: {
197
+ filter?: string | undefined;
198
+ };
199
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
200
+ optional: true;
201
+ }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
202
+ optional: true;
203
+ }>;
204
+ inputs: {};
153
205
  }>;
154
206
  "entity-card:catalog/has-subdomains": _backstage_frontend_plugin_api.ExtensionDefinition<{
155
- filter: string | undefined;
156
- }, {
157
- filter?: string | undefined;
158
- }, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
159
- optional: true;
160
- }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
161
- optional: true;
162
- }>, {}, {
163
207
  kind: "entity-card";
164
208
  namespace: undefined;
165
209
  name: "has-subdomains";
210
+ config: {
211
+ filter: string | undefined;
212
+ };
213
+ configInput: {
214
+ filter?: string | undefined;
215
+ };
216
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
217
+ optional: true;
218
+ }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
219
+ optional: true;
220
+ }>;
221
+ inputs: {};
166
222
  }>;
167
223
  "entity-card:catalog/has-systems": _backstage_frontend_plugin_api.ExtensionDefinition<{
168
- filter: string | undefined;
169
- }, {
170
- filter?: string | undefined;
171
- }, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
172
- optional: true;
173
- }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
174
- optional: true;
175
- }>, {}, {
176
224
  kind: "entity-card";
177
225
  namespace: undefined;
178
226
  name: "has-systems";
227
+ config: {
228
+ filter: string | undefined;
229
+ };
230
+ configInput: {
231
+ filter?: string | undefined;
232
+ };
233
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
234
+ optional: true;
235
+ }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
236
+ optional: true;
237
+ }>;
238
+ inputs: {};
179
239
  }>;
180
240
  "entity-content:catalog/overview": _backstage_frontend_plugin_api.ExtensionDefinition<{
181
- [x: string]: any;
182
- } & {
183
- path: string | undefined;
184
- title: string | undefined;
185
- filter: string | undefined;
186
- }, {
187
- [x: string]: any;
188
- } & {
189
- filter?: string | undefined;
190
- title?: string | undefined;
191
- path?: string | undefined;
192
- }, _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", {
193
- optional: true;
194
- }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-content-title", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
195
- optional: true;
196
- }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
197
- optional: true;
198
- }>, {
199
- cards: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
241
+ config: {
242
+ path: string | undefined;
243
+ title: string | undefined;
244
+ filter: string | undefined;
245
+ };
246
+ configInput: {
247
+ filter?: string | undefined;
248
+ title?: string | undefined;
249
+ path?: string | undefined;
250
+ };
251
+ output: _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", {
252
+ optional: true;
253
+ }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-content-title", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
200
254
  optional: true;
201
255
  }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
202
256
  optional: true;
203
- }>, {
204
- singleton: false;
205
- optional: false;
206
257
  }>;
207
- }, {
258
+ inputs: {
259
+ cards: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
260
+ optional: true;
261
+ }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
262
+ optional: true;
263
+ }>, {
264
+ singleton: false;
265
+ optional: false;
266
+ }>;
267
+ };
208
268
  kind: "entity-content";
209
269
  namespace: undefined;
210
270
  name: "overview";
211
271
  }>;
212
- "catalog-filter:catalog/tag": _backstage_frontend_plugin_api.ExtensionDefinition<{}, {}, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>, {}, {
272
+ "catalog-filter:catalog/tag": _backstage_frontend_plugin_api.ExtensionDefinition<{
213
273
  kind: "catalog-filter";
214
274
  namespace: undefined;
215
275
  name: "tag";
276
+ config: {};
277
+ configInput: {};
278
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>;
279
+ inputs: {};
216
280
  }>;
217
281
  "catalog-filter:catalog/kind": _backstage_frontend_plugin_api.ExtensionDefinition<{
218
- initialFilter: string;
219
- }, {
220
- initialFilter?: string | undefined;
221
- }, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>, {
222
- [x: string]: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.AnyExtensionDataRef, {
223
- optional: boolean;
224
- singleton: boolean;
225
- }>;
226
- }, {
282
+ config: {
283
+ initialFilter: string;
284
+ };
285
+ configInput: {
286
+ initialFilter?: string | undefined;
287
+ };
288
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>;
289
+ inputs: {
290
+ [x: string]: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.AnyExtensionDataRef, {
291
+ optional: boolean;
292
+ singleton: boolean;
293
+ }>;
294
+ };
227
295
  kind: "catalog-filter";
228
296
  namespace: undefined;
229
297
  name: "kind";
230
298
  }>;
231
- "catalog-filter:catalog/type": _backstage_frontend_plugin_api.ExtensionDefinition<{}, {}, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>, {}, {
299
+ "catalog-filter:catalog/type": _backstage_frontend_plugin_api.ExtensionDefinition<{
232
300
  kind: "catalog-filter";
233
301
  namespace: undefined;
234
302
  name: "type";
303
+ config: {};
304
+ configInput: {};
305
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>;
306
+ inputs: {};
235
307
  }>;
236
308
  "catalog-filter:catalog/mode": _backstage_frontend_plugin_api.ExtensionDefinition<{
237
- mode: "all" | "owners-only" | undefined;
238
- }, {
239
- mode?: "all" | "owners-only" | undefined;
240
- }, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>, {
241
- [x: string]: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.AnyExtensionDataRef, {
242
- optional: boolean;
243
- singleton: boolean;
244
- }>;
245
- }, {
309
+ config: {
310
+ mode: "all" | "owners-only" | undefined;
311
+ };
312
+ configInput: {
313
+ mode?: "all" | "owners-only" | undefined;
314
+ };
315
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>;
316
+ inputs: {
317
+ [x: string]: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.AnyExtensionDataRef, {
318
+ optional: boolean;
319
+ singleton: boolean;
320
+ }>;
321
+ };
246
322
  kind: "catalog-filter";
247
323
  namespace: undefined;
248
324
  name: "mode";
249
325
  }>;
250
- "catalog-filter:catalog/namespace": _backstage_frontend_plugin_api.ExtensionDefinition<{}, {}, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>, {}, {
326
+ "catalog-filter:catalog/namespace": _backstage_frontend_plugin_api.ExtensionDefinition<{
251
327
  kind: "catalog-filter";
252
328
  namespace: undefined;
253
329
  name: "namespace";
330
+ config: {};
331
+ configInput: {};
332
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>;
333
+ inputs: {};
254
334
  }>;
255
- "catalog-filter:catalog/lifecycle": _backstage_frontend_plugin_api.ExtensionDefinition<{}, {}, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>, {}, {
335
+ "catalog-filter:catalog/lifecycle": _backstage_frontend_plugin_api.ExtensionDefinition<{
256
336
  kind: "catalog-filter";
257
337
  namespace: undefined;
258
338
  name: "lifecycle";
339
+ config: {};
340
+ configInput: {};
341
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>;
342
+ inputs: {};
259
343
  }>;
260
- "catalog-filter:catalog/processing-status": _backstage_frontend_plugin_api.ExtensionDefinition<{}, {}, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>, {}, {
344
+ "catalog-filter:catalog/processing-status": _backstage_frontend_plugin_api.ExtensionDefinition<{
261
345
  kind: "catalog-filter";
262
346
  namespace: undefined;
263
347
  name: "processing-status";
348
+ config: {};
349
+ configInput: {};
350
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>;
351
+ inputs: {};
264
352
  }>;
265
353
  "catalog-filter:catalog/list": _backstage_frontend_plugin_api.ExtensionDefinition<{
266
- initialFilter: "all" | "owned" | "starred";
267
- }, {
268
- initialFilter?: "all" | "owned" | "starred" | undefined;
269
- }, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>, {
270
- [x: string]: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.AnyExtensionDataRef, {
271
- optional: boolean;
272
- singleton: boolean;
273
- }>;
274
- }, {
354
+ config: {
355
+ initialFilter: "all" | "owned" | "starred";
356
+ };
357
+ configInput: {
358
+ initialFilter?: "all" | "owned" | "starred" | undefined;
359
+ };
360
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>;
361
+ inputs: {
362
+ [x: string]: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.AnyExtensionDataRef, {
363
+ optional: boolean;
364
+ singleton: boolean;
365
+ }>;
366
+ };
275
367
  kind: "catalog-filter";
276
368
  namespace: undefined;
277
369
  name: "list";
278
370
  }>;
279
371
  "page:catalog": _backstage_frontend_plugin_api.ExtensionDefinition<{
280
- [x: string]: any;
281
- } & {
282
- path: string | undefined;
283
- }, {
284
- [x: string]: any;
285
- } & {
286
- path?: string | undefined;
287
- }, _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", {
288
- optional: true;
289
- }>, {
290
- filters: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>, {
291
- singleton: false;
292
- optional: false;
372
+ config: {
373
+ path: string | undefined;
374
+ };
375
+ configInput: {
376
+ path?: string | undefined;
377
+ };
378
+ output: _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", {
379
+ optional: true;
293
380
  }>;
294
- }, {
381
+ inputs: {
382
+ filters: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>, {
383
+ singleton: false;
384
+ optional: false;
385
+ }>;
386
+ };
295
387
  kind: "page";
296
388
  namespace: undefined;
297
389
  name: undefined;
298
390
  }>;
299
391
  "page:catalog/entity": _backstage_frontend_plugin_api.ExtensionDefinition<{
300
- [x: string]: any;
301
- } & {
302
- path: string | undefined;
303
- }, {
304
- [x: string]: any;
305
- } & {
306
- path?: string | undefined;
307
- }, _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", {
308
- optional: true;
309
- }>, {
310
- contents: _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", {
311
- optional: true;
312
- }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-content-title", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
313
- optional: true;
314
- }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
392
+ config: {
393
+ path: string | undefined;
394
+ };
395
+ configInput: {
396
+ path?: string | undefined;
397
+ };
398
+ output: _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", {
315
399
  optional: true;
316
- }>, {
317
- singleton: false;
318
- optional: false;
319
400
  }>;
320
- }, {
401
+ inputs: {
402
+ contents: _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", {
403
+ optional: true;
404
+ }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-content-title", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
405
+ optional: true;
406
+ }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
407
+ optional: true;
408
+ }>, {
409
+ singleton: false;
410
+ optional: false;
411
+ }>;
412
+ };
321
413
  kind: "page";
322
414
  namespace: undefined;
323
415
  name: "entity";
324
416
  }>;
325
417
  "search-result-list-item:catalog": _backstage_frontend_plugin_api.ExtensionDefinition<{
326
- noTrack: boolean;
327
- }, {
328
- noTrack?: boolean | undefined;
329
- }, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<{
330
- predicate?: _backstage_plugin_search_react_alpha.SearchResultItemExtensionPredicate | undefined;
331
- component: _backstage_plugin_search_react_alpha.SearchResultItemExtensionComponent;
332
- }, "search.search-result-list-item.item", {}>, {}, {
333
418
  kind: "search-result-list-item";
334
419
  namespace: undefined;
335
420
  name: undefined;
421
+ config: {
422
+ noTrack: boolean;
423
+ };
424
+ configInput: {
425
+ noTrack?: boolean | undefined;
426
+ };
427
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<{
428
+ predicate?: _backstage_plugin_search_react_alpha.SearchResultItemExtensionPredicate | undefined;
429
+ component: _backstage_plugin_search_react_alpha.SearchResultItemExtensionComponent;
430
+ }, "search.search-result-list-item.item", {}>;
431
+ inputs: {};
336
432
  }>;
337
433
  }>;
338
434
 
339
- /**
340
- * @alpha
341
- * @deprecated Use {@link CatalogFilterBlueprint} instead
342
- */
343
- declare function createCatalogFilterExtension<TInputs extends AnyExtensionInputMap, TConfig>(options: {
344
- namespace?: string;
345
- name?: string;
346
- inputs?: TInputs;
347
- configSchema?: PortableSchema<TConfig>;
348
- loader: (options: {
349
- config: TConfig;
350
- }) => Promise<JSX.Element>;
351
- }): _backstage_frontend_plugin_api.ExtensionDefinition<TConfig, TConfig, never, never, {
352
- kind?: string | undefined;
353
- namespace?: string | undefined;
354
- name?: string | undefined;
355
- }>;
356
-
357
435
  /**
358
436
  * Creates Catalog Filter Extensions
359
437
  * @alpha
@@ -362,9 +440,15 @@ declare const CatalogFilterBlueprint: _backstage_frontend_plugin_api.ExtensionBl
362
440
  kind: "catalog-filter";
363
441
  namespace: undefined;
364
442
  name: undefined;
365
- }, {
366
- loader: () => Promise<JSX.Element>;
367
- }, _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>, {}, {}, {}, never>;
443
+ params: {
444
+ loader: () => Promise<JSX.Element>;
445
+ };
446
+ output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}>;
447
+ inputs: {};
448
+ config: {};
449
+ configInput: {};
450
+ dataRefs: never;
451
+ }>;
368
452
 
369
453
  /** @alpha */
370
454
  declare const catalogTranslationRef: _backstage_core_plugin_api_alpha.TranslationRef<"catalog", {
@@ -448,4 +532,4 @@ declare const catalogTranslationRef: _backstage_core_plugin_api_alpha.Translatio
448
532
  readonly "systemDiagramCard.edgeLabels.provides": "provides";
449
533
  }>;
450
534
 
451
- export { CatalogFilterBlueprint, catalogTranslationRef, createCatalogFilterExtension, _default as default };
535
+ export { CatalogFilterBlueprint, catalogTranslationRef, _default as default };
package/dist/alpha.esm.js CHANGED
@@ -1,5 +1,4 @@
1
1
  export { default } from './alpha/plugin.esm.js';
2
- export { createCatalogFilterExtension } from './alpha/createCatalogFilterExtension.esm.js';
3
2
  export { CatalogFilterBlueprint } from './alpha/blueprints/CatalogFilterBlueprint.esm.js';
4
3
  export { catalogTranslationRef } from './alpha/translation.esm.js';
5
4
  //# sourceMappingURL=alpha.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"alpha.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
1
+ {"version":3,"file":"alpha.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
@@ -155,7 +155,16 @@ class DefaultEntityPresentationApi {
155
155
  return new DataLoader(
156
156
  async (entityRefs) => {
157
157
  const { items } = await options.catalogApi.getEntitiesByRefs({
158
- entityRefs
158
+ entityRefs,
159
+ fields: [
160
+ "kind",
161
+ "metadata.name",
162
+ "metadata.namespace",
163
+ "metadata.title",
164
+ "metadata.description",
165
+ "spec.profile.displayName",
166
+ "spec.type"
167
+ ]
159
168
  });
160
169
  const now = Date.now();
161
170
  entityRefs.forEach((entityRef, index) => {
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultEntityPresentationApi.esm.js","sources":["../../../src/apis/EntityPresentationApi/DefaultEntityPresentationApi.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Entity,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { IconComponent } from '@backstage/core-plugin-api';\nimport {\n CatalogApi,\n EntityPresentationApi,\n EntityRefPresentation,\n EntityRefPresentationSnapshot,\n} from '@backstage/plugin-catalog-react';\nimport { HumanDuration, durationToMilliseconds } from '@backstage/types';\nimport DataLoader from 'dataloader';\nimport ExpiryMap from 'expiry-map';\nimport ObservableImpl from 'zen-observable';\nimport {\n DEFAULT_BATCH_DELAY,\n DEFAULT_CACHE_TTL,\n DEFAULT_ICONS,\n createDefaultRenderer,\n} from './defaults';\n\n/**\n * A custom renderer for the {@link DefaultEntityPresentationApi}.\n *\n * @public\n */\nexport interface DefaultEntityPresentationApiRenderer {\n /**\n * Whether to request the entity from the catalog API asynchronously.\n *\n * @remarks\n *\n * If this is set to true, entity data will be streamed in from the catalog\n * whenever needed, and the render function may be called more than once:\n * first when no entity data existed (or with old cached data), and then again\n * at a later point when data is loaded from the catalog that proved to be\n * different from the old one.\n *\n * @defaultValue true\n */\n async?: boolean;\n\n /**\n * The actual render function.\n *\n * @remarks\n *\n * This function may be called multiple times.\n *\n * The loading flag signals that the framework MAY be trying to load more\n * entity data from the catalog and call the render function again, if it\n * succeeds. In some cases you may want to render a loading state in that\n * case.\n *\n * The entity may or may not be given. If the caller of the presentation API\n * did present an entity upfront, then that's what will be passed in here.\n * Otherwise, it may be a server-side entity that either comes from a local\n * cache or directly from the server.\n *\n * In either case, the renderer should return a presentation that is the most\n * useful possible for the end user, given the data that is available.\n */\n render: (options: {\n entityRef: string;\n loading: boolean;\n entity: Entity | undefined;\n context: {\n defaultKind?: string;\n defaultNamespace?: string;\n };\n }) => {\n snapshot: Omit<EntityRefPresentationSnapshot, 'entityRef'>;\n };\n}\n\n/**\n * Options for the {@link DefaultEntityPresentationApi}.\n *\n * @public\n */\nexport interface DefaultEntityPresentationApiOptions {\n /**\n * The catalog API to use. If you want to use any asynchronous features, you\n * must supply one.\n */\n catalogApi?: CatalogApi;\n\n /**\n * When to expire entities that have been loaded from the catalog API and\n * cached for a while.\n *\n * @defaultValue 10 seconds\n * @remarks\n *\n * The higher this value, the lower the load on the catalog API, but also the\n * higher the risk of users seeing stale data.\n */\n cacheTtl?: HumanDuration;\n\n /**\n * For how long to wait before sending a batch of entity references to the\n * catalog API.\n *\n * @defaultValue 50 milliseconds\n * @remarks\n *\n * The higher this value, the greater the chance of batching up requests from\n * across a page, but also the longer the lag time before displaying accurate\n * information.\n */\n batchDelay?: HumanDuration;\n\n /**\n * A mapping from kinds to icons.\n *\n * @remarks\n *\n * The keys are kinds (case insensitive) that map to icon values to represent\n * kinds by. These are merged with the default set of icons.\n */\n kindIcons?: Record<string, IconComponent>;\n\n /**\n * A custom renderer, if any.\n */\n renderer?: DefaultEntityPresentationApiRenderer;\n}\n\ninterface CacheEntry {\n updatedAt: number;\n entity: Entity | undefined;\n}\n\n/**\n * Default implementation of the {@link @backstage/plugin-catalog-react#EntityPresentationApi}.\n *\n * @public\n */\nexport class DefaultEntityPresentationApi implements EntityPresentationApi {\n /**\n * Creates a new presentation API that does not reach out to the catalog.\n */\n static createLocal(): EntityPresentationApi {\n return new DefaultEntityPresentationApi({\n renderer: createDefaultRenderer({ async: false }),\n });\n }\n\n /**\n * Creates a new presentation API that calls out to the catalog as needed to\n * get additional information about entities.\n */\n static create(\n options: DefaultEntityPresentationApiOptions,\n ): EntityPresentationApi {\n return new DefaultEntityPresentationApi(options);\n }\n\n // This cache holds on to all entity data ever loaded, no matter how old. Each\n // entry is tagged with a timestamp of when it was inserted. We use this map\n // to be able to always render SOME data even though the information is old.\n // Entities change very rarely, so it's likely that the rendered information\n // was perfectly fine in the first place.\n readonly #cache: Map<string, CacheEntry>;\n readonly #cacheTtlMs: number;\n readonly #loader: DataLoader<string, Entity | undefined> | undefined;\n readonly #kindIcons: Record<string, IconComponent>; // lowercased kinds\n readonly #renderer: DefaultEntityPresentationApiRenderer;\n\n private constructor(options: DefaultEntityPresentationApiOptions) {\n const cacheTtl = options.cacheTtl ?? DEFAULT_CACHE_TTL;\n const batchDelay = options.batchDelay ?? DEFAULT_BATCH_DELAY;\n const renderer = options.renderer ?? createDefaultRenderer({ async: true });\n\n const kindIcons: Record<string, IconComponent> = {};\n Object.entries(DEFAULT_ICONS).forEach(([kind, icon]) => {\n kindIcons[kind.toLocaleLowerCase('en-US')] = icon;\n });\n Object.entries(options.kindIcons ?? {}).forEach(([kind, icon]) => {\n kindIcons[kind.toLocaleLowerCase('en-US')] = icon;\n });\n\n if (renderer.async) {\n if (!options.catalogApi) {\n throw new TypeError(`Asynchronous rendering requires a catalog API`);\n }\n this.#loader = this.#createLoader({\n cacheTtl,\n batchDelay,\n renderer,\n catalogApi: options.catalogApi,\n });\n }\n\n this.#cacheTtlMs = durationToMilliseconds(cacheTtl);\n this.#cache = new Map();\n this.#kindIcons = kindIcons;\n this.#renderer = renderer;\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-react#EntityPresentationApi.forEntity} */\n forEntity(\n entityOrRef: Entity | string,\n context?: {\n defaultKind?: string;\n defaultNamespace?: string;\n },\n ): EntityRefPresentation {\n const { entityRef, kind, entity, needsLoad } =\n this.#getEntityForInitialRender(entityOrRef);\n\n // Make a wrapping helper for rendering\n const render = (options: {\n loading: boolean;\n entity?: Entity;\n }): EntityRefPresentationSnapshot => {\n const { snapshot } = this.#renderer.render({\n entityRef: entityRef,\n loading: options.loading,\n entity: options.entity,\n context: context || {},\n });\n return {\n ...snapshot,\n entityRef: entityRef,\n Icon: this.#maybeFallbackIcon(snapshot.Icon, kind),\n };\n };\n\n // First the initial render\n let initialSnapshot: EntityRefPresentationSnapshot;\n try {\n initialSnapshot = render({\n loading: needsLoad,\n entity: entity,\n });\n } catch {\n // This is what gets presented if the renderer throws an error\n initialSnapshot = {\n primaryTitle: entityRef,\n entityRef: entityRef,\n };\n }\n\n if (!needsLoad) {\n return {\n snapshot: initialSnapshot,\n promise: Promise.resolve(initialSnapshot),\n };\n }\n\n // Load the entity and render it\n const maybeUpdatedSnapshot = Promise.resolve()\n .then(() => {\n return this.#loader?.load(entityRef);\n })\n .then(newEntity => {\n // We re-render no matter if we get back a new entity or the old\n // one or nothing, because of the now false loading state - in\n // case the renderer outputs different data depending on that\n return render({\n loading: false,\n entity: newEntity ?? entity,\n });\n })\n .catch(() => {\n // Intentionally ignored - we do not propagate errors to the\n // caller here. The presentation API should be error free and\n // always return SOMETHING that makes sense to render, and we have\n // already ensured above that the initial snapshot was that.\n return undefined;\n });\n\n const observable = new ObservableImpl<EntityRefPresentationSnapshot>(\n subscriber => {\n let aborted = false;\n\n maybeUpdatedSnapshot\n .then(updatedSnapshot => {\n if (updatedSnapshot) {\n subscriber.next(updatedSnapshot);\n }\n })\n .finally(() => {\n if (!aborted) {\n subscriber.complete();\n }\n });\n\n return () => {\n aborted = true;\n };\n },\n );\n\n const promise = maybeUpdatedSnapshot.then(updatedSnapshot => {\n return updatedSnapshot ?? initialSnapshot;\n });\n\n return {\n snapshot: initialSnapshot,\n update$: observable,\n promise: promise,\n };\n }\n\n #getEntityForInitialRender(entityOrRef: Entity | string): {\n entity: Entity | undefined;\n kind: string;\n entityRef: string;\n needsLoad: boolean;\n } {\n // If we were given an entity in the first place, we use it for a single\n // pass of rendering and assume that it's up to date and not partial (i.e.\n // we expect that it wasn't fetched in such a way that the required fields\n // of the renderer were excluded)\n if (typeof entityOrRef !== 'string') {\n return {\n entity: entityOrRef,\n kind: entityOrRef.kind,\n entityRef: stringifyEntityRef(entityOrRef),\n needsLoad: false,\n };\n }\n\n const cached = this.#cache.get(entityOrRef);\n const cachedEntity: Entity | undefined = cached?.entity;\n const cacheNeedsUpdate =\n !cached || Date.now() - cached.updatedAt > this.#cacheTtlMs;\n const needsLoad =\n cacheNeedsUpdate &&\n this.#renderer.async !== false &&\n this.#loader !== undefined;\n\n return {\n entity: cachedEntity,\n kind: parseEntityRef(entityOrRef).kind,\n entityRef: entityOrRef,\n needsLoad,\n };\n }\n\n #createLoader(options: {\n catalogApi: CatalogApi;\n cacheTtl: HumanDuration;\n batchDelay: HumanDuration;\n renderer: DefaultEntityPresentationApiRenderer;\n }): DataLoader<string, Entity | undefined> {\n const cacheTtlMs = durationToMilliseconds(options.cacheTtl);\n const batchDelayMs = durationToMilliseconds(options.batchDelay);\n\n return new DataLoader(\n async (entityRefs: readonly string[]) => {\n const { items } = await options.catalogApi!.getEntitiesByRefs({\n entityRefs: entityRefs as string[],\n });\n\n const now = Date.now();\n entityRefs.forEach((entityRef, index) => {\n this.#cache.set(entityRef, {\n updatedAt: now,\n entity: items[index],\n });\n });\n\n return items;\n },\n {\n name: 'DefaultEntityPresentationApi',\n // This cache is the one that the data loader uses internally for\n // memoizing requests; essentially what it achieves is that multiple\n // requests for the same entity ref will be batched up into a single\n // request and then the resulting promises are held on to. We put an\n // expiring map here, which makes it so that it re-fetches data with the\n // expiry cadence of that map. Otherwise it would only fetch a given ref\n // once and then never try again. This cache does therefore not fulfill\n // the same purpose as the one that is in the root of the class.\n cacheMap: new ExpiryMap(cacheTtlMs),\n maxBatchSize: 100,\n batchScheduleFn: batchDelayMs\n ? cb => setTimeout(cb, batchDelayMs)\n : undefined,\n },\n );\n }\n\n #maybeFallbackIcon(\n renderedIcon: IconComponent | false | undefined,\n kind: string,\n ): IconComponent | false | undefined {\n if (renderedIcon) {\n return renderedIcon;\n } else if (renderedIcon === false) {\n return false;\n }\n\n return this.#kindIcons[kind.toLocaleLowerCase('en-US')];\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DefaultEntityPresentationApi.esm.js","sources":["../../../src/apis/EntityPresentationApi/DefaultEntityPresentationApi.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Entity,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { IconComponent } from '@backstage/core-plugin-api';\nimport {\n CatalogApi,\n EntityPresentationApi,\n EntityRefPresentation,\n EntityRefPresentationSnapshot,\n} from '@backstage/plugin-catalog-react';\nimport { durationToMilliseconds, HumanDuration } from '@backstage/types';\nimport DataLoader from 'dataloader';\nimport ExpiryMap from 'expiry-map';\nimport ObservableImpl from 'zen-observable';\nimport {\n createDefaultRenderer,\n DEFAULT_BATCH_DELAY,\n DEFAULT_CACHE_TTL,\n DEFAULT_ICONS,\n} from './defaults';\n\n/**\n * A custom renderer for the {@link DefaultEntityPresentationApi}.\n *\n * @public\n */\nexport interface DefaultEntityPresentationApiRenderer {\n /**\n * Whether to request the entity from the catalog API asynchronously.\n *\n * @remarks\n *\n * If this is set to true, entity data will be streamed in from the catalog\n * whenever needed, and the render function may be called more than once:\n * first when no entity data existed (or with old cached data), and then again\n * at a later point when data is loaded from the catalog that proved to be\n * different from the old one.\n *\n * @defaultValue true\n */\n async?: boolean;\n\n /**\n * The actual render function.\n *\n * @remarks\n *\n * This function may be called multiple times.\n *\n * The loading flag signals that the framework MAY be trying to load more\n * entity data from the catalog and call the render function again, if it\n * succeeds. In some cases you may want to render a loading state in that\n * case.\n *\n * The entity may or may not be given. If the caller of the presentation API\n * did present an entity upfront, then that's what will be passed in here.\n * Otherwise, it may be a server-side entity that either comes from a local\n * cache or directly from the server.\n *\n * In either case, the renderer should return a presentation that is the most\n * useful possible for the end user, given the data that is available.\n */\n render: (options: {\n entityRef: string;\n loading: boolean;\n entity: Entity | undefined;\n context: {\n defaultKind?: string;\n defaultNamespace?: string;\n };\n }) => {\n snapshot: Omit<EntityRefPresentationSnapshot, 'entityRef'>;\n };\n}\n\n/**\n * Options for the {@link DefaultEntityPresentationApi}.\n *\n * @public\n */\nexport interface DefaultEntityPresentationApiOptions {\n /**\n * The catalog API to use. If you want to use any asynchronous features, you\n * must supply one.\n */\n catalogApi?: CatalogApi;\n\n /**\n * When to expire entities that have been loaded from the catalog API and\n * cached for a while.\n *\n * @defaultValue 10 seconds\n * @remarks\n *\n * The higher this value, the lower the load on the catalog API, but also the\n * higher the risk of users seeing stale data.\n */\n cacheTtl?: HumanDuration;\n\n /**\n * For how long to wait before sending a batch of entity references to the\n * catalog API.\n *\n * @defaultValue 50 milliseconds\n * @remarks\n *\n * The higher this value, the greater the chance of batching up requests from\n * across a page, but also the longer the lag time before displaying accurate\n * information.\n */\n batchDelay?: HumanDuration;\n\n /**\n * A mapping from kinds to icons.\n *\n * @remarks\n *\n * The keys are kinds (case insensitive) that map to icon values to represent\n * kinds by. These are merged with the default set of icons.\n */\n kindIcons?: Record<string, IconComponent>;\n\n /**\n * A custom renderer, if any.\n */\n renderer?: DefaultEntityPresentationApiRenderer;\n}\n\ninterface CacheEntry {\n updatedAt: number;\n entity: Entity | undefined;\n}\n\n/**\n * Default implementation of the {@link @backstage/plugin-catalog-react#EntityPresentationApi}.\n *\n * @public\n */\nexport class DefaultEntityPresentationApi implements EntityPresentationApi {\n /**\n * Creates a new presentation API that does not reach out to the catalog.\n */\n static createLocal(): EntityPresentationApi {\n return new DefaultEntityPresentationApi({\n renderer: createDefaultRenderer({ async: false }),\n });\n }\n\n /**\n * Creates a new presentation API that calls out to the catalog as needed to\n * get additional information about entities.\n */\n static create(\n options: DefaultEntityPresentationApiOptions,\n ): EntityPresentationApi {\n return new DefaultEntityPresentationApi(options);\n }\n\n // This cache holds on to all entity data ever loaded, no matter how old. Each\n // entry is tagged with a timestamp of when it was inserted. We use this map\n // to be able to always render SOME data even though the information is old.\n // Entities change very rarely, so it's likely that the rendered information\n // was perfectly fine in the first place.\n readonly #cache: Map<string, CacheEntry>;\n readonly #cacheTtlMs: number;\n readonly #loader: DataLoader<string, Entity | undefined> | undefined;\n readonly #kindIcons: Record<string, IconComponent>; // lowercased kinds\n readonly #renderer: DefaultEntityPresentationApiRenderer;\n\n private constructor(options: DefaultEntityPresentationApiOptions) {\n const cacheTtl = options.cacheTtl ?? DEFAULT_CACHE_TTL;\n const batchDelay = options.batchDelay ?? DEFAULT_BATCH_DELAY;\n const renderer = options.renderer ?? createDefaultRenderer({ async: true });\n\n const kindIcons: Record<string, IconComponent> = {};\n Object.entries(DEFAULT_ICONS).forEach(([kind, icon]) => {\n kindIcons[kind.toLocaleLowerCase('en-US')] = icon;\n });\n Object.entries(options.kindIcons ?? {}).forEach(([kind, icon]) => {\n kindIcons[kind.toLocaleLowerCase('en-US')] = icon;\n });\n\n if (renderer.async) {\n if (!options.catalogApi) {\n throw new TypeError(`Asynchronous rendering requires a catalog API`);\n }\n this.#loader = this.#createLoader({\n cacheTtl,\n batchDelay,\n renderer,\n catalogApi: options.catalogApi,\n });\n }\n\n this.#cacheTtlMs = durationToMilliseconds(cacheTtl);\n this.#cache = new Map();\n this.#kindIcons = kindIcons;\n this.#renderer = renderer;\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-react#EntityPresentationApi.forEntity} */\n forEntity(\n entityOrRef: Entity | string,\n context?: {\n defaultKind?: string;\n defaultNamespace?: string;\n },\n ): EntityRefPresentation {\n const { entityRef, kind, entity, needsLoad } =\n this.#getEntityForInitialRender(entityOrRef);\n\n // Make a wrapping helper for rendering\n const render = (options: {\n loading: boolean;\n entity?: Entity;\n }): EntityRefPresentationSnapshot => {\n const { snapshot } = this.#renderer.render({\n entityRef: entityRef,\n loading: options.loading,\n entity: options.entity,\n context: context || {},\n });\n return {\n ...snapshot,\n entityRef: entityRef,\n Icon: this.#maybeFallbackIcon(snapshot.Icon, kind),\n };\n };\n\n // First the initial render\n let initialSnapshot: EntityRefPresentationSnapshot;\n try {\n initialSnapshot = render({\n loading: needsLoad,\n entity: entity,\n });\n } catch {\n // This is what gets presented if the renderer throws an error\n initialSnapshot = {\n primaryTitle: entityRef,\n entityRef: entityRef,\n };\n }\n\n if (!needsLoad) {\n return {\n snapshot: initialSnapshot,\n promise: Promise.resolve(initialSnapshot),\n };\n }\n\n // Load the entity and render it\n const maybeUpdatedSnapshot = Promise.resolve()\n .then(() => {\n return this.#loader?.load(entityRef);\n })\n .then(newEntity => {\n // We re-render no matter if we get back a new entity or the old\n // one or nothing, because of the now false loading state - in\n // case the renderer outputs different data depending on that\n return render({\n loading: false,\n entity: newEntity ?? entity,\n });\n })\n .catch(() => {\n // Intentionally ignored - we do not propagate errors to the\n // caller here. The presentation API should be error free and\n // always return SOMETHING that makes sense to render, and we have\n // already ensured above that the initial snapshot was that.\n return undefined;\n });\n\n const observable = new ObservableImpl<EntityRefPresentationSnapshot>(\n subscriber => {\n let aborted = false;\n\n maybeUpdatedSnapshot\n .then(updatedSnapshot => {\n if (updatedSnapshot) {\n subscriber.next(updatedSnapshot);\n }\n })\n .finally(() => {\n if (!aborted) {\n subscriber.complete();\n }\n });\n\n return () => {\n aborted = true;\n };\n },\n );\n\n const promise = maybeUpdatedSnapshot.then(updatedSnapshot => {\n return updatedSnapshot ?? initialSnapshot;\n });\n\n return {\n snapshot: initialSnapshot,\n update$: observable,\n promise: promise,\n };\n }\n\n #getEntityForInitialRender(entityOrRef: Entity | string): {\n entity: Entity | undefined;\n kind: string;\n entityRef: string;\n needsLoad: boolean;\n } {\n // If we were given an entity in the first place, we use it for a single\n // pass of rendering and assume that it's up to date and not partial (i.e.\n // we expect that it wasn't fetched in such a way that the required fields\n // of the renderer were excluded)\n if (typeof entityOrRef !== 'string') {\n return {\n entity: entityOrRef,\n kind: entityOrRef.kind,\n entityRef: stringifyEntityRef(entityOrRef),\n needsLoad: false,\n };\n }\n\n const cached = this.#cache.get(entityOrRef);\n const cachedEntity: Entity | undefined = cached?.entity;\n const cacheNeedsUpdate =\n !cached || Date.now() - cached.updatedAt > this.#cacheTtlMs;\n const needsLoad =\n cacheNeedsUpdate &&\n this.#renderer.async !== false &&\n this.#loader !== undefined;\n\n return {\n entity: cachedEntity,\n kind: parseEntityRef(entityOrRef).kind,\n entityRef: entityOrRef,\n needsLoad,\n };\n }\n\n #createLoader(options: {\n catalogApi: CatalogApi;\n cacheTtl: HumanDuration;\n batchDelay: HumanDuration;\n renderer: DefaultEntityPresentationApiRenderer;\n }): DataLoader<string, Entity | undefined> {\n const cacheTtlMs = durationToMilliseconds(options.cacheTtl);\n const batchDelayMs = durationToMilliseconds(options.batchDelay);\n\n return new DataLoader(\n async (entityRefs: readonly string[]) => {\n const { items } = await options.catalogApi!.getEntitiesByRefs({\n entityRefs: entityRefs as string[],\n fields: [\n 'kind',\n 'metadata.name',\n 'metadata.namespace',\n 'metadata.title',\n 'metadata.description',\n 'spec.profile.displayName',\n 'spec.type',\n ],\n });\n\n const now = Date.now();\n entityRefs.forEach((entityRef, index) => {\n this.#cache.set(entityRef, {\n updatedAt: now,\n entity: items[index],\n });\n });\n\n return items;\n },\n {\n name: 'DefaultEntityPresentationApi',\n // This cache is the one that the data loader uses internally for\n // memoizing requests; essentially what it achieves is that multiple\n // requests for the same entity ref will be batched up into a single\n // request and then the resulting promises are held on to. We put an\n // expiring map here, which makes it so that it re-fetches data with the\n // expiry cadence of that map. Otherwise it would only fetch a given ref\n // once and then never try again. This cache does therefore not fulfill\n // the same purpose as the one that is in the root of the class.\n cacheMap: new ExpiryMap(cacheTtlMs),\n maxBatchSize: 100,\n batchScheduleFn: batchDelayMs\n ? cb => setTimeout(cb, batchDelayMs)\n : undefined,\n },\n );\n }\n\n #maybeFallbackIcon(\n renderedIcon: IconComponent | false | undefined,\n kind: string,\n ): IconComponent | false | undefined {\n if (renderedIcon) {\n return renderedIcon;\n } else if (renderedIcon === false) {\n return false;\n }\n\n return this.#kindIcons[kind.toLocaleLowerCase('en-US')];\n }\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-catalog",
3
- "version": "1.22.0",
3
+ "version": "1.22.1-next.0",
4
4
  "description": "The Backstage plugin for browsing the Backstage catalog",
5
5
  "backstage": {
6
6
  "role": "frontend-plugin",
@@ -59,18 +59,18 @@
59
59
  "dependencies": {
60
60
  "@backstage/catalog-client": "^1.6.6",
61
61
  "@backstage/catalog-model": "^1.6.0",
62
- "@backstage/core-compat-api": "^0.2.8",
62
+ "@backstage/core-compat-api": "^0.2.9-next.0",
63
63
  "@backstage/core-components": "^0.14.10",
64
64
  "@backstage/core-plugin-api": "^1.9.3",
65
65
  "@backstage/errors": "^1.2.4",
66
- "@backstage/frontend-plugin-api": "^0.7.0",
66
+ "@backstage/frontend-plugin-api": "^0.8.0-next.0",
67
67
  "@backstage/integration-react": "^1.1.30",
68
68
  "@backstage/plugin-catalog-common": "^1.0.26",
69
- "@backstage/plugin-catalog-react": "^1.12.3",
69
+ "@backstage/plugin-catalog-react": "^1.12.4-next.0",
70
70
  "@backstage/plugin-permission-react": "^0.4.25",
71
71
  "@backstage/plugin-scaffolder-common": "^1.5.5",
72
72
  "@backstage/plugin-search-common": "^1.2.14",
73
- "@backstage/plugin-search-react": "^1.7.14",
73
+ "@backstage/plugin-search-react": "^1.8.0-next.0",
74
74
  "@backstage/types": "^1.1.1",
75
75
  "@material-ui/core": "^4.12.2",
76
76
  "@material-ui/icons": "^4.9.1",
@@ -86,12 +86,12 @@
86
86
  "zen-observable": "^0.10.0"
87
87
  },
88
88
  "devDependencies": {
89
- "@backstage/cli": "^0.27.0",
89
+ "@backstage/cli": "^0.27.1-next.0",
90
90
  "@backstage/core-app-api": "^1.14.2",
91
- "@backstage/dev-utils": "^1.0.37",
92
- "@backstage/frontend-test-utils": "^0.1.12",
91
+ "@backstage/dev-utils": "^1.0.38-next.0",
92
+ "@backstage/frontend-test-utils": "^0.2.0-next.0",
93
93
  "@backstage/plugin-permission-common": "^0.8.1",
94
- "@backstage/test-utils": "^1.5.10",
94
+ "@backstage/test-utils": "^1.6.0-next.0",
95
95
  "@testing-library/dom": "^10.0.0",
96
96
  "@testing-library/jest-dom": "^6.0.0",
97
97
  "@testing-library/react": "^15.0.0",
@@ -1,27 +0,0 @@
1
- import React, { lazy } from 'react';
2
- import { createExtension, coreExtensionData, ExtensionBoundary } from '@backstage/frontend-plugin-api';
3
-
4
- function createCatalogFilterExtension(options) {
5
- return createExtension({
6
- kind: "catalog-filter",
7
- namespace: options.namespace,
8
- name: options.name,
9
- attachTo: { id: "page:catalog", input: "filters" },
10
- inputs: options.inputs ?? {},
11
- configSchema: options.configSchema,
12
- output: {
13
- element: coreExtensionData.reactElement
14
- },
15
- factory({ config, node }) {
16
- const ExtensionComponent = lazy(
17
- () => options.loader({ config }).then((element) => ({ default: () => element }))
18
- );
19
- return {
20
- element: /* @__PURE__ */ React.createElement(ExtensionBoundary, { node }, /* @__PURE__ */ React.createElement(ExtensionComponent, null))
21
- };
22
- }
23
- });
24
- }
25
-
26
- export { createCatalogFilterExtension };
27
- //# sourceMappingURL=createCatalogFilterExtension.esm.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createCatalogFilterExtension.esm.js","sources":["../../src/alpha/createCatalogFilterExtension.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { lazy } from 'react';\nimport {\n AnyExtensionInputMap,\n ExtensionBoundary,\n PortableSchema,\n coreExtensionData,\n createExtension,\n} from '@backstage/frontend-plugin-api';\n\n/**\n * @alpha\n * @deprecated Use {@link CatalogFilterBlueprint} instead\n */\nexport function createCatalogFilterExtension<\n TInputs extends AnyExtensionInputMap,\n TConfig,\n>(options: {\n namespace?: string;\n name?: string;\n inputs?: TInputs;\n configSchema?: PortableSchema<TConfig>;\n loader: (options: { config: TConfig }) => Promise<JSX.Element>;\n}) {\n return createExtension({\n kind: 'catalog-filter',\n namespace: options.namespace,\n name: options.name,\n attachTo: { id: 'page:catalog', input: 'filters' },\n inputs: options.inputs ?? {},\n configSchema: options.configSchema,\n output: {\n element: coreExtensionData.reactElement,\n },\n factory({ config, node }) {\n const ExtensionComponent = lazy(() =>\n options\n .loader({ config })\n .then(element => ({ default: () => element })),\n );\n\n return {\n element: (\n <ExtensionBoundary node={node}>\n <ExtensionComponent />\n </ExtensionBoundary>\n ),\n };\n },\n });\n}\n"],"names":[],"mappings":";;;AA6BO,SAAS,6BAGd,OAMC,EAAA;AACD,EAAA,OAAO,eAAgB,CAAA;AAAA,IACrB,IAAM,EAAA,gBAAA;AAAA,IACN,WAAW,OAAQ,CAAA,SAAA;AAAA,IACnB,MAAM,OAAQ,CAAA,IAAA;AAAA,IACd,QAAU,EAAA,EAAE,EAAI,EAAA,cAAA,EAAgB,OAAO,SAAU,EAAA;AAAA,IACjD,MAAA,EAAQ,OAAQ,CAAA,MAAA,IAAU,EAAC;AAAA,IAC3B,cAAc,OAAQ,CAAA,YAAA;AAAA,IACtB,MAAQ,EAAA;AAAA,MACN,SAAS,iBAAkB,CAAA,YAAA;AAAA,KAC7B;AAAA,IACA,OAAQ,CAAA,EAAE,MAAQ,EAAA,IAAA,EAAQ,EAAA;AACxB,MAAA,MAAM,kBAAqB,GAAA,IAAA;AAAA,QAAK,MAC9B,OAAA,CACG,MAAO,CAAA,EAAE,MAAO,EAAC,CACjB,CAAA,IAAA,CAAK,CAAY,OAAA,MAAA,EAAE,OAAS,EAAA,MAAM,SAAU,CAAA,CAAA;AAAA,OACjD,CAAA;AAEA,MAAO,OAAA;AAAA,QACL,yBACG,KAAA,CAAA,aAAA,CAAA,iBAAA,EAAA,EAAkB,IACjB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,wBAAmB,CACtB,CAAA;AAAA,OAEJ,CAAA;AAAA,KACF;AAAA,GACD,CAAA,CAAA;AACH;;;;"}