core-api: add routes and externalRoutes to plugin interface

Co-authored-by: blam <ben@blam.sh>
This commit is contained in:
Patrik Oldsberg
2020-12-02 18:31:59 +01:00
parent e2aa76f19b
commit c78bc66cfb
6 changed files with 50 additions and 14 deletions
+3 -3
View File
@@ -59,7 +59,7 @@ import { ApiResolver, ApiFactoryRegistry } from '../apis/system';
type FullAppOptions = {
apis: Iterable<AnyApiFactory>;
icons: SystemIcons;
plugins: BackstagePlugin[];
plugins: BackstagePlugin<any, any>[];
components: AppComponents;
themes: AppTheme[];
configLoader?: AppConfigLoader;
@@ -107,7 +107,7 @@ export class PrivateAppImpl implements BackstageApp {
private readonly apis: Iterable<AnyApiFactory>;
private readonly icons: SystemIcons;
private readonly plugins: BackstagePlugin[];
private readonly plugins: BackstagePlugin<any, any>[];
private readonly components: AppComponents;
private readonly themes: AppTheme[];
private readonly configLoader?: AppConfigLoader;
@@ -125,7 +125,7 @@ export class PrivateAppImpl implements BackstageApp {
this.defaultApis = options.defaultApis;
}
getPlugins(): BackstagePlugin[] {
getPlugins(): BackstagePlugin<any, any>[] {
return this.plugins;
}
+2 -2
View File
@@ -93,7 +93,7 @@ export type AppOptions = {
/**
* A list of all plugins to include in the app.
*/
plugins?: BackstagePlugin[];
plugins?: BackstagePlugin<any, any>[];
/**
* Supply components to the app to override the default ones.
@@ -140,7 +140,7 @@ export type BackstageApp = {
/**
* Returns all plugins registered for the app.
*/
getPlugins(): BackstagePlugin[];
getPlugins(): BackstagePlugin<any, any>[];
/**
* Get a common icon for this app.
@@ -54,7 +54,7 @@ export function createReactExtension<Props extends {}>(options: {
}): Extension<NamedExoticComponent<Props>> {
const { component: Component, data = {} } = options;
return {
expose(plugin: BackstagePlugin): NamedExoticComponent<Props> {
expose(plugin: BackstagePlugin<any, any>): NamedExoticComponent<Props> {
const Result = (props: Props) => <Component {...props} />;
attachComponentData(Result, 'core.plugin', plugin);
+21 -3
View File
@@ -19,13 +19,18 @@ import {
PluginOutput,
BackstagePlugin,
Extension,
AnyRoutes,
AnyExternalRoutes,
} from './types';
import { AnyApiFactory } from '../apis';
export class PluginImpl implements BackstagePlugin {
export class PluginImpl<
Routes extends AnyRoutes,
ExternalRoutes extends AnyExternalRoutes
> implements BackstagePlugin<Routes, ExternalRoutes> {
private storedOutput?: PluginOutput[];
constructor(private readonly config: PluginConfig) {}
constructor(private readonly config: PluginConfig<Routes, ExternalRoutes>) {}
getId(): string {
return this.config.id;
@@ -35,6 +40,14 @@ export class PluginImpl implements BackstagePlugin {
return this.config.apis ?? [];
}
get routes(): Routes {
return this.config.routes ?? ({} as Routes);
}
get externalRoutes(): ExternalRoutes {
return this.config.externalRoutes ?? ({} as ExternalRoutes);
}
output(): PluginOutput[] {
if (this.storedOutput) {
return this.storedOutput;
@@ -79,6 +92,11 @@ export class PluginImpl implements BackstagePlugin {
}
}
export function createPlugin(config: PluginConfig): BackstagePlugin {
export function createPlugin<
Routes extends AnyRoutes,
ExternalRoutes extends AnyExternalRoutes
>(
config: PluginConfig<Routes, ExternalRoutes>,
): BackstagePlugin<Routes, ExternalRoutes> {
return new PluginImpl(config);
}
+5 -2
View File
@@ -34,9 +34,12 @@ import { getComponentData } from '../extensions';
import { createCollector } from '../extensions/traversal';
export const pluginCollector = createCollector(
() => new Set<BackstagePlugin>(),
() => new Set<BackstagePlugin<any, any>>(),
(acc, node) => {
const plugin = getComponentData<BackstagePlugin>(node, 'core.plugin');
const plugin = getComponentData<BackstagePlugin<any, any>>(
node,
'core.plugin',
);
if (plugin) {
acc.add(plugin);
}
+18 -3
View File
@@ -17,6 +17,7 @@
import { ComponentType } from 'react';
import { RouteRef } from '../routing';
import { AnyApiFactory } from '../apis/system';
import { ExternalRouteRef } from '../routing/RouteRef';
export type RouteOptions = {
// Whether the route path must match exactly, defaults to true.
@@ -67,20 +68,34 @@ export type PluginOutput =
| FeatureFlagOutput;
export type Extension<T> = {
expose(plugin: BackstagePlugin): T;
expose(plugin: BackstagePlugin<any, any>): T;
};
export type BackstagePlugin = {
export type AnyRoutes = { [name: string]: RouteRef<any> };
export type AnyExternalRoutes = { [name: string]: ExternalRouteRef };
export type BackstagePlugin<
Routes extends AnyRoutes,
ExternalRoutes extends AnyExternalRoutes
> = {
getId(): string;
output(): PluginOutput[];
getApis(): Iterable<AnyApiFactory>;
provide<T>(extension: Extension<T>): T;
routes: Routes;
externalRoutes: ExternalRoutes;
};
export type PluginConfig = {
export type PluginConfig<
Routes extends AnyRoutes,
ExternalRoutes extends AnyExternalRoutes
> = {
id: string;
apis?: Iterable<AnyApiFactory>;
register?(hooks: PluginHooks): void;
routes?: Routes;
externalRoutes?: ExternalRoutes;
};
export type PluginHooks = {