frontend-app-api: add config support

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-08 13:45:27 +02:00
parent b628d30a2b
commit e30df514e1
2 changed files with 31 additions and 8 deletions
@@ -16,7 +16,6 @@
import { AppConfig } from '@backstage/config';
import { JsonObject } from '@backstage/types';
import { AppConfigLoader } from './types';
/**
* The default config loader, which expects that config is available at compile-time
@@ -30,12 +29,17 @@ import { AppConfigLoader } from './types';
*
* @public
*/
export const defaultConfigLoader: AppConfigLoader = async (
export async function defaultConfigLoader(): Promise<AppConfig[]> {
return defaultConfigLoaderSync();
}
/** @internal */
export function defaultConfigLoaderSync(
// This string may be replaced at runtime to provide additional config.
// It should be replaced by a JSON-serialized config object.
// It's a param so we can test it, but at runtime this will always fall back to default.
runtimeConfigJson: string = '__APP_INJECTED_RUNTIME_CONFIG__',
) => {
) {
const appConfig = process.env.APP_CONFIG;
if (!appConfig) {
throw new Error('No static configuration provided');
@@ -70,4 +74,4 @@ export const defaultConfigLoader: AppConfigLoader = async (
});
}
return configs;
};
}
+23 -4
View File
@@ -35,6 +35,8 @@ import { RoutingProvider } from './routing/RoutingContext';
import {
ApiHolder,
appThemeApiRef,
ConfigApi,
configApiRef,
RouteRef,
} from '@backstage/core-plugin-api';
import { getAvailablePlugins } from './wiring/discovery';
@@ -44,16 +46,24 @@ import {
ApiResolver,
AppThemeSelector,
} from '@backstage/core-app-api';
// TODO: Get rid of all of these
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
import { AppThemeProvider } from '../../core-app-api/src/app/AppThemeProvider';
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
import { defaultConfigLoaderSync } from '../../core-app-api/src/app/defaultConfigLoader';
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
import { themes } from '../../app-defaults/src/defaults/themes';
/** @public */
export function createApp(options: { plugins: BackstagePlugin[] }): {
export function createApp(options: {
plugins: BackstagePlugin[];
config?: ConfigApi;
}): {
createRoot(): JSX.Element;
} {
const appConfig = ConfigReader.fromConfigs(process.env.APP_CONFIG as any);
const appConfig =
options?.config ?? ConfigReader.fromConfigs(defaultConfigLoaderSync());
const builtinExtensions = [CoreRouter, Core];
const discoveredPlugins = getAvailablePlugins();
@@ -135,7 +145,7 @@ export function createApp(options: { plugins: BackstagePlugin[] }): {
throw Error('Unable to find core extension instance');
}
const apiHolder = createApiHolder(coreInstance);
const apiHolder = createApiHolder(coreInstance, appConfig);
return {
createRoot() {
@@ -162,7 +172,10 @@ export function createApp(options: { plugins: BackstagePlugin[] }): {
};
}
function createApiHolder(coreExtension: ExtensionInstance): ApiHolder {
function createApiHolder(
coreExtension: ExtensionInstance,
configApi: ConfigApi,
): ApiHolder {
const factoryRegistry = new ApiFactoryRegistry();
const apiFactories =
@@ -187,6 +200,12 @@ function createApiHolder(coreExtension: ExtensionInstance): ApiHolder {
factory: () => AppThemeSelector.createWithStorage(themes),
});
factoryRegistry.register('static', {
api: configApiRef,
deps: {},
factory: () => configApi,
});
ApiResolver.validateFactories(factoryRegistry, factoryRegistry.getAllApis());
return new ApiResolver(factoryRegistry);