Merge pull request #24724 from backstage/freben/more-default-moves
move over most trivial services to backend-defaults
This commit is contained in:
@@ -2,4 +2,8 @@
|
||||
'@backstage/backend-defaults': patch
|
||||
---
|
||||
|
||||
Added the `schedulerServiceFactory` and its implementation, migrated over from `@backstage/backend-app-api`
|
||||
Added core service factories and implementations from
|
||||
`@backstage/backend-app-api`. They are now available as subpath exports, e.g.
|
||||
`@backstage/backend-defaults/scheduler` is where the service factory and default
|
||||
implementation of `coreServices.scheduler` now lives. They have been marked as
|
||||
deprecated in their old locations.
|
||||
|
||||
@@ -2,4 +2,7 @@
|
||||
'@backstage/backend-app-api': patch
|
||||
---
|
||||
|
||||
Deprecated `schedulerServiceFactory`, which should now instead be imported from `@backstage/backend-defaults/scheduler` instead
|
||||
Deprecated core service factories and implementations and moved them over to
|
||||
subpath exports on `@backstage/backend-defaults` instead. E.g.
|
||||
`@backstage/backend-defaults/scheduler` is where the service factory and default
|
||||
implementation of `coreServices.scheduler` now lives.
|
||||
|
||||
@@ -65,7 +65,7 @@ export interface Backend {
|
||||
stop(): Promise<void>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
// @public @deprecated (undocumented)
|
||||
export const cacheServiceFactory: () => ServiceFactory<CacheClient, 'plugin'>;
|
||||
|
||||
// @public (undocumented)
|
||||
@@ -100,7 +100,7 @@ export interface CreateSpecializedBackendOptions {
|
||||
defaultServiceFactories: ServiceFactoryOrFunction[];
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
// @public @deprecated (undocumented)
|
||||
export const databaseServiceFactory: () => ServiceFactory<
|
||||
PluginDatabaseManager,
|
||||
'plugin'
|
||||
@@ -121,7 +121,7 @@ export interface DefaultRootHttpRouterOptions {
|
||||
indexPath?: string | false;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
// @public @deprecated (undocumented)
|
||||
export const discoveryServiceFactory: () => ServiceFactory<
|
||||
DiscoveryService,
|
||||
'plugin'
|
||||
@@ -137,7 +137,7 @@ export interface ExtendedHttpServer extends http.Server {
|
||||
stop(): Promise<void>;
|
||||
}
|
||||
|
||||
// @public
|
||||
// @public @deprecated
|
||||
export class HostDiscovery implements DiscoveryService {
|
||||
static fromConfig(
|
||||
config: Config,
|
||||
@@ -190,13 +190,13 @@ export type HttpServerOptions = {
|
||||
};
|
||||
};
|
||||
|
||||
// @public
|
||||
// @public @deprecated
|
||||
export type IdentityFactoryOptions = {
|
||||
issuer?: string;
|
||||
algorithms?: string[];
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
// @public @deprecated (undocumented)
|
||||
export const identityServiceFactory: (
|
||||
options?: IdentityFactoryOptions | undefined,
|
||||
) => ServiceFactory<IdentityService, 'plugin'>;
|
||||
@@ -208,7 +208,7 @@ export interface LifecycleMiddlewareOptions {
|
||||
startupRequestPauseTimeout?: HumanDuration;
|
||||
}
|
||||
|
||||
// @public
|
||||
// @public @deprecated
|
||||
export const lifecycleServiceFactory: () => ServiceFactory<
|
||||
LifecycleService,
|
||||
'plugin'
|
||||
@@ -255,7 +255,7 @@ export interface MiddlewareFactoryOptions {
|
||||
logger: LoggerService;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
// @public @deprecated (undocumented)
|
||||
export const permissionsServiceFactory: () => ServiceFactory<
|
||||
PermissionsService,
|
||||
'plugin'
|
||||
@@ -270,7 +270,7 @@ export function readHelmetOptions(config?: Config): HelmetOptions;
|
||||
// @public
|
||||
export function readHttpServerOptions(config?: Config): HttpServerOptions;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public @deprecated (undocumented)
|
||||
export interface RootConfigFactoryOptions {
|
||||
argv?: string[];
|
||||
remote?: Pick<RemoteConfigSourceOptions, 'reloadInterval'>;
|
||||
@@ -278,7 +278,7 @@ export interface RootConfigFactoryOptions {
|
||||
watch?: boolean;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
// @public @deprecated (undocumented)
|
||||
export const rootConfigServiceFactory: (
|
||||
options?: RootConfigFactoryOptions | undefined,
|
||||
) => ServiceFactory<RootConfigService, 'root'>;
|
||||
@@ -314,7 +314,7 @@ export const rootHttpRouterServiceFactory: (
|
||||
options?: RootHttpRouterFactoryOptions | undefined,
|
||||
) => ServiceFactory<RootHttpRouterService, 'root'>;
|
||||
|
||||
// @public
|
||||
// @public @deprecated
|
||||
export const rootLifecycleServiceFactory: () => ServiceFactory<
|
||||
RootLifecycleService,
|
||||
'root'
|
||||
@@ -332,13 +332,13 @@ export const schedulerServiceFactory: () => ServiceFactory<
|
||||
'plugin'
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public @deprecated (undocumented)
|
||||
export const tokenManagerServiceFactory: () => ServiceFactory<
|
||||
TokenManagerService,
|
||||
'plugin'
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
// @public @deprecated (undocumented)
|
||||
export const urlReaderServiceFactory: () => ServiceFactory<UrlReader, 'plugin'>;
|
||||
|
||||
// @public (undocumented)
|
||||
|
||||
+4
-1
@@ -20,7 +20,10 @@ import {
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* @public
|
||||
* @deprecated Please import from `@backstage/backend-defaults/cache` instead.
|
||||
*/
|
||||
export const cacheServiceFactory = createServiceFactory({
|
||||
service: coreServices.cache,
|
||||
deps: {
|
||||
|
||||
+8
-2
@@ -23,7 +23,10 @@ import {
|
||||
RemoteConfigSourceOptions,
|
||||
} from '@backstage/config-loader';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* @public
|
||||
* @deprecated Please import from `@backstage/backend-defaults/rootConfig` instead.
|
||||
*/
|
||||
export interface RootConfigFactoryOptions {
|
||||
/**
|
||||
* Process arguments to use instead of the default `process.argv()`.
|
||||
@@ -37,7 +40,10 @@ export interface RootConfigFactoryOptions {
|
||||
watch?: boolean;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* @public
|
||||
* @deprecated Please import from `@backstage/backend-defaults/rootConfig` instead.
|
||||
*/
|
||||
export const rootConfigServiceFactory = createServiceFactory(
|
||||
(options?: RootConfigFactoryOptions) => ({
|
||||
service: coreServices.rootConfig,
|
||||
|
||||
+4
-1
@@ -21,7 +21,10 @@ import {
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* @public
|
||||
* @deprecated Please import from `@backstage/backend-defaults/database` instead.
|
||||
*/
|
||||
export const databaseServiceFactory = createServiceFactory({
|
||||
service: coreServices.database,
|
||||
deps: {
|
||||
|
||||
@@ -29,6 +29,7 @@ type Target = string | { internal: string; external: string };
|
||||
* resolved to the same host, so there won't be any balancing of internal traffic.
|
||||
*
|
||||
* @public
|
||||
* @deprecated Please import from `@backstage/backend-defaults/discovery` instead.
|
||||
*/
|
||||
export class HostDiscovery implements DiscoveryService {
|
||||
/**
|
||||
|
||||
+4
-1
@@ -20,7 +20,10 @@ import {
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { HostDiscovery } from './HostDiscovery';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* @public
|
||||
* @deprecated Please import from `@backstage/backend-defaults/discovery` instead.
|
||||
*/
|
||||
export const discoveryServiceFactory = createServiceFactory({
|
||||
service: coreServices.discovery,
|
||||
deps: {
|
||||
|
||||
+9
-3
@@ -24,16 +24,22 @@ import { DefaultIdentityClient } from '@backstage/plugin-auth-node';
|
||||
* An identity client options object which allows extra configurations
|
||||
*
|
||||
* @public
|
||||
* @deprecated Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead
|
||||
*/
|
||||
export type IdentityFactoryOptions = {
|
||||
issuer?: string;
|
||||
|
||||
/** JWS "alg" (Algorithm) Header Parameter values. Defaults to an array containing just ES256.
|
||||
* More info on supported algorithms: https://github.com/panva/jose */
|
||||
/**
|
||||
* JWS "alg" (Algorithm) Header Parameter values. Defaults to an array containing just ES256.
|
||||
* More info on supported algorithms: https://github.com/panva/jose
|
||||
*/
|
||||
algorithms?: string[];
|
||||
};
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* @public
|
||||
* @deprecated Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead
|
||||
*/
|
||||
export const identityServiceFactory = createServiceFactory(
|
||||
(options?: IdentityFactoryOptions) => ({
|
||||
service: coreServices.identity,
|
||||
|
||||
+6
-1
@@ -26,7 +26,10 @@ import {
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
/** @internal */
|
||||
/**
|
||||
* @internal
|
||||
* @deprecated
|
||||
*/
|
||||
export class BackendPluginLifecycleImpl implements LifecycleService {
|
||||
constructor(
|
||||
private readonly logger: LoggerService,
|
||||
@@ -85,7 +88,9 @@ export class BackendPluginLifecycleImpl implements LifecycleService {
|
||||
|
||||
/**
|
||||
* Allows plugins to register shutdown hooks that are run when the process is about to exit.
|
||||
*
|
||||
* @public
|
||||
* @deprecated Please import from `@backstage/backend-defaults/lifecycle` instead.
|
||||
*/
|
||||
export const lifecycleServiceFactory = createServiceFactory({
|
||||
service: coreServices.lifecycle,
|
||||
|
||||
+4
-1
@@ -20,7 +20,10 @@ import {
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { ServerPermissionClient } from '@backstage/plugin-permission-node';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* @public
|
||||
* @deprecated Please import from `@backstage/backend-defaults/permissions` instead.
|
||||
*/
|
||||
export const permissionsServiceFactory = createServiceFactory({
|
||||
service: coreServices.permissions,
|
||||
deps: {
|
||||
|
||||
+5
-1
@@ -25,7 +25,10 @@ import {
|
||||
LoggerService,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
/** @internal */
|
||||
/**
|
||||
* @internal
|
||||
* @deprecated
|
||||
*/
|
||||
export class BackendLifecycleImpl implements RootLifecycleService {
|
||||
constructor(private readonly logger: LoggerService) {}
|
||||
|
||||
@@ -108,6 +111,7 @@ export class BackendLifecycleImpl implements RootLifecycleService {
|
||||
* Allows plugins to register shutdown hooks that are run when the process is about to exit.
|
||||
*
|
||||
* @public
|
||||
* @deprecated Please import from `@backstage/backend-defaults/rootLifecycle` instead.
|
||||
*/
|
||||
export const rootLifecycleServiceFactory = createServiceFactory({
|
||||
service: coreServices.rootLifecycle,
|
||||
|
||||
+4
-1
@@ -20,7 +20,10 @@ import {
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { ServerTokenManager } from '@backstage/backend-common';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* @public
|
||||
* @deprecated Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead
|
||||
*/
|
||||
export const tokenManagerServiceFactory = createServiceFactory({
|
||||
service: coreServices.tokenManager,
|
||||
deps: {
|
||||
|
||||
+4
-1
@@ -20,7 +20,10 @@ import {
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* @public
|
||||
* @deprecated Please import from `@backstage/backend-defaults/urlReader` instead.
|
||||
*/
|
||||
export const urlReaderServiceFactory = createServiceFactory({
|
||||
service: coreServices.urlReader,
|
||||
deps: {
|
||||
|
||||
@@ -20,9 +20,9 @@ import {
|
||||
coreServices,
|
||||
ServiceRef,
|
||||
ServiceFactory,
|
||||
LifecycleService,
|
||||
RootLifecycleService,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { BackendLifecycleImpl } from '../services/implementations/rootLifecycle/rootLifecycleServiceFactory';
|
||||
import { BackendPluginLifecycleImpl } from '../services/implementations/lifecycle/lifecycleServiceFactory';
|
||||
import { ServiceOrExtensionPoint } from './types';
|
||||
// Direct internal import to avoid duplication
|
||||
// eslint-disable-next-line @backstage/no-forbidden-package-imports
|
||||
@@ -345,27 +345,42 @@ export class BackendInitializer {
|
||||
}
|
||||
|
||||
// Bit of a hacky way to grab the lifecycle services, potentially find a nicer way to do this
|
||||
async #getRootLifecycleImpl(): Promise<BackendLifecycleImpl> {
|
||||
async #getRootLifecycleImpl(): Promise<
|
||||
RootLifecycleService & {
|
||||
startup(): Promise<void>;
|
||||
shutdown(): Promise<void>;
|
||||
}
|
||||
> {
|
||||
const lifecycleService = await this.#serviceRegistry.get(
|
||||
coreServices.rootLifecycle,
|
||||
'root',
|
||||
);
|
||||
if (lifecycleService instanceof BackendLifecycleImpl) {
|
||||
return lifecycleService;
|
||||
|
||||
const service = lifecycleService as any;
|
||||
if (
|
||||
service &&
|
||||
typeof service.startup === 'function' &&
|
||||
typeof service.shutdown === 'function'
|
||||
) {
|
||||
return service;
|
||||
}
|
||||
|
||||
throw new Error('Unexpected root lifecycle service implementation');
|
||||
}
|
||||
|
||||
async #getPluginLifecycleImpl(
|
||||
pluginId: string,
|
||||
): Promise<BackendPluginLifecycleImpl> {
|
||||
): Promise<LifecycleService & { startup(): Promise<void> }> {
|
||||
const lifecycleService = await this.#serviceRegistry.get(
|
||||
coreServices.lifecycle,
|
||||
pluginId,
|
||||
);
|
||||
if (lifecycleService instanceof BackendPluginLifecycleImpl) {
|
||||
return lifecycleService;
|
||||
|
||||
const service = lifecycleService as any;
|
||||
if (service && typeof service.startup === 'function') {
|
||||
return service;
|
||||
}
|
||||
|
||||
throw new Error('Unexpected plugin lifecycle service implementation');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
## API Report File for "@backstage/backend-defaults"
|
||||
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
import { CacheClient } from '@backstage/backend-common';
|
||||
import { ServiceFactory } from '@backstage/backend-plugin-api';
|
||||
|
||||
// @public (undocumented)
|
||||
export const cacheServiceFactory: () => ServiceFactory<CacheClient, 'plugin'>;
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
@@ -0,0 +1,16 @@
|
||||
## API Report File for "@backstage/backend-defaults"
|
||||
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
import { PluginDatabaseManager } from '@backstage/backend-common';
|
||||
import { ServiceFactory } from '@backstage/backend-plugin-api';
|
||||
|
||||
// @public (undocumented)
|
||||
export const databaseServiceFactory: () => ServiceFactory<
|
||||
PluginDatabaseManager,
|
||||
'plugin'
|
||||
>;
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
@@ -0,0 +1,31 @@
|
||||
## API Report File for "@backstage/backend-defaults"
|
||||
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
import { Config } from '@backstage/config';
|
||||
import { DiscoveryService } from '@backstage/backend-plugin-api';
|
||||
import { ServiceFactory } from '@backstage/backend-plugin-api';
|
||||
|
||||
// @public (undocumented)
|
||||
export const discoveryServiceFactory: () => ServiceFactory<
|
||||
DiscoveryService,
|
||||
'plugin'
|
||||
>;
|
||||
|
||||
// @public
|
||||
export class HostDiscovery implements DiscoveryService {
|
||||
static fromConfig(
|
||||
config: Config,
|
||||
options?: {
|
||||
basePath?: string;
|
||||
},
|
||||
): HostDiscovery;
|
||||
// (undocumented)
|
||||
getBaseUrl(pluginId: string): Promise<string>;
|
||||
// (undocumented)
|
||||
getExternalBaseUrl(pluginId: string): Promise<string>;
|
||||
}
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
@@ -0,0 +1,16 @@
|
||||
## API Report File for "@backstage/backend-defaults"
|
||||
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
import { LifecycleService } from '@backstage/backend-plugin-api';
|
||||
import { ServiceFactory } from '@backstage/backend-plugin-api';
|
||||
|
||||
// @public
|
||||
export const lifecycleServiceFactory: () => ServiceFactory<
|
||||
LifecycleService,
|
||||
'plugin'
|
||||
>;
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
@@ -0,0 +1,16 @@
|
||||
## API Report File for "@backstage/backend-defaults"
|
||||
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
import { PermissionsService } from '@backstage/backend-plugin-api';
|
||||
import { ServiceFactory } from '@backstage/backend-plugin-api';
|
||||
|
||||
// @public (undocumented)
|
||||
export const permissionsServiceFactory: () => ServiceFactory<
|
||||
PermissionsService,
|
||||
'plugin'
|
||||
>;
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
@@ -0,0 +1,24 @@
|
||||
## API Report File for "@backstage/backend-defaults"
|
||||
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
import { RemoteConfigSourceOptions } from '@backstage/config-loader';
|
||||
import { RootConfigService } from '@backstage/backend-plugin-api';
|
||||
import { ServiceFactory } from '@backstage/backend-plugin-api';
|
||||
|
||||
// @public (undocumented)
|
||||
export interface RootConfigFactoryOptions {
|
||||
argv?: string[];
|
||||
remote?: Pick<RemoteConfigSourceOptions, 'reloadInterval'>;
|
||||
// (undocumented)
|
||||
watch?: boolean;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export const rootConfigServiceFactory: (
|
||||
options?: RootConfigFactoryOptions | undefined,
|
||||
) => ServiceFactory<RootConfigService, 'root'>;
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
@@ -0,0 +1,16 @@
|
||||
## API Report File for "@backstage/backend-defaults"
|
||||
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
import { RootLifecycleService } from '@backstage/backend-plugin-api';
|
||||
import { ServiceFactory } from '@backstage/backend-plugin-api';
|
||||
|
||||
// @public
|
||||
export const rootLifecycleServiceFactory: () => ServiceFactory<
|
||||
RootLifecycleService,
|
||||
'root'
|
||||
>;
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
@@ -0,0 +1,13 @@
|
||||
## API Report File for "@backstage/backend-defaults"
|
||||
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
import { ServiceFactory } from '@backstage/backend-plugin-api';
|
||||
import { UrlReader } from '@backstage/backend-common';
|
||||
|
||||
// @public (undocumented)
|
||||
export const urlReaderServiceFactory: () => ServiceFactory<UrlReader, 'plugin'>;
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2020 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 interface Config {
|
||||
/**
|
||||
* Options used by the default discovery service.
|
||||
*/
|
||||
discovery?: {
|
||||
/**
|
||||
* A list of target baseUrls and the associated plugins.
|
||||
*/
|
||||
endpoints: Array<{
|
||||
/**
|
||||
* The target base URL to use for the plugin.
|
||||
*
|
||||
* Can be either a string or an object with internal and external keys.
|
||||
* Targets with `{{pluginId}}` or `{{ pluginId }} in the URL will be replaced with the plugin ID.
|
||||
*/
|
||||
target: string | { internal: string; external: string };
|
||||
/**
|
||||
* Array of plugins which use the target base URL.
|
||||
*/
|
||||
plugins: string[];
|
||||
}>;
|
||||
};
|
||||
}
|
||||
@@ -20,22 +20,55 @@
|
||||
"license": "Apache-2.0",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./cache": "./src/entrypoints/cache/index.ts",
|
||||
"./database": "./src/entrypoints/database/index.ts",
|
||||
"./discovery": "./src/entrypoints/discovery/index.ts",
|
||||
"./lifecycle": "./src/entrypoints/lifecycle/index.ts",
|
||||
"./permissions": "./src/entrypoints/permissions/index.ts",
|
||||
"./rootConfig": "./src/entrypoints/rootConfig/index.ts",
|
||||
"./rootLifecycle": "./src/entrypoints/rootLifecycle/index.ts",
|
||||
"./scheduler": "./src/entrypoints/scheduler/index.ts",
|
||||
"./urlReader": "./src/entrypoints/urlReader/index.ts",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
"cache": [
|
||||
"src/entrypoints/cache/index.ts"
|
||||
],
|
||||
"database": [
|
||||
"src/entrypoints/database/index.ts"
|
||||
],
|
||||
"discovery": [
|
||||
"src/entrypoints/discovery/index.ts"
|
||||
],
|
||||
"lifecycle": [
|
||||
"src/entrypoints/lifecycle/index.ts"
|
||||
],
|
||||
"permissions": [
|
||||
"src/entrypoints/permissions/index.ts"
|
||||
],
|
||||
"rootConfig": [
|
||||
"src/entrypoints/rootConfig/index.ts"
|
||||
],
|
||||
"rootLifecycle": [
|
||||
"src/entrypoints/rootLifecycle/index.ts"
|
||||
],
|
||||
"scheduler": [
|
||||
"src/entrypoints/scheduler/index.ts"
|
||||
],
|
||||
"urlReader": [
|
||||
"src/entrypoints/urlReader/index.ts"
|
||||
],
|
||||
"package.json": [
|
||||
"package.json"
|
||||
]
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"config.d.ts",
|
||||
"dist",
|
||||
"migrations"
|
||||
],
|
||||
@@ -52,8 +85,11 @@
|
||||
"@backstage/backend-app-api": "workspace:^",
|
||||
"@backstage/backend-common": "workspace:^",
|
||||
"@backstage/backend-plugin-api": "workspace:^",
|
||||
"@backstage/config": "workspace:^",
|
||||
"@backstage/config-loader": "workspace:^",
|
||||
"@backstage/errors": "workspace:^",
|
||||
"@backstage/plugin-events-node": "workspace:^",
|
||||
"@backstage/plugin-permission-node": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"@opentelemetry/api": "^1.3.0",
|
||||
"cron": "^3.0.0",
|
||||
@@ -68,5 +104,6 @@
|
||||
"@backstage/backend-test-utils": "workspace:^",
|
||||
"@backstage/cli": "workspace:^",
|
||||
"wait-for-expect": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"configSchema": "config.d.ts"
|
||||
}
|
||||
|
||||
@@ -16,27 +16,27 @@
|
||||
|
||||
import {
|
||||
Backend,
|
||||
cacheServiceFactory,
|
||||
rootConfigServiceFactory,
|
||||
authServiceFactory,
|
||||
createSpecializedBackend,
|
||||
databaseServiceFactory,
|
||||
discoveryServiceFactory,
|
||||
httpAuthServiceFactory,
|
||||
httpRouterServiceFactory,
|
||||
rootHttpRouterServiceFactory,
|
||||
lifecycleServiceFactory,
|
||||
rootLifecycleServiceFactory,
|
||||
identityServiceFactory,
|
||||
loggerServiceFactory,
|
||||
permissionsServiceFactory,
|
||||
rootHttpRouterServiceFactory,
|
||||
rootLoggerServiceFactory,
|
||||
tokenManagerServiceFactory,
|
||||
urlReaderServiceFactory,
|
||||
identityServiceFactory,
|
||||
authServiceFactory,
|
||||
httpAuthServiceFactory,
|
||||
userInfoServiceFactory,
|
||||
} from '@backstage/backend-app-api';
|
||||
import { eventsServiceFactory } from '@backstage/plugin-events-node';
|
||||
import { cacheServiceFactory } from '@backstage/backend-defaults/cache';
|
||||
import { databaseServiceFactory } from '@backstage/backend-defaults/database';
|
||||
import { discoveryServiceFactory } from '@backstage/backend-defaults/discovery';
|
||||
import { lifecycleServiceFactory } from '@backstage/backend-defaults/lifecycle';
|
||||
import { permissionsServiceFactory } from '@backstage/backend-defaults/permissions';
|
||||
import { rootConfigServiceFactory } from '@backstage/backend-defaults/rootConfig';
|
||||
import { rootLifecycleServiceFactory } from '@backstage/backend-defaults/rootLifecycle';
|
||||
import { schedulerServiceFactory } from '@backstage/backend-defaults/scheduler';
|
||||
import { urlReaderServiceFactory } from '@backstage/backend-defaults/urlReader';
|
||||
import { eventsServiceFactory } from '@backstage/plugin-events-node';
|
||||
|
||||
export const defaultServiceFactories = [
|
||||
authServiceFactory(),
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2022 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 { CacheManager } from '@backstage/backend-common';
|
||||
import {
|
||||
coreServices,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const cacheServiceFactory = createServiceFactory({
|
||||
service: coreServices.cache,
|
||||
deps: {
|
||||
config: coreServices.rootConfig,
|
||||
plugin: coreServices.pluginMetadata,
|
||||
},
|
||||
async createRootContext({ config }) {
|
||||
return CacheManager.fromConfig(config);
|
||||
},
|
||||
async factory({ plugin }, manager) {
|
||||
return manager.forPlugin(plugin.getId()).getClient();
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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 { cacheServiceFactory } from './cacheServiceFactory';
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2022 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 { DatabaseManager } from '@backstage/backend-common';
|
||||
import {
|
||||
coreServices,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const databaseServiceFactory = createServiceFactory({
|
||||
service: coreServices.database,
|
||||
deps: {
|
||||
config: coreServices.rootConfig,
|
||||
lifecycle: coreServices.lifecycle,
|
||||
pluginMetadata: coreServices.pluginMetadata,
|
||||
},
|
||||
async createRootContext({ config }) {
|
||||
return config.getOptional('backend.database')
|
||||
? DatabaseManager.fromConfig(config)
|
||||
: DatabaseManager.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
database: { client: 'better-sqlite3', connection: ':memory:' },
|
||||
},
|
||||
}),
|
||||
);
|
||||
},
|
||||
async factory({ pluginMetadata, lifecycle }, databaseManager) {
|
||||
return databaseManager.forPlugin(pluginMetadata.getId(), {
|
||||
pluginMetadata,
|
||||
lifecycle,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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 { databaseServiceFactory } from './databaseServiceFactory';
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright 2020 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 { ConfigReader } from '@backstage/config';
|
||||
import { HostDiscovery } from './HostDiscovery';
|
||||
|
||||
describe('HostDiscovery', () => {
|
||||
it('is created from config', async () => {
|
||||
const discovery = HostDiscovery.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
baseUrl: 'http://localhost:40',
|
||||
listen: { port: 80, host: 'localhost' },
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
await expect(discovery.getBaseUrl('catalog')).resolves.toBe(
|
||||
'http://localhost:80/api/catalog',
|
||||
);
|
||||
await expect(discovery.getExternalBaseUrl('catalog')).resolves.toBe(
|
||||
'http://localhost:40/api/catalog',
|
||||
);
|
||||
});
|
||||
|
||||
it('strips trailing slashes in config', async () => {
|
||||
const discovery = HostDiscovery.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
baseUrl: 'http://localhost:40//',
|
||||
listen: { port: 80, host: 'localhost' },
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
await expect(discovery.getBaseUrl('catalog')).resolves.toBe(
|
||||
'http://localhost:80/api/catalog',
|
||||
);
|
||||
await expect(discovery.getExternalBaseUrl('catalog')).resolves.toBe(
|
||||
'http://localhost:40/api/catalog',
|
||||
);
|
||||
});
|
||||
|
||||
it('can configure the base path', async () => {
|
||||
const discovery = HostDiscovery.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
baseUrl: 'http://localhost:40',
|
||||
listen: { port: 80, host: 'localhost' },
|
||||
},
|
||||
}),
|
||||
{ basePath: '/service' },
|
||||
);
|
||||
|
||||
await expect(discovery.getBaseUrl('catalog')).resolves.toBe(
|
||||
'http://localhost:80/service/catalog',
|
||||
);
|
||||
await expect(discovery.getExternalBaseUrl('catalog')).resolves.toBe(
|
||||
'http://localhost:40/service/catalog',
|
||||
);
|
||||
});
|
||||
|
||||
it.each([
|
||||
[{ listen: ':80' }, 'http://localhost:80'],
|
||||
[{ listen: ':40', https: true }, 'https://localhost:40'],
|
||||
[{ listen: '127.0.0.1:80' }, 'http://127.0.0.1:80'],
|
||||
[{ listen: '127.0.0.1:80', https: true }, 'https://127.0.0.1:80'],
|
||||
[{ listen: '0.0.0.0:40' }, 'http://127.0.0.1:40'],
|
||||
[{ listen: { port: 80 } }, 'http://localhost:80'],
|
||||
[{ listen: { port: 8000 } }, 'http://localhost:8000'],
|
||||
[{ listen: { port: 80, host: '0.0.0.0' } }, 'http://127.0.0.1:80'],
|
||||
[{ listen: { port: 80, host: '::' } }, 'http://localhost:80'],
|
||||
[{ listen: { port: 80, host: '::1' } }, 'http://[::1]:80'],
|
||||
[{ listen: { port: 90, host: '::2' }, https: true }, 'https://[::2]:90'],
|
||||
])('resolves internal baseUrl for %j as %s', async (config, expected) => {
|
||||
const discovery = HostDiscovery.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
baseUrl: 'http://localhost:40',
|
||||
...config,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
await expect(discovery.getBaseUrl('catalog')).resolves.toBe(
|
||||
`${expected}/api/catalog`,
|
||||
);
|
||||
});
|
||||
|
||||
it('uses plugin specific targets from config if provided', async () => {
|
||||
const discovery = HostDiscovery.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
baseUrl: 'http://localhost:40',
|
||||
listen: { port: 80, host: 'localhost' },
|
||||
},
|
||||
discovery: {
|
||||
endpoints: [
|
||||
{
|
||||
target: {
|
||||
internal: 'http://catalog-backend-internal:8080/api/catalog',
|
||||
external: 'http://catalog-backend-external:8080/api/catalog',
|
||||
},
|
||||
plugins: ['catalog'],
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
await expect(discovery.getBaseUrl('catalog')).resolves.toBe(
|
||||
'http://catalog-backend-internal:8080/api/catalog',
|
||||
);
|
||||
await expect(discovery.getExternalBaseUrl('catalog')).resolves.toBe(
|
||||
'http://catalog-backend-external:8080/api/catalog',
|
||||
);
|
||||
});
|
||||
|
||||
it('uses a single target for internal and external for a plugin', async () => {
|
||||
const discovery = HostDiscovery.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
baseUrl: 'http://localhost:40',
|
||||
listen: { port: 80, host: 'localhost' },
|
||||
},
|
||||
discovery: {
|
||||
endpoints: [
|
||||
{
|
||||
target: 'http://catalog-backend:8080/api/catalog',
|
||||
plugins: ['catalog'],
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
await expect(discovery.getBaseUrl('catalog')).resolves.toBe(
|
||||
'http://catalog-backend:8080/api/catalog',
|
||||
);
|
||||
await expect(discovery.getExternalBaseUrl('catalog')).resolves.toBe(
|
||||
'http://catalog-backend:8080/api/catalog',
|
||||
);
|
||||
});
|
||||
|
||||
it('defaults to the backend baseUrl when there is not an endpoint for a plugin', async () => {
|
||||
const discovery = HostDiscovery.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
baseUrl: 'http://localhost:40',
|
||||
listen: { port: 80, host: 'localhost' },
|
||||
},
|
||||
discovery: {
|
||||
endpoints: [
|
||||
{
|
||||
target: 'http://catalog-backend:8080/api/catalog',
|
||||
plugins: ['catalog'],
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
await expect(discovery.getBaseUrl('scaffolder')).resolves.toBe(
|
||||
'http://localhost:80/api/scaffolder',
|
||||
);
|
||||
await expect(discovery.getExternalBaseUrl('scaffolder')).resolves.toBe(
|
||||
'http://localhost:40/api/scaffolder',
|
||||
);
|
||||
});
|
||||
|
||||
it('replaces {{pluginId}} or {{ pluginId }} in the target', async () => {
|
||||
const discovery = HostDiscovery.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
baseUrl: 'http://localhost:40',
|
||||
listen: { port: 80, host: 'localhost' },
|
||||
},
|
||||
discovery: {
|
||||
endpoints: [
|
||||
{
|
||||
target: 'http://common-backend:8080/api/{{pluginId}}',
|
||||
plugins: ['catalog', 'docs'],
|
||||
},
|
||||
{
|
||||
target: {
|
||||
internal: 'http://scaffolder-internal:8080/api/{{ pluginId }}',
|
||||
external: 'http://scaffolder-external:8080/api/{{ pluginId }}',
|
||||
},
|
||||
plugins: ['scaffolder'],
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
await expect(discovery.getBaseUrl('catalog')).resolves.toBe(
|
||||
'http://common-backend:8080/api/catalog',
|
||||
);
|
||||
await expect(discovery.getExternalBaseUrl('catalog')).resolves.toBe(
|
||||
'http://common-backend:8080/api/catalog',
|
||||
);
|
||||
await expect(discovery.getBaseUrl('docs')).resolves.toBe(
|
||||
'http://common-backend:8080/api/docs',
|
||||
);
|
||||
await expect(discovery.getExternalBaseUrl('docs')).resolves.toBe(
|
||||
'http://common-backend:8080/api/docs',
|
||||
);
|
||||
await expect(discovery.getBaseUrl('scaffolder')).resolves.toBe(
|
||||
'http://scaffolder-internal:8080/api/scaffolder',
|
||||
);
|
||||
await expect(discovery.getExternalBaseUrl('scaffolder')).resolves.toBe(
|
||||
'http://scaffolder-external:8080/api/scaffolder',
|
||||
);
|
||||
});
|
||||
|
||||
it('encodes the pluginId', async () => {
|
||||
const discovery = HostDiscovery.fromConfig(
|
||||
new ConfigReader({
|
||||
backend: {
|
||||
baseUrl: 'http://localhost:40',
|
||||
listen: { port: 80, host: 'localhost' },
|
||||
},
|
||||
discovery: {
|
||||
endpoints: [
|
||||
{
|
||||
target: 'http://common-backend:8080/api/{{pluginId}}',
|
||||
plugins: ['plugin/beta'],
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
await expect(discovery.getBaseUrl('plugin/beta')).resolves.toBe(
|
||||
'http://common-backend:8080/api/plugin%2Fbeta',
|
||||
);
|
||||
await expect(discovery.getBaseUrl('plugin/alpha')).resolves.toBe(
|
||||
'http://localhost:80/api/plugin%2Falpha',
|
||||
);
|
||||
await expect(discovery.getExternalBaseUrl('plugin/alpha')).resolves.toBe(
|
||||
'http://localhost:40/api/plugin%2Falpha',
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 2020 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 { Config } from '@backstage/config';
|
||||
import { readHttpServerOptions } from '@backstage/backend-app-api';
|
||||
import { DiscoveryService } from '@backstage/backend-plugin-api';
|
||||
|
||||
type Target = string | { internal: string; external: string };
|
||||
|
||||
/**
|
||||
* HostDiscovery is a basic PluginEndpointDiscovery implementation
|
||||
* that can handle plugins that are hosted in a single or multiple deployments.
|
||||
*
|
||||
* The deployment may be scaled horizontally, as long as the external URL
|
||||
* is the same for all instances. However, internal URLs will always be
|
||||
* resolved to the same host, so there won't be any balancing of internal traffic.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export class HostDiscovery implements DiscoveryService {
|
||||
/**
|
||||
* Creates a new HostDiscovery discovery instance by reading
|
||||
* from the `backend` config section, specifically the `.baseUrl` for
|
||||
* discovering the external URL, and the `.listen` and `.https` config
|
||||
* for the internal one.
|
||||
*
|
||||
* Can be overridden in config by providing a target and corresponding plugins in `discovery.endpoints`.
|
||||
* eg.
|
||||
* ```yaml
|
||||
* discovery:
|
||||
* endpoints:
|
||||
* - target: https://internal.example.com/internal-catalog
|
||||
* plugins: [catalog]
|
||||
* - target: https://internal.example.com/secure/api/{{pluginId}}
|
||||
* plugins: [auth, permission]
|
||||
* - target:
|
||||
* internal: https://internal.example.com/search
|
||||
* external: https://example.com/search
|
||||
* plugins: [search]
|
||||
* ```
|
||||
*
|
||||
* The basePath defaults to `/api`, meaning the default full internal
|
||||
* path for the `catalog` plugin will be `http://localhost:7007/api/catalog`.
|
||||
*/
|
||||
static fromConfig(config: Config, options?: { basePath?: string }) {
|
||||
const basePath = options?.basePath ?? '/api';
|
||||
const externalBaseUrl = config
|
||||
.getString('backend.baseUrl')
|
||||
.replace(/\/+$/, '');
|
||||
|
||||
const {
|
||||
listen: { host: listenHost = '::', port: listenPort },
|
||||
} = readHttpServerOptions(config.getConfig('backend'));
|
||||
const protocol = config.has('backend.https') ? 'https' : 'http';
|
||||
|
||||
// Translate bind-all to localhost, and support IPv6
|
||||
let host = listenHost;
|
||||
if (host === '::' || host === '') {
|
||||
// We use localhost instead of ::1, since IPv6-compatible systems should default
|
||||
// to using IPv6 when they see localhost, but if the system doesn't support IPv6
|
||||
// things will still work.
|
||||
host = 'localhost';
|
||||
} else if (host === '0.0.0.0') {
|
||||
host = '127.0.0.1';
|
||||
}
|
||||
if (host.includes(':')) {
|
||||
host = `[${host}]`;
|
||||
}
|
||||
|
||||
const internalBaseUrl = `${protocol}://${host}:${listenPort}`;
|
||||
|
||||
return new HostDiscovery(
|
||||
internalBaseUrl + basePath,
|
||||
externalBaseUrl + basePath,
|
||||
config.getOptionalConfig('discovery'),
|
||||
);
|
||||
}
|
||||
|
||||
private constructor(
|
||||
private readonly internalBaseUrl: string,
|
||||
private readonly externalBaseUrl: string,
|
||||
private readonly discoveryConfig: Config | undefined,
|
||||
) {}
|
||||
|
||||
private getTargetFromConfig(pluginId: string, type: 'internal' | 'external') {
|
||||
const endpoints = this.discoveryConfig?.getOptionalConfigArray('endpoints');
|
||||
|
||||
const target = endpoints
|
||||
?.find(endpoint => endpoint.getStringArray('plugins').includes(pluginId))
|
||||
?.get<Target>('target');
|
||||
|
||||
if (!target) {
|
||||
const baseUrl =
|
||||
type === 'external' ? this.externalBaseUrl : this.internalBaseUrl;
|
||||
|
||||
return `${baseUrl}/${encodeURIComponent(pluginId)}`;
|
||||
}
|
||||
|
||||
if (typeof target === 'string') {
|
||||
return target.replace(
|
||||
/\{\{\s*pluginId\s*\}\}/g,
|
||||
encodeURIComponent(pluginId),
|
||||
);
|
||||
}
|
||||
|
||||
return target[type].replace(
|
||||
/\{\{\s*pluginId\s*\}\}/g,
|
||||
encodeURIComponent(pluginId),
|
||||
);
|
||||
}
|
||||
|
||||
async getBaseUrl(pluginId: string): Promise<string> {
|
||||
return this.getTargetFromConfig(pluginId, 'internal');
|
||||
}
|
||||
|
||||
async getExternalBaseUrl(pluginId: string): Promise<string> {
|
||||
return this.getTargetFromConfig(pluginId, 'external');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2022 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 {
|
||||
coreServices,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { HostDiscovery } from './HostDiscovery';
|
||||
|
||||
/** @public */
|
||||
export const discoveryServiceFactory = createServiceFactory({
|
||||
service: coreServices.discovery,
|
||||
deps: {
|
||||
config: coreServices.rootConfig,
|
||||
},
|
||||
async factory({ config }) {
|
||||
return HostDiscovery.fromConfig(config);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 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 { discoveryServiceFactory } from './discoveryServiceFactory';
|
||||
export { HostDiscovery } from './HostDiscovery';
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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 { lifecycleServiceFactory } from './lifecycleServiceFactory';
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 2022 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 {
|
||||
LifecycleService,
|
||||
LifecycleServiceShutdownHook,
|
||||
LifecycleServiceShutdownOptions,
|
||||
LifecycleServiceStartupHook,
|
||||
LifecycleServiceStartupOptions,
|
||||
LoggerService,
|
||||
PluginMetadataService,
|
||||
RootLifecycleService,
|
||||
coreServices,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
/** @internal */
|
||||
export class BackendPluginLifecycleImpl implements LifecycleService {
|
||||
constructor(
|
||||
private readonly logger: LoggerService,
|
||||
private readonly rootLifecycle: RootLifecycleService,
|
||||
private readonly pluginMetadata: PluginMetadataService,
|
||||
) {}
|
||||
|
||||
#hasStarted = false;
|
||||
#startupTasks: Array<{
|
||||
hook: LifecycleServiceStartupHook;
|
||||
options?: LifecycleServiceStartupOptions;
|
||||
}> = [];
|
||||
|
||||
addStartupHook(
|
||||
hook: LifecycleServiceStartupHook,
|
||||
options?: LifecycleServiceStartupOptions,
|
||||
): void {
|
||||
if (this.#hasStarted) {
|
||||
throw new Error('Attempted to add startup hook after startup');
|
||||
}
|
||||
this.#startupTasks.push({ hook, options });
|
||||
}
|
||||
|
||||
async startup(): Promise<void> {
|
||||
if (this.#hasStarted) {
|
||||
return;
|
||||
}
|
||||
this.#hasStarted = true;
|
||||
|
||||
this.logger.debug(
|
||||
`Running ${this.#startupTasks.length} plugin startup tasks...`,
|
||||
);
|
||||
await Promise.all(
|
||||
this.#startupTasks.map(async ({ hook, options }) => {
|
||||
const logger = options?.logger ?? this.logger;
|
||||
try {
|
||||
await hook();
|
||||
logger.debug(`Plugin startup hook succeeded`);
|
||||
} catch (error) {
|
||||
logger.error(`Plugin startup hook failed, ${error}`);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
addShutdownHook(
|
||||
hook: LifecycleServiceShutdownHook,
|
||||
options?: LifecycleServiceShutdownOptions,
|
||||
): void {
|
||||
const plugin = this.pluginMetadata.getId();
|
||||
this.rootLifecycle.addShutdownHook(hook, {
|
||||
logger: options?.logger?.child({ plugin }) ?? this.logger,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows plugins to register shutdown hooks that are run when the process is about to exit.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const lifecycleServiceFactory = createServiceFactory({
|
||||
service: coreServices.lifecycle,
|
||||
deps: {
|
||||
logger: coreServices.logger,
|
||||
rootLifecycle: coreServices.rootLifecycle,
|
||||
pluginMetadata: coreServices.pluginMetadata,
|
||||
},
|
||||
async factory({ rootLifecycle, logger, pluginMetadata }) {
|
||||
return new BackendPluginLifecycleImpl(
|
||||
logger,
|
||||
rootLifecycle,
|
||||
pluginMetadata,
|
||||
);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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 { permissionsServiceFactory } from './permissionsServiceFactory';
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2022 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 {
|
||||
coreServices,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { ServerPermissionClient } from '@backstage/plugin-permission-node';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const permissionsServiceFactory = createServiceFactory({
|
||||
service: coreServices.permissions,
|
||||
deps: {
|
||||
auth: coreServices.auth,
|
||||
config: coreServices.rootConfig,
|
||||
discovery: coreServices.discovery,
|
||||
tokenManager: coreServices.tokenManager,
|
||||
},
|
||||
async factory({ auth, config, discovery, tokenManager }) {
|
||||
return ServerPermissionClient.fromConfig(config, {
|
||||
auth,
|
||||
discovery,
|
||||
tokenManager,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 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 { rootConfigServiceFactory } from './rootConfigServiceFactory';
|
||||
export type { RootConfigFactoryOptions } from './rootConfigServiceFactory';
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2022 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 {
|
||||
coreServices,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
ConfigSources,
|
||||
RemoteConfigSourceOptions,
|
||||
} from '@backstage/config-loader';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface RootConfigFactoryOptions {
|
||||
/**
|
||||
* Process arguments to use instead of the default `process.argv()`.
|
||||
*/
|
||||
argv?: string[];
|
||||
|
||||
/**
|
||||
* Enables and sets options for remote configuration loading.
|
||||
*/
|
||||
remote?: Pick<RemoteConfigSourceOptions, 'reloadInterval'>;
|
||||
watch?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const rootConfigServiceFactory = createServiceFactory(
|
||||
(options?: RootConfigFactoryOptions) => ({
|
||||
service: coreServices.rootConfig,
|
||||
deps: {},
|
||||
async factory() {
|
||||
const source = ConfigSources.default({
|
||||
argv: options?.argv,
|
||||
remote: options?.remote,
|
||||
watch: options?.watch,
|
||||
});
|
||||
console.log(`Loading config from ${source}`);
|
||||
return await ConfigSources.toConfig(source);
|
||||
},
|
||||
}),
|
||||
);
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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 { rootLifecycleServiceFactory } from './rootLifecycleServiceFactory';
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2022 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 { getVoidLogger } from '@backstage/backend-common';
|
||||
import { BackendLifecycleImpl } from './rootLifecycleServiceFactory';
|
||||
|
||||
describe('lifecycleService', () => {
|
||||
it('should execute registered shutdown hook', async () => {
|
||||
const service = new BackendLifecycleImpl(getVoidLogger());
|
||||
const hook = jest.fn();
|
||||
service.addShutdownHook(() => hook());
|
||||
// should not execute the hook more than once.
|
||||
await service.shutdown();
|
||||
await service.shutdown();
|
||||
await service.shutdown();
|
||||
expect(hook).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should not throw errors', async () => {
|
||||
const service = new BackendLifecycleImpl(getVoidLogger());
|
||||
service.addShutdownHook(() => {
|
||||
throw new Error('oh no');
|
||||
});
|
||||
await expect(service.shutdown()).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it('should not throw async errors', async () => {
|
||||
const service = new BackendLifecycleImpl(getVoidLogger());
|
||||
service.addShutdownHook(async () => {
|
||||
throw new Error('oh no');
|
||||
});
|
||||
await expect(service.shutdown()).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it('should reject hooks after trigger', async () => {
|
||||
const service = new BackendLifecycleImpl(getVoidLogger());
|
||||
await service.startup();
|
||||
expect(() => {
|
||||
service.addStartupHook(() => {});
|
||||
}).toThrow('Attempted to add startup hook after startup');
|
||||
|
||||
await service.shutdown();
|
||||
expect(() => {
|
||||
service.addShutdownHook(() => {});
|
||||
}).toThrow('Attempted to add shutdown hook after shutdown');
|
||||
});
|
||||
});
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2022 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 {
|
||||
createServiceFactory,
|
||||
coreServices,
|
||||
LifecycleServiceStartupHook,
|
||||
LifecycleServiceStartupOptions,
|
||||
LifecycleServiceShutdownHook,
|
||||
LifecycleServiceShutdownOptions,
|
||||
RootLifecycleService,
|
||||
LoggerService,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
/** @internal */
|
||||
export class BackendLifecycleImpl implements RootLifecycleService {
|
||||
constructor(private readonly logger: LoggerService) {}
|
||||
|
||||
#hasStarted = false;
|
||||
#startupTasks: Array<{
|
||||
hook: LifecycleServiceStartupHook;
|
||||
options?: LifecycleServiceStartupOptions;
|
||||
}> = [];
|
||||
|
||||
addStartupHook(
|
||||
hook: LifecycleServiceStartupHook,
|
||||
options?: LifecycleServiceStartupOptions,
|
||||
): void {
|
||||
if (this.#hasStarted) {
|
||||
throw new Error('Attempted to add startup hook after startup');
|
||||
}
|
||||
this.#startupTasks.push({ hook, options });
|
||||
}
|
||||
|
||||
async startup(): Promise<void> {
|
||||
if (this.#hasStarted) {
|
||||
return;
|
||||
}
|
||||
this.#hasStarted = true;
|
||||
|
||||
this.logger.debug(`Running ${this.#startupTasks.length} startup tasks...`);
|
||||
await Promise.all(
|
||||
this.#startupTasks.map(async ({ hook, options }) => {
|
||||
const logger = options?.logger ?? this.logger;
|
||||
try {
|
||||
await hook();
|
||||
logger.debug(`Startup hook succeeded`);
|
||||
} catch (error) {
|
||||
logger.error(`Startup hook failed, ${error}`);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
#hasShutdown = false;
|
||||
#shutdownTasks: Array<{
|
||||
hook: LifecycleServiceShutdownHook;
|
||||
options?: LifecycleServiceShutdownOptions;
|
||||
}> = [];
|
||||
|
||||
addShutdownHook(
|
||||
hook: LifecycleServiceShutdownHook,
|
||||
options?: LifecycleServiceShutdownOptions,
|
||||
): void {
|
||||
if (this.#hasShutdown) {
|
||||
throw new Error('Attempted to add shutdown hook after shutdown');
|
||||
}
|
||||
this.#shutdownTasks.push({ hook, options });
|
||||
}
|
||||
|
||||
async shutdown(): Promise<void> {
|
||||
if (this.#hasShutdown) {
|
||||
return;
|
||||
}
|
||||
this.#hasShutdown = true;
|
||||
|
||||
this.logger.debug(
|
||||
`Running ${this.#shutdownTasks.length} shutdown tasks...`,
|
||||
);
|
||||
await Promise.all(
|
||||
this.#shutdownTasks.map(async ({ hook, options }) => {
|
||||
const logger = options?.logger ?? this.logger;
|
||||
try {
|
||||
await hook();
|
||||
logger.debug(`Shutdown hook succeeded`);
|
||||
} catch (error) {
|
||||
logger.error(`Shutdown hook failed, ${error}`);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows plugins to register shutdown hooks that are run when the process is about to exit.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const rootLifecycleServiceFactory = createServiceFactory({
|
||||
service: coreServices.rootLifecycle,
|
||||
deps: {
|
||||
logger: coreServices.rootLogger,
|
||||
},
|
||||
async factory({ logger }) {
|
||||
return new BackendLifecycleImpl(logger);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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 { urlReaderServiceFactory } from './urlReaderServiceFactory';
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2022 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 { UrlReaders } from '@backstage/backend-common';
|
||||
import {
|
||||
coreServices,
|
||||
createServiceFactory,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
/** @public */
|
||||
export const urlReaderServiceFactory = createServiceFactory({
|
||||
service: coreServices.urlReader,
|
||||
deps: {
|
||||
config: coreServices.rootConfig,
|
||||
logger: coreServices.logger,
|
||||
},
|
||||
async factory({ config, logger }) {
|
||||
return UrlReaders.default({
|
||||
config,
|
||||
logger,
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -204,9 +204,11 @@ export namespace coreServices {
|
||||
const rootLifecycle: ServiceRef<RootLifecycleService, 'root'>;
|
||||
const rootLogger: ServiceRef<RootLoggerService, 'root'>;
|
||||
const scheduler: ServiceRef<SchedulerService, 'plugin'>;
|
||||
const tokenManager: ServiceRef<TokenManagerService, 'plugin'>;
|
||||
const // @deprecated
|
||||
tokenManager: ServiceRef<TokenManagerService, 'plugin'>;
|
||||
const urlReader: ServiceRef<UrlReaderService, 'plugin'>;
|
||||
const identity: ServiceRef<IdentityService, 'plugin'>;
|
||||
const // @deprecated
|
||||
identity: ServiceRef<IdentityService, 'plugin'>;
|
||||
}
|
||||
|
||||
// @public
|
||||
|
||||
@@ -172,6 +172,7 @@ export namespace coreServices {
|
||||
* The service reference for the plugin scoped {@link TokenManagerService}.
|
||||
*
|
||||
* @public
|
||||
* @deprecated Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead
|
||||
*/
|
||||
export const tokenManager = createServiceRef<
|
||||
import('./TokenManagerService').TokenManagerService
|
||||
@@ -190,6 +191,7 @@ export namespace coreServices {
|
||||
* The service reference for the plugin scoped {@link IdentityService}.
|
||||
*
|
||||
* @public
|
||||
* @deprecated Please migrate to the new `coreServices.auth`, `coreServices.httpAuth`, and `coreServices.userInfo` services as needed instead
|
||||
*/
|
||||
export const identity = createServiceRef<
|
||||
import('./IdentityService').IdentityService
|
||||
|
||||
@@ -3433,8 +3433,11 @@ __metadata:
|
||||
"@backstage/backend-plugin-api": "workspace:^"
|
||||
"@backstage/backend-test-utils": "workspace:^"
|
||||
"@backstage/cli": "workspace:^"
|
||||
"@backstage/config": "workspace:^"
|
||||
"@backstage/config-loader": "workspace:^"
|
||||
"@backstage/errors": "workspace:^"
|
||||
"@backstage/plugin-events-node": "workspace:^"
|
||||
"@backstage/plugin-permission-node": "workspace:^"
|
||||
"@backstage/types": "workspace:^"
|
||||
"@opentelemetry/api": ^1.3.0
|
||||
cron: ^3.0.0
|
||||
|
||||
Reference in New Issue
Block a user