@backstage/frontend-plugin-api 0.18.1 → 0.18.2-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.
Files changed (83) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/alpha.d.ts +1 -1
  3. package/dist/analytics/AnalyticsContext.esm.js.map +1 -1
  4. package/dist/analytics/Tracker.esm.js.map +1 -1
  5. package/dist/analytics/useAnalytics.esm.js.map +1 -1
  6. package/dist/apis/definitions/AlertApi.esm.js.map +1 -1
  7. package/dist/apis/definitions/AnalyticsApi.esm.js.map +1 -1
  8. package/dist/apis/definitions/AppLanguageApi.esm.js.map +1 -1
  9. package/dist/apis/definitions/AppThemeApi.esm.js.map +1 -1
  10. package/dist/apis/definitions/AppTreeApi.esm.js.map +1 -1
  11. package/dist/apis/definitions/ConfigApi.esm.js.map +1 -1
  12. package/dist/apis/definitions/DialogApi.esm.js.map +1 -1
  13. package/dist/apis/definitions/DiscoveryApi.esm.js.map +1 -1
  14. package/dist/apis/definitions/ErrorApi.esm.js.map +1 -1
  15. package/dist/apis/definitions/FeatureFlagsApi.esm.js.map +1 -1
  16. package/dist/apis/definitions/FetchApi.esm.js.map +1 -1
  17. package/dist/apis/definitions/IconsApi.esm.js.map +1 -1
  18. package/dist/apis/definitions/IdentityApi.esm.js.map +1 -1
  19. package/dist/apis/definitions/OAuthRequestApi.esm.js.map +1 -1
  20. package/dist/apis/definitions/PluginHeaderActionsApi.esm.js.map +1 -1
  21. package/dist/apis/definitions/PluginWrapperApi.esm.js.map +1 -1
  22. package/dist/apis/definitions/RouteResolutionApi.esm.js.map +1 -1
  23. package/dist/apis/definitions/StorageApi.esm.js.map +1 -1
  24. package/dist/apis/definitions/SwappableComponentsApi.esm.js.map +1 -1
  25. package/dist/apis/definitions/ToastApi.esm.js.map +1 -1
  26. package/dist/apis/definitions/TranslationApi.esm.js.map +1 -1
  27. package/dist/apis/definitions/auth.esm.js.map +1 -1
  28. package/dist/apis/system/ApiRef.esm.js.map +1 -1
  29. package/dist/apis/system/helpers.esm.js.map +1 -1
  30. package/dist/apis/system/useApi.esm.js.map +1 -1
  31. package/dist/blueprints/AnalyticsImplementationBlueprint.esm.js.map +1 -1
  32. package/dist/blueprints/ApiBlueprint.esm.js.map +1 -1
  33. package/dist/blueprints/AppRootElementBlueprint.esm.js.map +1 -1
  34. package/dist/blueprints/PageBlueprint.esm.js.map +1 -1
  35. package/dist/blueprints/PluginHeaderActionBlueprint.esm.js.map +1 -1
  36. package/dist/blueprints/PluginWrapperBlueprint.esm.js.map +1 -1
  37. package/dist/blueprints/SubPageBlueprint.esm.js.map +1 -1
  38. package/dist/breadcrumbs/useBreadcrumbEntries.esm.js.map +1 -1
  39. package/dist/components/AppNodeProvider.esm.js.map +1 -1
  40. package/dist/components/DefaultSwappableComponents.esm.js.map +1 -1
  41. package/dist/components/ErrorApiBoundary.esm.js.map +1 -1
  42. package/dist/components/ErrorDisplayBoundary.esm.js.map +1 -1
  43. package/dist/components/ExtensionBoundary.esm.js.map +1 -1
  44. package/dist/components/PageLayout.esm.js.map +1 -1
  45. package/dist/components/createSwappableComponent.esm.js.map +1 -1
  46. package/dist/core-plugin-api/src/analytics/Tracker.esm.js.map +1 -1
  47. package/dist/frontend-internal/src/apis/OpaqueApiRef.esm.js.map +1 -1
  48. package/dist/frontend-internal/src/routing/OpaqueExternalRouteRef.esm.js.map +1 -1
  49. package/dist/frontend-internal/src/routing/OpaqueRouteRef.esm.js.map +1 -1
  50. package/dist/frontend-internal/src/routing/OpaqueSubRouteRef.esm.js.map +1 -1
  51. package/dist/frontend-internal/src/wiring/InternalExtensionDefinition.esm.js.map +1 -1
  52. package/dist/frontend-internal/src/wiring/InternalExtensionInput.esm.js.map +1 -1
  53. package/dist/frontend-internal/src/wiring/InternalFrontendPlugin.esm.js.map +1 -1
  54. package/dist/frontend-internal/src/wiring/InternalSwappableComponentRef.esm.js.map +1 -1
  55. package/dist/frontend-internal/src/wiring/createExtensionDataContainer.esm.js.map +1 -1
  56. package/dist/index.d.ts +75 -75
  57. package/dist/opaque-internal/src/OpaqueType.esm.js.map +1 -1
  58. package/dist/routing/ExternalRouteRef.esm.js.map +1 -1
  59. package/dist/routing/RouteRef.esm.js.map +1 -1
  60. package/dist/routing/SubRouteRef.esm.js.map +1 -1
  61. package/dist/routing/describeParentCallSite.esm.js.map +1 -1
  62. package/dist/routing/useRouteRef.esm.js.map +1 -1
  63. package/dist/routing/useRouteRefParams.esm.js.map +1 -1
  64. package/dist/schema/assertNoLegacyConfigSchema.esm.js.map +1 -1
  65. package/dist/schema/createPortableSchema.esm.js.map +1 -1
  66. package/dist/schema/optionalStringSchema.esm.js.map +1 -1
  67. package/dist/translation/TranslationMessages.esm.js.map +1 -1
  68. package/dist/translation/TranslationRef.esm.js.map +1 -1
  69. package/dist/translation/TranslationResource.esm.js.map +1 -1
  70. package/dist/translation/useTranslationRef.esm.js.map +1 -1
  71. package/dist/types/{alpha.d-DZG-WVJf.d.ts → alpha.d-BVLu8HlA.d.ts} +412 -412
  72. package/dist/wiring/constants.esm.js.map +1 -1
  73. package/dist/wiring/coreExtensionData.esm.js.map +1 -1
  74. package/dist/wiring/createExtension.esm.js.map +1 -1
  75. package/dist/wiring/createExtensionBlueprint.esm.js.map +1 -1
  76. package/dist/wiring/createExtensionDataRef.esm.js.map +1 -1
  77. package/dist/wiring/createExtensionInput.esm.js.map +1 -1
  78. package/dist/wiring/createFrontendFeatureLoader.esm.js.map +1 -1
  79. package/dist/wiring/createFrontendModule.esm.js.map +1 -1
  80. package/dist/wiring/createFrontendPlugin.esm.js.map +1 -1
  81. package/dist/wiring/resolveExtensionDefinition.esm.js.map +1 -1
  82. package/dist/wiring/resolveInputOverrides.esm.js.map +1 -1
  83. package/package.json +10 -10
