Merge pull request #19646 from backstage/mob/createPageExtension

Add a `createPageExtension` wrapper to the plugin API
This commit is contained in:
Fredrik Adelöw
2023-08-30 10:45:21 +02:00
committed by GitHub
4 changed files with 139 additions and 31 deletions
@@ -15,25 +15,15 @@
*/
import {
createExtension,
createPageExtension,
createPlugin,
coreExtensionData,
createSchemaFromZod,
} from '@backstage/frontend-plugin-api';
import { Router as GraphiQLPage } from '@backstage/plugin-graphiql';
import React from 'react';
export const GraphiqlPageExtension = createExtension({
output: {
component: coreExtensionData.reactComponent,
path: coreExtensionData.routePath,
},
configSchema: createSchemaFromZod(z =>
z.object({ path: z.string().default('/graphiql') }),
),
factory({ bind, config }) {
bind.component(GraphiQLPage);
bind.path(config.path);
},
export const GraphiqlPage = createPageExtension({
defaultPath: '/graphiql',
component: () =>
import('@backstage/plugin-graphiql').then(({ Router }) => <Router />),
});
export const graphiqlPlugin = createPlugin({
@@ -42,7 +32,7 @@ export const graphiqlPlugin = createPlugin({
{
id: 'graphiql.page',
at: 'core.router/routes',
extension: GraphiqlPageExtension,
extension: GraphiqlPage,
},
],
});
@@ -3,6 +3,8 @@
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
/// <reference types="react" />
import { ComponentType } from 'react';
import { JsonObject } from '@backstage/types';
import { z } from 'zod';
@@ -77,6 +79,38 @@ export interface CreateExtensionOptions<
output: TData;
}
// @public
export function createPageExtension<
TConfig extends {
path: string;
},
TInputs extends Record<
string,
{
extensionData: AnyExtensionDataMap;
}
>,
>(
options: (
| {
defaultPath: string;
}
| {
configSchema: PortableSchema<TConfig>;
}
) & {
inputs?: TInputs;
component: (props: {
config: TConfig;
inputs: {
[pointName in keyof TInputs]: ExtensionDataValue<
TInputs[pointName]['extensionData']
>[];
};
}) => Promise<JSX.Element>;
},
): Extension<TConfig>;
// @public (undocumented)
export function createPlugin(options: BackstagePluginOptions): BackstagePlugin;
@@ -0,0 +1,83 @@
/*
* Copyright 2023 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { createSchemaFromZod, PortableSchema } from './createSchemaFromZod';
import {
AnyExtensionDataMap,
coreExtensionData,
createExtension,
Extension,
ExtensionDataValue,
} from './types';
/**
* Helper for creating extensions for a routable React page component.
*
* @public
*/
export function createPageExtension<
TConfig extends { path: string },
TInputs extends Record<string, { extensionData: AnyExtensionDataMap }>,
>(
options: (
| {
defaultPath: string;
}
| {
configSchema: PortableSchema<TConfig>;
}
) & {
inputs?: TInputs;
component: (props: {
config: TConfig;
inputs: {
[pointName in keyof TInputs]: ExtensionDataValue<
TInputs[pointName]['extensionData']
>[];
};
}) => Promise<JSX.Element>;
},
): Extension<TConfig> {
const configSchema =
'configSchema' in options
? options.configSchema
: (createSchemaFromZod(z =>
z.object({ path: z.string().default(options.defaultPath) }),
) as PortableSchema<TConfig>);
return createExtension({
output: {
component: coreExtensionData.reactComponent,
path: coreExtensionData.routePath,
},
inputs: options.inputs,
configSchema,
factory({ bind, config, inputs }) {
const LazyComponent = React.lazy(() =>
options
.component({ config, inputs })
.then(element => ({ default: () => element })),
);
bind.path(config.path);
bind.component(() => (
<React.Suspense fallback="...">
<LazyComponent />
</React.Suspense>
));
},
});
}
+15 -14
View File
@@ -20,21 +20,22 @@
* @packageDocumentation
*/
export {
createExtension,
coreExtensionData,
createPlugin,
type ExtensionInstanceParameters,
type BackstagePlugin,
type Extension,
type AnyExtensionDataMap,
type BackstagePluginOptions,
type CreateExtensionOptions,
type ExtensionDataBind,
type ExtensionDataRef,
type ExtensionDataValue,
} from './types';
export { createPageExtension } from './createPageExtension';
export {
createSchemaFromZod,
type PortableSchema,
} from './createSchemaFromZod';
export {
coreExtensionData,
createExtension,
createPlugin,
type AnyExtensionDataMap,
type BackstagePlugin,
type BackstagePluginOptions,
type CreateExtensionOptions,
type Extension,
type ExtensionDataBind,
type ExtensionDataRef,
type ExtensionDataValue,
type ExtensionInstanceParameters,
} from './types';