backend-plugin-api,backend-defaults: add createSharedEnvironment

Co-authored-by: blam <ben@blam.sh>
Co-authored-by: Johan Haals <johan.haals@gmail.com>
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2023-01-13 11:53:33 +01:00
parent 3adb716e58
commit e6e77f073a
5 changed files with 131 additions and 8 deletions
+3
View File
@@ -5,12 +5,15 @@
```ts
import { Backend } from '@backstage/backend-app-api';
import { ServiceFactoryOrFunction } from '@backstage/backend-plugin-api';
import { SharedBackendEnvironment } from '@backstage/backend-plugin-api';
// @public (undocumented)
export function createBackend(options?: CreateBackendOptions): Backend;
// @public (undocumented)
export interface CreateBackendOptions {
// (undocumented)
env?: SharedBackendEnvironment;
// (undocumented)
services?: ServiceFactoryOrFunction[];
}
+35 -8
View File
@@ -33,7 +33,15 @@ import {
urlReaderFactory,
identityFactory,
} from '@backstage/backend-app-api';
import { ServiceFactoryOrFunction } from '@backstage/backend-plugin-api';
import {
ServiceFactory,
ServiceFactoryOrFunction,
SharedBackendEnvironment,
} from '@backstage/backend-plugin-api';
// Internal import of the type to avoid needing to export this.
// eslint-disable-next-line monorepo/no-internal-import
import type { InternalSharedBackendEnvironment } from '@backstage/backend-plugin-api/src/wiring/createSharedEnvironment';
export const defaultServiceFactories = [
cacheFactory(),
@@ -57,6 +65,7 @@ export const defaultServiceFactories = [
* @public
*/
export interface CreateBackendOptions {
env?: SharedBackendEnvironment;
services?: ServiceFactoryOrFunction[];
}
@@ -64,15 +73,33 @@ export interface CreateBackendOptions {
* @public
*/
export function createBackend(options?: CreateBackendOptions): Backend {
const services = new Array<ServiceFactory>();
// Highest priority: Services passed directly to createBackend
const providedServices = (options?.services ?? []).map(sf =>
typeof sf === 'function' ? sf() : sf,
);
const providedIds = new Set(providedServices.map(sf => sf.service.id));
const neededDefaultFactories = defaultServiceFactories.filter(
sf => !providedIds.has(sf.service.id),
);
services.push(...providedServices);
return createSpecializedBackend({
services: [...neededDefaultFactories, ...providedServices],
});
// Middle priority: Services from the shared environment
if (options?.env) {
const env = options.env as unknown as InternalSharedBackendEnvironment;
if (env.version !== 'v1') {
throw new Error(`Unsupported shared environment version: ${env.version}`);
}
const environmentServices =
env.services?.filter(
sf => !services.some(({ service }) => sf.service.id === service.id),
) ?? [];
services.push(...environmentServices);
}
// Lowest priority: Default services that are not already provided by environment or directly to createBackend
const defaultServices = defaultServiceFactories.filter(
sf => !services.some(({ service }) => service.id === sf.service.id),
);
services.push(...defaultServices);
return createSpecializedBackend({ services });
}
+21
View File
@@ -153,6 +153,15 @@ export function createServiceRef<TService>(
config: ServiceRefConfig<TService, 'root'>,
): ServiceRef<TService, 'root'>;
// @public
export function createSharedEnvironment<
TOptions extends [options?: object] = [],
>(
config:
| SharedBackendEnvironmentConfig
| ((...params: TOptions) => SharedBackendEnvironmentConfig),
): (...options: TOptions) => SharedBackendEnvironment;
// @public
export interface DatabaseService {
getClient(): Promise<Knex>;
@@ -382,6 +391,18 @@ export interface ServiceRefConfig<TService, TScope extends 'root' | 'plugin'> {
scope?: TScope;
}
// @public (undocumented)
export interface SharedBackendEnvironment {
// (undocumented)
$$type: 'SharedBackendEnvironment';
}
// @public (undocumented)
export interface SharedBackendEnvironmentConfig {
// (undocumented)
services?: ServiceFactoryOrFunction[];
}
// @public
export interface TokenManagerService {
authenticate(token: string): Promise<void>;
@@ -0,0 +1,67 @@
/*
* 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 { ServiceFactory, ServiceFactoryOrFunction } from '../services';
/** @public */
export interface SharedBackendEnvironmentConfig {
services?: ServiceFactoryOrFunction[];
}
// This type is opaque in order to allow for future API evolution without
// cluttering the external API. For example we might want to add support
// for more powerful callback based backend modifications.
//
// By making this opaque we also ensure that the type doesn't become an input
// type that we need to care about, as it would otherwise be possible to pass
// a custom environment definition to `createBackend`, which we don't want.
/**
* @public
*/
export interface SharedBackendEnvironment {
$$type: 'SharedBackendEnvironment';
}
/**
* This type is NOT supposed to be used by anyone except internally by the backend-app-api package.
* @internal */
export interface InternalSharedBackendEnvironment {
version: 'v1';
services?: ServiceFactory[];
}
/**
* Creates a shared backend environment which can be used to create multiple backends
* @public
*/
export function createSharedEnvironment<
TOptions extends [options?: object] = [],
>(
config:
| SharedBackendEnvironmentConfig
| ((...params: TOptions) => SharedBackendEnvironmentConfig),
): (...options: TOptions) => SharedBackendEnvironment {
const configCallback = typeof config === 'function' ? config : () => config;
return (...options) => {
const actualConfig = configCallback(...options);
const services = actualConfig?.services?.map(sf =>
typeof sf === 'function' ? sf() : sf,
);
return { services } as unknown as SharedBackendEnvironment;
};
}
@@ -14,6 +14,11 @@
* limitations under the License.
*/
export { createSharedEnvironment } from './createSharedEnvironment';
export type {
SharedBackendEnvironment,
SharedBackendEnvironmentConfig,
} from './createSharedEnvironment';
export type {
BackendModuleConfig,
BackendPluginConfig,