@backstage/frontend-plugin-api 0.10.0-next.2 → 0.10.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,25 @@
|
|
|
1
1
|
# @backstage/frontend-plugin-api
|
|
2
2
|
|
|
3
|
+
## 0.10.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 4823831: Introduced a `createFrontendFeatureLoader()` function, as well as a `FrontendFeatureLoader` interface, to gather several frontend plugins, modules or feature loaders in a single exported entrypoint and load them, possibly asynchronously. This new feature, very similar to the `createBackendFeatureLoader()` already available on the backend, supersedes the previous `CreateAppFeatureLoader` type which has been deprecated.
|
|
8
|
+
- 8250ffe: **BREAKING**: Removed the deprecated `ExtensionOverrides` and `FrontendFeature` types.
|
|
9
|
+
- 0d1a397: **BREAKING**: Removed deprecated variant of `createExtensionDataRef` where the ID is passed directly.
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 5aa7f2c: Added a new Utility API, `DialogApi`, which can be used to show dialogs in the React tree that can collect input from the user.
|
|
14
|
+
- e23f5e0: Added new `ExtensionMiddlewareFactory` type.
|
|
15
|
+
- a6cb67d: The extensions map for plugins created with `createFrontendPlugin` is now sorted alphabetically by ID in the TypeScript type.
|
|
16
|
+
- de72253: Added a new `ExtensionBoundary.lazyComponent` helper in addition to the existing `ExtensionBoundary.lazy` helper.
|
|
17
|
+
- Updated dependencies
|
|
18
|
+
- @backstage/core-components@0.17.0
|
|
19
|
+
- @backstage/core-plugin-api@1.10.5
|
|
20
|
+
- @backstage/types@1.2.1
|
|
21
|
+
- @backstage/version-bridge@1.0.11
|
|
22
|
+
|
|
3
23
|
## 0.10.0-next.2
|
|
4
24
|
|
|
5
25
|
### Minor Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React$1 from 'react';
|
|
2
2
|
import React__default, { ReactNode, JSX as JSX$1, ComponentType, PropsWithChildren } from 'react';
|
|
3
3
|
import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
|
|
4
|
-
import { ApiHolder, ApiRef, AnyApiFactory, IconComponent as IconComponent$1, SignInPageProps, AppTheme } from '@backstage/core-plugin-api';
|
|
4
|
+
import { ApiHolder, ConfigApi, ApiRef, AnyApiFactory, IconComponent as IconComponent$1, SignInPageProps, AppTheme } from '@backstage/core-plugin-api';
|
|
5
5
|
export { AlertApi, AlertMessage, AnyApiFactory, AnyApiRef, ApiFactory, ApiHolder, ApiRef, ApiRefConfig, AppTheme, AppThemeApi, AuthProviderInfo, AuthRequestOptions, BackstageIdentityApi, BackstageIdentityResponse, BackstageUserIdentity, ConfigApi, DiscoveryApi, ErrorApi, ErrorApiError, ErrorApiErrorContext, FeatureFlag, FeatureFlagState, FeatureFlagsApi, FeatureFlagsSaveOptions, FetchApi, IdentityApi, OAuthApi, OAuthRequestApi, OAuthRequester, OAuthRequesterOptions, OAuthScope, OpenIdConnectApi, PendingOAuthRequest, ProfileInfo, ProfileInfoApi, SessionApi, SessionState, StorageApi, StorageValueSnapshot, TypesToApiRefs, alertApiRef, appThemeApiRef, atlassianAuthApiRef, bitbucketAuthApiRef, bitbucketServerAuthApiRef, configApiRef, createApiFactory, createApiRef, discoveryApiRef, errorApiRef, featureFlagsApiRef, fetchApiRef, githubAuthApiRef, gitlabAuthApiRef, googleAuthApiRef, identityApiRef, microsoftAuthApiRef, oauthRequestApiRef, oktaAuthApiRef, oneloginAuthApiRef, storageApiRef, useApi, useApiHolder, vmwareCloudAuthApiRef, withApis } from '@backstage/core-plugin-api';
|
|
6
6
|
import { Expand, JsonObject } from '@backstage/types';
|
|
7
7
|
import { z } from 'zod';
|
|
@@ -316,6 +316,102 @@ type ResolveInputValueOverrides<TInputs extends {
|
|
|
316
316
|
}> ? ISingleton extends true ? Iterable<ExtensionDataRefToValue<IDataRefs>> : Array<Iterable<ExtensionDataRefToValue<IDataRefs>>> : never;
|
|
317
317
|
}>;
|
|
318
318
|
|
|
319
|
+
/** @public */
|
|
320
|
+
interface CreateFrontendModuleOptions<TPluginId extends string, TExtensions extends readonly ExtensionDefinition[]> {
|
|
321
|
+
pluginId: TPluginId;
|
|
322
|
+
extensions?: TExtensions;
|
|
323
|
+
featureFlags?: FeatureFlagConfig[];
|
|
324
|
+
}
|
|
325
|
+
/** @public */
|
|
326
|
+
interface FrontendModule {
|
|
327
|
+
readonly $$type: '@backstage/FrontendModule';
|
|
328
|
+
readonly pluginId: string;
|
|
329
|
+
}
|
|
330
|
+
/** @public */
|
|
331
|
+
declare function createFrontendModule<TId extends string, TExtensions extends readonly ExtensionDefinition[] = []>(options: CreateFrontendModuleOptions<TId, TExtensions>): FrontendModule;
|
|
332
|
+
|
|
333
|
+
/** @public */
|
|
334
|
+
type PortableSchema<TOutput, TInput = TOutput> = {
|
|
335
|
+
parse: (input: TInput) => TOutput;
|
|
336
|
+
schema: JsonObject;
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
/** @public */
|
|
340
|
+
interface Extension<TConfig, TConfigInput = TConfig> {
|
|
341
|
+
$$type: '@backstage/Extension';
|
|
342
|
+
readonly id: string;
|
|
343
|
+
readonly attachTo: ExtensionAttachToSpec;
|
|
344
|
+
readonly disabled: boolean;
|
|
345
|
+
readonly configSchema?: PortableSchema<TConfig, TConfigInput>;
|
|
346
|
+
}
|
|
347
|
+
/** @ignore */
|
|
348
|
+
type ResolveExtensionId<TExtension extends ExtensionDefinition, TNamespace extends string> = TExtension extends ExtensionDefinition<{
|
|
349
|
+
kind: infer IKind extends string | undefined;
|
|
350
|
+
name: infer IName extends string | undefined;
|
|
351
|
+
}> ? [string] extends [IKind | IName] ? never : (undefined extends IName ? TNamespace : `${TNamespace}/${IName}`) extends infer INamePart extends string ? IKind extends string ? `${IKind}:${INamePart}` : INamePart : never : never;
|
|
352
|
+
|
|
353
|
+
type CompareChars<A extends string, B extends string> = [A, B] extends [
|
|
354
|
+
`${infer IAHead}${infer IARest}`,
|
|
355
|
+
`${infer IBHead}${infer IBRest}`
|
|
356
|
+
] ? IAHead extends IBHead ? IBRest extends '' ? IARest extends '' ? 'eq' : 'gt' : IARest extends '' ? 'lt' : CompareChars<IARest, IBRest> : `0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz` extends `${string}${IAHead}${string}${IBHead}${string}` ? 'lt' : 'gt' : 'eq';
|
|
357
|
+
type CompareStrings<A extends string | undefined, B extends string | undefined> = A extends B ? 'eq' : A extends undefined ? 'lt' : B extends undefined ? 'gt' : CompareChars<A & string, B & string>;
|
|
358
|
+
type CompareExtensions<A extends ExtensionDefinition, B extends ExtensionDefinition> = CompareStrings<A['T']['kind'], B['T']['kind']> extends 'eq' ? CompareStrings<A['T']['name'], B['T']['name']> : CompareStrings<A['T']['kind'], B['T']['kind']>;
|
|
359
|
+
type SortExtensionsInner<TPivot extends ExtensionDefinition, TRest extends readonly ExtensionDefinition[], TLow extends readonly ExtensionDefinition[], THigh extends readonly ExtensionDefinition[]> = TRest extends [
|
|
360
|
+
infer IHead extends ExtensionDefinition,
|
|
361
|
+
...infer IRest extends readonly ExtensionDefinition[]
|
|
362
|
+
] ? CompareExtensions<IHead, TPivot> extends 'lt' ? SortExtensionsInner<TPivot, IRest, [...TLow, IHead], THigh> : SortExtensionsInner<TPivot, IRest, TLow, [...THigh, IHead]> : [low: TLow, high: THigh];
|
|
363
|
+
type SortExtensions<T extends readonly ExtensionDefinition[]> = T extends [
|
|
364
|
+
infer IPivot extends ExtensionDefinition,
|
|
365
|
+
...infer IRest extends readonly ExtensionDefinition[]
|
|
366
|
+
] ? SortExtensionsInner<IPivot, IRest, [], []> extends [
|
|
367
|
+
low: infer ILow extends readonly ExtensionDefinition[],
|
|
368
|
+
high: infer IHigh extends readonly ExtensionDefinition[]
|
|
369
|
+
] ? [...SortExtensions<ILow>, IPivot, ...SortExtensions<IHigh>] : 'invalid SortExtensionsInner' : [];
|
|
370
|
+
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
|
371
|
+
type PopUnion$1<U> = UnionToIntersection<U extends any ? () => U : never> extends () => infer R ? [next: R, rest: Exclude<U, R>] : undefined;
|
|
372
|
+
type UnionToArray<U, T = U, TResult extends T[] = []> = PopUnion$1<U> extends [
|
|
373
|
+
next: infer INext extends T,
|
|
374
|
+
rest: infer IRest extends T
|
|
375
|
+
] ? UnionToArray<IRest, T, [INext, ...TResult]> : TResult;
|
|
376
|
+
type ExtensionArrayToMap<T extends ExtensionDefinition[], TId extends string, TOut extends {
|
|
377
|
+
[KId in string]: ExtensionDefinition;
|
|
378
|
+
} = {}> = T extends [
|
|
379
|
+
infer IHead extends ExtensionDefinition,
|
|
380
|
+
...infer IRest extends ExtensionDefinition[]
|
|
381
|
+
] ? ExtensionArrayToMap<IRest, TId, TOut & {
|
|
382
|
+
[K in ResolveExtensionId<IHead, TId>]: IHead;
|
|
383
|
+
}> : TOut extends infer O ? {
|
|
384
|
+
[K in keyof O]: O[K];
|
|
385
|
+
} : never;
|
|
386
|
+
/** @ignore */
|
|
387
|
+
type MakeSortedExtensionsMap<UExtensions extends ExtensionDefinition, TId extends string> = ExtensionArrayToMap<SortExtensions<UnionToArray<UExtensions>>, TId>;
|
|
388
|
+
|
|
389
|
+
/** @public */
|
|
390
|
+
interface FrontendPlugin<TRoutes extends AnyRoutes = AnyRoutes, TExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes, TExtensionMap extends {
|
|
391
|
+
[id in string]: ExtensionDefinition;
|
|
392
|
+
} = {
|
|
393
|
+
[id in string]: ExtensionDefinition;
|
|
394
|
+
}> {
|
|
395
|
+
readonly $$type: '@backstage/FrontendPlugin';
|
|
396
|
+
readonly id: string;
|
|
397
|
+
readonly routes: TRoutes;
|
|
398
|
+
readonly externalRoutes: TExternalRoutes;
|
|
399
|
+
getExtension<TId extends keyof TExtensionMap>(id: TId): TExtensionMap[TId];
|
|
400
|
+
withOverrides(options: {
|
|
401
|
+
extensions: Array<ExtensionDefinition>;
|
|
402
|
+
}): FrontendPlugin<TRoutes, TExternalRoutes, TExtensionMap>;
|
|
403
|
+
}
|
|
404
|
+
/** @public */
|
|
405
|
+
interface PluginOptions<TId extends string, TRoutes extends AnyRoutes, TExternalRoutes extends AnyExternalRoutes, TExtensions extends readonly ExtensionDefinition[]> {
|
|
406
|
+
id: TId;
|
|
407
|
+
routes?: TRoutes;
|
|
408
|
+
externalRoutes?: TExternalRoutes;
|
|
409
|
+
extensions?: TExtensions;
|
|
410
|
+
featureFlags?: FeatureFlagConfig[];
|
|
411
|
+
}
|
|
412
|
+
/** @public */
|
|
413
|
+
declare function createFrontendPlugin<TId extends string, TRoutes extends AnyRoutes = {}, TExternalRoutes extends AnyExternalRoutes = {}, TExtensions extends readonly ExtensionDefinition[] = []>(options: PluginOptions<TId, TRoutes, TExternalRoutes, TExtensions>): FrontendPlugin<TRoutes, TExternalRoutes, MakeSortedExtensionsMap<TExtensions[number], TId>>;
|
|
414
|
+
|
|
319
415
|
/**
|
|
320
416
|
* Feature flag configuration.
|
|
321
417
|
*
|
|
@@ -345,6 +441,8 @@ type ExtensionFactoryMiddleware = (originalFactory: (contextOverrides?: {
|
|
|
345
441
|
apis: ApiHolder;
|
|
346
442
|
config?: JsonObject;
|
|
347
443
|
}) => Iterable<ExtensionDataValue<any, any>>;
|
|
444
|
+
/** @public */
|
|
445
|
+
type FrontendFeature = FrontendPlugin | FrontendModule;
|
|
348
446
|
|
|
349
447
|
/**
|
|
350
448
|
* Convert a single extension input into a matching resolved input.
|
|
@@ -363,9 +461,9 @@ type ResolvedExtensionInputs<TInputs extends {
|
|
|
363
461
|
[InputName in keyof TInputs]: false extends TInputs[InputName]['config']['singleton'] ? Array<Expand<ResolvedExtensionInput<TInputs[InputName]>>> : false extends TInputs[InputName]['config']['optional'] ? Expand<ResolvedExtensionInput<TInputs[InputName]>> : Expand<ResolvedExtensionInput<TInputs[InputName]> | undefined>;
|
|
364
462
|
};
|
|
365
463
|
type ToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
|
366
|
-
type PopUnion
|
|
464
|
+
type PopUnion<U> = ToIntersection<U extends any ? () => U : never> extends () => infer R ? [rest: Exclude<U, R>, next: R] : undefined;
|
|
367
465
|
/** @ignore */
|
|
368
|
-
type JoinStringUnion<U, TDiv extends string = ', ', TResult extends string = ''> = PopUnion
|
|
466
|
+
type JoinStringUnion<U, TDiv extends string = ', ', TResult extends string = ''> = PopUnion<U> extends [infer IRest extends string, infer INext extends string] ? TResult extends '' ? JoinStringUnion<IRest, TDiv, INext> : JoinStringUnion<IRest, TDiv, `${TResult}${TDiv}${INext}`> : TResult;
|
|
369
467
|
/** @ignore */
|
|
370
468
|
type VerifyExtensionFactoryOutput<UDeclaredOutput extends AnyExtensionDataRef, UFactoryOutput extends ExtensionDataValue<any, any>> = (UDeclaredOutput extends any ? UDeclaredOutput['config']['optional'] extends true ? never : UDeclaredOutput['id'] : never) extends infer IRequiredOutputIds ? [IRequiredOutputIds] extends [UFactoryOutput['id']] ? [UFactoryOutput['id']] extends [UDeclaredOutput['id']] ? {} : `Error: The extension factory has undeclared output(s): ${JoinStringUnion<Exclude<UFactoryOutput['id'], UDeclaredOutput['id']>>}` : `Error: The extension factory is missing the following output(s): ${JoinStringUnion<Exclude<IRequiredOutputIds, UFactoryOutput['id']>>}` : never;
|
|
371
469
|
/** @public */
|
|
@@ -496,100 +594,23 @@ declare function createExtension<UOutput extends AnyExtensionDataRef, TInputs ex
|
|
|
496
594
|
}>;
|
|
497
595
|
|
|
498
596
|
/** @public */
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
readonly disabled: boolean;
|
|
510
|
-
readonly configSchema?: PortableSchema<TConfig, TConfigInput>;
|
|
511
|
-
}
|
|
512
|
-
/** @ignore */
|
|
513
|
-
type ResolveExtensionId<TExtension extends ExtensionDefinition, TNamespace extends string> = TExtension extends ExtensionDefinition<{
|
|
514
|
-
kind: infer IKind extends string | undefined;
|
|
515
|
-
name: infer IName extends string | undefined;
|
|
516
|
-
}> ? [string] extends [IKind | IName] ? never : (undefined extends IName ? TNamespace : `${TNamespace}/${IName}`) extends infer INamePart extends string ? IKind extends string ? `${IKind}:${INamePart}` : INamePart : never : never;
|
|
517
|
-
|
|
518
|
-
type CompareChars<A extends string, B extends string> = [A, B] extends [
|
|
519
|
-
`${infer IAHead}${infer IARest}`,
|
|
520
|
-
`${infer IBHead}${infer IBRest}`
|
|
521
|
-
] ? IAHead extends IBHead ? IBRest extends '' ? IARest extends '' ? 'eq' : 'gt' : IARest extends '' ? 'lt' : CompareChars<IARest, IBRest> : `0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz` extends `${string}${IAHead}${string}${IBHead}${string}` ? 'lt' : 'gt' : 'eq';
|
|
522
|
-
type CompareStrings<A extends string | undefined, B extends string | undefined> = A extends B ? 'eq' : A extends undefined ? 'lt' : B extends undefined ? 'gt' : CompareChars<A & string, B & string>;
|
|
523
|
-
type CompareExtensions<A extends ExtensionDefinition, B extends ExtensionDefinition> = CompareStrings<A['T']['kind'], B['T']['kind']> extends 'eq' ? CompareStrings<A['T']['name'], B['T']['name']> : CompareStrings<A['T']['kind'], B['T']['kind']>;
|
|
524
|
-
type SortExtensionsInner<TPivot extends ExtensionDefinition, TRest extends readonly ExtensionDefinition[], TLow extends readonly ExtensionDefinition[], THigh extends readonly ExtensionDefinition[]> = TRest extends [
|
|
525
|
-
infer IHead extends ExtensionDefinition,
|
|
526
|
-
...infer IRest extends readonly ExtensionDefinition[]
|
|
527
|
-
] ? CompareExtensions<IHead, TPivot> extends 'lt' ? SortExtensionsInner<TPivot, IRest, [...TLow, IHead], THigh> : SortExtensionsInner<TPivot, IRest, TLow, [...THigh, IHead]> : [low: TLow, high: THigh];
|
|
528
|
-
type SortExtensions<T extends readonly ExtensionDefinition[]> = T extends [
|
|
529
|
-
infer IPivot extends ExtensionDefinition,
|
|
530
|
-
...infer IRest extends readonly ExtensionDefinition[]
|
|
531
|
-
] ? SortExtensionsInner<IPivot, IRest, [], []> extends [
|
|
532
|
-
low: infer ILow extends readonly ExtensionDefinition[],
|
|
533
|
-
high: infer IHigh extends readonly ExtensionDefinition[]
|
|
534
|
-
] ? [...SortExtensions<ILow>, IPivot, ...SortExtensions<IHigh>] : 'invalid SortExtensionsInner' : [];
|
|
535
|
-
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
|
536
|
-
type PopUnion<U> = UnionToIntersection<U extends any ? () => U : never> extends () => infer R ? [next: R, rest: Exclude<U, R>] : undefined;
|
|
537
|
-
type UnionToArray<U, T = U, TResult extends T[] = []> = PopUnion<U> extends [
|
|
538
|
-
next: infer INext extends T,
|
|
539
|
-
rest: infer IRest extends T
|
|
540
|
-
] ? UnionToArray<IRest, T, [INext, ...TResult]> : TResult;
|
|
541
|
-
type ExtensionArrayToMap<T extends ExtensionDefinition[], TId extends string, TOut extends {
|
|
542
|
-
[KId in string]: ExtensionDefinition;
|
|
543
|
-
} = {}> = T extends [
|
|
544
|
-
infer IHead extends ExtensionDefinition,
|
|
545
|
-
...infer IRest extends ExtensionDefinition[]
|
|
546
|
-
] ? ExtensionArrayToMap<IRest, TId, TOut & {
|
|
547
|
-
[K in ResolveExtensionId<IHead, TId>]: IHead;
|
|
548
|
-
}> : TOut extends infer O ? {
|
|
549
|
-
[K in keyof O]: O[K];
|
|
550
|
-
} : never;
|
|
551
|
-
/** @ignore */
|
|
552
|
-
type MakeSortedExtensionsMap<UExtensions extends ExtensionDefinition, TId extends string> = ExtensionArrayToMap<SortExtensions<UnionToArray<UExtensions>>, TId>;
|
|
553
|
-
|
|
554
|
-
/** @public */
|
|
555
|
-
interface FrontendPlugin<TRoutes extends AnyRoutes = AnyRoutes, TExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes, TExtensionMap extends {
|
|
556
|
-
[id in string]: ExtensionDefinition;
|
|
557
|
-
} = {
|
|
558
|
-
[id in string]: ExtensionDefinition;
|
|
559
|
-
}> {
|
|
560
|
-
readonly $$type: '@backstage/FrontendPlugin';
|
|
561
|
-
readonly id: string;
|
|
562
|
-
readonly routes: TRoutes;
|
|
563
|
-
readonly externalRoutes: TExternalRoutes;
|
|
564
|
-
getExtension<TId extends keyof TExtensionMap>(id: TId): TExtensionMap[TId];
|
|
565
|
-
withOverrides(options: {
|
|
566
|
-
extensions: Array<ExtensionDefinition>;
|
|
567
|
-
}): FrontendPlugin<TRoutes, TExternalRoutes, TExtensionMap>;
|
|
568
|
-
}
|
|
569
|
-
/** @public */
|
|
570
|
-
interface PluginOptions<TId extends string, TRoutes extends AnyRoutes, TExternalRoutes extends AnyExternalRoutes, TExtensions extends readonly ExtensionDefinition[]> {
|
|
571
|
-
id: TId;
|
|
572
|
-
routes?: TRoutes;
|
|
573
|
-
externalRoutes?: TExternalRoutes;
|
|
574
|
-
extensions?: TExtensions;
|
|
575
|
-
featureFlags?: FeatureFlagConfig[];
|
|
576
|
-
}
|
|
577
|
-
/** @public */
|
|
578
|
-
declare function createFrontendPlugin<TId extends string, TRoutes extends AnyRoutes = {}, TExternalRoutes extends AnyExternalRoutes = {}, TExtensions extends readonly ExtensionDefinition[] = []>(options: PluginOptions<TId, TRoutes, TExternalRoutes, TExtensions>): FrontendPlugin<TRoutes, TExternalRoutes, MakeSortedExtensionsMap<TExtensions[number], TId>>;
|
|
579
|
-
|
|
580
|
-
/** @public */
|
|
581
|
-
interface CreateFrontendModuleOptions<TPluginId extends string, TExtensions extends readonly ExtensionDefinition[]> {
|
|
582
|
-
pluginId: TPluginId;
|
|
583
|
-
extensions?: TExtensions;
|
|
584
|
-
featureFlags?: FeatureFlagConfig[];
|
|
597
|
+
interface CreateFrontendFeatureLoaderOptions {
|
|
598
|
+
loader(deps: {
|
|
599
|
+
config: ConfigApi;
|
|
600
|
+
}): Iterable<FrontendFeature | FrontendFeatureLoader | Promise<{
|
|
601
|
+
default: FrontendFeature | FrontendFeatureLoader;
|
|
602
|
+
}>> | Promise<Iterable<FrontendFeature | FrontendFeatureLoader | Promise<{
|
|
603
|
+
default: FrontendFeature | FrontendFeatureLoader;
|
|
604
|
+
}>>> | AsyncIterable<FrontendFeature | FrontendFeatureLoader | {
|
|
605
|
+
default: FrontendFeature | FrontendFeatureLoader;
|
|
606
|
+
}>;
|
|
585
607
|
}
|
|
586
608
|
/** @public */
|
|
587
|
-
interface
|
|
588
|
-
readonly $$type: '@backstage/
|
|
589
|
-
readonly pluginId: string;
|
|
609
|
+
interface FrontendFeatureLoader {
|
|
610
|
+
readonly $$type: '@backstage/FrontendFeatureLoader';
|
|
590
611
|
}
|
|
591
612
|
/** @public */
|
|
592
|
-
declare function
|
|
613
|
+
declare function createFrontendFeatureLoader(options: CreateFrontendFeatureLoaderOptions): FrontendFeatureLoader;
|
|
593
614
|
|
|
594
615
|
/**
|
|
595
616
|
* @public
|
|
@@ -1525,4 +1546,4 @@ declare namespace createComponentExtension {
|
|
|
1525
1546
|
}, "core.component.component", {}>;
|
|
1526
1547
|
}
|
|
1527
1548
|
|
|
1528
|
-
export { type AnalyticsApi, AnalyticsContext, type AnalyticsContextValue, type AnalyticsEvent, type AnalyticsEventAttributes, type AnalyticsTracker, type AnyExtensionDataRef, type AnyExternalRoutes, type AnyRouteRefParams, type AnyRoutes, ApiBlueprint, type AppNode, type AppNodeEdges, type AppNodeInstance, type AppNodeSpec, AppRootElementBlueprint, AppRootWrapperBlueprint, type AppTree, type AppTreeApi, type CommonAnalyticsContext, type ComponentRef, type ComponentsApi, type ConfigurableExtensionDataRef, type CoreErrorBoundaryFallbackProps, type CoreNotFoundErrorPageProps, type CoreProgressProps, type CreateExtensionBlueprintOptions, type CreateExtensionOptions, type CreateFrontendModuleOptions, type DialogApi, type DialogApiDialog, type Extension, type ExtensionAttachToSpec, type ExtensionBlueprint, type ExtensionBlueprintParameters, ExtensionBoundary, type ExtensionBoundaryProps, type ExtensionDataContainer, type ExtensionDataRef, type ExtensionDataRefToValue, type ExtensionDataValue, type ExtensionDefinition, type ExtensionDefinitionParameters, type ExtensionFactoryMiddleware, type ExtensionInput, type ExternalRouteRef, type FeatureFlagConfig, type FrontendModule, type FrontendPlugin, IconBundleBlueprint, type IconComponent, type IconsApi, NavItemBlueprint, NavLogoBlueprint, PageBlueprint, type PluginOptions, type PortableSchema, type ResolveInputValueOverrides, type ResolvedExtensionInput, type ResolvedExtensionInputs, type RouteFunc, type RouteRef, type RouteResolutionApi, type RouteResolutionApiResolveOptions, RouterBlueprint, SignInPageBlueprint, type SubRouteRef, ThemeBlueprint, TranslationBlueprint, analyticsApiRef, appTreeApiRef, componentsApiRef, coreComponentRefs, coreExtensionData, createComponentExtension, createComponentRef, createExtension, createExtensionBlueprint, createExtensionDataRef, createExtensionInput, createExternalRouteRef, createFrontendModule, createFrontendPlugin, createRouteRef, createSubRouteRef, dialogApiRef, iconsApiRef, routeResolutionApiRef, useAnalytics, useComponentRef, useRouteRef, useRouteRefParams };
|
|
1549
|
+
export { type AnalyticsApi, AnalyticsContext, type AnalyticsContextValue, type AnalyticsEvent, type AnalyticsEventAttributes, type AnalyticsTracker, type AnyExtensionDataRef, type AnyExternalRoutes, type AnyRouteRefParams, type AnyRoutes, ApiBlueprint, type AppNode, type AppNodeEdges, type AppNodeInstance, type AppNodeSpec, AppRootElementBlueprint, AppRootWrapperBlueprint, type AppTree, type AppTreeApi, type CommonAnalyticsContext, type ComponentRef, type ComponentsApi, type ConfigurableExtensionDataRef, type CoreErrorBoundaryFallbackProps, type CoreNotFoundErrorPageProps, type CoreProgressProps, type CreateExtensionBlueprintOptions, type CreateExtensionOptions, type CreateFrontendFeatureLoaderOptions, type CreateFrontendModuleOptions, type DialogApi, type DialogApiDialog, type Extension, type ExtensionAttachToSpec, type ExtensionBlueprint, type ExtensionBlueprintParameters, ExtensionBoundary, type ExtensionBoundaryProps, type ExtensionDataContainer, type ExtensionDataRef, type ExtensionDataRefToValue, type ExtensionDataValue, type ExtensionDefinition, type ExtensionDefinitionParameters, type ExtensionFactoryMiddleware, type ExtensionInput, type ExternalRouteRef, type FeatureFlagConfig, type FrontendFeature, type FrontendFeatureLoader, type FrontendModule, type FrontendPlugin, IconBundleBlueprint, type IconComponent, type IconsApi, NavItemBlueprint, NavLogoBlueprint, PageBlueprint, type PluginOptions, type PortableSchema, type ResolveInputValueOverrides, type ResolvedExtensionInput, type ResolvedExtensionInputs, type RouteFunc, type RouteRef, type RouteResolutionApi, type RouteResolutionApiResolveOptions, RouterBlueprint, SignInPageBlueprint, type SubRouteRef, ThemeBlueprint, TranslationBlueprint, analyticsApiRef, appTreeApiRef, componentsApiRef, coreComponentRefs, coreExtensionData, createComponentExtension, createComponentRef, createExtension, createExtensionBlueprint, createExtensionDataRef, createExtensionInput, createExternalRouteRef, createFrontendFeatureLoader, createFrontendModule, createFrontendPlugin, createRouteRef, createSubRouteRef, dialogApiRef, iconsApiRef, routeResolutionApiRef, useAnalytics, useComponentRef, useRouteRef, useRouteRefParams };
|
package/dist/index.esm.js
CHANGED
|
@@ -34,5 +34,6 @@ export { createExtensionInput } from './wiring/createExtensionInput.esm.js';
|
|
|
34
34
|
export { createExtensionDataRef } from './wiring/createExtensionDataRef.esm.js';
|
|
35
35
|
export { createFrontendPlugin } from './wiring/createFrontendPlugin.esm.js';
|
|
36
36
|
export { createFrontendModule } from './wiring/createFrontendModule.esm.js';
|
|
37
|
+
export { createFrontendFeatureLoader } from './wiring/createFrontendFeatureLoader.esm.js';
|
|
37
38
|
export { createExtensionBlueprint } from './wiring/createExtensionBlueprint.esm.js';
|
|
38
39
|
//# sourceMappingURL=index.esm.js.map
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { describeParentCallSite } from '../routing/describeParentCallSite.esm.js';
|
|
2
|
+
|
|
3
|
+
function createFrontendFeatureLoader(options) {
|
|
4
|
+
const description = `created at '${describeParentCallSite()}'`;
|
|
5
|
+
return {
|
|
6
|
+
$$type: "@backstage/FrontendFeatureLoader",
|
|
7
|
+
version: "v1",
|
|
8
|
+
description,
|
|
9
|
+
toString() {
|
|
10
|
+
return `FeatureLoader{description=${description}}`;
|
|
11
|
+
},
|
|
12
|
+
async loader(deps) {
|
|
13
|
+
const it = await options.loader(deps);
|
|
14
|
+
const result = new Array();
|
|
15
|
+
for await (const item of it) {
|
|
16
|
+
if (isFeatureOrLoader(item)) {
|
|
17
|
+
result.push(item);
|
|
18
|
+
} else if ("default" in item) {
|
|
19
|
+
result.push(item.default);
|
|
20
|
+
} else {
|
|
21
|
+
throw new Error(`Invalid item "${item}"`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function isFeatureOrLoader(obj) {
|
|
29
|
+
if (obj !== null && typeof obj === "object" && "$$type" in obj) {
|
|
30
|
+
return obj.$$type === "@backstage/FrontendPlugin" || obj.$$type === "@backstage/FrontendModule" || obj.$$type === "@backstage/FrontendFeatureLoader";
|
|
31
|
+
}
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export { createFrontendFeatureLoader };
|
|
36
|
+
//# sourceMappingURL=createFrontendFeatureLoader.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createFrontendFeatureLoader.esm.js","sources":["../../src/wiring/createFrontendFeatureLoader.ts"],"sourcesContent":["/*\n * Copyright 2025 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 { ConfigApi } from '../apis/definitions';\nimport { describeParentCallSite } from '../routing/describeParentCallSite';\nimport { FrontendFeature } from './types';\n\n/** @public */\nexport interface CreateFrontendFeatureLoaderOptions {\n loader(deps: {\n config: ConfigApi;\n }):\n | Iterable<\n | FrontendFeature\n | FrontendFeatureLoader\n | Promise<{ default: FrontendFeature | FrontendFeatureLoader }>\n >\n | Promise<\n Iterable<\n | FrontendFeature\n | FrontendFeatureLoader\n | Promise<{ default: FrontendFeature | FrontendFeatureLoader }>\n >\n >\n | AsyncIterable<\n | FrontendFeature\n | FrontendFeatureLoader\n | { default: FrontendFeature | FrontendFeatureLoader }\n >;\n}\n\n/** @public */\nexport interface FrontendFeatureLoader {\n readonly $$type: '@backstage/FrontendFeatureLoader';\n}\n\n/** @internal */\nexport interface InternalFrontendFeatureLoader extends FrontendFeatureLoader {\n readonly version: 'v1';\n readonly description: string;\n readonly loader: (deps: {\n config: ConfigApi;\n }) => Promise<(FrontendFeature | FrontendFeatureLoader)[]>;\n}\n\n/** @public */\nexport function createFrontendFeatureLoader(\n options: CreateFrontendFeatureLoaderOptions,\n): FrontendFeatureLoader {\n const description = `created at '${describeParentCallSite()}'`;\n return {\n $$type: '@backstage/FrontendFeatureLoader',\n version: 'v1',\n description,\n toString() {\n return `FeatureLoader{description=${description}}`;\n },\n async loader(deps: {\n config: ConfigApi;\n }): Promise<(FrontendFeature | FrontendFeatureLoader)[]> {\n const it = await options.loader(deps);\n const result = new Array<FrontendFeature | FrontendFeatureLoader>();\n for await (const item of it) {\n if (isFeatureOrLoader(item)) {\n result.push(item);\n } else if ('default' in item) {\n result.push(item.default);\n } else {\n throw new Error(`Invalid item \"${item}\"`);\n }\n }\n return result;\n },\n } as InternalFrontendFeatureLoader;\n}\n\n/** @internal */\nexport function isInternalFrontendFeatureLoader(opaque: {\n $$type: string;\n}): opaque is InternalFrontendFeatureLoader {\n if (opaque.$$type === '@backstage/FrontendFeatureLoader') {\n // Make sure we throw if invalid\n toInternalFrontendFeatureLoader(opaque as FrontendFeatureLoader);\n return true;\n }\n return false;\n}\n\n/** @internal */\nexport function toInternalFrontendFeatureLoader(\n plugin: FrontendFeatureLoader,\n): InternalFrontendFeatureLoader {\n const internal = plugin as InternalFrontendFeatureLoader;\n if (internal.$$type !== '@backstage/FrontendFeatureLoader') {\n throw new Error(`Invalid plugin instance, bad type '${internal.$$type}'`);\n }\n if (internal.version !== 'v1') {\n throw new Error(\n `Invalid plugin instance, bad version '${internal.version}'`,\n );\n }\n return internal;\n}\n\nfunction isFeatureOrLoader(\n obj: unknown,\n): obj is FrontendFeature | FrontendFeatureLoader {\n if (obj !== null && typeof obj === 'object' && '$$type' in obj) {\n return (\n obj.$$type === '@backstage/FrontendPlugin' ||\n obj.$$type === '@backstage/FrontendModule' ||\n obj.$$type === '@backstage/FrontendFeatureLoader'\n );\n }\n return false;\n}\n"],"names":[],"mappings":";;AA2DO,SAAS,4BACd,OACuB,EAAA;AACvB,EAAM,MAAA,WAAA,GAAc,CAAe,YAAA,EAAA,sBAAA,EAAwB,CAAA,CAAA,CAAA;AAC3D,EAAO,OAAA;AAAA,IACL,MAAQ,EAAA,kCAAA;AAAA,IACR,OAAS,EAAA,IAAA;AAAA,IACT,WAAA;AAAA,IACA,QAAW,GAAA;AACT,MAAA,OAAO,6BAA6B,WAAW,CAAA,CAAA,CAAA;AAAA,KACjD;AAAA,IACA,MAAM,OAAO,IAE4C,EAAA;AACvD,MAAA,MAAM,EAAK,GAAA,MAAM,OAAQ,CAAA,MAAA,CAAO,IAAI,CAAA;AACpC,MAAM,MAAA,MAAA,GAAS,IAAI,KAA+C,EAAA;AAClE,MAAA,WAAA,MAAiB,QAAQ,EAAI,EAAA;AAC3B,QAAI,IAAA,iBAAA,CAAkB,IAAI,CAAG,EAAA;AAC3B,UAAA,MAAA,CAAO,KAAK,IAAI,CAAA;AAAA,SAClB,MAAA,IAAW,aAAa,IAAM,EAAA;AAC5B,UAAO,MAAA,CAAA,IAAA,CAAK,KAAK,OAAO,CAAA;AAAA,SACnB,MAAA;AACL,UAAA,MAAM,IAAI,KAAA,CAAM,CAAiB,cAAA,EAAA,IAAI,CAAG,CAAA,CAAA,CAAA;AAAA;AAC1C;AAEF,MAAO,OAAA,MAAA;AAAA;AACT,GACF;AACF;AA8BA,SAAS,kBACP,GACgD,EAAA;AAChD,EAAA,IAAI,QAAQ,IAAQ,IAAA,OAAO,GAAQ,KAAA,QAAA,IAAY,YAAY,GAAK,EAAA;AAC9D,IAAA,OACE,IAAI,MAAW,KAAA,2BAAA,IACf,IAAI,MAAW,KAAA,2BAAA,IACf,IAAI,MAAW,KAAA,kCAAA;AAAA;AAGnB,EAAO,OAAA,KAAA;AACT;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/frontend-plugin-api",
|
|
3
|
-
"version": "0.10.0
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"backstage": {
|
|
5
5
|
"role": "web-library"
|
|
6
6
|
},
|
|
@@ -31,20 +31,20 @@
|
|
|
31
31
|
"test": "backstage-cli package test"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@backstage/core-components": "0.
|
|
35
|
-
"@backstage/core-plugin-api": "1.10.
|
|
36
|
-
"@backstage/types": "1.2.1",
|
|
37
|
-
"@backstage/version-bridge": "1.0.11",
|
|
34
|
+
"@backstage/core-components": "^0.17.0",
|
|
35
|
+
"@backstage/core-plugin-api": "^1.10.5",
|
|
36
|
+
"@backstage/types": "^1.2.1",
|
|
37
|
+
"@backstage/version-bridge": "^1.0.11",
|
|
38
38
|
"@material-ui/core": "^4.12.4",
|
|
39
39
|
"lodash": "^4.17.21",
|
|
40
40
|
"zod": "^3.22.4",
|
|
41
41
|
"zod-to-json-schema": "^3.21.4"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@backstage/cli": "0.31.0
|
|
45
|
-
"@backstage/frontend-app-api": "0.11.0
|
|
46
|
-
"@backstage/frontend-test-utils": "0.3.0
|
|
47
|
-
"@backstage/test-utils": "1.7.6
|
|
44
|
+
"@backstage/cli": "^0.31.0",
|
|
45
|
+
"@backstage/frontend-app-api": "^0.11.0",
|
|
46
|
+
"@backstage/frontend-test-utils": "^0.3.0",
|
|
47
|
+
"@backstage/test-utils": "^1.7.6",
|
|
48
48
|
"@testing-library/jest-dom": "^6.0.0",
|
|
49
49
|
"@testing-library/react": "^16.0.0",
|
|
50
50
|
"@types/react": "^18.0.0",
|