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:
@@ -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[];
|
||||
}
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user