frontend-plugin-api: move out several coreExtensionData refs

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2023-12-13 15:54:49 +01:00
parent 85e9e8f1b7
commit f9ef6326fd
18 changed files with 167 additions and 94 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/frontend-plugin-api': minor
---
Moved several extension data references from `coreExtensionData` to their respective extension creators.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/frontend-app-api': patch
---
Updates to match the new `coreExtensionData` structure.
@@ -16,8 +16,11 @@
import {
coreExtensionData,
createApiExtension,
createComponentExtension,
createExtension,
createExtensionInput,
createThemeExtension,
createTranslationExtension,
} from '@backstage/frontend-plugin-api';
@@ -26,13 +29,13 @@ export const Core = createExtension({
attachTo: { id: 'root', input: 'default' }, // ignored
inputs: {
apis: createExtensionInput({
api: coreExtensionData.apiFactory,
api: createApiExtension.factoryDataRef,
}),
themes: createExtensionInput({
theme: coreExtensionData.theme,
theme: createThemeExtension.themeDataRef,
}),
components: createExtensionInput({
component: coreExtensionData.component,
component: createComponentExtension.componentDataRef,
}),
translations: createExtensionInput({
translation: createTranslationExtension.translationDataRef,
@@ -19,9 +19,9 @@ import {
createExtension,
coreExtensionData,
createExtensionInput,
LogoElements,
NavTarget,
useRouteRef,
createNavItemExtension,
createNavLogoExtension,
} from '@backstage/frontend-plugin-api';
import { makeStyles } from '@material-ui/core';
import {
@@ -52,7 +52,9 @@ const useSidebarLogoStyles = makeStyles({
},
});
const SidebarLogo = (props: LogoElements) => {
const SidebarLogo = (
props: (typeof createNavLogoExtension.logoElementsDataRef)['T'],
) => {
const classes = useSidebarLogoStyles();
const { isOpen } = useSidebarOpenState();
@@ -67,7 +69,9 @@ const SidebarLogo = (props: LogoElements) => {
);
};
const SidebarNavItem = (props: NavTarget) => {
const SidebarNavItem = (
props: (typeof createNavItemExtension.targetDataRef)['T'],
) => {
const { icon: Icon, title, routeRef } = props;
const to = useRouteRef(routeRef)();
// TODO: Support opening modal, for example, the search one
@@ -80,11 +84,11 @@ export const CoreNav = createExtension({
attachTo: { id: 'core/layout', input: 'nav' },
inputs: {
items: createExtensionInput({
target: coreExtensionData.navTarget,
target: createNavItemExtension.targetDataRef,
}),
logos: createExtensionInput(
{
elements: coreExtensionData.logoElements,
elements: createNavLogoExtension.logoElementsDataRef,
},
{
singleton: true,
@@ -19,6 +19,7 @@ import {
coreExtensionData,
createExtension,
createExtensionInput,
createSignInPageExtension,
} from '@backstage/frontend-plugin-api';
import {
ConfigApi,
@@ -31,8 +32,6 @@ import { InternalAppContext } from '../wiring/InternalAppContext';
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
import { AppIdentityProxy } from '../../../core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy';
import { BrowserRouter } from 'react-router-dom';
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
import { signInPageComponentDataRef } from '../../../frontend-plugin-api/src/extensions/createSignInPageExtension';
import { RouteTracker } from '../routing/RouteTracker';
export const CoreRouter = createExtension({
@@ -42,7 +41,7 @@ export const CoreRouter = createExtension({
inputs: {
signInPage: createExtensionInput(
{
component: signInPageComponentDataRef,
component: createSignInPageExtension.componentDataRef,
},
{ singleton: true, optional: true },
),
@@ -201,13 +201,13 @@ describe('createApp', () => {
</core/router>
]
components [
<component:core.components.progress out=[core.component] />
<component:core.components.errorBoundaryFallback out=[core.component] />
<component:core.components.notFoundErrorPage out=[core.component] />
<component:core.components.progress out=[core.component.component] />
<component:core.components.errorBoundaryFallback out=[core.component.component] />
<component:core.components.notFoundErrorPage out=[core.component.component] />
]
themes [
<theme:app/light out=[core.theme] />
<theme:app/dark out=[core.theme] />
<theme:app/light out=[core.theme.theme] />
<theme:app/dark out=[core.theme.theme] />
]
</core>"
`);
@@ -23,6 +23,10 @@ import {
ComponentRef,
componentsApiRef,
coreExtensionData,
createApiExtension,
createComponentExtension,
createNavItemExtension,
createThemeExtension,
createTranslationExtension,
ExtensionDataRef,
ExtensionOverrides,
@@ -194,7 +198,7 @@ export function createExtensionTree(options: {
return this.getExtensionAttachments('core/nav', 'items')
.map((node, index) => {
const target = node.getData(coreExtensionData.navTarget);
const target = node.getData(createNavItemExtension.targetDataRef);
if (!target) {
return null;
}
@@ -365,13 +369,13 @@ function createApiHolder(
const pluginApis =
tree.root.edges.attachments
.get('apis')
?.map(e => e.instance?.getData(coreExtensionData.apiFactory))
?.map(e => e.instance?.getData(createApiExtension.factoryDataRef))
.filter((x): x is AnyApiFactory => !!x) ?? [];
const themeExtensions =
tree.root.edges.attachments
.get('themes')
?.map(e => e.instance?.getData(coreExtensionData.theme))
?.map(e => e.instance?.getData(createThemeExtension.themeDataRef))
.filter((x): x is AppTheme => !!x) ?? [];
const translationResources =
@@ -412,7 +416,7 @@ function createApiHolder(
const componentsExtensions =
tree.root.edges.attachments
.get('components')
?.map(e => e.instance?.getData(coreExtensionData.component))
?.map(e => e.instance?.getData(createComponentExtension.componentDataRef))
.filter(x => !!x) ?? [];
const componentsMap = componentsExtensions.reduce(
+66 -24
View File
@@ -347,18 +347,7 @@ export type CoreErrorBoundaryFallbackProps = {
export const coreExtensionData: {
reactElement: ConfigurableExtensionDataRef<JSX_2.Element, {}>;
routePath: ConfigurableExtensionDataRef<string, {}>;
apiFactory: ConfigurableExtensionDataRef<AnyApiFactory, {}>;
routeRef: ConfigurableExtensionDataRef<RouteRef<AnyRouteRefParams>, {}>;
navTarget: ConfigurableExtensionDataRef<NavTarget, {}>;
theme: ConfigurableExtensionDataRef<AppTheme, {}>;
logoElements: ConfigurableExtensionDataRef<LogoElements, {}>;
component: ConfigurableExtensionDataRef<
{
ref: ComponentRef;
impl: ComponentType;
},
{}
>;
};
// @public (undocumented)
@@ -391,6 +380,12 @@ export function createApiExtension<
},
): ExtensionDefinition<TConfig>;
// @public (undocumented)
export namespace createApiExtension {
const // (undocumented)
factoryDataRef: ConfigurableExtensionDataRef<AnyApiFactory, {}>;
}
export { createApiFactory };
export { createApiRef };
@@ -421,6 +416,18 @@ export function createComponentExtension<
};
}): ExtensionDefinition<TConfig>;
// @public (undocumented)
export namespace createComponentExtension {
const // (undocumented)
componentDataRef: ConfigurableExtensionDataRef<
{
ref: ComponentRef;
impl: ComponentType;
},
{}
>;
}
// @public (undocumented)
export function createExtension<
TOutput extends AnyExtensionDataMap,
@@ -527,6 +534,39 @@ export function createNavItemExtension(options: {
title: string;
}>;
// @public (undocumented)
export namespace createNavItemExtension {
const // (undocumented)
targetDataRef: ConfigurableExtensionDataRef<
{
title: string;
icon: IconComponent_2;
routeRef: RouteRef<undefined>;
},
{}
>;
}
// @public
export function createNavLogoExtension(options: {
name?: string;
namespace?: string;
logoIcon: JSX.Element;
logoFull: JSX.Element;
}): ExtensionDefinition<never>;
// @public (undocumented)
export namespace createNavLogoExtension {
const // (undocumented)
logoElementsDataRef: ConfigurableExtensionDataRef<
{
logoIcon?: JSX.Element | undefined;
logoFull?: JSX.Element | undefined;
},
{}
>;
}
// @public
export function createPageExtension<
TConfig extends {
@@ -611,6 +651,15 @@ export function createSignInPageExtension<
}) => Promise<ComponentType<SignInPageProps>>;
}): ExtensionDefinition<TConfig>;
// @public (undocumented)
export namespace createSignInPageExtension {
const // (undocumented)
componentDataRef: ConfigurableExtensionDataRef<
React_2.ComponentType<SignInPageProps>,
{}
>;
}
// @public
export function createSubRouteRef<
Path extends string,
@@ -625,6 +674,12 @@ export function createThemeExtension(
theme: AppTheme,
): ExtensionDefinition<never>;
// @public (undocumented)
export namespace createThemeExtension {
const // (undocumented)
themeDataRef: ConfigurableExtensionDataRef<AppTheme, {}>;
}
// @public (undocumented)
export function createTranslationExtension(options: {
name?: string;
@@ -848,21 +903,8 @@ export { IdentityApi };
export { identityApiRef };
// @public (undocumented)
export type LogoElements = {
logoIcon?: JSX_2.Element;
logoFull?: JSX_2.Element;
};
export { microsoftAuthApiRef };
// @public (undocumented)
export type NavTarget = {
title: string;
icon: IconComponent_2;
routeRef: RouteRef<undefined>;
};
export { OAuthApi };
export { OAuthRequestApi };
@@ -19,7 +19,7 @@ import { PortableSchema } from '../schema';
import {
ResolvedExtensionInputs,
createExtension,
coreExtensionData,
createExtensionDataRef,
} from '../wiring';
import { AnyExtensionInputMap } from '../wiring/createExtension';
import { Expand } from '../types';
@@ -59,7 +59,7 @@ export function createApiExtension<
inputs: extensionInputs,
configSchema,
output: {
api: coreExtensionData.apiFactory,
api: createApiExtension.factoryDataRef,
},
factory({ config, inputs }) {
if (typeof factory === 'function') {
@@ -69,3 +69,9 @@ export function createApiExtension<
},
});
}
/** @public */
export namespace createApiExtension {
export const factoryDataRef =
createExtensionDataRef<AnyApiFactory>('core.api.factory');
}
@@ -18,8 +18,8 @@ import React, { lazy, ComponentType } from 'react';
import {
AnyExtensionInputMap,
ResolvedExtensionInputs,
coreExtensionData,
createExtension,
createExtensionDataRef,
} from '../wiring';
import { Expand } from '../types';
import { PortableSchema } from '../schema';
@@ -59,7 +59,7 @@ export function createComponentExtension<
disabled: options.disabled,
configSchema: options.configSchema,
output: {
component: coreExtensionData.component,
component: createComponentExtension.componentDataRef,
},
factory({ config, inputs, node }) {
let ExtensionComponent: ComponentType<TProps>;
@@ -88,3 +88,11 @@ export function createComponentExtension<
},
});
}
/** @public */
export namespace createComponentExtension {
export const componentDataRef = createExtensionDataRef<{
ref: ComponentRef;
impl: ComponentType;
}>('core.component.component');
}
@@ -16,7 +16,7 @@
import { IconComponent } from '@backstage/core-plugin-api';
import { createSchemaFromZod } from '../schema/createSchemaFromZod';
import { coreExtensionData, createExtension } from '../wiring';
import { createExtension, createExtensionDataRef } from '../wiring';
import { RouteRef } from '../routing';
/**
@@ -42,7 +42,7 @@ export function createNavItemExtension(options: {
}),
),
output: {
navTarget: coreExtensionData.navTarget,
navTarget: createNavItemExtension.targetDataRef,
},
factory: ({ config }) => ({
navTarget: {
@@ -53,3 +53,13 @@ export function createNavItemExtension(options: {
}),
});
}
/** @public */
export namespace createNavItemExtension {
// TODO(Rugvip): Should this be broken apart into separate refs? title/icon/routeRef
export const targetDataRef = createExtensionDataRef<{
title: string;
icon: IconComponent;
routeRef: RouteRef<undefined>;
}>('core.nav-item.target');
}
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import { coreExtensionData, createExtension } from '../wiring';
import { createExtension, createExtensionDataRef } from '../wiring';
/**
* Helper for creating extensions for a nav logos.
@@ -33,7 +33,7 @@ export function createNavLogoExtension(options: {
namespace: options?.namespace,
attachTo: { id: 'core/nav', input: 'logos' },
output: {
logos: coreExtensionData.logoElements,
logos: createNavLogoExtension.logoElementsDataRef,
},
factory: () => {
return {
@@ -45,3 +45,11 @@ export function createNavLogoExtension(options: {
},
});
}
/** @public */
export namespace createNavLogoExtension {
export const logoElementsDataRef = createExtensionDataRef<{
logoIcon?: JSX.Element;
logoFull?: JSX.Element;
}>('core.nav-logo.logo-elements');
}
@@ -27,10 +27,6 @@ import {
import { Expand } from '../types';
import { SignInPageProps } from '@backstage/core-plugin-api';
/** @internal */
export const signInPageComponentDataRef =
createExtensionDataRef<ComponentType<SignInPageProps>>('core.signInPage');
/**
*
* @public
@@ -59,7 +55,7 @@ export function createSignInPageExtension<
inputs: options.inputs,
disabled: options.disabled,
output: {
component: signInPageComponentDataRef,
component: createSignInPageExtension.componentDataRef,
},
factory({ config, inputs, node }) {
const ExtensionComponent = lazy(() =>
@@ -78,3 +74,10 @@ export function createSignInPageExtension<
},
});
}
/** @public */
export namespace createSignInPageExtension {
export const componentDataRef = createExtensionDataRef<
ComponentType<SignInPageProps>
>('core.sign-in-page.component');
}
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import { createExtension, coreExtensionData } from '../wiring';
import { createExtension, createExtensionDataRef } from '../wiring';
import { AppTheme } from '@backstage/core-plugin-api';
/** @public */
@@ -25,8 +25,14 @@ export function createThemeExtension(theme: AppTheme) {
name: theme.id,
attachTo: { id: 'core', input: 'themes' },
output: {
theme: coreExtensionData.theme,
theme: createThemeExtension.themeDataRef,
},
factory: () => ({ theme }),
});
}
/** @public */
export namespace createThemeExtension {
export const themeDataRef =
createExtensionDataRef<AppTheme>('core.theme.theme');
}
@@ -38,5 +38,5 @@ export function createTranslationExtension(options: {
export namespace createTranslationExtension {
export const translationDataRef = createExtensionDataRef<
TranslationResource | TranslationMessages
>('core.translationResource');
>('core.translation.translation');
}
@@ -17,6 +17,7 @@
export { createApiExtension } from './createApiExtension';
export { createPageExtension } from './createPageExtension';
export { createNavItemExtension } from './createNavItemExtension';
export { createNavLogoExtension } from './createNavLogoExtension';
export { createSignInPageExtension } from './createSignInPageExtension';
export { createThemeExtension } from './createThemeExtension';
export { createComponentExtension } from './createComponentExtension';
@@ -14,40 +14,13 @@
* limitations under the License.
*/
import { ComponentType, JSX } from 'react';
import {
AnyApiFactory,
AppTheme,
IconComponent,
} from '@backstage/core-plugin-api';
import { JSX } from 'react';
import { RouteRef } from '../routing';
import { ComponentRef } from '../components';
import { createExtensionDataRef } from './createExtensionDataRef';
/** @public */
export type NavTarget = {
title: string;
icon: IconComponent;
routeRef: RouteRef<undefined>;
};
/** @public */
export type LogoElements = {
logoIcon?: JSX.Element;
logoFull?: JSX.Element;
};
/** @public */
export const coreExtensionData = {
reactElement: createExtensionDataRef<JSX.Element>('core.reactElement'),
routePath: createExtensionDataRef<string>('core.routing.path'),
apiFactory: createExtensionDataRef<AnyApiFactory>('core.api.factory'),
routeRef: createExtensionDataRef<RouteRef>('core.routing.ref'),
navTarget: createExtensionDataRef<NavTarget>('core.nav.target'),
theme: createExtensionDataRef<AppTheme>('core.theme'),
logoElements: createExtensionDataRef<LogoElements>('core.logos'),
component: createExtensionDataRef<{
ref: ComponentRef;
impl: ComponentType;
}>('core.component'),
};
@@ -14,11 +14,7 @@
* limitations under the License.
*/
export {
coreExtensionData,
type LogoElements,
type NavTarget,
} from './coreExtensionData';
export { coreExtensionData } from './coreExtensionData';
export {
createExtension,
type Extension,