From 90f25476ac68f20b2ac151ee5d167da0c3e11c08 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 Aug 2021 12:49:45 +0200 Subject: [PATCH] config,backend-common: move config subscribe method to the base config interface Signed-off-by: Patrik Oldsberg --- .changeset/modern-ladybugs-promise.md | 5 +++++ .changeset/tricky-starfishes-cheer.md | 2 +- packages/backend-common/api-report.md | 14 +------------- packages/backend-common/src/config.ts | 12 +++--------- packages/config/api-report.md | 3 +++ packages/config/src/types.ts | 11 +++++++++++ plugins/catalog-backend/api-report.md | 1 - .../next/ConfigLocationEntityProvider.test.ts | 18 ++++++------------ .../src/next/ConfigLocationEntityProvider.ts | 5 ++--- .../src/next/NextCatalogBuilder.ts | 3 +-- 10 files changed, 33 insertions(+), 41 deletions(-) create mode 100644 .changeset/modern-ladybugs-promise.md diff --git a/.changeset/modern-ladybugs-promise.md b/.changeset/modern-ladybugs-promise.md new file mode 100644 index 0000000000..8ad48d42f4 --- /dev/null +++ b/.changeset/modern-ladybugs-promise.md @@ -0,0 +1,5 @@ +--- +'@backstage/config': patch +--- + +Extended the `Config` interface to have an optional `subscribe` method that can be used be notified of updates to the configuration. diff --git a/.changeset/tricky-starfishes-cheer.md b/.changeset/tricky-starfishes-cheer.md index 455c8f42eb..bc2fb6a91b 100644 --- a/.changeset/tricky-starfishes-cheer.md +++ b/.changeset/tricky-starfishes-cheer.md @@ -2,4 +2,4 @@ '@backstage/backend-common': patch --- -Add support for watching configuration through a new `ObservableConfig` type that is now returned by `loadBackendConfig`. +Add support for watching configuration by implementing the `subscribe` method in the configuration returned by `loadBackendConfig`. diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index a97d50c10f..2652dad122 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -386,25 +386,13 @@ export { isChildPath }; // Warning: (ae-missing-release-tag) "loadBackendConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public -export function loadBackendConfig(options: Options): Promise; +export function loadBackendConfig(options: Options): Promise; // Warning: (ae-missing-release-tag) "notFoundHandler" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public export function notFoundHandler(): RequestHandler; -// Warning: (ae-missing-release-tag) "ObservableConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export interface ObservableConfig extends Config { - // (undocumented) - subscribe( - onChange: () => void, - ): { - unsubscribe: () => void; - }; -} - // Warning: (ae-missing-release-tag) "PluginCacheManager" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public diff --git a/packages/backend-common/src/config.ts b/packages/backend-common/src/config.ts index d955aae71e..7c660ee4e6 100644 --- a/packages/backend-common/src/config.ts +++ b/packages/backend-common/src/config.ts @@ -21,11 +21,7 @@ import { findPaths } from '@backstage/cli-common'; import { Config, ConfigReader, JsonValue } from '@backstage/config'; import { loadConfig } from '@backstage/config-loader'; -export interface ObservableConfig extends Config { - subscribe(onChange: () => void): { unsubscribe: () => void }; -} - -class ObservableConfigProxy implements ObservableConfig { +class ObservableConfigProxy implements Config { private config: Config = new ConfigReader({}); private readonly subscribers: (() => void)[] = []; @@ -38,7 +34,7 @@ class ObservableConfigProxy implements ObservableConfig { try { subscriber(); } catch (error) { - this.logger.error(`ObservableConfig subscriber threw error, ${error}`); + this.logger.error(`Config subscriber threw error, ${error}`); } } } @@ -119,9 +115,7 @@ let currentCancelFunc: () => void; * * This function should only be called once, during the initialization of the backend. */ -export async function loadBackendConfig( - options: Options, -): Promise { +export async function loadBackendConfig(options: Options): Promise { const args = parseArgs(options.argv); const configPaths: string[] = [args.config ?? []].flat(); diff --git a/packages/config/api-report.md b/packages/config/api-report.md index eff4236026..91f37894c0 100644 --- a/packages/config/api-report.md +++ b/packages/config/api-report.md @@ -16,6 +16,9 @@ export type AppConfig = { // // @public (undocumented) export type Config = { + subscribe?(onChange: () => void): { + unsubscribe: () => void; + }; has(key: string): boolean; keys(): string[]; get(key?: string): T; diff --git a/packages/config/src/types.ts b/packages/config/src/types.ts index 1135e7d554..84de5dae70 100644 --- a/packages/config/src/types.ts +++ b/packages/config/src/types.ts @@ -26,6 +26,17 @@ export type AppConfig = { }; export type Config = { + /** + * Subscribes to the configuration object in order to receive a notification + * whenever any value within the configuration has changed. + * + * This method is optional to implement, and consumers need to check if it is + * implemented before invoking it. + */ + subscribe?(onChange: () => void): { + unsubscribe: () => void; + }; + has(key: string): boolean; keys(): string[]; diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index 688780039b..7286855d4e 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -21,7 +21,6 @@ import { Knex } from 'knex'; import { Location as Location_2 } from '@backstage/catalog-model'; import { LocationSpec } from '@backstage/catalog-model'; import { Logger as Logger_2 } from 'winston'; -import { ObservableConfig } from '@backstage/backend-common'; import { Organizations } from 'aws-sdk'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; diff --git a/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.test.ts b/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.test.ts index e97de4eea4..ef3e47eb8b 100644 --- a/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.test.ts +++ b/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.test.ts @@ -14,10 +14,7 @@ * limitations under the License. */ -import { - resolvePackagePath, - ObservableConfig, -} from '@backstage/backend-common'; +import { resolvePackagePath } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import path from 'path'; import { ConfigLocationEntityProvider } from './ConfigLocationEntityProvider'; @@ -83,15 +80,12 @@ describe('ConfigLocationEntityProvider', () => { }, }; - const mockConfig: ObservableConfig = Object.assign( - new ConfigReader(mutableConfigData), - { - subscribe: (s: () => void) => { - subscriber = s; - return { unsubscribe: () => {} }; - }, + const mockConfig = Object.assign(new ConfigReader(mutableConfigData), { + subscribe: (s: () => void) => { + subscriber = s; + return { unsubscribe: () => {} }; }, - ); + }); const mockConnection = { applyMutation: jest.fn(), diff --git a/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.ts b/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.ts index 3c148e808d..5deca09944 100644 --- a/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.ts +++ b/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.ts @@ -15,14 +15,13 @@ */ import { Config } from '@backstage/config'; -import { ObservableConfig } from '@backstage/backend-common'; import path from 'path'; import { getEntityLocationRef } from './processing/util'; import { EntityProvider, EntityProviderConnection } from './types'; import { locationSpecToLocationEntity } from './util'; export class ConfigLocationEntityProvider implements EntityProvider { - constructor(private readonly config: Config | ObservableConfig) {} + constructor(private readonly config: Config) {} getProviderName(): string { return 'ConfigLocationProvider'; @@ -35,7 +34,7 @@ export class ConfigLocationEntityProvider implements EntityProvider { entities, }); - if ('subscribe' in this.config) { + if (this.config.subscribe) { let currentKey = JSON.stringify(entities); this.config.subscribe(() => { diff --git a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts index 8d796d442e..fb12077508 100644 --- a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts +++ b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts @@ -15,7 +15,6 @@ */ import { - ObservableConfig, PluginDatabaseManager, resolvePackagePath, UrlReader, @@ -80,7 +79,7 @@ import { Stitcher } from './stitching/Stitcher'; export type CatalogEnvironment = { logger: Logger; database: PluginDatabaseManager; - config: Config | ObservableConfig; + config: Config; reader: UrlReader; };