frontend-*-api: introduce ExtensionBoundary and pass source to extension factories

Co-authored-by: Fredrik Adelöw <freben@gmail.com>
Co-authored-by: Johan Haals <johan.haals@gmail.com>
Co-authored-by: Camila Belo <camilaibs@gmail.com>
Co-authored-by: Philipp Hugenroth <philipph@spotify.com>
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2023-09-04 14:20:24 +02:00
parent f4a9884c62
commit d81c13f21a
10 changed files with 154 additions and 46 deletions
@@ -9,6 +9,8 @@ import { AnyApiFactory } from '@backstage/core-plugin-api';
import { AnyApiRef } from '@backstage/core-plugin-api';
import { ComponentType } from 'react';
import { JsonObject } from '@backstage/types';
import { default as React_2 } from 'react';
import { ReactNode } from 'react';
import { z } from 'zod';
import { ZodSchema } from 'zod';
import { ZodTypeDef } from 'zod';
@@ -95,6 +97,7 @@ export interface CreateExtensionOptions<
disabled?: boolean;
// (undocumented)
factory(options: {
source?: BackstagePlugin;
bind: ExtensionDataBind<TData>;
config: TConfig;
inputs: {
@@ -166,6 +169,7 @@ export interface Extension<TConfig> {
disabled: boolean;
// (undocumented)
factory(options: {
source?: BackstagePlugin;
bind: ExtensionDataBind<AnyExtensionDataMap>;
config: TConfig;
inputs: Record<string, Array<Record<string, unknown>>>;
@@ -183,6 +187,19 @@ export interface Extension<TConfig> {
output: AnyExtensionDataMap;
}
// @public (undocumented)
export function ExtensionBoundary(
props: ExtensionBoundaryProps,
): React_2.JSX.Element;
// @public (undocumented)
export interface ExtensionBoundaryProps {
// (undocumented)
children: ReactNode;
// (undocumented)
source?: BackstagePlugin;
}
// @public (undocumented)
export type ExtensionDataBind<TData extends AnyExtensionDataMap> = {
[K in keyof TData]: (value: TData[K]['T']) => void;
@@ -0,0 +1,29 @@
/*
* 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, { ReactNode } from 'react';
import { BackstagePlugin } from '../wiring';
/** @public */
export interface ExtensionBoundaryProps {
children: ReactNode;
source?: BackstagePlugin;
}
/** @public */
export function ExtensionBoundary(props: ExtensionBoundaryProps) {
return <>{props.children}</>;
}
@@ -0,0 +1,20 @@
/*
* 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.
*/
export {
ExtensionBoundary,
type ExtensionBoundaryProps,
} from './ExtensionBoundary';
@@ -15,6 +15,7 @@
*/
import React from 'react';
import { ExtensionBoundary } from '../components';
import { createSchemaFromZod, PortableSchema } from '../createSchemaFromZod';
import {
AnyExtensionDataMap,
@@ -72,7 +73,7 @@ export function createPageExtension<
},
inputs: options.inputs,
configSchema,
factory({ bind, config, inputs }) {
factory({ bind, config, inputs, source }) {
const LazyComponent = React.lazy(() =>
options
.component({ config, inputs })
@@ -80,9 +81,11 @@ export function createPageExtension<
);
bind.path(config.path);
bind.component(() => (
<React.Suspense fallback="...">
<LazyComponent />
</React.Suspense>
<ExtensionBoundary source={source}>
<React.Suspense fallback="...">
<LazyComponent />
</React.Suspense>
</ExtensionBoundary>
));
},
});
@@ -24,6 +24,7 @@ export {
createSchemaFromZod,
type PortableSchema,
} from './createSchemaFromZod';
export * from './components';
export * from './extensions';
export {
coreExtensionData,
@@ -17,6 +17,7 @@
import { AnyApiFactory } from '@backstage/core-plugin-api';
import { ComponentType } from 'react';
import { PortableSchema } from './createSchemaFromZod';
import { BackstagePlugin } from './wiring';
/** @public */
export type ExtensionDataRef<T> = {
@@ -64,6 +65,7 @@ export interface CreateExtensionOptions<
output: TData;
configSchema?: PortableSchema<TConfig>;
factory(options: {
source?: BackstagePlugin;
bind: ExtensionDataBind<TData>;
config: TConfig;
inputs: {
@@ -84,6 +86,7 @@ export interface Extension<TConfig> {
output: AnyExtensionDataMap;
configSchema?: PortableSchema<TConfig>;
factory(options: {
source?: BackstagePlugin;
bind: ExtensionDataBind<AnyExtensionDataMap>;
config: TConfig;
inputs: Record<string, Array<Record<string, unknown>>>;