@@ -1,9 +1,60 @@
1
1
  import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
2
- import { JSX, ComponentType, ReactNode } from 'react';
3
- import { Expand, JsonObject } from '@backstage/types';
2
+ import { ComponentType, ReactNode, JSX } from 'react';
3
+ import { JsonObject, Expand } from '@backstage/types';
4
4
  import { FilterPredicate } from '@backstage/filter-predicates';
5
5
  import { StandardSchemaV1 } from '@standard-schema/spec';
6
6
 
7
+ /**
8
+ * Defines the structure of a plugin wrapper, optionally including a shared
9
+ * hook value.
10
+ *
11
+ * @remarks
12
+ *
13
+ * When `useWrapperValue` is provided, the hook is called in a single location
14
+ * in the app and the resulting value is forwarded as the `value` prop to the
15
+ * component. The hook obeys the rules of React hooks and is not called until a
16
+ * component from the plugin is rendered.
17
+ *
18
+ * @public
19
+ */
20
+ type PluginWrapperDefinition<TValue = unknown | never> = {
21
+ /**
22
+ * Creates a shared value that is forwarded as the `value` prop to the
23
+ * component.
24
+ *
25
+ * @remarks
26
+ *
27
+ * This function obeys the rules of React hooks and is only invoked in a
28
+ * single location in the app. Note that the hook will not be called until a
29
+ * component from the plugin is rendered.
30
+ */
31
+ useWrapperValue?: () => TValue;
32
+ component: ComponentType<{
33
+ children: ReactNode;
34
+ value: TValue;
35
+ }>;
36
+ };
37
+ /**
38
+ * Creates extensions that wrap plugin extensions with providers.
39
+ *
40
+ * @public
41
+ */
42
+ declare const PluginWrapperBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprint<{
43
+ kind: "plugin-wrapper";
44
+ params: <TValue = never>(params: {
45
+ loader: () => Promise<PluginWrapperDefinition<TValue>>;
46
+ }) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<{
47
+ loader: () => Promise<PluginWrapperDefinition>;
48
+ }>;
49
+ output: _backstage_frontend_plugin_api.ExtensionDataRef<() => Promise<PluginWrapperDefinition>, "core.plugin-wrapper.loader", {}>;
50
+ inputs: {};
51
+ config: {};
52
+ configInput: {};
53
+ dataRefs: {
54
+ wrapper: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<() => Promise<PluginWrapperDefinition>, "core.plugin-wrapper.loader", {}>;
55
+ };
56
+ }>;
57
+
7
58
  /**
8
59
  * IconComponent is the common icon type used throughout Backstage when
9
60
  * working with and rendering generic icons, including the app system icons.
@@ -80,6 +131,138 @@ declare function createRouteRef<TParamKey extends string = never>(config?: {
80
131
  [param in TParamKey]: string;
81
132
  }>;
82
133
 
134
+ /** @public */
135
+ type PortableSchema<TOutput = unknown, TInput = TOutput> = {
136
+ parse: (input: TInput) => TOutput;
137
+ schema: () => {
138
+ schema: JsonObject;
139
+ };
140
+ };
141
+
142
+ /** @public */
143
+ type ExtensionAttachTo = {
144
+ id: string;
145
+ input: string;
146
+ };
147
+ /** @public */
148
+ interface Extension<TConfig, TConfigInput = TConfig> {
149
+ $$type: '@backstage/Extension';
150
+ readonly id: string;
151
+ readonly attachTo: ExtensionAttachTo;
152
+ readonly disabled: boolean;
153
+ readonly configSchema?: PortableSchema<TConfig, TConfigInput>;
154
+ }
155
+ /** @ignore */
156
+ type ResolveExtensionId<TExtension extends ExtensionDefinition, TNamespace extends string> = TExtension extends ExtensionDefinition<{
157
+ kind: infer IKind extends string | undefined;
158
+ name: infer IName extends string | undefined;
159
+ params: any;
160
+ }> ? [string] extends [IKind | IName] ? never : (undefined extends IName ? TNamespace : `${TNamespace}/${IName}`) extends infer INamePart extends string ? IKind extends string ? `${IKind}:${INamePart}` : INamePart : never : never;
161
+
162
+ /**
163
+ * The specification for this {@link AppNode} in the {@link AppTree}.
164
+ *
165
+ * @public
166
+ * @remarks
167
+ *
168
+ * The specifications for a collection of app nodes is all the information needed
169
+ * to build the tree and instantiate the nodes.
170
+ */
171
+ interface AppNodeSpec {
172
+ readonly id: string;
173
+ readonly attachTo: ExtensionAttachTo;
174
+ readonly extension: Extension<unknown, unknown>;
175
+ readonly disabled: boolean;
176
+ readonly if?: FilterPredicate;
177
+ readonly config?: unknown;
178
+ readonly plugin: FrontendPlugin;
179
+ }
180
+ /**
181
+ * The connections from this {@link AppNode} to other nodes.
182
+ *
183
+ * @public
184
+ * @remarks
185
+ *
186
+ * The app node edges are resolved based on the app node specs, regardless of whether
187
+ * adjacent nodes are disabled or not. If no parent attachment is present or
188
+ */
189
+ interface AppNodeEdges {
190
+ readonly attachedTo?: {
191
+ node: AppNode;
192
+ input: string;
193
+ };
194
+ readonly attachments: ReadonlyMap<string, AppNode[]>;
195
+ }
196
+ /**
197
+ * The instance of this {@link AppNode} in the {@link AppTree}.
198
+ *
199
+ * @public
200
+ * @remarks
201
+ *
202
+ * The app node instance is created when the `factory` function of an extension is called.
203
+ * Instances will only be present for nodes in the app that are connected to the root
204
+ * node and not disabled
205
+ */
206
+ interface AppNodeInstance {
207
+ /** Returns a sequence of all extension data refs that were output by this instance */
208
+ getDataRefs(): Iterable<ExtensionDataRef<unknown>>;
209
+ /** Get the output data for a single extension data ref */
210
+ getData<T>(ref: ExtensionDataRef<T>): T | undefined;
211
+ }
212
+ /**
213
+ * A node in the {@link AppTree}.
214
+ *
215
+ * @public
216
+ */
217
+ interface AppNode {
218
+ /** The specification for how this node should be instantiated */
219
+ readonly spec: AppNodeSpec;
220
+ /** The edges from this node to other nodes in the app tree */
221
+ readonly edges: AppNodeEdges;
222
+ /** The instance of this node, if it was instantiated */
223
+ readonly instance?: AppNodeInstance;
224
+ }
225
+ /**
226
+ * The app tree containing all {@link AppNode}s of the app.
227
+ *
228
+ * @public
229
+ */
230
+ interface AppTree {
231
+ /** The root node of the app */
232
+ readonly root: AppNode;
233
+ /** A map of all nodes in the app by ID, including orphaned or disabled nodes */
234
+ readonly nodes: ReadonlyMap<string, AppNode>;
235
+ /** A sequence of all nodes with a parent that is not reachable from the app root node */
236
+ readonly orphans: Iterable<AppNode>;
237
+ }
238
+ /**
239
+ * The API for interacting with the {@link AppTree}.
240
+ *
241
+ * @public
242
+ */
243
+ interface AppTreeApi {
244
+ /**
245
+ * Get the {@link AppTree} for the app.
246
+ */
247
+ getTree(): {
248
+ tree: AppTree;
249
+ };
250
+ /**
251
+ * Get all nodes in the app that are mounted at a given route path.
252
+ */
253
+ getNodesByRoutePath(routePath: string): {
254
+ nodes: AppNode[];
255
+ };
256
+ }
257
+ /**
258
+ * The `ApiRef` of {@link AppTreeApi}.
259
+ *
260
+ * @public
261
+ */
262
+ declare const appTreeApiRef: _backstage_frontend_plugin_api.ApiRef<AppTreeApi, "core.app-tree"> & {
263
+ readonly $$type: "@backstage/ApiRef";
264
+ };
265
+
83
266
  /** @public */
