frontend-plugin-api: add resolveExtensionDefinition helper + use for extension overrides

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2023-11-21 16:58:01 +01:00
parent 9351d17834
commit 1227f693f0
3 changed files with 53 additions and 19 deletions
@@ -14,12 +14,13 @@
* limitations under the License.
*/
import { Extension } from './createExtension';
import { Extension, ExtensionDefinition } from './createExtension';
import { resolveExtensionDefinition } from './resolveExtensionDefinition';
import { FeatureFlagConfig } from './types';
/** @public */
export interface ExtensionOverridesOptions {
extensions: Extension<unknown>[];
extensions: ExtensionDefinition<unknown>[];
featureFlags?: FeatureFlagConfig[];
}
@@ -42,7 +43,7 @@ export function createExtensionOverrides(
return {
$$type: '@backstage/ExtensionOverrides',
version: 'v1',
extensions: options.extensions,
extensions: options.extensions.map(def => resolveExtensionDefinition(def)),
featureFlags: options.featureFlags ?? [],
} as InternalExtensionOverrides;
}
@@ -17,6 +17,7 @@
import { Extension, ExtensionDefinition } from './createExtension';
import { ExternalRouteRef, RouteRef } from '../routing';
import { FeatureFlagConfig } from './types';
import { resolveExtensionDefinition } from './resolveExtensionDefinition';
/** @public */
export type AnyRoutes = { [name in string]: RouteRef };
@@ -71,22 +72,9 @@ export function createPlugin<
routes: options.routes ?? ({} as Routes),
externalRoutes: options.externalRoutes ?? ({} as ExternalRoutes),
featureFlags: options.featureFlags ?? [],
extensions: (options.extensions ?? []).map(definition => {
const { name, namespace: _, kind, ...rest } = definition;
let id;
if (kind && name) {
id = `${kind}:${options.id}/${name}`;
} else if (kind) {
id = `${kind}:${options.id}`;
} else if (name) {
id = `${options.id}/${name}`;
} else {
id = options.id;
}
return { id, ...rest, $$type: '@backstage/Extension' };
}),
extensions: (options.extensions ?? []).map(def =>
resolveExtensionDefinition(def, { namespace: options.id }),
),
} as InternalBackstagePlugin<Routes, ExternalRoutes>;
}
@@ -0,0 +1,45 @@
/*
* 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 { Extension, ExtensionDefinition } from './createExtension';
/** @internal */
export function resolveExtensionDefinition<TConfig>(
definition: ExtensionDefinition<TConfig>,
context?: { namespace?: string },
): Extension<TConfig> {
const { name, kind, namespace: _, ...rest } = definition;
const namespace = context?.namespace ?? definition.namespace;
if (!namespace) {
throw new Error(
`Extension must declare an explicit namespace as it could not be resolved from context, name=${name} kind=${kind}`,
);
}
let id;
if (kind && name) {
id = `${kind}:${namespace}/${name}`; // nav-item:catalog/index
} else if (kind) {
id = `${kind}:${namespace}`; // nav-item:search
} else if (name) {
id = `${namespace}/${name}`; // core/nav
} else {
id = namespace; // core
}
return { id, ...rest, $$type: '@backstage/Extension' };
}