84
267
  type ExtensionDataValue<TData, TId extends string> = {
85
268
  readonly $$type: '@backstage/ExtensionDataValue';
@@ -104,127 +287,16 @@ interface ConfigurableExtensionDataRef<TData, TId extends string, TConfig extend
104
287
  optional?: true;
105
288
  } = {}> extends ExtensionDataRef<TData, TId, TConfig> {
106
289
  optional(): ConfigurableExtensionDataRef<TData, TId, TConfig & {
107
- optional: true;
108
- }>;
109
- (t: TData): ExtensionDataValue<TData, TId>;
110
- }
111
- /** @public */
112
- declare function createExtensionDataRef<TData>(): {
113
- with<TId extends string>(options: {
114
- id: TId;
115
- }): ConfigurableExtensionDataRef<TData, TId>;
116
- };
117
-
118
- /** @public */
119
- interface ExtensionInput<UExtensionData extends ExtensionDataRef<unknown, string, {
120
- optional?: true;
121
- }> = ExtensionDataRef, TConfig extends {
122
- singleton: boolean;
123
- optional: boolean;
124
- internal?: boolean;
125
- } = {
126
- singleton: boolean;
127
- optional: boolean;
128
- internal?: boolean;
129
- }> {
130
- readonly $$type: '@backstage/ExtensionInput';
131
- readonly extensionData: Array<UExtensionData>;
132
- readonly config: TConfig;
133
- readonly replaces?: Array<{
134
- id: string;
135
- input: string;
136
- }>;
137
- }
138
- /**
139
- * Creates a new extension input to be passed to the input map of an extension.
140
- *
141
- * @remarks
142
- *
143
- * Extension inputs created with this function can be passed to any `inputs` map
144
- * as part of creating or overriding an extension.
145
- *
146
- * The array of extension data references defines the data this input expects.
147
- * If the required data is not provided by the attached extension, the
148
- * attachment will fail.
149
- *
150
- * The `config` object can be used to restrict the behavior and shape of the
151
- * input. By default an input will accept zero or more extensions from any
152
- * plugin. The following options are available:
153
- *
154
- * - `singleton`: If set to `true`, only one extension can be attached to the
155
- * input at a time. Additional extensions will trigger an app error and be
156
- * ignored.
157
- * - `optional`: If set to `true`, the input is optional and can be omitted,
158
- * this only has an effect if the `singleton` is set to `true`.
159
- * - `internal`: If set to `true`, only extensions from the same plugin will be
160
- * allowed to attach to this input. Other extensions will trigger an app error
161
- * and be ignored.
162
- *
163
- * @param extensionData - The array of extension data references that this input
164
- * expects.
165
- * @param config - The configuration object for the input.
166
- * @returns An extension input declaration.
167
- * @example
168
- * ```ts
169
- * const extension = createExtension({
170
- * attachTo: { id: 'example-parent', input: 'example-input' },
171
- * inputs: {
172
- * content: createExtensionInput([coreExtensionData.reactElement], {
173
- * singleton: true,
174
- * }),
175
- * },
176
- * output: [coreExtensionData.reactElement],
177
- * *factory({ inputs }) {
178
- * const content = inputs.content?.get(coreExtensionData.reactElement);
179
- * yield coreExtensionData.reactElement(<ContentWrapper>{content}</ContentWrapper>);
180
- * },
181
- * });
182
- * ```
183
- * @public
184
- */
185
- declare function createExtensionInput<UExtensionData extends ExtensionDataRef<unknown, string, {
186
- optional?: true;
187
- }>, TConfig extends {
188
- singleton?: boolean;
189
- optional?: boolean;
190
- internal?: boolean;
191
- }>(extensionData: Array<UExtensionData>, config?: TConfig & {
192
- replaces?: Array<{
193
- id: string;
194
- input: string;
195
- }>;
196
- }): ExtensionInput<UExtensionData, {
197
- singleton: TConfig['singleton'] extends true ? true : false;
198
- optional: TConfig['optional'] extends true ? true : false;
199
- internal: TConfig['internal'] extends true ? true : false;
200
- }>;
201
-
202
- /** @ignore */
203
- type ResolvedInputValueOverrides<TInputs extends {
204
- [inputName in string]: ExtensionInput;
205
- } = {
206
- [inputName in string]: ExtensionInput;
207
- }> = Expand<{
208
- [KName in keyof TInputs as TInputs[KName] extends ExtensionInput<any, {
209
- optional: infer IOptional extends boolean;
210
- singleton: boolean;
211
- internal?: boolean;
212
- }> ? IOptional extends true ? never : KName : never]: TInputs[KName] extends ExtensionInput<infer IDataRefs, {
213
- optional: boolean;
214
- singleton: infer ISingleton extends boolean;
215
- internal?: boolean;
216
- }> ? ISingleton extends true ? Iterable<ExtensionDataRefToValue<IDataRefs>> : Array<Iterable<ExtensionDataRefToValue<IDataRefs>>> : never;
217
- } & {
218
- [KName in keyof TInputs as TInputs[KName] extends ExtensionInput<any, {
219
- optional: infer IOptional extends boolean;
220
- singleton: boolean;
221
- internal?: boolean;
222
- }> ? IOptional extends true ? KName : never : never]?: TInputs[KName] extends ExtensionInput<infer IDataRefs, {
223
- optional: boolean;
224
- singleton: infer ISingleton extends boolean;
225
- internal?: boolean;
226
- }> ? ISingleton extends true ? Iterable<ExtensionDataRefToValue<IDataRefs>> : Array<Iterable<ExtensionDataRefToValue<IDataRefs>>> : never;
227
- }>;
290
+ optional: true;
291
+ }>;
292
+ (t: TData): ExtensionDataValue<TData, TId>;
293
+ }
294
+ /** @public */
295
+ declare function createExtensionDataRef<TData>(): {
296
+ with<TId extends string>(options: {
297
+ id: TId;
298
+ }): ConfigurableExtensionDataRef<TData, TId>;
299
+ };
228
300
 
229
301
  /** @public */
230
302
  interface CreateFrontendModuleOptions<TPluginId extends string, TExtensions extends readonly ExtensionDefinition[]> {
@@ -279,33 +351,36 @@ interface FrontendModule {
279
351
  */
280
352
  declare function createFrontendModule<TId extends string, TExtensions extends readonly ExtensionDefinition[]>(options: CreateFrontendModuleOptions<TId, TExtensions>): FrontendModule;
281
353
 
282
- /** @public */
283
- type PortableSchema<TOutput = unknown, TInput = TOutput> = {
284
- parse: (input: TInput) => TOutput;
285
- schema: () => {
286
- schema: JsonObject;
287
- };
354
+ /**
355
+ * Feature flag configuration.
356
+ *
357
+ * @public
358
+ */
359
+ type FeatureFlagConfig = {
360
+ /** Feature flag name */
361
+ name: string;
362
+ /** Feature flag description */
363
+ description?: string;
288
364
  };
289
-
290
365
  /** @public */
291
- type ExtensionAttachTo = {
292
- id: string;
293
- input: string;
366
+ type ExtensionDataContainer<UExtensionData extends ExtensionDataRef> = Iterable<UExtensionData extends ExtensionDataRef<infer IData, infer IId, infer IConfig> ? IConfig['optional'] extends true ? never : ExtensionDataValue<IData, IId> : never> & {
367
+ get<TId extends UExtensionData['id']>(ref: ExtensionDataRef<any, TId, any>): UExtensionData extends ExtensionDataRef<infer IData, TId, infer IConfig> ? IConfig['optional'] extends true ? IData | undefined : IData : never;
294
368
  };
295
- /** @public */
296
- interface Extension<TConfig, TConfigInput = TConfig> {
297
- $$type: '@backstage/Extension';
298
- readonly id: string;
299
- readonly attachTo: ExtensionAttachTo;
300
- readonly disabled: boolean;
301
- readonly configSchema?: PortableSchema<TConfig, TConfigInput>;
302
- }
303
- /** @ignore */
304
- type ResolveExtensionId<TExtension extends ExtensionDefinition, TNamespace extends string> = TExtension extends ExtensionDefinition<{
305
- kind: infer IKind extends string | undefined;
306
- name: infer IName extends string | undefined;
307
- params: any;
308
- }> ? [string] extends [IKind | IName] ? never : (undefined extends IName ? TNamespace : `${TNamespace}/${IName}`) extends infer INamePart extends string ? IKind extends string ? `${IKind}:${INamePart}` : INamePart : never : never;
369
+ /**
370
+ * @public
371
+ * @deprecated Moved to {@link @backstage/frontend-app-api#ExtensionFactoryMiddleware}
372
+ */
373
+ type ExtensionFactoryMiddleware = (originalFactory: (contextOverrides?: {
374
+ config?: JsonObject;
375
+ }) => ExtensionDataContainer<ExtensionDataRef>, context: {
376
+ node: AppNode;
377
+ apis: ApiHolder;
378
+ config?: JsonObject;
379
+ }) => Iterable<ExtensionDataValue<any, any>>;
380
+ /** @public */
381
+ type FrontendFeature = (Omit<FrontendPlugin, 'pluginId'> & {
382
+ pluginId?: string;
383
+ }) | FrontendModule;
309
384
 
310
385
  type CompareChars<A extends string, B extends string> = [A, B] extends [
311
386
  `${infer IAHead}${infer IARest}`,
@@ -663,35 +738,202 @@ declare function createFrontendPlugin<TId extends string, TExtensions extends re
663
738
  } = {}>(options: CreateFrontendPluginOptions<TId, TRoutes, TExternalRoutes, TExtensions>): OverridableFrontendPlugin<TRoutes, TExternalRoutes, MakeSortedExtensionsMap<TExtensions[number], TId>>;
664
739
 
665
740
  /**
666
- * Feature flag configuration.
741
+ * API reference.
667
742
  *
668
743
  * @public
669
744
  */
670
- type FeatureFlagConfig = {
671
- /** Feature flag name */
672
- name: string;
673
- /** Feature flag description */
674
- description?: string;
745
+ type ApiRef<T, TId extends string = string> = {
746
+ readonly $$type?: '@backstage/ApiRef';
747
+ readonly id: TId;
748
+ readonly T: T;
675
749
  };
676
- /** @public */
677
- type ExtensionDataContainer<UExtensionData extends ExtensionDataRef> = Iterable<UExtensionData extends ExtensionDataRef<infer IData, infer IId, infer IConfig> ? IConfig['optional'] extends true ? never : ExtensionDataValue<IData, IId> : never> & {
678
- get<TId extends UExtensionData['id']>(ref: ExtensionDataRef<any, TId, any>): UExtensionData extends ExtensionDataRef<infer IData, TId, infer IConfig> ? IConfig['optional'] extends true ? IData | undefined : IData : never;
750
+ /**
751
+ * Catch-all {@link ApiRef} type.
752
+ *
753
+ * @public
754
+ */
755
+ type AnyApiRef = ApiRef<unknown>;
756
+ /**
757
+ * Wraps a type with API properties into a type holding their respective {@link ApiRef}s.
758
+ *
759
+ * @public
760
+ */
761
+ type TypesToApiRefs<T> = {
762
+ [key in keyof T]: ApiRef<T[key]>;
679
763
  };
680
764
  /**
765
+ * Provides lookup of APIs through their {@link ApiRef}s.
766
+ *
681
767
  * @public
682
- * @deprecated Moved to {@link @backstage/frontend-app-api#ExtensionFactoryMiddleware}
683
768
  */
684
- type ExtensionFactoryMiddleware = (originalFactory: (contextOverrides?: {
685
- config?: JsonObject;
686
- }) => ExtensionDataContainer<ExtensionDataRef>, context: {
687
- node: AppNode;
688
- apis: ApiHolder;
689
- config?: JsonObject;
690
- }) => Iterable<ExtensionDataValue<any, any>>;
691
- /** @public */
692
- type FrontendFeature = (Omit<FrontendPlugin, 'pluginId'> & {
693
- pluginId?: string;
694
- }) | FrontendModule;
769
+ type ApiHolder = {
770
+ get<T>(api: ApiRef<T>): T | undefined;
771
+ };
772
+ /**
773
+ * Describes type returning API implementations.
774
+ *
775
+ * @public
776
+ */
777
+ type ApiFactory<Api, Impl extends Api, Deps extends {
778
+ [name in string]: unknown;
779
+ }> = {
780
+ api: ApiRef<Api>;
781
+ deps: TypesToApiRefs<Deps>;
782
+ factory(deps: Deps): Impl;
783
+ };
784
+ /**
785
+ * Catch-all {@link ApiFactory} type.
786
+ *
787
+ * @public
788
+ */
789
+ type AnyApiFactory = ApiFactory<unknown, unknown, {
790
+ [key in string]: unknown;
791
+ }>;
792
+
793
+ /**
794
+ * The Plugin Wrapper API allows plugins to wrap their extensions with
795
+ * providers. This API is only intended for internal use by the Backstage
796
+ * frontend system. To provide contexts to plugin components, use
797
+ * `ExtensionBoundary` instead.
798
+ *
799
+ * @public
800
+ */
801
+ type PluginWrapperApi = {
802
+ /**
803
+ * Returns the root wrapper that manages the global plugin state across
804
+ * plugin wrapper instances.
805
+ */
806
+ getRootWrapper(): ComponentType<{
807
+ children: ReactNode;
808
+ }>;
809
+ /**
810
+ * Returns a wrapper component for a specific plugin, or undefined if no
811
+ * wrappers exist. Do not use this API directly, instead use
812
+ * `ExtensionBoundary` to wrap your plugin components if needed.
813
+ */
814
+ getPluginWrapper(pluginId: string): ComponentType<{
815
+ children: ReactNode;
816
+ }> | undefined;
817
+ };
818
+ /**
819
+ * The API reference of {@link PluginWrapperApi}.
820
+ *
821
+ * @public
822
+ */
823
+ declare const pluginWrapperApiRef: _backstage_frontend_plugin_api.ApiRef<PluginWrapperApi, "core.plugin-wrapper"> & {
824
+ readonly $$type: "@backstage/ApiRef";
825
+ };
826
+
827
+ /** @public */
828
+ interface ExtensionInput<UExtensionData extends ExtensionDataRef<unknown, string, {
829
+ optional?: true;
830
+ }> = ExtensionDataRef, TConfig extends {
831
+ singleton: boolean;
832
+ optional: boolean;
833
+ internal?: boolean;
834
+ } = {
835
+ singleton: boolean;
836
+ optional: boolean;
837
+ internal?: boolean;
838
+ }> {
839
+ readonly $$type: '@backstage/ExtensionInput';
840
+ readonly extensionData: Array<UExtensionData>;
841
+ readonly config: TConfig;
842
+ readonly replaces?: Array<{
843
+ id: string;
844
+ input: string;
845
+ }>;
846
+ }
847
+ /**
848
+ * Creates a new extension input to be passed to the input map of an extension.
849
+ *
850
+ * @remarks
851
+ *
852
+ * Extension inputs created with this function can be passed to any `inputs` map
853
+ * as part of creating or overriding an extension.
854
+ *
855
+ * The array of extension data references defines the data this input expects.
856
+ * If the required data is not provided by the attached extension, the
857
+ * attachment will fail.
858
+ *
859
+ * The `config` object can be used to restrict the behavior and shape of the
860
+ * input. By default an input will accept zero or more extensions from any
861
+ * plugin. The following options are available:
862
+ *
863
+ * - `singleton`: If set to `true`, only one extension can be attached to the
864
+ * input at a time. Additional extensions will trigger an app error and be
865
+ * ignored.
866
+ * - `optional`: If set to `true`, the input is optional and can be omitted,
867
+ * this only has an effect if the `singleton` is set to `true`.
868
+ * - `internal`: If set to `true`, only extensions from the same plugin will be
869
+ * allowed to attach to this input. Other extensions will trigger an app error
870
+ * and be ignored.
871
+ *
872
+ * @param extensionData - The array of extension data references that this input
873
+ * expects.
874
+ * @param config - The configuration object for the input.
875
+ * @returns An extension input declaration.
876
+ * @example
877
+ * ```ts
878
+ * const extension = createExtension({
879
+ * attachTo: { id: 'example-parent', input: 'example-input' },
880
+ * inputs: {
881
+ * content: createExtensionInput([coreExtensionData.reactElement], {
882
+ * singleton: true,
883
+ * }),
884
+ * },
885
+ * output: [coreExtensionData.reactElement],
886
+ * *factory({ inputs }) {
887
+ * const content = inputs.content?.get(coreExtensionData.reactElement);
888
+ * yield coreExtensionData.reactElement(<ContentWrapper>{content}</ContentWrapper>);
889
+ * },
890
+ * });
891
+ * ```
892
+ * @public
893
+ */
894
+ declare function createExtensionInput<UExtensionData extends ExtensionDataRef<unknown, string, {
895
+ optional?: true;
896
+ }>, TConfig extends {
897
+ singleton?: boolean;
898
+ optional?: boolean;
899
+ internal?: boolean;
900
+ }>(extensionData: Array<UExtensionData>, config?: TConfig & {
901
+ replaces?: Array<{
902
+ id: string;
903
+ input: string;
904
+ }>;
905
+ }): ExtensionInput<UExtensionData, {
906
+ singleton: TConfig['singleton'] extends true ? true : false;
907
+ optional: TConfig['optional'] extends true ? true : false;
908
+ internal: TConfig['internal'] extends true ? true : false;
909
+ }>;
910
+
911
+ /** @ignore */
912
+ type ResolvedInputValueOverrides<TInputs extends {
913
+ [inputName in string]: ExtensionInput;
914
+ } = {
915
+ [inputName in string]: ExtensionInput;
916
+ }> = Expand<{
917
+ [KName in keyof TInputs as TInputs[KName] extends ExtensionInput<any, {
918
+ optional: infer IOptional extends boolean;
919
+ singleton: boolean;
920
+ internal?: boolean;
921
+ }> ? IOptional extends true ? never : KName : never]: TInputs[KName] extends ExtensionInput<infer IDataRefs, {
922
+ optional: boolean;
923
+ singleton: infer ISingleton extends boolean;
924
+ internal?: boolean;
925
+ }> ? ISingleton extends true ? Iterable<ExtensionDataRefToValue<IDataRefs>> : Array<Iterable<ExtensionDataRefToValue<IDataRefs>>> : never;
926
+ } & {
927
+ [KName in keyof TInputs as TInputs[KName] extends ExtensionInput<any, {
928
+ optional: infer IOptional extends boolean;
929
+ singleton: boolean;
930
+ internal?: boolean;
931
+ }> ? IOptional extends true ? KName : never : never]?: TInputs[KName] extends ExtensionInput<infer IDataRefs, {
932
+ optional: boolean;
933
+ singleton: infer ISingleton extends boolean;
934
+ internal?: boolean;
935
+ }> ? ISingleton extends true ? Iterable<ExtensionDataRefToValue<IDataRefs>> : Array<Iterable<ExtensionDataRefToValue<IDataRefs>>> : never;
936
+ }>;
695
937
 
696
938
  /**
697
939
  * A function used to define a parameter mapping function in order to facilitate
@@ -1198,247 +1440,5 @@ declare function createExtension<UOutput extends ExtensionDataRef, TInputs exten
1198
1440
  name: string | undefined extends TName ? undefined : TName;
1199
1441
  }>;
1200
1442
 
1201
- /**
1202
- * The specification for this {@link AppNode} in the {@link AppTree}.
1203
- *
1204
- * @public
1205
- * @remarks
1206
- *
1207
- * The specifications for a collection of app nodes is all the information needed
1208
- * to build the tree and instantiate the nodes.
1209
- */
1210
- interface AppNodeSpec {
1211
- readonly id: string;
1212
- readonly attachTo: ExtensionAttachTo;
1213
- readonly extension: Extension<unknown, unknown>;
1214
- readonly disabled: boolean;
1215
- readonly if?: FilterPredicate;
1216
- readonly config?: unknown;
1217
- readonly plugin: FrontendPlugin;
1218
- }
1219
- /**
1220
- * The connections from this {@link AppNode} to other nodes.
1221
- *
1222
- * @public
1223
- * @remarks
1224
- *
1225
- * The app node edges are resolved based on the app node specs, regardless of whether
1226
- * adjacent nodes are disabled or not. If no parent attachment is present or
1227
- */
1228
- interface AppNodeEdges {
1229
- readonly attachedTo?: {
1230
- node: AppNode;
1231
- input: string;
1232
- };
1233
- readonly attachments: ReadonlyMap<string, AppNode[]>;
1234
- }
1235
- /**
1236
- * The instance of this {@link AppNode} in the {@link AppTree}.
1237
- *
1238
- * @public
1239
- * @remarks
1240
- *
1241
- * The app node instance is created when the `factory` function of an extension is called.
1242
- * Instances will only be present for nodes in the app that are connected to the root
1243
- * node and not disabled
1244
- */
1245
- interface AppNodeInstance {
1246
- /** Returns a sequence of all extension data refs that were output by this instance */
1247
- getDataRefs(): Iterable<ExtensionDataRef<unknown>>;
1248
- /** Get the output data for a single extension data ref */
1249
- getData<T>(ref: ExtensionDataRef<T>): T | undefined;
1250
- }
1251
- /**
1252
- * A node in the {@link AppTree}.
1253
- *
1254
- * @public
1255
- */
1256
- interface AppNode {
1257
- /** The specification for how this node should be instantiated */
1258
- readonly spec: AppNodeSpec;
1259
- /** The edges from this node to other nodes in the app tree */
1260
- readonly edges: AppNodeEdges;
1261
- /** The instance of this node, if it was instantiated */
1262
- readonly instance?: AppNodeInstance;
1263
- }
1264
- /**
1265
- * The app tree containing all {@link AppNode}s of the app.
1266
- *
1267
- * @public
1268
- */
1269
- interface AppTree {
1270
- /** The root node of the app */
1271
- readonly root: AppNode;
1272
- /** A map of all nodes in the app by ID, including orphaned or disabled nodes */
1273
- readonly nodes: ReadonlyMap<string, AppNode>;
1274
- /** A sequence of all nodes with a parent that is not reachable from the app root node */
1275
- readonly orphans: Iterable<AppNode>;
1276
- }
1277
- /**
1278
- * The API for interacting with the {@link AppTree}.
1279
- *
1280
- * @public
1281
- */
1282
- interface AppTreeApi {
1283
- /**
1284
- * Get the {@link AppTree} for the app.
1285
- */
1286
- getTree(): {
1287
- tree: AppTree;
1288
- };
1289
- /**
1290
- * Get all nodes in the app that are mounted at a given route path.
1291
- */
1292
- getNodesByRoutePath(routePath: string): {
1293
- nodes: AppNode[];
1294
- };
1295
- }
1296
- /**
1297
- * The `ApiRef` of {@link AppTreeApi}.
1298
- *
1299
- * @public
1300
- */
1301
- declare const appTreeApiRef: _backstage_frontend_plugin_api.ApiRef<AppTreeApi, "core.app-tree"> & {
1302
- readonly $$type: "@backstage/ApiRef";
1303
- };
1304
-
1305
- /**
1306
- * API reference.
1307
- *
1308
- * @public
1309
- */
1310
- type ApiRef<T, TId extends string = string> = {
1311
- readonly $$type?: '@backstage/ApiRef';
1312
- readonly id: TId;
1313
- readonly T: T;
1314
- };
1315
- /**
1316
- * Catch-all {@link ApiRef} type.
1317
- *
1318
- * @public
1319
- */
1320
- type AnyApiRef = ApiRef<unknown>;
1321
- /**
1322
- * Wraps a type with API properties into a type holding their respective {@link ApiRef}s.
1323
- *
1324
- * @public
1325
- */
1326
- type TypesToApiRefs<T> = {
1327
- [key in keyof T]: ApiRef<T[key]>;
1328
- };
1329
- /**
1330
- * Provides lookup of APIs through their {@link ApiRef}s.
1331
- *
1332
- * @public
1333
- */
1334
- type ApiHolder = {
1335
- get<T>(api: ApiRef<T>): T | undefined;
1336
- };
1337
- /**
1338
- * Describes type returning API implementations.
1339
- *
1340
- * @public
1341
- */
1342
- type ApiFactory<Api, Impl extends Api, Deps extends {
1343
- [name in string]: unknown;
1344
- }> = {
1345
- api: ApiRef<Api>;
1346
- deps: TypesToApiRefs<Deps>;
1347
- factory(deps: Deps): Impl;
1348
- };
1349
- /**
1350
- * Catch-all {@link ApiFactory} type.
1351
- *
1352
- * @public
1353
- */
1354
- type AnyApiFactory = ApiFactory<unknown, unknown, {
1355
- [key in string]: unknown;
1356
- }>;
1357
-
1358
- /**
1359
- * The Plugin Wrapper API allows plugins to wrap their extensions with
1360
- * providers. This API is only intended for internal use by the Backstage
1361
- * frontend system. To provide contexts to plugin components, use
1362
- * `ExtensionBoundary` instead.
1363
- *
1364
- * @public
1365
- */
1366
- type PluginWrapperApi = {
1367
- /**
1368
- * Returns the root wrapper that manages the global plugin state across
1369
- * plugin wrapper instances.
1370
- */
1371
- getRootWrapper(): ComponentType<{
1372
- children: ReactNode;
1373
- }>;
1374
- /**
1375
- * Returns a wrapper component for a specific plugin, or undefined if no
1376
- * wrappers exist. Do not use this API directly, instead use
1377
- * `ExtensionBoundary` to wrap your plugin components if needed.
1378
- */
1379
- getPluginWrapper(pluginId: string): ComponentType<{
1380
- children: ReactNode;
1381
- }> | undefined;
1382
- };
1383
- /**
1384
- * The API reference of {@link PluginWrapperApi}.
1385
- *
1386
- * @public
1387
- */
1388
- declare const pluginWrapperApiRef: _backstage_frontend_plugin_api.ApiRef<PluginWrapperApi, "core.plugin-wrapper"> & {
1389
- readonly $$type: "@backstage/ApiRef";
1390
- };
1391
-
1392
- /**
1393
- * Defines the structure of a plugin wrapper, optionally including a shared
1394
- * hook value.
1395
- *
1396
- * @remarks
1397
- *
1398
- * When `useWrapperValue` is provided, the hook is called in a single location
1399
- * in the app and the resulting value is forwarded as the `value` prop to the
1400
- * component. The hook obeys the rules of React hooks and is not called until a
1401
- * component from the plugin is rendered.
1402
- *
1403
- * @public
1404
- */
1405
- type PluginWrapperDefinition<TValue = unknown | never> = {
1406
- /**
1407
- * Creates a shared value that is forwarded as the `value` prop to the
1408
- * component.
1409
- *
1410
- * @remarks
1411
- *
1412
- * This function obeys the rules of React hooks and is only invoked in a
1413
- * single location in the app. Note that the hook will not be called until a
1414
- * component from the plugin is rendered.
1415
- */
1416
- useWrapperValue?: () => TValue;
1417
- component: ComponentType<{
1418
- children: ReactNode;
1419
- value: TValue;
1420
- }>;
1421
- };
1422
- /**
1423
- * Creates extensions that wrap plugin extensions with providers.
1424
- *
1425
- * @public
1426
- */
1427
- declare const PluginWrapperBlueprint: _backstage_frontend_plugin_api.ExtensionBlueprint<{
1428
- kind: "plugin-wrapper";
1429
- params: <TValue = never>(params: {
1430
- loader: () => Promise<PluginWrapperDefinition<TValue>>;
1431
- }) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<{
1432
- loader: () => Promise<PluginWrapperDefinition>;
1433
- }>;
1434
- output: _backstage_frontend_plugin_api.ExtensionDataRef<() => Promise<PluginWrapperDefinition>, "core.plugin-wrapper.loader", {}>;
1435
- inputs: {};
1436
- config: {};
1437
- configInput: {};
1438
- dataRefs: {
1439
- wrapper: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<() => Promise<PluginWrapperDefinition>, "core.plugin-wrapper.loader", {}>;
1440
- };
1441
- }>;
1442
-
1443
- export { createExtensionBlueprintParams as $, PluginWrapperBlueprint as S, appTreeApiRef as Y, createExtension as Z, createExtensionBlueprint as _, createExtensionDataRef as a0, createExtensionInput as a1, createExternalRouteRef as a2, createFrontendModule as a3, createFrontendPlugin as a4, createRouteRef as a5, createSubRouteRef as a6, pluginWrapperApiRef as a7 };
1444
- export type { AnyApiFactory as A, ExtensionFactoryMiddleware as B, ConfigurableExtensionDataRef as C, ExtensionInput as D, Extension as E, ExternalRouteRef as F, FeatureFlagConfig as G, FrontendFeature as H, FrontendModule as I, FrontendPlugin as J, FrontendPluginInfo as K, FrontendPluginInfoOptions as L, IconComponent as M, IconElement as N, OverridableExtensionDefinition as O, OverridableFrontendPlugin as P, PluginOptions as Q, PluginWrapperApi as R, PluginWrapperDefinition as T, PortableSchema as U, RouteRef as V, SubRouteRef as W, TypesToApiRefs as X, AnyApiRef as a, AnyRouteRefParams as b, ApiFactory as c, ApiHolder as d, ApiRef as e, AppNode as f, AppNodeEdges as g, AppNodeInstance as h, AppNodeSpec as i, AppTree as j, AppTreeApi as k, CreateExtensionBlueprintOptions as l, CreateExtensionOptions as m, CreateFrontendModuleOptions as n, CreateFrontendPluginOptions as o, ExtensionAttachTo as p, ExtensionBlueprint as q, ExtensionBlueprintDefineParams as r, ExtensionBlueprintParameters as s, ExtensionBlueprintParams as t, ExtensionDataContainer as u, ExtensionDataRef as v, ExtensionDataValue as w, ExtensionDefinition as x, ExtensionDefinitionAttachTo as y, ExtensionDefinitionParameters as z };
1443
+ export { createExtensionBlueprintParams as $, PluginWrapperBlueprint as V, appTreeApiRef as Y, createExtension as Z, createExtensionBlueprint as _, createExtensionDataRef as a0, createExtensionInput as a1, createExternalRouteRef as a2, createFrontendModule as a3, createFrontendPlugin as a4, createRouteRef as a5, createSubRouteRef as a6, pluginWrapperApiRef as a7 };
1444
+ export type { AppNode as A, ExtensionDefinition as B, ConfigurableExtensionDataRef as C, ExtensionDefinitionAttachTo as D, ExternalRouteRef as E, FrontendPlugin as F, ExtensionDefinitionParameters as G, ExtensionFactoryMiddleware as H, IconElement as I, ExtensionInput as J, FeatureFlagConfig as K, FrontendModule as L, FrontendPluginInfo as M, FrontendPluginInfoOptions as N, OverridableExtensionDefinition as O, OverridableFrontendPlugin as P, PluginOptions as Q, RouteRef as R, SubRouteRef as S, TypesToApiRefs as T, PluginWrapperApi as U, PluginWrapperDefinition as W, PortableSchema as X, IconComponent as a, AnyRouteRefParams as b, ApiRef as c, ApiHolder as d, ApiFactory as e, FrontendFeature as f, AnyApiFactory as g, AnyApiRef as h, AppNodeEdges as i, AppNodeInstance as j, AppNodeSpec as k, AppTree as l, AppTreeApi as m, CreateExtensionBlueprintOptions as n, CreateExtensionOptions as o, CreateFrontendModuleOptions as p, CreateFrontendPluginOptions as q, Extension as r, ExtensionAttachTo as s, ExtensionBlueprint as t, ExtensionBlueprintDefineParams as u, ExtensionBlueprintParameters as v, ExtensionBlueprintParams as w, ExtensionDataContainer as x, ExtensionDataRef as y, ExtensionDataValue as z };