@backstage/backend-defaults 0.4.4 → 0.5.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +104 -12
- package/auth/package.json +1 -1
- package/cache/package.json +1 -1
- package/config.d.ts +221 -0
- package/database/package.json +1 -1
- package/discovery/package.json +1 -1
- package/dist/auth.cjs.js +16 -45
- package/dist/auth.cjs.js.map +1 -1
- package/dist/auth.d.ts +1 -1
- package/dist/cache.cjs.js +22 -3
- package/dist/cache.cjs.js.map +1 -1
- package/dist/cache.d.ts +1 -1
- package/dist/database.cjs.js +4 -2
- package/dist/database.cjs.js.map +1 -1
- package/dist/database.d.ts +1 -1
- package/dist/discovery.d.ts +1 -1
- package/dist/httpAuth.d.ts +1 -1
- package/dist/httpRouter.d.ts +1 -1
- package/dist/index.cjs.js +118 -2
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +22 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/logger.d.ts +1 -1
- package/dist/permissions.cjs.js +3 -5
- package/dist/permissions.cjs.js.map +1 -1
- package/dist/permissions.d.ts +1 -1
- package/dist/rootConfig.cjs.js +1 -1
- package/dist/rootConfig.cjs.js.map +1 -1
- package/dist/rootHealth.d.ts +1 -1
- package/dist/rootHttpRouter.cjs.js +1 -1
- package/dist/rootHttpRouter.cjs.js.map +1 -1
- package/dist/rootLifecycle.d.ts +1 -1
- package/dist/rootLogger.d.ts +1 -1
- package/dist/scheduler.d.ts +1 -1
- package/dist/urlReader.cjs.js +2 -1
- package/dist/urlReader.cjs.js.map +1 -1
- package/dist/urlReader.d.ts +1 -1
- package/dist/userInfo.d.ts +1 -1
- package/httpAuth/package.json +1 -1
- package/httpRouter/package.json +1 -1
- package/lifecycle/package.json +1 -1
- package/logger/package.json +1 -1
- package/package.json +11 -10
- package/permissions/package.json +1 -1
- package/rootConfig/package.json +1 -1
- package/rootHealth/package.json +1 -1
- package/rootHttpRouter/package.json +1 -1
- package/rootLifecycle/package.json +1 -1
- package/rootLogger/package.json +1 -1
- package/scheduler/package.json +1 -1
- package/urlReader/package.json +1 -1
- package/userInfo/package.json +1 -1
package/dist/cache.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.cjs.js","sources":["../src/entrypoints/cache/CacheClient.ts","../src/entrypoints/cache/CacheManager.ts","../src/entrypoints/cache/cacheServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n CacheService,\n CacheServiceOptions,\n CacheServiceSetOptions,\n} from '@backstage/backend-plugin-api';\nimport { JsonValue } from '@backstage/types';\nimport { createHash } from 'crypto';\nimport Keyv from 'keyv';\n\nexport type CacheClientFactory = (options: CacheServiceOptions) => Keyv;\n\n/**\n * A basic, concrete implementation of the CacheService, suitable for almost\n * all uses in Backstage.\n */\nexport class DefaultCacheClient implements CacheService {\n #client: Keyv;\n #clientFactory: CacheClientFactory;\n #options: CacheServiceOptions;\n\n constructor(\n client: Keyv,\n clientFactory: CacheClientFactory,\n options: CacheServiceOptions,\n ) {\n this.#client = client;\n this.#clientFactory = clientFactory;\n this.#options = options;\n }\n\n async get<TValue extends JsonValue>(\n key: string,\n ): Promise<TValue | undefined> {\n const k = this.getNormalizedKey(key);\n const value = await this.#client.get(k);\n return value as TValue | undefined;\n }\n\n async set(\n key: string,\n value: JsonValue,\n opts: CacheServiceSetOptions = {},\n ): Promise<void> {\n const k = this.getNormalizedKey(key);\n await this.#client.set(k, value, opts.ttl);\n }\n\n async delete(key: string): Promise<void> {\n const k = this.getNormalizedKey(key);\n await this.#client.delete(k);\n }\n\n withOptions(options: CacheServiceOptions): CacheService {\n const newOptions = { ...this.#options, ...options };\n return new DefaultCacheClient(\n this.#clientFactory(newOptions),\n this.#clientFactory,\n newOptions,\n );\n }\n\n /**\n * Ensures keys are well-formed for any/all cache stores.\n */\n private getNormalizedKey(candidateKey: string): string {\n // Remove potentially invalid characters.\n const wellFormedKey = Buffer.from(candidateKey).toString('base64');\n\n // Memcache in particular doesn't do well with keys > 250 bytes.\n // Padded because a plugin ID is also prepended to the key.\n if (wellFormedKey.length < 200) {\n return wellFormedKey;\n }\n\n return createHash('sha256').update(candidateKey).digest('base64');\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n CacheServiceOptions,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport Keyv from 'keyv';\nimport { DefaultCacheClient } from './CacheClient';\nimport { CacheManagerOptions, PluginCacheManager } from './types';\n\ntype StoreFactory = (pluginId: string, defaultTtl: number | undefined) => Keyv;\n\n/**\n * Implements a Cache Manager which will automatically create new cache clients\n * for plugins when requested. All requested cache clients are created with the\n * connection details provided.\n *\n * @public\n */\nexport class CacheManager {\n /**\n * Keys represent supported `backend.cache.store` values, mapped to factories\n * that return Keyv instances appropriate to the store.\n */\n private readonly storeFactories = {\n redis: this.createRedisStoreFactory(),\n memcache: this.createMemcacheStoreFactory(),\n memory: this.createMemoryStoreFactory(),\n };\n\n private readonly logger?: LoggerService;\n private readonly store: keyof CacheManager['storeFactories'];\n private readonly connection: string;\n private readonly useRedisSets: boolean;\n private readonly errorHandler: CacheManagerOptions['onError'];\n private readonly defaultTtl?: number;\n\n /**\n * Creates a new {@link CacheManager} instance by reading from the `backend`\n * config section, specifically the `.cache` key.\n *\n * @param config - The loaded application configuration.\n */\n static fromConfig(\n config: Config,\n options: CacheManagerOptions = {},\n ): CacheManager {\n // If no `backend.cache` config is provided, instantiate the CacheManager\n // with an in-memory cache client.\n const store = config.getOptionalString('backend.cache.store') || 'memory';\n const defaultTtl = config.getOptionalNumber('backend.cache.defaultTtl');\n const connectionString =\n config.getOptionalString('backend.cache.connection') || '';\n const useRedisSets =\n config.getOptionalBoolean('backend.cache.useRedisSets') ?? true;\n const logger = options.logger?.child({\n type: 'cacheManager',\n });\n return new CacheManager(\n store,\n connectionString,\n useRedisSets,\n options.onError,\n logger,\n defaultTtl,\n );\n }\n\n /** @internal */\n constructor(\n store: string,\n connectionString: string,\n useRedisSets: boolean,\n errorHandler: CacheManagerOptions['onError'],\n logger?: LoggerService,\n defaultTtl?: number,\n ) {\n if (!this.storeFactories.hasOwnProperty(store)) {\n throw new Error(`Unknown cache store: ${store}`);\n }\n this.logger = logger;\n this.store = store as keyof CacheManager['storeFactories'];\n this.connection = connectionString;\n this.useRedisSets = useRedisSets;\n this.errorHandler = errorHandler;\n this.defaultTtl = defaultTtl;\n }\n\n /**\n * Generates a PluginCacheManager for consumption by plugins.\n *\n * @param pluginId - The plugin that the cache manager should be created for.\n * Plugin names should be unique.\n */\n forPlugin(pluginId: string): PluginCacheManager {\n return {\n getClient: (defaultOptions = {}) => {\n const clientFactory = (options: CacheServiceOptions) => {\n return this.getClientWithTtl(\n pluginId,\n options.defaultTtl ?? this.defaultTtl,\n );\n };\n\n return new DefaultCacheClient(\n clientFactory(defaultOptions),\n clientFactory,\n defaultOptions,\n );\n },\n };\n }\n\n private getClientWithTtl(pluginId: string, ttl: number | undefined): Keyv {\n return this.storeFactories[this.store](pluginId, ttl);\n }\n\n private createRedisStoreFactory(): StoreFactory {\n const KeyvRedis = require('@keyv/redis');\n let store: typeof KeyvRedis | undefined;\n return (pluginId, defaultTtl) => {\n if (!store) {\n store = new KeyvRedis(this.connection);\n // Always provide an error handler to avoid stopping the process\n store.on('error', (err: Error) => {\n this.logger?.error('Failed to create redis cache client', err);\n this.errorHandler?.(err);\n });\n }\n return new Keyv({\n namespace: pluginId,\n ttl: defaultTtl,\n store,\n emitErrors: false,\n useRedisSets: this.useRedisSets,\n });\n };\n }\n\n private createMemcacheStoreFactory(): StoreFactory {\n const KeyvMemcache = require('@keyv/memcache');\n let store: typeof KeyvMemcache | undefined;\n return (pluginId, defaultTtl) => {\n if (!store) {\n store = new KeyvMemcache(this.connection);\n // Always provide an error handler to avoid stopping the process\n store.on('error', (err: Error) => {\n this.logger?.error('Failed to create memcache cache client', err);\n this.errorHandler?.(err);\n });\n }\n return new Keyv({\n namespace: pluginId,\n ttl: defaultTtl,\n emitErrors: false,\n store,\n });\n };\n }\n\n private createMemoryStoreFactory(): StoreFactory {\n const store = new Map();\n return (pluginId, defaultTtl) =>\n new Keyv({\n namespace: pluginId,\n ttl: defaultTtl,\n emitErrors: false,\n store,\n });\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { CacheManager } from './CacheManager';\n\n/**\n * Key-value store for caching data.\n *\n * See {@link @backstage/code-plugin-api#CacheService}\n * and {@link https://backstage.io/docs/backend-system/core-services/cache | the service docs}\n * for more information.\n *\n * @public\n */\nexport const cacheServiceFactory = createServiceFactory({\n service: coreServices.cache,\n deps: {\n config: coreServices.rootConfig,\n plugin: coreServices.pluginMetadata,\n logger: coreServices.rootLogger,\n },\n async createRootContext({ config, logger }) {\n return CacheManager.fromConfig(config, { logger });\n },\n async factory({ plugin }, manager) {\n return manager.forPlugin(plugin.getId()).getClient();\n },\n});\n"],"names":["createHash","Keyv","createServiceFactory","coreServices"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cache.cjs.js","sources":["../src/entrypoints/cache/types.ts","../src/entrypoints/cache/CacheClient.ts","../src/entrypoints/cache/CacheManager.ts","../src/entrypoints/cache/cacheServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport {\n CacheService,\n CacheServiceOptions,\n} from '@backstage/backend-plugin-api';\nimport { HumanDuration, durationToMilliseconds } from '@backstage/types';\n\n/**\n * Options given when constructing a {@link CacheManager}.\n *\n * @public\n */\nexport type CacheManagerOptions = {\n /**\n * An optional logger for use by the PluginCacheManager.\n */\n logger?: LoggerService;\n\n /**\n * An optional handler for connection errors emitted from the underlying data\n * store.\n */\n onError?: (err: Error) => void;\n};\n\n/**\n * @public\n */\nexport interface PluginCacheManager {\n getClient(options?: CacheServiceOptions): CacheService;\n}\n\nexport function ttlToMilliseconds(ttl: number | HumanDuration): number {\n return typeof ttl === 'number' ? ttl : durationToMilliseconds(ttl);\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n CacheService,\n CacheServiceOptions,\n CacheServiceSetOptions,\n} from '@backstage/backend-plugin-api';\nimport { JsonValue } from '@backstage/types';\nimport { createHash } from 'crypto';\nimport Keyv from 'keyv';\nimport { ttlToMilliseconds } from './types';\n\nexport type CacheClientFactory = (options: CacheServiceOptions) => Keyv;\n\n/**\n * A basic, concrete implementation of the CacheService, suitable for almost\n * all uses in Backstage.\n */\nexport class DefaultCacheClient implements CacheService {\n #client: Keyv;\n #clientFactory: CacheClientFactory;\n #options: CacheServiceOptions;\n\n constructor(\n client: Keyv,\n clientFactory: CacheClientFactory,\n options: CacheServiceOptions,\n ) {\n this.#client = client;\n this.#clientFactory = clientFactory;\n this.#options = options;\n }\n\n async get<TValue extends JsonValue>(\n key: string,\n ): Promise<TValue | undefined> {\n const k = this.getNormalizedKey(key);\n const value = await this.#client.get(k);\n return value as TValue | undefined;\n }\n\n async set(\n key: string,\n value: JsonValue,\n opts: CacheServiceSetOptions = {},\n ): Promise<void> {\n const k = this.getNormalizedKey(key);\n const ttl =\n opts.ttl !== undefined ? ttlToMilliseconds(opts.ttl) : undefined;\n await this.#client.set(k, value, ttl);\n }\n\n async delete(key: string): Promise<void> {\n const k = this.getNormalizedKey(key);\n await this.#client.delete(k);\n }\n\n withOptions(options: CacheServiceOptions): CacheService {\n const newOptions = { ...this.#options, ...options };\n return new DefaultCacheClient(\n this.#clientFactory(newOptions),\n this.#clientFactory,\n newOptions,\n );\n }\n\n /**\n * Ensures keys are well-formed for any/all cache stores.\n */\n private getNormalizedKey(candidateKey: string): string {\n // Remove potentially invalid characters.\n const wellFormedKey = Buffer.from(candidateKey).toString('base64');\n\n // Memcache in particular doesn't do well with keys > 250 bytes.\n // Padded because a plugin ID is also prepended to the key.\n if (wellFormedKey.length < 200) {\n return wellFormedKey;\n }\n\n return createHash('sha256').update(candidateKey).digest('base64');\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n CacheServiceOptions,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport Keyv from 'keyv';\nimport { DefaultCacheClient } from './CacheClient';\nimport {\n CacheManagerOptions,\n PluginCacheManager,\n ttlToMilliseconds,\n} from './types';\nimport { durationToMilliseconds } from '@backstage/types';\n\ntype StoreFactory = (pluginId: string, defaultTtl: number | undefined) => Keyv;\n\n/**\n * Implements a Cache Manager which will automatically create new cache clients\n * for plugins when requested. All requested cache clients are created with the\n * connection details provided.\n *\n * @public\n */\nexport class CacheManager {\n /**\n * Keys represent supported `backend.cache.store` values, mapped to factories\n * that return Keyv instances appropriate to the store.\n */\n private readonly storeFactories = {\n redis: this.createRedisStoreFactory(),\n memcache: this.createMemcacheStoreFactory(),\n memory: this.createMemoryStoreFactory(),\n };\n\n private readonly logger?: LoggerService;\n private readonly store: keyof CacheManager['storeFactories'];\n private readonly connection: string;\n private readonly useRedisSets: boolean;\n private readonly errorHandler: CacheManagerOptions['onError'];\n private readonly defaultTtl?: number;\n\n /**\n * Creates a new {@link CacheManager} instance by reading from the `backend`\n * config section, specifically the `.cache` key.\n *\n * @param config - The loaded application configuration.\n */\n static fromConfig(\n config: Config,\n options: CacheManagerOptions = {},\n ): CacheManager {\n // If no `backend.cache` config is provided, instantiate the CacheManager\n // with an in-memory cache client.\n const store = config.getOptionalString('backend.cache.store') || 'memory';\n const defaultTtlConfig = config.getOptional('backend.cache.defaultTtl');\n const connectionString =\n config.getOptionalString('backend.cache.connection') || '';\n const useRedisSets =\n config.getOptionalBoolean('backend.cache.useRedisSets') ?? true;\n const logger = options.logger?.child({\n type: 'cacheManager',\n });\n\n let defaultTtl: number | undefined;\n if (defaultTtlConfig !== undefined && defaultTtlConfig !== null) {\n if (typeof defaultTtlConfig === 'number') {\n defaultTtl = defaultTtlConfig;\n } else if (\n typeof defaultTtlConfig === 'object' &&\n !Array.isArray(defaultTtlConfig)\n ) {\n defaultTtl = durationToMilliseconds(defaultTtlConfig);\n } else {\n throw new Error(\n `Invalid configuration backend.cache.defaultTtl: ${defaultTtlConfig}, expected milliseconds number or HumanDuration object`,\n );\n }\n }\n\n return new CacheManager(\n store,\n connectionString,\n useRedisSets,\n options.onError,\n logger,\n defaultTtl,\n );\n }\n\n /** @internal */\n constructor(\n store: string,\n connectionString: string,\n useRedisSets: boolean,\n errorHandler: CacheManagerOptions['onError'],\n logger?: LoggerService,\n defaultTtl?: number,\n ) {\n if (!this.storeFactories.hasOwnProperty(store)) {\n throw new Error(`Unknown cache store: ${store}`);\n }\n this.logger = logger;\n this.store = store as keyof CacheManager['storeFactories'];\n this.connection = connectionString;\n this.useRedisSets = useRedisSets;\n this.errorHandler = errorHandler;\n this.defaultTtl = defaultTtl;\n }\n\n /**\n * Generates a PluginCacheManager for consumption by plugins.\n *\n * @param pluginId - The plugin that the cache manager should be created for.\n * Plugin names should be unique.\n */\n forPlugin(pluginId: string): PluginCacheManager {\n return {\n getClient: (defaultOptions = {}) => {\n const clientFactory = (options: CacheServiceOptions) => {\n const ttl = options.defaultTtl ?? this.defaultTtl;\n return this.getClientWithTtl(\n pluginId,\n ttl !== undefined ? ttlToMilliseconds(ttl) : undefined,\n );\n };\n\n return new DefaultCacheClient(\n clientFactory(defaultOptions),\n clientFactory,\n defaultOptions,\n );\n },\n };\n }\n\n private getClientWithTtl(pluginId: string, ttl: number | undefined): Keyv {\n return this.storeFactories[this.store](pluginId, ttl);\n }\n\n private createRedisStoreFactory(): StoreFactory {\n const KeyvRedis = require('@keyv/redis');\n let store: typeof KeyvRedis | undefined;\n return (pluginId, defaultTtl) => {\n if (!store) {\n store = new KeyvRedis(this.connection);\n // Always provide an error handler to avoid stopping the process\n store.on('error', (err: Error) => {\n this.logger?.error('Failed to create redis cache client', err);\n this.errorHandler?.(err);\n });\n }\n return new Keyv({\n namespace: pluginId,\n ttl: defaultTtl,\n store,\n emitErrors: false,\n useRedisSets: this.useRedisSets,\n });\n };\n }\n\n private createMemcacheStoreFactory(): StoreFactory {\n const KeyvMemcache = require('@keyv/memcache');\n let store: typeof KeyvMemcache | undefined;\n return (pluginId, defaultTtl) => {\n if (!store) {\n store = new KeyvMemcache(this.connection);\n // Always provide an error handler to avoid stopping the process\n store.on('error', (err: Error) => {\n this.logger?.error('Failed to create memcache cache client', err);\n this.errorHandler?.(err);\n });\n }\n return new Keyv({\n namespace: pluginId,\n ttl: defaultTtl,\n emitErrors: false,\n store,\n });\n };\n }\n\n private createMemoryStoreFactory(): StoreFactory {\n const store = new Map();\n return (pluginId, defaultTtl) =>\n new Keyv({\n namespace: pluginId,\n ttl: defaultTtl,\n emitErrors: false,\n store,\n });\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { CacheManager } from './CacheManager';\n\n/**\n * Key-value store for caching data.\n *\n * See {@link @backstage/code-plugin-api#CacheService}\n * and {@link https://backstage.io/docs/backend-system/core-services/cache | the service docs}\n * for more information.\n *\n * @public\n */\nexport const cacheServiceFactory = createServiceFactory({\n service: coreServices.cache,\n deps: {\n config: coreServices.rootConfig,\n plugin: coreServices.pluginMetadata,\n logger: coreServices.rootLogger,\n },\n async createRootContext({ config, logger }) {\n return CacheManager.fromConfig(config, { logger });\n },\n async factory({ plugin }, manager) {\n return manager.forPlugin(plugin.getId()).getClient();\n },\n});\n"],"names":["durationToMilliseconds","createHash","Keyv","createServiceFactory","coreServices"],"mappings":"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"}
|
package/dist/cache.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { Config } from '@backstage/config';
|
|
|
11
11
|
*
|
|
12
12
|
* @public
|
|
13
13
|
*/
|
|
14
|
-
declare const cacheServiceFactory: _backstage_backend_plugin_api.
|
|
14
|
+
declare const cacheServiceFactory: _backstage_backend_plugin_api.ServiceFactory<_backstage_backend_plugin_api.CacheService, "plugin", "singleton">;
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Options given when constructing a {@link CacheManager}.
|
package/dist/database.cjs.js
CHANGED
|
@@ -868,8 +868,10 @@ class DatabaseManagerImpl {
|
|
|
868
868
|
);
|
|
869
869
|
}
|
|
870
870
|
const getClient = () => this.getDatabase(pluginId, connector, deps);
|
|
871
|
-
const
|
|
872
|
-
|
|
871
|
+
const skip = this.options?.migrations?.skip ?? this.config.getOptionalBoolean(
|
|
872
|
+
`backend.database.plugin.${pluginId}.skipMigrations`
|
|
873
|
+
) ?? this.config.getOptionalBoolean("backend.database.skipMigrations") ?? false;
|
|
874
|
+
return { getClient, migrations: { skip } };
|
|
873
875
|
}
|
|
874
876
|
/**
|
|
875
877
|
* Provides the client type which should be used for a given plugin.
|
package/dist/database.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.cjs.js","sources":["../src/entrypoints/database/connectors/defaultNameOverride.ts","../src/entrypoints/database/connectors/mergeDatabaseConfig.ts","../src/entrypoints/database/connectors/mysql.ts","../src/entrypoints/database/connectors/defaultSchemaOverride.ts","../src/entrypoints/database/connectors/postgres.ts","../src/entrypoints/database/connectors/sqlite3.ts","../src/entrypoints/database/DatabaseManager.ts","../src/entrypoints/database/databaseServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Knex } from 'knex';\n\n/**\n * Provides a partial knex config with database name override.\n *\n * Default override for knex database drivers which accept ConnectionConfig\n * with `connection.database` as the database name field.\n *\n * @param name - database name to get config override for\n */\nexport default function defaultNameOverride(\n name: string,\n): Partial<Knex.Config> {\n return {\n connection: {\n database: name,\n },\n };\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { merge } from 'lodash';\n\n/**\n * Merges database objects together\n *\n * @public\n * @param config - The base config. The input is not modified\n * @param overrides - Any additional overrides\n */\nexport function mergeDatabaseConfig(config: any, ...overrides: any[]) {\n return merge({}, config, ...overrides);\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n LifecycleService,\n PluginMetadataService,\n} from '@backstage/backend-plugin-api';\nimport { Config, ConfigReader } from '@backstage/config';\nimport { InputError } from '@backstage/errors';\nimport { JsonObject } from '@backstage/types';\nimport knexFactory, { Knex } from 'knex';\nimport { merge, omit } from 'lodash';\nimport limiterFactory from 'p-limit';\nimport yn from 'yn';\nimport { Connector } from '../types';\nimport defaultNameOverride from './defaultNameOverride';\nimport { mergeDatabaseConfig } from './mergeDatabaseConfig';\n\n// Limits the number of concurrent DDL operations to 1\nconst ddlLimiter = limiterFactory(1);\n\n/**\n * Creates a knex mysql database connection\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function createMysqlDatabaseClient(\n dbConfig: Config,\n overrides?: Knex.Config,\n) {\n const knexConfig = buildMysqlDatabaseConfig(dbConfig, overrides);\n const database = knexFactory(knexConfig);\n return database;\n}\n\n/**\n * Builds a knex mysql database connection\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function buildMysqlDatabaseConfig(\n dbConfig: Config,\n overrides?: Knex.Config,\n) {\n return mergeDatabaseConfig(\n dbConfig.get(),\n {\n connection: getMysqlConnectionConfig(dbConfig, !!overrides),\n useNullAsDefault: true,\n },\n overrides,\n );\n}\n\n/**\n * Gets the mysql connection config\n *\n * @param dbConfig - The database config\n * @param parseConnectionString - Flag to explicitly control connection string parsing\n */\nexport function getMysqlConnectionConfig(\n dbConfig: Config,\n parseConnectionString?: boolean,\n): Knex.MySqlConnectionConfig | string {\n const connection = dbConfig.get('connection') as any;\n const isConnectionString =\n typeof connection === 'string' || connection instanceof String;\n const autoParse = typeof parseConnectionString !== 'boolean';\n\n const shouldParseConnectionString = autoParse\n ? isConnectionString\n : parseConnectionString && isConnectionString;\n\n return shouldParseConnectionString\n ? parseMysqlConnectionString(connection as string)\n : connection;\n}\n\n/**\n * Parses a mysql connection string.\n *\n * e.g. mysql://examplename:somepassword@examplehost:3306/dbname\n * @param connectionString - The mysql connection string\n */\nexport function parseMysqlConnectionString(\n connectionString: string,\n): Knex.MySqlConnectionConfig {\n try {\n const {\n protocol,\n username,\n password,\n port,\n hostname,\n pathname,\n searchParams,\n } = new URL(connectionString);\n\n if (protocol !== 'mysql:') {\n throw new Error(`Unknown protocol ${protocol}`);\n } else if (!username || !password) {\n throw new Error(`Missing username/password`);\n } else if (!pathname.match(/^\\/[^/]+$/)) {\n throw new Error(`Expected single path segment`);\n }\n\n const result: Knex.MySqlConnectionConfig = {\n user: username,\n password,\n host: hostname,\n port: Number(port || 3306),\n database: decodeURIComponent(pathname.substring(1)),\n };\n\n const ssl = searchParams.get('ssl');\n if (ssl) {\n result.ssl = ssl;\n }\n\n const debug = searchParams.get('debug');\n if (debug) {\n result.debug = yn(debug);\n }\n\n return result;\n } catch (e) {\n throw new InputError(\n `Error while parsing MySQL connection string, ${e}`,\n e,\n );\n }\n}\n\n/**\n * Creates the missing mysql database if it does not exist\n *\n * @param dbConfig - The database config\n * @param databases - The names of the databases to create\n */\nexport async function ensureMysqlDatabaseExists(\n dbConfig: Config,\n ...databases: Array<string>\n) {\n const admin = createMysqlDatabaseClient(dbConfig, {\n connection: {\n database: null as unknown as string,\n },\n pool: {\n min: 0,\n acquireTimeoutMillis: 10000,\n },\n });\n\n try {\n const ensureDatabase = async (database: string) => {\n await admin.raw(`CREATE DATABASE IF NOT EXISTS ??`, [database]);\n };\n await Promise.all(\n databases.map(async database => {\n // For initial setup we use a smaller timeout but several retries. Given that this\n // is a separate connection pool we should never really run into issues with connection\n // acquisition timeouts, but we do anyway. This might be a bug in knex or some other dependency.\n let lastErr: Error | undefined = undefined;\n for (let i = 0; i < 3; i++) {\n try {\n return await ddlLimiter(() => ensureDatabase(database));\n } catch (err) {\n lastErr = err;\n }\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n throw lastErr;\n }),\n );\n } finally {\n await admin.destroy();\n }\n}\n\n/**\n * Drops the given mysql databases.\n *\n * @param dbConfig - The database config\n * @param databases - The names of the databases to create\n */\nexport async function dropMysqlDatabase(\n dbConfig: Config,\n ...databases: Array<string>\n) {\n const admin = createMysqlDatabaseClient(dbConfig, {\n connection: {\n database: null as unknown as string,\n },\n pool: {\n min: 0,\n acquireTimeoutMillis: 10000,\n },\n });\n\n try {\n const dropDatabase = async (database: string) => {\n await admin.raw(`DROP DATABASE ??`, [database]);\n };\n await Promise.all(\n databases.map(async database => {\n return await ddlLimiter(() => dropDatabase(database));\n }),\n );\n } finally {\n await admin.destroy();\n }\n}\n\n/**\n * Provides a config lookup path for a plugin's config block.\n */\nfunction pluginPath(pluginId: string): string {\n return `plugin.${pluginId}`;\n}\n\nfunction normalizeConnection(\n connection: Knex.StaticConnectionConfig | JsonObject | string | undefined,\n): Partial<Knex.StaticConnectionConfig> {\n if (typeof connection === 'undefined' || connection === null) {\n return {};\n }\n\n return typeof connection === 'string' || connection instanceof String\n ? parseMysqlConnectionString(connection as string)\n : connection;\n}\n\nexport class MysqlConnector implements Connector {\n constructor(\n private readonly config: Config,\n private readonly prefix: string,\n ) {}\n\n async getClient(\n pluginId: string,\n _deps?: {\n lifecycle: LifecycleService;\n pluginMetadata: PluginMetadataService;\n },\n ): Promise<Knex> {\n const pluginConfig = new ConfigReader(\n this.getConfigForPlugin(pluginId) as JsonObject,\n );\n\n const databaseName = this.getDatabaseName(pluginId);\n if (databaseName && this.getEnsureExistsConfig(pluginId)) {\n try {\n await ensureMysqlDatabaseExists(pluginConfig, databaseName);\n } catch (error) {\n throw new Error(\n `Failed to connect to the database to make sure that '${databaseName}' exists, ${error}`,\n );\n }\n }\n\n const pluginDivisionMode = this.getPluginDivisionModeConfig();\n if (pluginDivisionMode !== 'database') {\n throw new Error(\n `The MySQL driver does not support plugin division mode '${pluginDivisionMode}'`,\n );\n }\n\n const databaseClientOverrides = mergeDatabaseConfig(\n {},\n this.getDatabaseOverrides(pluginId),\n );\n\n const client = createMysqlDatabaseClient(\n pluginConfig,\n databaseClientOverrides,\n );\n\n return client;\n }\n\n async dropDatabase(...databaseNames: string[]): Promise<void> {\n return await dropMysqlDatabase(this.config, ...databaseNames);\n }\n\n /**\n * Provides the canonical database name for a given plugin.\n *\n * This method provides the effective database name which is determined using\n * global and plugin specific database config. If no explicit database name,\n * this method will provide a generated name which is the pluginId prefixed\n * with 'backstage_plugin_'.\n *\n * @param pluginId - Lookup the database name for given plugin\n * @returns String representing the plugin's database name\n */\n private getDatabaseName(pluginId: string): string | undefined {\n const connection = this.getConnectionConfig(pluginId);\n const databaseName = (connection as Knex.ConnectionConfig)?.database;\n return databaseName ?? `${this.prefix}${pluginId}`;\n }\n\n /**\n * Provides the client type which should be used for a given plugin.\n *\n * The client type is determined by plugin specific config if present.\n * Otherwise the base client is used as the fallback.\n *\n * @param pluginId - Plugin to get the client type for\n * @returns Object with client type returned as `client` and boolean\n * representing whether or not the client was overridden as\n * `overridden`\n */\n private getClientType(pluginId: string): {\n client: string;\n overridden: boolean;\n } {\n const pluginClient = this.config.getOptionalString(\n `${pluginPath(pluginId)}.client`,\n );\n\n const baseClient = this.config.getString('client');\n const client = pluginClient ?? baseClient;\n return {\n client,\n overridden: client !== baseClient,\n };\n }\n\n private getRoleConfig(pluginId: string): string | undefined {\n return (\n this.config.getOptionalString(`${pluginPath(pluginId)}.role`) ??\n this.config.getOptionalString('role')\n );\n }\n\n /**\n * Provides the knexConfig which should be used for a given plugin.\n *\n * @param pluginId - Plugin to get the knexConfig for\n * @returns The merged knexConfig value or undefined if it isn't specified\n */\n private getAdditionalKnexConfig(pluginId: string): JsonObject | undefined {\n const pluginConfig = this.config\n .getOptionalConfig(`${pluginPath(pluginId)}.knexConfig`)\n ?.get<JsonObject>();\n\n const baseConfig = this.config\n .getOptionalConfig('knexConfig')\n ?.get<JsonObject>();\n\n return merge(baseConfig, pluginConfig);\n }\n\n private getEnsureExistsConfig(pluginId: string): boolean {\n const baseConfig = this.config.getOptionalBoolean('ensureExists') ?? true;\n return (\n this.config.getOptionalBoolean(`${pluginPath(pluginId)}.ensureExists`) ??\n baseConfig\n );\n }\n\n private getPluginDivisionModeConfig(): string {\n return this.config.getOptionalString('pluginDivisionMode') ?? 'database';\n }\n\n /**\n * Provides a Knex connection plugin config by combining base and plugin\n * config.\n *\n * This method provides a baseConfig for a plugin database connector. If the\n * client type has not been overridden, the global connection config will be\n * included with plugin specific config as the base. Values from the plugin\n * connection take precedence over the base. Base database name is omitted\n * unless `pluginDivisionMode` is set to `schema`.\n */\n private getConnectionConfig(pluginId: string): Knex.StaticConnectionConfig {\n const { overridden } = this.getClientType(pluginId);\n\n let baseConnection = normalizeConnection(this.config.get('connection'));\n\n // Databases cannot be shared unless the `pluginDivisionMode` is set to `schema`. The\n // `database` property from the base connection is omitted unless `pluginDivisionMode`\n // is set to `schema`.\n if (this.getPluginDivisionModeConfig() !== 'schema') {\n baseConnection = omit(baseConnection, 'database');\n }\n\n // get and normalize optional plugin specific database connection\n const connection = normalizeConnection(\n this.config.getOptional(`${pluginPath(pluginId)}.connection`),\n );\n\n return {\n // include base connection if client type has not been overridden\n ...(overridden ? {} : baseConnection),\n ...connection,\n } as Knex.StaticConnectionConfig;\n }\n\n /**\n * Provides a Knex database config for a given plugin.\n *\n * This method provides a Knex configuration object along with the plugin's\n * client type.\n *\n * @param pluginId - The plugin that the database config should correspond with\n */\n private getConfigForPlugin(pluginId: string): Knex.Config {\n const { client } = this.getClientType(pluginId);\n const role = this.getRoleConfig(pluginId);\n\n return {\n ...this.getAdditionalKnexConfig(pluginId),\n client,\n connection: this.getConnectionConfig(pluginId),\n ...(role && { role }),\n };\n }\n\n /**\n * Provides a partial `Knex.Config`• database name override for a given plugin.\n *\n * @param pluginId - Target plugin to get database name override\n * @returns Partial `Knex.Config` with database name override\n */\n private getDatabaseOverrides(pluginId: string): Knex.Config {\n const databaseName = this.getDatabaseName(pluginId);\n return databaseName ? defaultNameOverride(databaseName) : {};\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Knex } from 'knex';\n\n/**\n * Provides a partial knex config with schema name override.\n *\n * @param name - schema name to get config override for\n */\nexport default function defaultSchemaOverride(\n name: string,\n): Partial<Knex.Config> {\n return {\n searchPath: [name],\n };\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n LifecycleService,\n PluginMetadataService,\n} from '@backstage/backend-plugin-api';\nimport { Config, ConfigReader } from '@backstage/config';\nimport { ForwardedError } from '@backstage/errors';\nimport { JsonObject } from '@backstage/types';\nimport knexFactory, { Knex } from 'knex';\nimport { merge, omit } from 'lodash';\nimport limiterFactory from 'p-limit';\nimport { Client } from 'pg';\nimport { Connector } from '../types';\nimport defaultNameOverride from './defaultNameOverride';\nimport defaultSchemaOverride from './defaultSchemaOverride';\nimport { mergeDatabaseConfig } from './mergeDatabaseConfig';\nimport format from 'pg-format';\n\n// Limits the number of concurrent DDL operations to 1\nconst ddlLimiter = limiterFactory(1);\n\n/**\n * Creates a knex postgres database connection\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function createPgDatabaseClient(\n dbConfig: Config,\n overrides?: Knex.Config,\n) {\n const knexConfig = buildPgDatabaseConfig(dbConfig, overrides);\n const database = knexFactory(knexConfig);\n\n const role = dbConfig.getOptionalString('role');\n\n if (role) {\n database.client.pool.on(\n 'createSuccess',\n async (_event: number, pgClient: Client) => {\n const query = format('SET ROLE %I', role);\n await pgClient.query(query);\n },\n );\n }\n return database;\n}\n\n/**\n * Builds a knex postgres database connection\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function buildPgDatabaseConfig(\n dbConfig: Config,\n overrides?: Knex.Config,\n) {\n return mergeDatabaseConfig(\n dbConfig.get(),\n {\n connection: getPgConnectionConfig(dbConfig, !!overrides),\n useNullAsDefault: true,\n },\n overrides,\n );\n}\n\n/**\n * Gets the postgres connection config\n *\n * @param dbConfig - The database config\n * @param parseConnectionString - Flag to explicitly control connection string parsing\n */\nexport function getPgConnectionConfig(\n dbConfig: Config,\n parseConnectionString?: boolean,\n): Knex.PgConnectionConfig | string {\n const connection = dbConfig.get('connection') as any;\n const isConnectionString =\n typeof connection === 'string' || connection instanceof String;\n const autoParse = typeof parseConnectionString !== 'boolean';\n\n const shouldParseConnectionString = autoParse\n ? isConnectionString\n : parseConnectionString && isConnectionString;\n\n return shouldParseConnectionString\n ? parsePgConnectionString(connection as string)\n : connection;\n}\n\n/**\n * Parses a connection string using pg-connection-string\n *\n * @param connectionString - The postgres connection string\n */\nexport function parsePgConnectionString(connectionString: string) {\n const parse = requirePgConnectionString();\n return parse(connectionString);\n}\n\nfunction requirePgConnectionString() {\n try {\n return require('pg-connection-string').parse;\n } catch (e) {\n throw new ForwardedError(\"Postgres: Install 'pg-connection-string'\", e);\n }\n}\n\n/**\n * Creates the missing Postgres database if it does not exist\n *\n * @param dbConfig - The database config\n * @param databases - The name of the databases to create\n */\nexport async function ensurePgDatabaseExists(\n dbConfig: Config,\n ...databases: Array<string>\n) {\n const admin = createPgDatabaseClient(dbConfig, {\n connection: {\n database: 'postgres',\n },\n pool: {\n min: 0,\n acquireTimeoutMillis: 10000,\n },\n });\n\n try {\n const ensureDatabase = async (database: string) => {\n const result = await admin\n .from('pg_database')\n .where('datname', database)\n .count<Record<string, { count: string }>>();\n\n if (parseInt(result[0].count, 10) > 0) {\n return;\n }\n\n await admin.raw(`CREATE DATABASE ??`, [database]);\n };\n\n await Promise.all(\n databases.map(async database => {\n // For initial setup we use a smaller timeout but several retries. Given that this\n // is a separate connection pool we should never really run into issues with connection\n // acquisition timeouts, but we do anyway. This might be a bug in knex or some other dependency.\n let lastErr: Error | undefined = undefined;\n for (let i = 0; i < 3; i++) {\n try {\n return await ddlLimiter(() => ensureDatabase(database));\n } catch (err) {\n lastErr = err;\n }\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n throw lastErr;\n }),\n );\n } finally {\n await admin.destroy();\n }\n}\n\n/**\n * Creates the missing Postgres schema if it does not exist\n *\n * @param dbConfig - The database config\n * @param schemas - The name of the schemas to create\n */\nexport async function ensurePgSchemaExists(\n dbConfig: Config,\n ...schemas: Array<string>\n): Promise<void> {\n const admin = createPgDatabaseClient(dbConfig);\n const role = dbConfig.getOptionalString('role');\n\n try {\n const ensureSchema = async (database: string) => {\n if (role) {\n await admin.raw(`CREATE SCHEMA IF NOT EXISTS ?? AUTHORIZATION ??`, [\n database,\n role,\n ]);\n } else {\n await admin.raw(`CREATE SCHEMA IF NOT EXISTS ??`, [database]);\n }\n };\n\n await Promise.all(\n schemas.map(database => ddlLimiter(() => ensureSchema(database))),\n );\n } finally {\n await admin.destroy();\n }\n}\n\n/**\n * Drops the Postgres databases.\n *\n * @param dbConfig - The database config\n * @param databases - The name of the databases to drop\n */\nexport async function dropPgDatabase(\n dbConfig: Config,\n ...databases: Array<string>\n) {\n const admin = createPgDatabaseClient(dbConfig);\n try {\n await Promise.all(\n databases.map(async database => {\n await ddlLimiter(() => admin.raw(`DROP DATABASE ??`, [database]));\n }),\n );\n } finally {\n await admin.destroy();\n }\n}\n\n/**\n * Provides a config lookup path for a plugin's config block.\n */\nfunction pluginPath(pluginId: string): string {\n return `plugin.${pluginId}`;\n}\n\nfunction normalizeConnection(\n connection: Knex.StaticConnectionConfig | JsonObject | string | undefined,\n): Partial<Knex.StaticConnectionConfig> {\n if (typeof connection === 'undefined' || connection === null) {\n return {};\n }\n\n return typeof connection === 'string' || connection instanceof String\n ? parsePgConnectionString(connection as string)\n : connection;\n}\n\nexport class PgConnector implements Connector {\n constructor(\n private readonly config: Config,\n private readonly prefix: string,\n ) {}\n\n async getClient(\n pluginId: string,\n _deps?: {\n lifecycle: LifecycleService;\n pluginMetadata: PluginMetadataService;\n },\n ): Promise<Knex> {\n const pluginConfig = new ConfigReader(\n this.getConfigForPlugin(pluginId) as JsonObject,\n );\n\n const databaseName = this.getDatabaseName(pluginId);\n if (databaseName && this.getEnsureExistsConfig(pluginId)) {\n try {\n await ensurePgDatabaseExists(pluginConfig, databaseName);\n } catch (error) {\n throw new Error(\n `Failed to connect to the database to make sure that '${databaseName}' exists, ${error}`,\n );\n }\n }\n\n let schemaOverrides;\n if (this.getPluginDivisionModeConfig() === 'schema') {\n schemaOverrides = defaultSchemaOverride(pluginId);\n if (\n this.getEnsureSchemaExistsConfig(pluginId) ||\n this.getEnsureExistsConfig(pluginId)\n ) {\n try {\n await ensurePgSchemaExists(pluginConfig, pluginId);\n } catch (error) {\n throw new Error(\n `Failed to connect to the database to make sure that schema for plugin '${pluginId}' exists, ${error}`,\n );\n }\n }\n }\n\n const databaseClientOverrides = mergeDatabaseConfig(\n {},\n this.getDatabaseOverrides(pluginId),\n schemaOverrides,\n );\n\n const client = createPgDatabaseClient(\n pluginConfig,\n databaseClientOverrides,\n );\n\n return client;\n }\n\n async dropDatabase(...databaseNames: string[]): Promise<void> {\n return await dropPgDatabase(this.config, ...databaseNames);\n }\n\n /**\n * Provides the canonical database name for a given plugin.\n *\n * This method provides the effective database name which is determined using global\n * and plugin specific database config. If no explicit database name is configured\n * and `pluginDivisionMode` is not `schema`, this method will provide a generated name\n * which is the pluginId prefixed with 'backstage_plugin_'. If `pluginDivisionMode` is\n * `schema`, it will fallback to using the default database for the knex instance.\n *\n * @param pluginId - Lookup the database name for given plugin\n * @returns String representing the plugin's database name\n */\n private getDatabaseName(pluginId: string): string | undefined {\n const connection = this.getConnectionConfig(pluginId);\n\n const databaseName = (connection as Knex.ConnectionConfig)?.database;\n\n // `pluginDivisionMode` as `schema` should use overridden databaseName if supplied or fallback to default knex database\n if (this.getPluginDivisionModeConfig() === 'schema') {\n return databaseName;\n }\n\n // all other supported databases should fallback to an auto-prefixed name\n return databaseName ?? `${this.prefix}${pluginId}`;\n }\n\n /**\n * Provides the client type which should be used for a given plugin.\n *\n * The client type is determined by plugin specific config if present.\n * Otherwise the base client is used as the fallback.\n *\n * @param pluginId - Plugin to get the client type for\n * @returns Object with client type returned as `client` and boolean\n * representing whether or not the client was overridden as\n * `overridden`\n */\n private getClientType(pluginId: string): {\n client: string;\n overridden: boolean;\n } {\n const pluginClient = this.config.getOptionalString(\n `${pluginPath(pluginId)}.client`,\n );\n\n const baseClient = this.config.getString('client');\n const client = pluginClient ?? baseClient;\n return {\n client,\n overridden: client !== baseClient,\n };\n }\n\n private getRoleConfig(pluginId: string): string | undefined {\n return (\n this.config.getOptionalString(`${pluginPath(pluginId)}.role`) ??\n this.config.getOptionalString('role')\n );\n }\n\n /**\n * Provides the knexConfig which should be used for a given plugin.\n *\n * @param pluginId - Plugin to get the knexConfig for\n * @returns The merged knexConfig value or undefined if it isn't specified\n */\n private getAdditionalKnexConfig(pluginId: string): JsonObject | undefined {\n const pluginConfig = this.config\n .getOptionalConfig(`${pluginPath(pluginId)}.knexConfig`)\n ?.get<JsonObject>();\n\n const baseConfig = this.config\n .getOptionalConfig('knexConfig')\n ?.get<JsonObject>();\n\n return merge(baseConfig, pluginConfig);\n }\n\n private getEnsureExistsConfig(pluginId: string): boolean {\n const baseConfig = this.config.getOptionalBoolean('ensureExists') ?? true;\n return (\n this.config.getOptionalBoolean(`${pluginPath(pluginId)}.ensureExists`) ??\n baseConfig\n );\n }\n\n private getEnsureSchemaExistsConfig(pluginId: string): boolean {\n const baseConfig =\n this.config.getOptionalBoolean('ensureSchemaExists') ?? false;\n return (\n this.config.getOptionalBoolean(\n `${pluginPath(pluginId)}.getEnsureSchemaExistsConfig`,\n ) ?? baseConfig\n );\n }\n\n private getPluginDivisionModeConfig(): string {\n return this.config.getOptionalString('pluginDivisionMode') ?? 'database';\n }\n\n /**\n * Provides a Knex connection plugin config by combining base and plugin\n * config.\n *\n * This method provides a baseConfig for a plugin database connector. If the\n * client type has not been overridden, the global connection config will be\n * included with plugin specific config as the base. Values from the plugin\n * connection take precedence over the base. Base database name is omitted\n * unless `pluginDivisionMode` is set to `schema`.\n */\n private getConnectionConfig(pluginId: string): Knex.StaticConnectionConfig {\n const { overridden } = this.getClientType(pluginId);\n\n let baseConnection = normalizeConnection(this.config.get('connection'));\n\n // Databases cannot be shared unless the `pluginDivisionMode` is set to `schema`. The\n // `database` property from the base connection is omitted unless `pluginDivisionMode`\n // is set to `schema`.\n if (this.getPluginDivisionModeConfig() !== 'schema') {\n baseConnection = omit(baseConnection, 'database');\n }\n\n // get and normalize optional plugin specific database connection\n const connection = normalizeConnection(\n this.config.getOptional(`${pluginPath(pluginId)}.connection`),\n );\n\n (\n baseConnection as Knex.PgConnectionConfig\n ).application_name ||= `backstage_plugin_${pluginId}`;\n\n return {\n // include base connection if client type has not been overridden\n ...(overridden ? {} : baseConnection),\n ...connection,\n } as Knex.StaticConnectionConfig;\n }\n\n /**\n * Provides a Knex database config for a given plugin.\n *\n * This method provides a Knex configuration object along with the plugin's\n * client type.\n *\n * @param pluginId - The plugin that the database config should correspond with\n */\n private getConfigForPlugin(pluginId: string): Knex.Config {\n const { client } = this.getClientType(pluginId);\n const role = this.getRoleConfig(pluginId);\n\n return {\n ...this.getAdditionalKnexConfig(pluginId),\n client,\n connection: this.getConnectionConfig(pluginId),\n ...(role && { role }),\n };\n }\n\n /**\n * Provides a partial `Knex.Config`• database name override for a given plugin.\n *\n * @param pluginId - Target plugin to get database name override\n * @returns Partial `Knex.Config` with database name override\n */\n private getDatabaseOverrides(pluginId: string): Knex.Config {\n const databaseName = this.getDatabaseName(pluginId);\n return databaseName ? defaultNameOverride(databaseName) : {};\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DevDataStore } from '@backstage/backend-dev-utils';\nimport {\n LifecycleService,\n PluginMetadataService,\n} from '@backstage/backend-plugin-api';\nimport { Config, ConfigReader } from '@backstage/config';\nimport { JsonObject } from '@backstage/types';\nimport { ensureDirSync } from 'fs-extra';\nimport knexFactory, { Knex } from 'knex';\nimport { merge, omit } from 'lodash';\nimport path from 'path';\nimport { Connector } from '../types';\nimport { mergeDatabaseConfig } from './mergeDatabaseConfig';\n\n/**\n * Creates a knex SQLite3 database connection\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function createSqliteDatabaseClient(\n dbConfig: Config,\n overrides?: Knex.Config,\n deps?: {\n lifecycle: LifecycleService;\n pluginMetadata: PluginMetadataService;\n },\n) {\n const knexConfig = buildSqliteDatabaseConfig(dbConfig, overrides);\n const connConfig = knexConfig.connection as Knex.Sqlite3ConnectionConfig;\n\n const filename = connConfig.filename ?? ':memory:';\n\n // If storage on disk is used, ensure that the directory exists\n if (filename !== ':memory:') {\n const directory = path.dirname(filename);\n ensureDirSync(directory);\n }\n\n let database: Knex;\n\n if (deps && filename === ':memory:') {\n // The dev store is used during watch mode to store and restore the database\n // across reloads. It is only available when running the backend through\n // `backstage-cli package start`.\n const devStore = DevDataStore.get();\n\n if (devStore) {\n const dataKey = `sqlite3-db-${deps.pluginMetadata.getId()}`;\n\n const connectionLoader = async () => {\n // If seed data is available, use it tconnectionLoader restore the database\n const { data: seedData } = await devStore.load(dataKey);\n\n return {\n ...(knexConfig.connection as Knex.Sqlite3ConnectionConfig),\n filename: seedData ?? ':memory:',\n };\n };\n\n database = knexFactory({\n ...knexConfig,\n connection: Object.assign(connectionLoader, {\n // This is a workaround for the knex SQLite driver always warning when using a config loader\n filename: ':memory:',\n }),\n });\n\n // If the dev store is available we save the database state on shutdown\n deps.lifecycle.addShutdownHook(async () => {\n const connection = await database.client.acquireConnection();\n const data = connection.serialize();\n await devStore.save(dataKey, data);\n });\n } else {\n database = knexFactory(knexConfig);\n }\n } else {\n database = knexFactory(knexConfig);\n }\n\n database.client.pool.on('createSuccess', (_eventId: any, resource: any) => {\n resource.run('PRAGMA foreign_keys = ON', () => {});\n });\n\n return database;\n}\n\n/**\n * Builds a knex SQLite3 connection config\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function buildSqliteDatabaseConfig(\n dbConfig: Config,\n overrides?: Knex.Config,\n): Knex.Config {\n const baseConfig = dbConfig.get<Knex.Config>();\n\n // Normalize config to always contain a connection object\n if (typeof baseConfig.connection === 'string') {\n baseConfig.connection = { filename: baseConfig.connection };\n }\n if (overrides && typeof overrides.connection === 'string') {\n overrides.connection = { filename: overrides.connection };\n }\n\n const config: Knex.Config = mergeDatabaseConfig(\n {\n connection: {},\n },\n baseConfig,\n {\n useNullAsDefault: true,\n },\n overrides,\n );\n\n return config;\n}\n\n/**\n * Provides a partial knex SQLite3 config to override database name.\n */\nexport function createSqliteNameOverride(name: string): Partial<Knex.Config> {\n return {\n connection: parseSqliteConnectionString(name),\n };\n}\n\n/**\n * Produces a partial knex SQLite3 connection config with database name.\n */\nexport function parseSqliteConnectionString(\n name: string,\n): Knex.Sqlite3ConnectionConfig {\n return {\n filename: name,\n };\n}\n\n/**\n * Provides a config lookup path for a plugin's config block.\n */\nfunction pluginPath(pluginId: string): string {\n return `plugin.${pluginId}`;\n}\n\nfunction normalizeConnection(\n connection: Knex.StaticConnectionConfig | JsonObject | string | undefined,\n): Partial<Knex.StaticConnectionConfig> {\n if (typeof connection === 'undefined' || connection === null) {\n return {};\n }\n\n return typeof connection === 'string' || connection instanceof String\n ? parseSqliteConnectionString(connection as string)\n : connection;\n}\n\nexport class Sqlite3Connector implements Connector {\n constructor(private readonly config: Config) {}\n\n async getClient(\n pluginId: string,\n deps?: {\n lifecycle: LifecycleService;\n pluginMetadata: PluginMetadataService;\n },\n ): Promise<Knex> {\n const pluginConfig = new ConfigReader(\n this.getConfigForPlugin(pluginId) as JsonObject,\n );\n\n const pluginDivisionMode = this.getPluginDivisionModeConfig();\n if (pluginDivisionMode !== 'database') {\n throw new Error(\n `The SQLite driver does not support plugin division mode '${pluginDivisionMode}'`,\n );\n }\n\n const databaseClientOverrides = mergeDatabaseConfig(\n {},\n this.getDatabaseOverrides(pluginId),\n );\n\n const client = createSqliteDatabaseClient(\n pluginConfig,\n databaseClientOverrides,\n deps,\n );\n\n return client;\n }\n\n async dropDatabase(..._databaseNames: string[]): Promise<void> {\n // do nothing\n }\n\n /**\n * Provides the canonical database name for a given plugin.\n *\n * This method provides the effective database name which is determined using global\n * and plugin specific database config. If no explicit database name is configured\n * and `pluginDivisionMode` is not `schema`, this method will provide a generated name\n * which is the pluginId prefixed with 'backstage_plugin_'. If `pluginDivisionMode` is\n * `schema`, it will fallback to using the default database for the knex instance.\n *\n * @param pluginId - Lookup the database name for given plugin\n * @returns String representing the plugin's database name\n */\n private getDatabaseName(pluginId: string): string | undefined {\n const connection = this.getConnectionConfig(pluginId);\n\n const sqliteFilename: string | undefined = (\n connection as Knex.Sqlite3ConnectionConfig\n ).filename;\n\n if (sqliteFilename === ':memory:') {\n return sqliteFilename;\n }\n\n const sqliteDirectory =\n (connection as { directory?: string }).directory ?? '.';\n\n return path.join(sqliteDirectory, sqliteFilename ?? `${pluginId}.sqlite`);\n }\n\n /**\n * Provides the client type which should be used for a given plugin.\n *\n * The client type is determined by plugin specific config if present.\n * Otherwise the base client is used as the fallback.\n *\n * @param pluginId - Plugin to get the client type for\n * @returns Object with client type returned as `client` and boolean\n * representing whether or not the client was overridden as\n * `overridden`\n */\n private getClientType(pluginId: string): {\n client: string;\n overridden: boolean;\n } {\n const pluginClient = this.config.getOptionalString(\n `${pluginPath(pluginId)}.client`,\n );\n\n const baseClient = this.config.getString('client');\n const client = pluginClient ?? baseClient;\n return {\n client,\n overridden: client !== baseClient,\n };\n }\n\n private getRoleConfig(pluginId: string): string | undefined {\n return (\n this.config.getOptionalString(`${pluginPath(pluginId)}.role`) ??\n this.config.getOptionalString('role')\n );\n }\n\n /**\n * Provides the knexConfig which should be used for a given plugin.\n *\n * @param pluginId - Plugin to get the knexConfig for\n * @returns The merged knexConfig value or undefined if it isn't specified\n */\n private getAdditionalKnexConfig(pluginId: string): JsonObject | undefined {\n const pluginConfig = this.config\n .getOptionalConfig(`${pluginPath(pluginId)}.knexConfig`)\n ?.get<JsonObject>();\n\n const baseConfig = this.config\n .getOptionalConfig('knexConfig')\n ?.get<JsonObject>();\n\n return merge(baseConfig, pluginConfig);\n }\n\n private getPluginDivisionModeConfig(): string {\n return this.config.getOptionalString('pluginDivisionMode') ?? 'database';\n }\n\n /**\n * Provides a Knex connection plugin config by combining base and plugin\n * config.\n *\n * This method provides a baseConfig for a plugin database connector. If the\n * client type has not been overridden, the global connection config will be\n * included with plugin specific config as the base. Values from the plugin\n * connection take precedence over the base. Base database name is omitted for\n * all supported databases excluding SQLite unless `pluginDivisionMode` is set\n * to `schema`.\n */\n private getConnectionConfig(pluginId: string): Knex.StaticConnectionConfig {\n const { client, overridden } = this.getClientType(pluginId);\n\n let baseConnection = normalizeConnection(this.config.get('connection'));\n\n if (\n client.includes('sqlite3') &&\n 'filename' in baseConnection &&\n baseConnection.filename !== ':memory:'\n ) {\n throw new Error(\n '`connection.filename` is not supported for the base sqlite connection. Prefer `connection.directory` or provide a filename for the plugin connection instead.',\n );\n }\n\n // Databases cannot be shared unless the `pluginDivisionMode` is set to `schema`. The\n // `database` property from the base connection is omitted unless `pluginDivisionMode`\n // is set to `schema`. SQLite3's `filename` property is an exception as this is used as a\n // directory elsewhere so we preserve `filename`.\n if (this.getPluginDivisionModeConfig() !== 'schema') {\n baseConnection = omit(baseConnection, 'database');\n }\n\n // get and normalize optional plugin specific database connection\n const connection = normalizeConnection(\n this.config.getOptional(`${pluginPath(pluginId)}.connection`),\n );\n\n return {\n // include base connection if client type has not been overridden\n ...(overridden ? {} : baseConnection),\n ...connection,\n } as Knex.StaticConnectionConfig;\n }\n\n /**\n * Provides a Knex database config for a given plugin.\n *\n * This method provides a Knex configuration object along with the plugin's\n * client type.\n *\n * @param pluginId - The plugin that the database config should correspond with\n */\n private getConfigForPlugin(pluginId: string): Knex.Config {\n const { client } = this.getClientType(pluginId);\n const role = this.getRoleConfig(pluginId);\n\n return {\n ...this.getAdditionalKnexConfig(pluginId),\n client,\n connection: this.getConnectionConfig(pluginId),\n ...(role && { role }),\n };\n }\n\n /**\n * Provides a partial `Knex.Config`• database name override for a given plugin.\n *\n * @param pluginId - Target plugin to get database name override\n * @returns Partial `Knex.Config` with database name override\n */\n private getDatabaseOverrides(pluginId: string): Knex.Config {\n const databaseName = this.getDatabaseName(pluginId);\n return databaseName ? createSqliteNameOverride(databaseName) : {};\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n DatabaseService,\n LifecycleService,\n LoggerService,\n PluginMetadataService,\n} from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { stringifyError } from '@backstage/errors';\nimport { Knex } from 'knex';\nimport { MysqlConnector } from './connectors/mysql';\nimport { PgConnector } from './connectors/postgres';\nimport { Sqlite3Connector } from './connectors/sqlite3';\nimport { Connector, PluginDatabaseManager } from './types';\n\n/**\n * Provides a config lookup path for a plugin's config block.\n */\nfunction pluginPath(pluginId: string): string {\n return `plugin.${pluginId}`;\n}\n\n/**\n * Creation options for {@link DatabaseManager}.\n *\n * @public\n */\nexport type DatabaseManagerOptions = {\n migrations?: DatabaseService['migrations'];\n logger?: LoggerService;\n};\n\n/**\n * An interface that represents the legacy global DatabaseManager implementation.\n * @public\n */\nexport type LegacyRootDatabaseService = {\n forPlugin(pluginId: string): DatabaseService;\n};\n\n/**\n * Testable implementation class for {@link DatabaseManager} below.\n */\nexport class DatabaseManagerImpl implements LegacyRootDatabaseService {\n constructor(\n private readonly config: Config,\n private readonly connectors: Record<string, Connector>,\n private readonly options?: DatabaseManagerOptions,\n private readonly databaseCache: Map<string, Promise<Knex>> = new Map(),\n ) {}\n\n /**\n * Generates a PluginDatabaseManager for consumption by plugins.\n *\n * @param pluginId - The plugin that the database manager should be created for. Plugin names\n * should be unique as they are used to look up database config overrides under\n * `backend.database.plugin`.\n */\n forPlugin(\n pluginId: string,\n deps?: {\n lifecycle: LifecycleService;\n pluginMetadata: PluginMetadataService;\n },\n ): PluginDatabaseManager {\n const client = this.getClientType(pluginId).client;\n const connector = this.connectors[client];\n if (!connector) {\n throw new Error(\n `Unsupported database client type '${client}' specified for plugin '${pluginId}'`,\n );\n }\n const getClient = () => this.getDatabase(pluginId, connector, deps);\n const migrations = { skip: false, ...this.options?.migrations };\n return { getClient, migrations };\n }\n\n /**\n * Provides the client type which should be used for a given plugin.\n *\n * The client type is determined by plugin specific config if present.\n * Otherwise the base client is used as the fallback.\n *\n * @param pluginId - Plugin to get the client type for\n * @returns Object with client type returned as `client` and boolean\n * representing whether or not the client was overridden as\n * `overridden`\n */\n private getClientType(pluginId: string): {\n client: string;\n overridden: boolean;\n } {\n const pluginClient = this.config.getOptionalString(\n `${pluginPath(pluginId)}.client`,\n );\n\n const baseClient = this.config.getString('client');\n const client = pluginClient ?? baseClient;\n return {\n client,\n overridden: client !== baseClient,\n };\n }\n\n /**\n * Provides a scoped Knex client for a plugin as per application config.\n *\n * @param pluginId - Plugin to get a Knex client for\n * @returns Promise which resolves to a scoped Knex database client for a\n * plugin\n */\n private async getDatabase(\n pluginId: string,\n connector: Connector,\n deps?: {\n lifecycle: LifecycleService;\n pluginMetadata: PluginMetadataService;\n },\n ): Promise<Knex> {\n if (this.databaseCache.has(pluginId)) {\n return this.databaseCache.get(pluginId)!;\n }\n\n const clientPromise = connector.getClient(pluginId, deps);\n this.databaseCache.set(pluginId, clientPromise);\n\n if (process.env.NODE_ENV !== 'test') {\n clientPromise.then(client => this.startKeepaliveLoop(pluginId, client));\n }\n\n return clientPromise;\n }\n\n private startKeepaliveLoop(pluginId: string, client: Knex): void {\n let lastKeepaliveFailed = false;\n\n setInterval(() => {\n // During testing it can happen that the environment is torn down and\n // this client is `undefined`, but this interval is still run.\n client?.raw('select 1').then(\n () => {\n lastKeepaliveFailed = false;\n },\n (error: unknown) => {\n if (!lastKeepaliveFailed) {\n lastKeepaliveFailed = true;\n this.options?.logger?.warn(\n `Database keepalive failed for plugin ${pluginId}, ${stringifyError(\n error,\n )}`,\n );\n }\n },\n );\n }, 60 * 1000);\n }\n}\n\n// NOTE: This class looks odd but is kept around for API compatibility reasons\n/**\n * Manages database connections for Backstage backend plugins.\n *\n * @public\n * @remarks\n *\n * The database manager allows the user to set connection and client settings on\n * a per pluginId basis by defining a database config block under\n * `plugin.<pluginId>` in addition to top level defaults. Optionally, a user may\n * set `prefix` which is used to prefix generated database names if config is\n * not provided.\n */\nexport class DatabaseManager implements LegacyRootDatabaseService {\n /**\n * Creates a {@link DatabaseManager} from `backend.database` config.\n *\n * @param config - The loaded application configuration.\n * @param options - An optional configuration object.\n */\n static fromConfig(\n config: Config,\n options?: DatabaseManagerOptions,\n ): DatabaseManager {\n const databaseConfig = config.getConfig('backend.database');\n const prefix =\n databaseConfig.getOptionalString('prefix') || 'backstage_plugin_';\n return new DatabaseManager(\n new DatabaseManagerImpl(\n databaseConfig,\n {\n pg: new PgConnector(databaseConfig, prefix),\n sqlite3: new Sqlite3Connector(databaseConfig),\n 'better-sqlite3': new Sqlite3Connector(databaseConfig),\n mysql: new MysqlConnector(databaseConfig, prefix),\n mysql2: new MysqlConnector(databaseConfig, prefix),\n },\n options,\n ),\n );\n }\n\n private constructor(private readonly impl: DatabaseManagerImpl) {}\n\n /**\n * Generates a PluginDatabaseManager for consumption by plugins.\n *\n * @param pluginId - The plugin that the database manager should be created for. Plugin names\n * should be unique as they are used to look up database config overrides under\n * `backend.database.plugin`.\n */\n forPlugin(\n pluginId: string,\n deps?: {\n lifecycle: LifecycleService;\n pluginMetadata: PluginMetadataService;\n },\n ): PluginDatabaseManager {\n return this.impl.forPlugin(pluginId, deps);\n }\n}\n\n/**\n * Helper for deleting databases.\n *\n * @public\n * @deprecated Will be removed in a future release.\n */\nexport async function dropDatabase(\n dbConfig: Config,\n ...databaseNames: string[]\n): Promise<void> {\n const client = dbConfig.getString('client');\n const prefix = dbConfig.getOptionalString('prefix') || 'backstage_plugin_';\n\n if (client === 'pg') {\n await new PgConnector(dbConfig, prefix).dropDatabase(...databaseNames);\n } else if (client === 'mysql' || client === 'mysql2') {\n await new MysqlConnector(dbConfig, prefix).dropDatabase(...databaseNames);\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { ConfigReader } from '@backstage/config';\nimport { DatabaseManager } from './DatabaseManager';\n\n/**\n * Database access and management via `knex`.\n *\n * See {@link @backstage/code-plugin-api#DatabaseService}\n * and {@link https://backstage.io/docs/backend-system/core-services/database | the service docs}\n * for more information.\n *\n * @public\n */\nexport const databaseServiceFactory = createServiceFactory({\n service: coreServices.database,\n deps: {\n config: coreServices.rootConfig,\n lifecycle: coreServices.lifecycle,\n pluginMetadata: coreServices.pluginMetadata,\n },\n async createRootContext({ config }) {\n return config.getOptional('backend.database')\n ? DatabaseManager.fromConfig(config)\n : DatabaseManager.fromConfig(\n new ConfigReader({\n backend: {\n database: { client: 'better-sqlite3', connection: ':memory:' },\n },\n }),\n );\n },\n async factory({ pluginMetadata, lifecycle }, databaseManager) {\n return databaseManager.forPlugin(pluginMetadata.getId(), {\n pluginMetadata,\n lifecycle,\n });\n },\n});\n"],"names":["merge","ddlLimiter","limiterFactory","knexFactory","yn","InputError","pluginPath","normalizeConnection","ConfigReader","omit","format","ForwardedError","path","ensureDirSync","DevDataStore","stringifyError","createServiceFactory","coreServices","config"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"database.cjs.js","sources":["../src/entrypoints/database/connectors/defaultNameOverride.ts","../src/entrypoints/database/connectors/mergeDatabaseConfig.ts","../src/entrypoints/database/connectors/mysql.ts","../src/entrypoints/database/connectors/defaultSchemaOverride.ts","../src/entrypoints/database/connectors/postgres.ts","../src/entrypoints/database/connectors/sqlite3.ts","../src/entrypoints/database/DatabaseManager.ts","../src/entrypoints/database/databaseServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Knex } from 'knex';\n\n/**\n * Provides a partial knex config with database name override.\n *\n * Default override for knex database drivers which accept ConnectionConfig\n * with `connection.database` as the database name field.\n *\n * @param name - database name to get config override for\n */\nexport default function defaultNameOverride(\n name: string,\n): Partial<Knex.Config> {\n return {\n connection: {\n database: name,\n },\n };\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { merge } from 'lodash';\n\n/**\n * Merges database objects together\n *\n * @public\n * @param config - The base config. The input is not modified\n * @param overrides - Any additional overrides\n */\nexport function mergeDatabaseConfig(config: any, ...overrides: any[]) {\n return merge({}, config, ...overrides);\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n LifecycleService,\n PluginMetadataService,\n} from '@backstage/backend-plugin-api';\nimport { Config, ConfigReader } from '@backstage/config';\nimport { InputError } from '@backstage/errors';\nimport { JsonObject } from '@backstage/types';\nimport knexFactory, { Knex } from 'knex';\nimport { merge, omit } from 'lodash';\nimport limiterFactory from 'p-limit';\nimport yn from 'yn';\nimport { Connector } from '../types';\nimport defaultNameOverride from './defaultNameOverride';\nimport { mergeDatabaseConfig } from './mergeDatabaseConfig';\n\n// Limits the number of concurrent DDL operations to 1\nconst ddlLimiter = limiterFactory(1);\n\n/**\n * Creates a knex mysql database connection\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function createMysqlDatabaseClient(\n dbConfig: Config,\n overrides?: Knex.Config,\n) {\n const knexConfig = buildMysqlDatabaseConfig(dbConfig, overrides);\n const database = knexFactory(knexConfig);\n return database;\n}\n\n/**\n * Builds a knex mysql database connection\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function buildMysqlDatabaseConfig(\n dbConfig: Config,\n overrides?: Knex.Config,\n) {\n return mergeDatabaseConfig(\n dbConfig.get(),\n {\n connection: getMysqlConnectionConfig(dbConfig, !!overrides),\n useNullAsDefault: true,\n },\n overrides,\n );\n}\n\n/**\n * Gets the mysql connection config\n *\n * @param dbConfig - The database config\n * @param parseConnectionString - Flag to explicitly control connection string parsing\n */\nexport function getMysqlConnectionConfig(\n dbConfig: Config,\n parseConnectionString?: boolean,\n): Knex.MySqlConnectionConfig | string {\n const connection = dbConfig.get('connection') as any;\n const isConnectionString =\n typeof connection === 'string' || connection instanceof String;\n const autoParse = typeof parseConnectionString !== 'boolean';\n\n const shouldParseConnectionString = autoParse\n ? isConnectionString\n : parseConnectionString && isConnectionString;\n\n return shouldParseConnectionString\n ? parseMysqlConnectionString(connection as string)\n : connection;\n}\n\n/**\n * Parses a mysql connection string.\n *\n * e.g. mysql://examplename:somepassword@examplehost:3306/dbname\n * @param connectionString - The mysql connection string\n */\nexport function parseMysqlConnectionString(\n connectionString: string,\n): Knex.MySqlConnectionConfig {\n try {\n const {\n protocol,\n username,\n password,\n port,\n hostname,\n pathname,\n searchParams,\n } = new URL(connectionString);\n\n if (protocol !== 'mysql:') {\n throw new Error(`Unknown protocol ${protocol}`);\n } else if (!username || !password) {\n throw new Error(`Missing username/password`);\n } else if (!pathname.match(/^\\/[^/]+$/)) {\n throw new Error(`Expected single path segment`);\n }\n\n const result: Knex.MySqlConnectionConfig = {\n user: username,\n password,\n host: hostname,\n port: Number(port || 3306),\n database: decodeURIComponent(pathname.substring(1)),\n };\n\n const ssl = searchParams.get('ssl');\n if (ssl) {\n result.ssl = ssl;\n }\n\n const debug = searchParams.get('debug');\n if (debug) {\n result.debug = yn(debug);\n }\n\n return result;\n } catch (e) {\n throw new InputError(\n `Error while parsing MySQL connection string, ${e}`,\n e,\n );\n }\n}\n\n/**\n * Creates the missing mysql database if it does not exist\n *\n * @param dbConfig - The database config\n * @param databases - The names of the databases to create\n */\nexport async function ensureMysqlDatabaseExists(\n dbConfig: Config,\n ...databases: Array<string>\n) {\n const admin = createMysqlDatabaseClient(dbConfig, {\n connection: {\n database: null as unknown as string,\n },\n pool: {\n min: 0,\n acquireTimeoutMillis: 10000,\n },\n });\n\n try {\n const ensureDatabase = async (database: string) => {\n await admin.raw(`CREATE DATABASE IF NOT EXISTS ??`, [database]);\n };\n await Promise.all(\n databases.map(async database => {\n // For initial setup we use a smaller timeout but several retries. Given that this\n // is a separate connection pool we should never really run into issues with connection\n // acquisition timeouts, but we do anyway. This might be a bug in knex or some other dependency.\n let lastErr: Error | undefined = undefined;\n for (let i = 0; i < 3; i++) {\n try {\n return await ddlLimiter(() => ensureDatabase(database));\n } catch (err) {\n lastErr = err;\n }\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n throw lastErr;\n }),\n );\n } finally {\n await admin.destroy();\n }\n}\n\n/**\n * Drops the given mysql databases.\n *\n * @param dbConfig - The database config\n * @param databases - The names of the databases to create\n */\nexport async function dropMysqlDatabase(\n dbConfig: Config,\n ...databases: Array<string>\n) {\n const admin = createMysqlDatabaseClient(dbConfig, {\n connection: {\n database: null as unknown as string,\n },\n pool: {\n min: 0,\n acquireTimeoutMillis: 10000,\n },\n });\n\n try {\n const dropDatabase = async (database: string) => {\n await admin.raw(`DROP DATABASE ??`, [database]);\n };\n await Promise.all(\n databases.map(async database => {\n return await ddlLimiter(() => dropDatabase(database));\n }),\n );\n } finally {\n await admin.destroy();\n }\n}\n\n/**\n * Provides a config lookup path for a plugin's config block.\n */\nfunction pluginPath(pluginId: string): string {\n return `plugin.${pluginId}`;\n}\n\nfunction normalizeConnection(\n connection: Knex.StaticConnectionConfig | JsonObject | string | undefined,\n): Partial<Knex.StaticConnectionConfig> {\n if (typeof connection === 'undefined' || connection === null) {\n return {};\n }\n\n return typeof connection === 'string' || connection instanceof String\n ? parseMysqlConnectionString(connection as string)\n : connection;\n}\n\nexport class MysqlConnector implements Connector {\n constructor(\n private readonly config: Config,\n private readonly prefix: string,\n ) {}\n\n async getClient(\n pluginId: string,\n _deps?: {\n lifecycle: LifecycleService;\n pluginMetadata: PluginMetadataService;\n },\n ): Promise<Knex> {\n const pluginConfig = new ConfigReader(\n this.getConfigForPlugin(pluginId) as JsonObject,\n );\n\n const databaseName = this.getDatabaseName(pluginId);\n if (databaseName && this.getEnsureExistsConfig(pluginId)) {\n try {\n await ensureMysqlDatabaseExists(pluginConfig, databaseName);\n } catch (error) {\n throw new Error(\n `Failed to connect to the database to make sure that '${databaseName}' exists, ${error}`,\n );\n }\n }\n\n const pluginDivisionMode = this.getPluginDivisionModeConfig();\n if (pluginDivisionMode !== 'database') {\n throw new Error(\n `The MySQL driver does not support plugin division mode '${pluginDivisionMode}'`,\n );\n }\n\n const databaseClientOverrides = mergeDatabaseConfig(\n {},\n this.getDatabaseOverrides(pluginId),\n );\n\n const client = createMysqlDatabaseClient(\n pluginConfig,\n databaseClientOverrides,\n );\n\n return client;\n }\n\n async dropDatabase(...databaseNames: string[]): Promise<void> {\n return await dropMysqlDatabase(this.config, ...databaseNames);\n }\n\n /**\n * Provides the canonical database name for a given plugin.\n *\n * This method provides the effective database name which is determined using\n * global and plugin specific database config. If no explicit database name,\n * this method will provide a generated name which is the pluginId prefixed\n * with 'backstage_plugin_'.\n *\n * @param pluginId - Lookup the database name for given plugin\n * @returns String representing the plugin's database name\n */\n private getDatabaseName(pluginId: string): string | undefined {\n const connection = this.getConnectionConfig(pluginId);\n const databaseName = (connection as Knex.ConnectionConfig)?.database;\n return databaseName ?? `${this.prefix}${pluginId}`;\n }\n\n /**\n * Provides the client type which should be used for a given plugin.\n *\n * The client type is determined by plugin specific config if present.\n * Otherwise the base client is used as the fallback.\n *\n * @param pluginId - Plugin to get the client type for\n * @returns Object with client type returned as `client` and boolean\n * representing whether or not the client was overridden as\n * `overridden`\n */\n private getClientType(pluginId: string): {\n client: string;\n overridden: boolean;\n } {\n const pluginClient = this.config.getOptionalString(\n `${pluginPath(pluginId)}.client`,\n );\n\n const baseClient = this.config.getString('client');\n const client = pluginClient ?? baseClient;\n return {\n client,\n overridden: client !== baseClient,\n };\n }\n\n private getRoleConfig(pluginId: string): string | undefined {\n return (\n this.config.getOptionalString(`${pluginPath(pluginId)}.role`) ??\n this.config.getOptionalString('role')\n );\n }\n\n /**\n * Provides the knexConfig which should be used for a given plugin.\n *\n * @param pluginId - Plugin to get the knexConfig for\n * @returns The merged knexConfig value or undefined if it isn't specified\n */\n private getAdditionalKnexConfig(pluginId: string): JsonObject | undefined {\n const pluginConfig = this.config\n .getOptionalConfig(`${pluginPath(pluginId)}.knexConfig`)\n ?.get<JsonObject>();\n\n const baseConfig = this.config\n .getOptionalConfig('knexConfig')\n ?.get<JsonObject>();\n\n return merge(baseConfig, pluginConfig);\n }\n\n private getEnsureExistsConfig(pluginId: string): boolean {\n const baseConfig = this.config.getOptionalBoolean('ensureExists') ?? true;\n return (\n this.config.getOptionalBoolean(`${pluginPath(pluginId)}.ensureExists`) ??\n baseConfig\n );\n }\n\n private getPluginDivisionModeConfig(): string {\n return this.config.getOptionalString('pluginDivisionMode') ?? 'database';\n }\n\n /**\n * Provides a Knex connection plugin config by combining base and plugin\n * config.\n *\n * This method provides a baseConfig for a plugin database connector. If the\n * client type has not been overridden, the global connection config will be\n * included with plugin specific config as the base. Values from the plugin\n * connection take precedence over the base. Base database name is omitted\n * unless `pluginDivisionMode` is set to `schema`.\n */\n private getConnectionConfig(pluginId: string): Knex.StaticConnectionConfig {\n const { overridden } = this.getClientType(pluginId);\n\n let baseConnection = normalizeConnection(this.config.get('connection'));\n\n // Databases cannot be shared unless the `pluginDivisionMode` is set to `schema`. The\n // `database` property from the base connection is omitted unless `pluginDivisionMode`\n // is set to `schema`.\n if (this.getPluginDivisionModeConfig() !== 'schema') {\n baseConnection = omit(baseConnection, 'database');\n }\n\n // get and normalize optional plugin specific database connection\n const connection = normalizeConnection(\n this.config.getOptional(`${pluginPath(pluginId)}.connection`),\n );\n\n return {\n // include base connection if client type has not been overridden\n ...(overridden ? {} : baseConnection),\n ...connection,\n } as Knex.StaticConnectionConfig;\n }\n\n /**\n * Provides a Knex database config for a given plugin.\n *\n * This method provides a Knex configuration object along with the plugin's\n * client type.\n *\n * @param pluginId - The plugin that the database config should correspond with\n */\n private getConfigForPlugin(pluginId: string): Knex.Config {\n const { client } = this.getClientType(pluginId);\n const role = this.getRoleConfig(pluginId);\n\n return {\n ...this.getAdditionalKnexConfig(pluginId),\n client,\n connection: this.getConnectionConfig(pluginId),\n ...(role && { role }),\n };\n }\n\n /**\n * Provides a partial `Knex.Config`• database name override for a given plugin.\n *\n * @param pluginId - Target plugin to get database name override\n * @returns Partial `Knex.Config` with database name override\n */\n private getDatabaseOverrides(pluginId: string): Knex.Config {\n const databaseName = this.getDatabaseName(pluginId);\n return databaseName ? defaultNameOverride(databaseName) : {};\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Knex } from 'knex';\n\n/**\n * Provides a partial knex config with schema name override.\n *\n * @param name - schema name to get config override for\n */\nexport default function defaultSchemaOverride(\n name: string,\n): Partial<Knex.Config> {\n return {\n searchPath: [name],\n };\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n LifecycleService,\n PluginMetadataService,\n} from '@backstage/backend-plugin-api';\nimport { Config, ConfigReader } from '@backstage/config';\nimport { ForwardedError } from '@backstage/errors';\nimport { JsonObject } from '@backstage/types';\nimport knexFactory, { Knex } from 'knex';\nimport { merge, omit } from 'lodash';\nimport limiterFactory from 'p-limit';\nimport { Client } from 'pg';\nimport { Connector } from '../types';\nimport defaultNameOverride from './defaultNameOverride';\nimport defaultSchemaOverride from './defaultSchemaOverride';\nimport { mergeDatabaseConfig } from './mergeDatabaseConfig';\nimport format from 'pg-format';\n\n// Limits the number of concurrent DDL operations to 1\nconst ddlLimiter = limiterFactory(1);\n\n/**\n * Creates a knex postgres database connection\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function createPgDatabaseClient(\n dbConfig: Config,\n overrides?: Knex.Config,\n) {\n const knexConfig = buildPgDatabaseConfig(dbConfig, overrides);\n const database = knexFactory(knexConfig);\n\n const role = dbConfig.getOptionalString('role');\n\n if (role) {\n database.client.pool.on(\n 'createSuccess',\n async (_event: number, pgClient: Client) => {\n const query = format('SET ROLE %I', role);\n await pgClient.query(query);\n },\n );\n }\n return database;\n}\n\n/**\n * Builds a knex postgres database connection\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function buildPgDatabaseConfig(\n dbConfig: Config,\n overrides?: Knex.Config,\n) {\n return mergeDatabaseConfig(\n dbConfig.get(),\n {\n connection: getPgConnectionConfig(dbConfig, !!overrides),\n useNullAsDefault: true,\n },\n overrides,\n );\n}\n\n/**\n * Gets the postgres connection config\n *\n * @param dbConfig - The database config\n * @param parseConnectionString - Flag to explicitly control connection string parsing\n */\nexport function getPgConnectionConfig(\n dbConfig: Config,\n parseConnectionString?: boolean,\n): Knex.PgConnectionConfig | string {\n const connection = dbConfig.get('connection') as any;\n const isConnectionString =\n typeof connection === 'string' || connection instanceof String;\n const autoParse = typeof parseConnectionString !== 'boolean';\n\n const shouldParseConnectionString = autoParse\n ? isConnectionString\n : parseConnectionString && isConnectionString;\n\n return shouldParseConnectionString\n ? parsePgConnectionString(connection as string)\n : connection;\n}\n\n/**\n * Parses a connection string using pg-connection-string\n *\n * @param connectionString - The postgres connection string\n */\nexport function parsePgConnectionString(connectionString: string) {\n const parse = requirePgConnectionString();\n return parse(connectionString);\n}\n\nfunction requirePgConnectionString() {\n try {\n return require('pg-connection-string').parse;\n } catch (e) {\n throw new ForwardedError(\"Postgres: Install 'pg-connection-string'\", e);\n }\n}\n\n/**\n * Creates the missing Postgres database if it does not exist\n *\n * @param dbConfig - The database config\n * @param databases - The name of the databases to create\n */\nexport async function ensurePgDatabaseExists(\n dbConfig: Config,\n ...databases: Array<string>\n) {\n const admin = createPgDatabaseClient(dbConfig, {\n connection: {\n database: 'postgres',\n },\n pool: {\n min: 0,\n acquireTimeoutMillis: 10000,\n },\n });\n\n try {\n const ensureDatabase = async (database: string) => {\n const result = await admin\n .from('pg_database')\n .where('datname', database)\n .count<Record<string, { count: string }>>();\n\n if (parseInt(result[0].count, 10) > 0) {\n return;\n }\n\n await admin.raw(`CREATE DATABASE ??`, [database]);\n };\n\n await Promise.all(\n databases.map(async database => {\n // For initial setup we use a smaller timeout but several retries. Given that this\n // is a separate connection pool we should never really run into issues with connection\n // acquisition timeouts, but we do anyway. This might be a bug in knex or some other dependency.\n let lastErr: Error | undefined = undefined;\n for (let i = 0; i < 3; i++) {\n try {\n return await ddlLimiter(() => ensureDatabase(database));\n } catch (err) {\n lastErr = err;\n }\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n throw lastErr;\n }),\n );\n } finally {\n await admin.destroy();\n }\n}\n\n/**\n * Creates the missing Postgres schema if it does not exist\n *\n * @param dbConfig - The database config\n * @param schemas - The name of the schemas to create\n */\nexport async function ensurePgSchemaExists(\n dbConfig: Config,\n ...schemas: Array<string>\n): Promise<void> {\n const admin = createPgDatabaseClient(dbConfig);\n const role = dbConfig.getOptionalString('role');\n\n try {\n const ensureSchema = async (database: string) => {\n if (role) {\n await admin.raw(`CREATE SCHEMA IF NOT EXISTS ?? AUTHORIZATION ??`, [\n database,\n role,\n ]);\n } else {\n await admin.raw(`CREATE SCHEMA IF NOT EXISTS ??`, [database]);\n }\n };\n\n await Promise.all(\n schemas.map(database => ddlLimiter(() => ensureSchema(database))),\n );\n } finally {\n await admin.destroy();\n }\n}\n\n/**\n * Drops the Postgres databases.\n *\n * @param dbConfig - The database config\n * @param databases - The name of the databases to drop\n */\nexport async function dropPgDatabase(\n dbConfig: Config,\n ...databases: Array<string>\n) {\n const admin = createPgDatabaseClient(dbConfig);\n try {\n await Promise.all(\n databases.map(async database => {\n await ddlLimiter(() => admin.raw(`DROP DATABASE ??`, [database]));\n }),\n );\n } finally {\n await admin.destroy();\n }\n}\n\n/**\n * Provides a config lookup path for a plugin's config block.\n */\nfunction pluginPath(pluginId: string): string {\n return `plugin.${pluginId}`;\n}\n\nfunction normalizeConnection(\n connection: Knex.StaticConnectionConfig | JsonObject | string | undefined,\n): Partial<Knex.StaticConnectionConfig> {\n if (typeof connection === 'undefined' || connection === null) {\n return {};\n }\n\n return typeof connection === 'string' || connection instanceof String\n ? parsePgConnectionString(connection as string)\n : connection;\n}\n\nexport class PgConnector implements Connector {\n constructor(\n private readonly config: Config,\n private readonly prefix: string,\n ) {}\n\n async getClient(\n pluginId: string,\n _deps?: {\n lifecycle: LifecycleService;\n pluginMetadata: PluginMetadataService;\n },\n ): Promise<Knex> {\n const pluginConfig = new ConfigReader(\n this.getConfigForPlugin(pluginId) as JsonObject,\n );\n\n const databaseName = this.getDatabaseName(pluginId);\n if (databaseName && this.getEnsureExistsConfig(pluginId)) {\n try {\n await ensurePgDatabaseExists(pluginConfig, databaseName);\n } catch (error) {\n throw new Error(\n `Failed to connect to the database to make sure that '${databaseName}' exists, ${error}`,\n );\n }\n }\n\n let schemaOverrides;\n if (this.getPluginDivisionModeConfig() === 'schema') {\n schemaOverrides = defaultSchemaOverride(pluginId);\n if (\n this.getEnsureSchemaExistsConfig(pluginId) ||\n this.getEnsureExistsConfig(pluginId)\n ) {\n try {\n await ensurePgSchemaExists(pluginConfig, pluginId);\n } catch (error) {\n throw new Error(\n `Failed to connect to the database to make sure that schema for plugin '${pluginId}' exists, ${error}`,\n );\n }\n }\n }\n\n const databaseClientOverrides = mergeDatabaseConfig(\n {},\n this.getDatabaseOverrides(pluginId),\n schemaOverrides,\n );\n\n const client = createPgDatabaseClient(\n pluginConfig,\n databaseClientOverrides,\n );\n\n return client;\n }\n\n async dropDatabase(...databaseNames: string[]): Promise<void> {\n return await dropPgDatabase(this.config, ...databaseNames);\n }\n\n /**\n * Provides the canonical database name for a given plugin.\n *\n * This method provides the effective database name which is determined using global\n * and plugin specific database config. If no explicit database name is configured\n * and `pluginDivisionMode` is not `schema`, this method will provide a generated name\n * which is the pluginId prefixed with 'backstage_plugin_'. If `pluginDivisionMode` is\n * `schema`, it will fallback to using the default database for the knex instance.\n *\n * @param pluginId - Lookup the database name for given plugin\n * @returns String representing the plugin's database name\n */\n private getDatabaseName(pluginId: string): string | undefined {\n const connection = this.getConnectionConfig(pluginId);\n\n const databaseName = (connection as Knex.ConnectionConfig)?.database;\n\n // `pluginDivisionMode` as `schema` should use overridden databaseName if supplied or fallback to default knex database\n if (this.getPluginDivisionModeConfig() === 'schema') {\n return databaseName;\n }\n\n // all other supported databases should fallback to an auto-prefixed name\n return databaseName ?? `${this.prefix}${pluginId}`;\n }\n\n /**\n * Provides the client type which should be used for a given plugin.\n *\n * The client type is determined by plugin specific config if present.\n * Otherwise the base client is used as the fallback.\n *\n * @param pluginId - Plugin to get the client type for\n * @returns Object with client type returned as `client` and boolean\n * representing whether or not the client was overridden as\n * `overridden`\n */\n private getClientType(pluginId: string): {\n client: string;\n overridden: boolean;\n } {\n const pluginClient = this.config.getOptionalString(\n `${pluginPath(pluginId)}.client`,\n );\n\n const baseClient = this.config.getString('client');\n const client = pluginClient ?? baseClient;\n return {\n client,\n overridden: client !== baseClient,\n };\n }\n\n private getRoleConfig(pluginId: string): string | undefined {\n return (\n this.config.getOptionalString(`${pluginPath(pluginId)}.role`) ??\n this.config.getOptionalString('role')\n );\n }\n\n /**\n * Provides the knexConfig which should be used for a given plugin.\n *\n * @param pluginId - Plugin to get the knexConfig for\n * @returns The merged knexConfig value or undefined if it isn't specified\n */\n private getAdditionalKnexConfig(pluginId: string): JsonObject | undefined {\n const pluginConfig = this.config\n .getOptionalConfig(`${pluginPath(pluginId)}.knexConfig`)\n ?.get<JsonObject>();\n\n const baseConfig = this.config\n .getOptionalConfig('knexConfig')\n ?.get<JsonObject>();\n\n return merge(baseConfig, pluginConfig);\n }\n\n private getEnsureExistsConfig(pluginId: string): boolean {\n const baseConfig = this.config.getOptionalBoolean('ensureExists') ?? true;\n return (\n this.config.getOptionalBoolean(`${pluginPath(pluginId)}.ensureExists`) ??\n baseConfig\n );\n }\n\n private getEnsureSchemaExistsConfig(pluginId: string): boolean {\n const baseConfig =\n this.config.getOptionalBoolean('ensureSchemaExists') ?? false;\n return (\n this.config.getOptionalBoolean(\n `${pluginPath(pluginId)}.getEnsureSchemaExistsConfig`,\n ) ?? baseConfig\n );\n }\n\n private getPluginDivisionModeConfig(): string {\n return this.config.getOptionalString('pluginDivisionMode') ?? 'database';\n }\n\n /**\n * Provides a Knex connection plugin config by combining base and plugin\n * config.\n *\n * This method provides a baseConfig for a plugin database connector. If the\n * client type has not been overridden, the global connection config will be\n * included with plugin specific config as the base. Values from the plugin\n * connection take precedence over the base. Base database name is omitted\n * unless `pluginDivisionMode` is set to `schema`.\n */\n private getConnectionConfig(pluginId: string): Knex.StaticConnectionConfig {\n const { overridden } = this.getClientType(pluginId);\n\n let baseConnection = normalizeConnection(this.config.get('connection'));\n\n // Databases cannot be shared unless the `pluginDivisionMode` is set to `schema`. The\n // `database` property from the base connection is omitted unless `pluginDivisionMode`\n // is set to `schema`.\n if (this.getPluginDivisionModeConfig() !== 'schema') {\n baseConnection = omit(baseConnection, 'database');\n }\n\n // get and normalize optional plugin specific database connection\n const connection = normalizeConnection(\n this.config.getOptional(`${pluginPath(pluginId)}.connection`),\n );\n\n (\n baseConnection as Knex.PgConnectionConfig\n ).application_name ||= `backstage_plugin_${pluginId}`;\n\n return {\n // include base connection if client type has not been overridden\n ...(overridden ? {} : baseConnection),\n ...connection,\n } as Knex.StaticConnectionConfig;\n }\n\n /**\n * Provides a Knex database config for a given plugin.\n *\n * This method provides a Knex configuration object along with the plugin's\n * client type.\n *\n * @param pluginId - The plugin that the database config should correspond with\n */\n private getConfigForPlugin(pluginId: string): Knex.Config {\n const { client } = this.getClientType(pluginId);\n const role = this.getRoleConfig(pluginId);\n\n return {\n ...this.getAdditionalKnexConfig(pluginId),\n client,\n connection: this.getConnectionConfig(pluginId),\n ...(role && { role }),\n };\n }\n\n /**\n * Provides a partial `Knex.Config`• database name override for a given plugin.\n *\n * @param pluginId - Target plugin to get database name override\n * @returns Partial `Knex.Config` with database name override\n */\n private getDatabaseOverrides(pluginId: string): Knex.Config {\n const databaseName = this.getDatabaseName(pluginId);\n return databaseName ? defaultNameOverride(databaseName) : {};\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DevDataStore } from '@backstage/backend-dev-utils';\nimport {\n LifecycleService,\n PluginMetadataService,\n} from '@backstage/backend-plugin-api';\nimport { Config, ConfigReader } from '@backstage/config';\nimport { JsonObject } from '@backstage/types';\nimport { ensureDirSync } from 'fs-extra';\nimport knexFactory, { Knex } from 'knex';\nimport { merge, omit } from 'lodash';\nimport path from 'path';\nimport { Connector } from '../types';\nimport { mergeDatabaseConfig } from './mergeDatabaseConfig';\n\n/**\n * Creates a knex SQLite3 database connection\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function createSqliteDatabaseClient(\n dbConfig: Config,\n overrides?: Knex.Config,\n deps?: {\n lifecycle: LifecycleService;\n pluginMetadata: PluginMetadataService;\n },\n) {\n const knexConfig = buildSqliteDatabaseConfig(dbConfig, overrides);\n const connConfig = knexConfig.connection as Knex.Sqlite3ConnectionConfig;\n\n const filename = connConfig.filename ?? ':memory:';\n\n // If storage on disk is used, ensure that the directory exists\n if (filename !== ':memory:') {\n const directory = path.dirname(filename);\n ensureDirSync(directory);\n }\n\n let database: Knex;\n\n if (deps && filename === ':memory:') {\n // The dev store is used during watch mode to store and restore the database\n // across reloads. It is only available when running the backend through\n // `backstage-cli package start`.\n const devStore = DevDataStore.get();\n\n if (devStore) {\n const dataKey = `sqlite3-db-${deps.pluginMetadata.getId()}`;\n\n const connectionLoader = async () => {\n // If seed data is available, use it tconnectionLoader restore the database\n const { data: seedData } = await devStore.load(dataKey);\n\n return {\n ...(knexConfig.connection as Knex.Sqlite3ConnectionConfig),\n filename: seedData ?? ':memory:',\n };\n };\n\n database = knexFactory({\n ...knexConfig,\n connection: Object.assign(connectionLoader, {\n // This is a workaround for the knex SQLite driver always warning when using a config loader\n filename: ':memory:',\n }),\n });\n\n // If the dev store is available we save the database state on shutdown\n deps.lifecycle.addShutdownHook(async () => {\n const connection = await database.client.acquireConnection();\n const data = connection.serialize();\n await devStore.save(dataKey, data);\n });\n } else {\n database = knexFactory(knexConfig);\n }\n } else {\n database = knexFactory(knexConfig);\n }\n\n database.client.pool.on('createSuccess', (_eventId: any, resource: any) => {\n resource.run('PRAGMA foreign_keys = ON', () => {});\n });\n\n return database;\n}\n\n/**\n * Builds a knex SQLite3 connection config\n *\n * @param dbConfig - The database config\n * @param overrides - Additional options to merge with the config\n */\nexport function buildSqliteDatabaseConfig(\n dbConfig: Config,\n overrides?: Knex.Config,\n): Knex.Config {\n const baseConfig = dbConfig.get<Knex.Config>();\n\n // Normalize config to always contain a connection object\n if (typeof baseConfig.connection === 'string') {\n baseConfig.connection = { filename: baseConfig.connection };\n }\n if (overrides && typeof overrides.connection === 'string') {\n overrides.connection = { filename: overrides.connection };\n }\n\n const config: Knex.Config = mergeDatabaseConfig(\n {\n connection: {},\n },\n baseConfig,\n {\n useNullAsDefault: true,\n },\n overrides,\n );\n\n return config;\n}\n\n/**\n * Provides a partial knex SQLite3 config to override database name.\n */\nexport function createSqliteNameOverride(name: string): Partial<Knex.Config> {\n return {\n connection: parseSqliteConnectionString(name),\n };\n}\n\n/**\n * Produces a partial knex SQLite3 connection config with database name.\n */\nexport function parseSqliteConnectionString(\n name: string,\n): Knex.Sqlite3ConnectionConfig {\n return {\n filename: name,\n };\n}\n\n/**\n * Provides a config lookup path for a plugin's config block.\n */\nfunction pluginPath(pluginId: string): string {\n return `plugin.${pluginId}`;\n}\n\nfunction normalizeConnection(\n connection: Knex.StaticConnectionConfig | JsonObject | string | undefined,\n): Partial<Knex.StaticConnectionConfig> {\n if (typeof connection === 'undefined' || connection === null) {\n return {};\n }\n\n return typeof connection === 'string' || connection instanceof String\n ? parseSqliteConnectionString(connection as string)\n : connection;\n}\n\nexport class Sqlite3Connector implements Connector {\n constructor(private readonly config: Config) {}\n\n async getClient(\n pluginId: string,\n deps?: {\n lifecycle: LifecycleService;\n pluginMetadata: PluginMetadataService;\n },\n ): Promise<Knex> {\n const pluginConfig = new ConfigReader(\n this.getConfigForPlugin(pluginId) as JsonObject,\n );\n\n const pluginDivisionMode = this.getPluginDivisionModeConfig();\n if (pluginDivisionMode !== 'database') {\n throw new Error(\n `The SQLite driver does not support plugin division mode '${pluginDivisionMode}'`,\n );\n }\n\n const databaseClientOverrides = mergeDatabaseConfig(\n {},\n this.getDatabaseOverrides(pluginId),\n );\n\n const client = createSqliteDatabaseClient(\n pluginConfig,\n databaseClientOverrides,\n deps,\n );\n\n return client;\n }\n\n async dropDatabase(..._databaseNames: string[]): Promise<void> {\n // do nothing\n }\n\n /**\n * Provides the canonical database name for a given plugin.\n *\n * This method provides the effective database name which is determined using global\n * and plugin specific database config. If no explicit database name is configured\n * and `pluginDivisionMode` is not `schema`, this method will provide a generated name\n * which is the pluginId prefixed with 'backstage_plugin_'. If `pluginDivisionMode` is\n * `schema`, it will fallback to using the default database for the knex instance.\n *\n * @param pluginId - Lookup the database name for given plugin\n * @returns String representing the plugin's database name\n */\n private getDatabaseName(pluginId: string): string | undefined {\n const connection = this.getConnectionConfig(pluginId);\n\n const sqliteFilename: string | undefined = (\n connection as Knex.Sqlite3ConnectionConfig\n ).filename;\n\n if (sqliteFilename === ':memory:') {\n return sqliteFilename;\n }\n\n const sqliteDirectory =\n (connection as { directory?: string }).directory ?? '.';\n\n return path.join(sqliteDirectory, sqliteFilename ?? `${pluginId}.sqlite`);\n }\n\n /**\n * Provides the client type which should be used for a given plugin.\n *\n * The client type is determined by plugin specific config if present.\n * Otherwise the base client is used as the fallback.\n *\n * @param pluginId - Plugin to get the client type for\n * @returns Object with client type returned as `client` and boolean\n * representing whether or not the client was overridden as\n * `overridden`\n */\n private getClientType(pluginId: string): {\n client: string;\n overridden: boolean;\n } {\n const pluginClient = this.config.getOptionalString(\n `${pluginPath(pluginId)}.client`,\n );\n\n const baseClient = this.config.getString('client');\n const client = pluginClient ?? baseClient;\n return {\n client,\n overridden: client !== baseClient,\n };\n }\n\n private getRoleConfig(pluginId: string): string | undefined {\n return (\n this.config.getOptionalString(`${pluginPath(pluginId)}.role`) ??\n this.config.getOptionalString('role')\n );\n }\n\n /**\n * Provides the knexConfig which should be used for a given plugin.\n *\n * @param pluginId - Plugin to get the knexConfig for\n * @returns The merged knexConfig value or undefined if it isn't specified\n */\n private getAdditionalKnexConfig(pluginId: string): JsonObject | undefined {\n const pluginConfig = this.config\n .getOptionalConfig(`${pluginPath(pluginId)}.knexConfig`)\n ?.get<JsonObject>();\n\n const baseConfig = this.config\n .getOptionalConfig('knexConfig')\n ?.get<JsonObject>();\n\n return merge(baseConfig, pluginConfig);\n }\n\n private getPluginDivisionModeConfig(): string {\n return this.config.getOptionalString('pluginDivisionMode') ?? 'database';\n }\n\n /**\n * Provides a Knex connection plugin config by combining base and plugin\n * config.\n *\n * This method provides a baseConfig for a plugin database connector. If the\n * client type has not been overridden, the global connection config will be\n * included with plugin specific config as the base. Values from the plugin\n * connection take precedence over the base. Base database name is omitted for\n * all supported databases excluding SQLite unless `pluginDivisionMode` is set\n * to `schema`.\n */\n private getConnectionConfig(pluginId: string): Knex.StaticConnectionConfig {\n const { client, overridden } = this.getClientType(pluginId);\n\n let baseConnection = normalizeConnection(this.config.get('connection'));\n\n if (\n client.includes('sqlite3') &&\n 'filename' in baseConnection &&\n baseConnection.filename !== ':memory:'\n ) {\n throw new Error(\n '`connection.filename` is not supported for the base sqlite connection. Prefer `connection.directory` or provide a filename for the plugin connection instead.',\n );\n }\n\n // Databases cannot be shared unless the `pluginDivisionMode` is set to `schema`. The\n // `database` property from the base connection is omitted unless `pluginDivisionMode`\n // is set to `schema`. SQLite3's `filename` property is an exception as this is used as a\n // directory elsewhere so we preserve `filename`.\n if (this.getPluginDivisionModeConfig() !== 'schema') {\n baseConnection = omit(baseConnection, 'database');\n }\n\n // get and normalize optional plugin specific database connection\n const connection = normalizeConnection(\n this.config.getOptional(`${pluginPath(pluginId)}.connection`),\n );\n\n return {\n // include base connection if client type has not been overridden\n ...(overridden ? {} : baseConnection),\n ...connection,\n } as Knex.StaticConnectionConfig;\n }\n\n /**\n * Provides a Knex database config for a given plugin.\n *\n * This method provides a Knex configuration object along with the plugin's\n * client type.\n *\n * @param pluginId - The plugin that the database config should correspond with\n */\n private getConfigForPlugin(pluginId: string): Knex.Config {\n const { client } = this.getClientType(pluginId);\n const role = this.getRoleConfig(pluginId);\n\n return {\n ...this.getAdditionalKnexConfig(pluginId),\n client,\n connection: this.getConnectionConfig(pluginId),\n ...(role && { role }),\n };\n }\n\n /**\n * Provides a partial `Knex.Config`• database name override for a given plugin.\n *\n * @param pluginId - Target plugin to get database name override\n * @returns Partial `Knex.Config` with database name override\n */\n private getDatabaseOverrides(pluginId: string): Knex.Config {\n const databaseName = this.getDatabaseName(pluginId);\n return databaseName ? createSqliteNameOverride(databaseName) : {};\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n DatabaseService,\n LifecycleService,\n LoggerService,\n PluginMetadataService,\n} from '@backstage/backend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { stringifyError } from '@backstage/errors';\nimport { Knex } from 'knex';\nimport { MysqlConnector } from './connectors/mysql';\nimport { PgConnector } from './connectors/postgres';\nimport { Sqlite3Connector } from './connectors/sqlite3';\nimport { Connector, PluginDatabaseManager } from './types';\n\n/**\n * Provides a config lookup path for a plugin's config block.\n */\nfunction pluginPath(pluginId: string): string {\n return `plugin.${pluginId}`;\n}\n\n/**\n * Creation options for {@link DatabaseManager}.\n *\n * @public\n */\nexport type DatabaseManagerOptions = {\n migrations?: DatabaseService['migrations'];\n logger?: LoggerService;\n};\n\n/**\n * An interface that represents the legacy global DatabaseManager implementation.\n * @public\n */\nexport type LegacyRootDatabaseService = {\n forPlugin(pluginId: string): DatabaseService;\n};\n\n/**\n * Testable implementation class for {@link DatabaseManager} below.\n */\nexport class DatabaseManagerImpl implements LegacyRootDatabaseService {\n constructor(\n private readonly config: Config,\n private readonly connectors: Record<string, Connector>,\n private readonly options?: DatabaseManagerOptions,\n private readonly databaseCache: Map<string, Promise<Knex>> = new Map(),\n ) {}\n\n /**\n * Generates a PluginDatabaseManager for consumption by plugins.\n *\n * @param pluginId - The plugin that the database manager should be created for. Plugin names\n * should be unique as they are used to look up database config overrides under\n * `backend.database.plugin`.\n */\n forPlugin(\n pluginId: string,\n deps?: {\n lifecycle: LifecycleService;\n pluginMetadata: PluginMetadataService;\n },\n ): PluginDatabaseManager {\n const client = this.getClientType(pluginId).client;\n const connector = this.connectors[client];\n if (!connector) {\n throw new Error(\n `Unsupported database client type '${client}' specified for plugin '${pluginId}'`,\n );\n }\n const getClient = () => this.getDatabase(pluginId, connector, deps);\n\n const skip =\n this.options?.migrations?.skip ??\n this.config.getOptionalBoolean(\n `backend.database.plugin.${pluginId}.skipMigrations`,\n ) ??\n this.config.getOptionalBoolean('backend.database.skipMigrations') ??\n false;\n\n return { getClient, migrations: { skip } };\n }\n\n /**\n * Provides the client type which should be used for a given plugin.\n *\n * The client type is determined by plugin specific config if present.\n * Otherwise the base client is used as the fallback.\n *\n * @param pluginId - Plugin to get the client type for\n * @returns Object with client type returned as `client` and boolean\n * representing whether or not the client was overridden as\n * `overridden`\n */\n private getClientType(pluginId: string): {\n client: string;\n overridden: boolean;\n } {\n const pluginClient = this.config.getOptionalString(\n `${pluginPath(pluginId)}.client`,\n );\n\n const baseClient = this.config.getString('client');\n const client = pluginClient ?? baseClient;\n return {\n client,\n overridden: client !== baseClient,\n };\n }\n\n /**\n * Provides a scoped Knex client for a plugin as per application config.\n *\n * @param pluginId - Plugin to get a Knex client for\n * @returns Promise which resolves to a scoped Knex database client for a\n * plugin\n */\n private async getDatabase(\n pluginId: string,\n connector: Connector,\n deps?: {\n lifecycle: LifecycleService;\n pluginMetadata: PluginMetadataService;\n },\n ): Promise<Knex> {\n if (this.databaseCache.has(pluginId)) {\n return this.databaseCache.get(pluginId)!;\n }\n\n const clientPromise = connector.getClient(pluginId, deps);\n this.databaseCache.set(pluginId, clientPromise);\n\n if (process.env.NODE_ENV !== 'test') {\n clientPromise.then(client => this.startKeepaliveLoop(pluginId, client));\n }\n\n return clientPromise;\n }\n\n private startKeepaliveLoop(pluginId: string, client: Knex): void {\n let lastKeepaliveFailed = false;\n\n setInterval(() => {\n // During testing it can happen that the environment is torn down and\n // this client is `undefined`, but this interval is still run.\n client?.raw('select 1').then(\n () => {\n lastKeepaliveFailed = false;\n },\n (error: unknown) => {\n if (!lastKeepaliveFailed) {\n lastKeepaliveFailed = true;\n this.options?.logger?.warn(\n `Database keepalive failed for plugin ${pluginId}, ${stringifyError(\n error,\n )}`,\n );\n }\n },\n );\n }, 60 * 1000);\n }\n}\n\n// NOTE: This class looks odd but is kept around for API compatibility reasons\n/**\n * Manages database connections for Backstage backend plugins.\n *\n * @public\n * @remarks\n *\n * The database manager allows the user to set connection and client settings on\n * a per pluginId basis by defining a database config block under\n * `plugin.<pluginId>` in addition to top level defaults. Optionally, a user may\n * set `prefix` which is used to prefix generated database names if config is\n * not provided.\n */\nexport class DatabaseManager implements LegacyRootDatabaseService {\n /**\n * Creates a {@link DatabaseManager} from `backend.database` config.\n *\n * @param config - The loaded application configuration.\n * @param options - An optional configuration object.\n */\n static fromConfig(\n config: Config,\n options?: DatabaseManagerOptions,\n ): DatabaseManager {\n const databaseConfig = config.getConfig('backend.database');\n const prefix =\n databaseConfig.getOptionalString('prefix') || 'backstage_plugin_';\n return new DatabaseManager(\n new DatabaseManagerImpl(\n databaseConfig,\n {\n pg: new PgConnector(databaseConfig, prefix),\n sqlite3: new Sqlite3Connector(databaseConfig),\n 'better-sqlite3': new Sqlite3Connector(databaseConfig),\n mysql: new MysqlConnector(databaseConfig, prefix),\n mysql2: new MysqlConnector(databaseConfig, prefix),\n },\n options,\n ),\n );\n }\n\n private constructor(private readonly impl: DatabaseManagerImpl) {}\n\n /**\n * Generates a PluginDatabaseManager for consumption by plugins.\n *\n * @param pluginId - The plugin that the database manager should be created for. Plugin names\n * should be unique as they are used to look up database config overrides under\n * `backend.database.plugin`.\n */\n forPlugin(\n pluginId: string,\n deps?: {\n lifecycle: LifecycleService;\n pluginMetadata: PluginMetadataService;\n },\n ): PluginDatabaseManager {\n return this.impl.forPlugin(pluginId, deps);\n }\n}\n\n/**\n * Helper for deleting databases.\n *\n * @public\n * @deprecated Will be removed in a future release.\n */\nexport async function dropDatabase(\n dbConfig: Config,\n ...databaseNames: string[]\n): Promise<void> {\n const client = dbConfig.getString('client');\n const prefix = dbConfig.getOptionalString('prefix') || 'backstage_plugin_';\n\n if (client === 'pg') {\n await new PgConnector(dbConfig, prefix).dropDatabase(...databaseNames);\n } else if (client === 'mysql' || client === 'mysql2') {\n await new MysqlConnector(dbConfig, prefix).dropDatabase(...databaseNames);\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { ConfigReader } from '@backstage/config';\nimport { DatabaseManager } from './DatabaseManager';\n\n/**\n * Database access and management via `knex`.\n *\n * See {@link @backstage/code-plugin-api#DatabaseService}\n * and {@link https://backstage.io/docs/backend-system/core-services/database | the service docs}\n * for more information.\n *\n * @public\n */\nexport const databaseServiceFactory = createServiceFactory({\n service: coreServices.database,\n deps: {\n config: coreServices.rootConfig,\n lifecycle: coreServices.lifecycle,\n pluginMetadata: coreServices.pluginMetadata,\n },\n async createRootContext({ config }) {\n return config.getOptional('backend.database')\n ? DatabaseManager.fromConfig(config)\n : DatabaseManager.fromConfig(\n new ConfigReader({\n backend: {\n database: { client: 'better-sqlite3', connection: ':memory:' },\n },\n }),\n );\n },\n async factory({ pluginMetadata, lifecycle }, databaseManager) {\n return databaseManager.forPlugin(pluginMetadata.getId(), {\n pluginMetadata,\n lifecycle,\n });\n },\n});\n"],"names":["merge","ddlLimiter","limiterFactory","knexFactory","yn","InputError","pluginPath","normalizeConnection","ConfigReader","omit","format","ForwardedError","path","ensureDirSync","DevDataStore","stringifyError","createServiceFactory","coreServices","config"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA0BA,SAAwB,oBACtB,IACsB,EAAA;AACtB,EAAO,OAAA;AAAA,IACL,UAAY,EAAA;AAAA,MACV,QAAU,EAAA,IAAA;AAAA,KACZ;AAAA,GACF,CAAA;AACF;;ACTgB,SAAA,mBAAA,CAAoB,WAAgB,SAAkB,EAAA;AACpE,EAAA,OAAOA,YAAM,CAAA,EAAI,EAAA,MAAA,EAAQ,GAAG,SAAS,CAAA,CAAA;AACvC;;ACKA,MAAMC,YAAA,GAAaC,gCAAe,CAAC,CAAA,CAAA;AAQnB,SAAA,yBAAA,CACd,UACA,SACA,EAAA;AACA,EAAM,MAAA,UAAA,GAAa,wBAAyB,CAAA,QAAA,EAAU,SAAS,CAAA,CAAA;AAC/D,EAAM,MAAA,QAAA,GAAWC,6BAAY,UAAU,CAAA,CAAA;AACvC,EAAO,OAAA,QAAA,CAAA;AACT,CAAA;AAQgB,SAAA,wBAAA,CACd,UACA,SACA,EAAA;AACA,EAAO,OAAA,mBAAA;AAAA,IACL,SAAS,GAAI,EAAA;AAAA,IACb;AAAA,MACE,UAAY,EAAA,wBAAA,CAAyB,QAAU,EAAA,CAAC,CAAC,SAAS,CAAA;AAAA,MAC1D,gBAAkB,EAAA,IAAA;AAAA,KACpB;AAAA,IACA,SAAA;AAAA,GACF,CAAA;AACF,CAAA;AAQgB,SAAA,wBAAA,CACd,UACA,qBACqC,EAAA;AACrC,EAAM,MAAA,UAAA,GAAa,QAAS,CAAA,GAAA,CAAI,YAAY,CAAA,CAAA;AAC5C,EAAA,MAAM,kBACJ,GAAA,OAAO,UAAe,KAAA,QAAA,IAAY,UAAsB,YAAA,MAAA,CAAA;AAC1D,EAAM,MAAA,SAAA,GAAY,OAAO,qBAA0B,KAAA,SAAA,CAAA;AAEnD,EAAM,MAAA,2BAAA,GAA8B,SAChC,GAAA,kBAAA,GACA,qBAAyB,IAAA,kBAAA,CAAA;AAE7B,EAAO,OAAA,2BAAA,GACH,0BAA2B,CAAA,UAAoB,CAC/C,GAAA,UAAA,CAAA;AACN,CAAA;AAQO,SAAS,2BACd,gBAC4B,EAAA;AAC5B,EAAI,IAAA;AACF,IAAM,MAAA;AAAA,MACJ,QAAA;AAAA,MACA,QAAA;AAAA,MACA,QAAA;AAAA,MACA,IAAA;AAAA,MACA,QAAA;AAAA,MACA,QAAA;AAAA,MACA,YAAA;AAAA,KACF,GAAI,IAAI,GAAA,CAAI,gBAAgB,CAAA,CAAA;AAE5B,IAAA,IAAI,aAAa,QAAU,EAAA;AACzB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAoB,iBAAA,EAAA,QAAQ,CAAE,CAAA,CAAA,CAAA;AAAA,KACrC,MAAA,IAAA,CAAC,QAAY,IAAA,CAAC,QAAU,EAAA;AACjC,MAAM,MAAA,IAAI,MAAM,CAA2B,yBAAA,CAAA,CAAA,CAAA;AAAA,KAClC,MAAA,IAAA,CAAC,QAAS,CAAA,KAAA,CAAM,WAAW,CAAG,EAAA;AACvC,MAAM,MAAA,IAAI,MAAM,CAA8B,4BAAA,CAAA,CAAA,CAAA;AAAA,KAChD;AAEA,IAAA,MAAM,MAAqC,GAAA;AAAA,MACzC,IAAM,EAAA,QAAA;AAAA,MACN,QAAA;AAAA,MACA,IAAM,EAAA,QAAA;AAAA,MACN,IAAA,EAAM,MAAO,CAAA,IAAA,IAAQ,IAAI,CAAA;AAAA,MACzB,QAAU,EAAA,kBAAA,CAAmB,QAAS,CAAA,SAAA,CAAU,CAAC,CAAC,CAAA;AAAA,KACpD,CAAA;AAEA,IAAM,MAAA,GAAA,GAAM,YAAa,CAAA,GAAA,CAAI,KAAK,CAAA,CAAA;AAClC,IAAA,IAAI,GAAK,EAAA;AACP,MAAA,MAAA,CAAO,GAAM,GAAA,GAAA,CAAA;AAAA,KACf;AAEA,IAAM,MAAA,KAAA,GAAQ,YAAa,CAAA,GAAA,CAAI,OAAO,CAAA,CAAA;AACtC,IAAA,IAAI,KAAO,EAAA;AACT,MAAO,MAAA,CAAA,KAAA,GAAQC,oBAAG,KAAK,CAAA,CAAA;AAAA,KACzB;AAEA,IAAO,OAAA,MAAA,CAAA;AAAA,WACA,CAAG,EAAA;AACV,IAAA,MAAM,IAAIC,iBAAA;AAAA,MACR,gDAAgD,CAAC,CAAA,CAAA;AAAA,MACjD,CAAA;AAAA,KACF,CAAA;AAAA,GACF;AACF,CAAA;AAQsB,eAAA,yBAAA,CACpB,aACG,SACH,EAAA;AACA,EAAM,MAAA,KAAA,GAAQ,0BAA0B,QAAU,EAAA;AAAA,IAChD,UAAY,EAAA;AAAA,MACV,QAAU,EAAA,IAAA;AAAA,KACZ;AAAA,IACA,IAAM,EAAA;AAAA,MACJ,GAAK,EAAA,CAAA;AAAA,MACL,oBAAsB,EAAA,GAAA;AAAA,KACxB;AAAA,GACD,CAAA,CAAA;AAED,EAAI,IAAA;AACF,IAAM,MAAA,cAAA,GAAiB,OAAO,QAAqB,KAAA;AACjD,MAAA,MAAM,KAAM,CAAA,GAAA,CAAI,CAAoC,gCAAA,CAAA,EAAA,CAAC,QAAQ,CAAC,CAAA,CAAA;AAAA,KAChE,CAAA;AACA,IAAA,MAAM,OAAQ,CAAA,GAAA;AAAA,MACZ,SAAA,CAAU,GAAI,CAAA,OAAM,QAAY,KAAA;AAI9B,QAAA,IAAI,OAA6B,GAAA,KAAA,CAAA,CAAA;AACjC,QAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,CAAA,EAAG,CAAK,EAAA,EAAA;AAC1B,UAAI,IAAA;AACF,YAAA,OAAO,MAAMJ,YAAA,CAAW,MAAM,cAAA,CAAe,QAAQ,CAAC,CAAA,CAAA;AAAA,mBAC/C,GAAK,EAAA;AACZ,YAAU,OAAA,GAAA,GAAA,CAAA;AAAA,WACZ;AACA,UAAA,MAAM,IAAI,OAAQ,CAAA,CAAA,OAAA,KAAW,UAAW,CAAA,OAAA,EAAS,GAAG,CAAC,CAAA,CAAA;AAAA,SACvD;AACA,QAAM,MAAA,OAAA,CAAA;AAAA,OACP,CAAA;AAAA,KACH,CAAA;AAAA,GACA,SAAA;AACA,IAAA,MAAM,MAAM,OAAQ,EAAA,CAAA;AAAA,GACtB;AACF,CAAA;AAQsB,eAAA,iBAAA,CACpB,aACG,SACH,EAAA;AACA,EAAM,MAAA,KAAA,GAAQ,0BAA0B,QAAU,EAAA;AAAA,IAChD,UAAY,EAAA;AAAA,MACV,QAAU,EAAA,IAAA;AAAA,KACZ;AAAA,IACA,IAAM,EAAA;AAAA,MACJ,GAAK,EAAA,CAAA;AAAA,MACL,oBAAsB,EAAA,GAAA;AAAA,KACxB;AAAA,GACD,CAAA,CAAA;AAED,EAAI,IAAA;AACF,IAAM,MAAA,YAAA,GAAe,OAAO,QAAqB,KAAA;AAC/C,MAAA,MAAM,KAAM,CAAA,GAAA,CAAI,CAAoB,gBAAA,CAAA,EAAA,CAAC,QAAQ,CAAC,CAAA,CAAA;AAAA,KAChD,CAAA;AACA,IAAA,MAAM,OAAQ,CAAA,GAAA;AAAA,MACZ,SAAA,CAAU,GAAI,CAAA,OAAM,QAAY,KAAA;AAC9B,QAAA,OAAO,MAAMA,YAAA,CAAW,MAAM,YAAA,CAAa,QAAQ,CAAC,CAAA,CAAA;AAAA,OACrD,CAAA;AAAA,KACH,CAAA;AAAA,GACA,SAAA;AACA,IAAA,MAAM,MAAM,OAAQ,EAAA,CAAA;AAAA,GACtB;AACF,CAAA;AAKA,SAASK,aAAW,QAA0B,EAAA;AAC5C,EAAA,OAAO,UAAU,QAAQ,CAAA,CAAA,CAAA;AAC3B,CAAA;AAEA,SAASC,sBACP,UACsC,EAAA;AACtC,EAAA,IAAI,OAAO,UAAA,KAAe,WAAe,IAAA,UAAA,KAAe,IAAM,EAAA;AAC5D,IAAA,OAAO,EAAC,CAAA;AAAA,GACV;AAEA,EAAA,OAAO,OAAO,UAAe,KAAA,QAAA,IAAY,sBAAsB,MAC3D,GAAA,0BAAA,CAA2B,UAAoB,CAC/C,GAAA,UAAA,CAAA;AACN,CAAA;AAEO,MAAM,cAAoC,CAAA;AAAA,EAC/C,WAAA,CACmB,QACA,MACjB,EAAA;AAFiB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA,CAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA,CAAA;AAAA,GAChB;AAAA,EAEH,MAAM,SACJ,CAAA,QAAA,EACA,KAIe,EAAA;AACf,IAAA,MAAM,eAAe,IAAIC,mBAAA;AAAA,MACvB,IAAA,CAAK,mBAAmB,QAAQ,CAAA;AAAA,KAClC,CAAA;AAEA,IAAM,MAAA,YAAA,GAAe,IAAK,CAAA,eAAA,CAAgB,QAAQ,CAAA,CAAA;AAClD,IAAA,IAAI,YAAgB,IAAA,IAAA,CAAK,qBAAsB,CAAA,QAAQ,CAAG,EAAA;AACxD,MAAI,IAAA;AACF,QAAM,MAAA,yBAAA,CAA0B,cAAc,YAAY,CAAA,CAAA;AAAA,eACnD,KAAO,EAAA;AACd,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,qDAAA,EAAwD,YAAY,CAAA,UAAA,EAAa,KAAK,CAAA,CAAA;AAAA,SACxF,CAAA;AAAA,OACF;AAAA,KACF;AAEA,IAAM,MAAA,kBAAA,GAAqB,KAAK,2BAA4B,EAAA,CAAA;AAC5D,IAAA,IAAI,uBAAuB,UAAY,EAAA;AACrC,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,2DAA2D,kBAAkB,CAAA,CAAA,CAAA;AAAA,OAC/E,CAAA;AAAA,KACF;AAEA,IAAA,MAAM,uBAA0B,GAAA,mBAAA;AAAA,MAC9B,EAAC;AAAA,MACD,IAAA,CAAK,qBAAqB,QAAQ,CAAA;AAAA,KACpC,CAAA;AAEA,IAAA,MAAM,MAAS,GAAA,yBAAA;AAAA,MACb,YAAA;AAAA,MACA,uBAAA;AAAA,KACF,CAAA;AAEA,IAAO,OAAA,MAAA,CAAA;AAAA,GACT;AAAA,EAEA,MAAM,gBAAgB,aAAwC,EAAA;AAC5D,IAAA,OAAO,MAAM,iBAAA,CAAkB,IAAK,CAAA,MAAA,EAAQ,GAAG,aAAa,CAAA,CAAA;AAAA,GAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaQ,gBAAgB,QAAsC,EAAA;AAC5D,IAAM,MAAA,UAAA,GAAa,IAAK,CAAA,mBAAA,CAAoB,QAAQ,CAAA,CAAA;AACpD,IAAA,MAAM,eAAgB,UAAsC,EAAA,QAAA,CAAA;AAC5D,IAAA,OAAO,YAAgB,IAAA,CAAA,EAAG,IAAK,CAAA,MAAM,GAAG,QAAQ,CAAA,CAAA,CAAA;AAAA,GAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaQ,cAAc,QAGpB,EAAA;AACA,IAAM,MAAA,YAAA,GAAe,KAAK,MAAO,CAAA,iBAAA;AAAA,MAC/B,CAAA,EAAGF,YAAW,CAAA,QAAQ,CAAC,CAAA,OAAA,CAAA;AAAA,KACzB,CAAA;AAEA,IAAA,MAAM,UAAa,GAAA,IAAA,CAAK,MAAO,CAAA,SAAA,CAAU,QAAQ,CAAA,CAAA;AACjD,IAAA,MAAM,SAAS,YAAgB,IAAA,UAAA,CAAA;AAC/B,IAAO,OAAA;AAAA,MACL,MAAA;AAAA,MACA,YAAY,MAAW,KAAA,UAAA;AAAA,KACzB,CAAA;AAAA,GACF;AAAA,EAEQ,cAAc,QAAsC,EAAA;AAC1D,IAAA,OACE,IAAK,CAAA,MAAA,CAAO,iBAAkB,CAAA,CAAA,EAAGA,YAAW,CAAA,QAAQ,CAAC,CAAA,KAAA,CAAO,CAC5D,IAAA,IAAA,CAAK,MAAO,CAAA,iBAAA,CAAkB,MAAM,CAAA,CAAA;AAAA,GAExC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,wBAAwB,QAA0C,EAAA;AACxE,IAAM,MAAA,YAAA,GAAe,IAAK,CAAA,MAAA,CACvB,iBAAkB,CAAA,CAAA,EAAGA,aAAW,QAAQ,CAAC,CAAa,WAAA,CAAA,CAAA,EACrD,GAAgB,EAAA,CAAA;AAEpB,IAAA,MAAM,aAAa,IAAK,CAAA,MAAA,CACrB,iBAAkB,CAAA,YAAY,GAC7B,GAAgB,EAAA,CAAA;AAEpB,IAAO,OAAAN,YAAA,CAAM,YAAY,YAAY,CAAA,CAAA;AAAA,GACvC;AAAA,EAEQ,sBAAsB,QAA2B,EAAA;AACvD,IAAA,MAAM,UAAa,GAAA,IAAA,CAAK,MAAO,CAAA,kBAAA,CAAmB,cAAc,CAAK,IAAA,IAAA,CAAA;AACrE,IACE,OAAA,IAAA,CAAK,OAAO,kBAAmB,CAAA,CAAA,EAAGM,aAAW,QAAQ,CAAC,eAAe,CACrE,IAAA,UAAA,CAAA;AAAA,GAEJ;AAAA,EAEQ,2BAAsC,GAAA;AAC5C,IAAA,OAAO,IAAK,CAAA,MAAA,CAAO,iBAAkB,CAAA,oBAAoB,CAAK,IAAA,UAAA,CAAA;AAAA,GAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYQ,oBAAoB,QAA+C,EAAA;AACzE,IAAA,MAAM,EAAE,UAAA,EAAe,GAAA,IAAA,CAAK,cAAc,QAAQ,CAAA,CAAA;AAElD,IAAA,IAAI,iBAAiBC,qBAAoB,CAAA,IAAA,CAAK,MAAO,CAAA,GAAA,CAAI,YAAY,CAAC,CAAA,CAAA;AAKtE,IAAI,IAAA,IAAA,CAAK,2BAA4B,EAAA,KAAM,QAAU,EAAA;AACnD,MAAiB,cAAA,GAAAE,WAAA,CAAK,gBAAgB,UAAU,CAAA,CAAA;AAAA,KAClD;AAGA,IAAA,MAAM,UAAa,GAAAF,qBAAA;AAAA,MACjB,KAAK,MAAO,CAAA,WAAA,CAAY,GAAGD,YAAW,CAAA,QAAQ,CAAC,CAAa,WAAA,CAAA,CAAA;AAAA,KAC9D,CAAA;AAEA,IAAO,OAAA;AAAA;AAAA,MAEL,GAAI,UAAa,GAAA,EAAK,GAAA,cAAA;AAAA,MACtB,GAAG,UAAA;AAAA,KACL,CAAA;AAAA,GACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,mBAAmB,QAA+B,EAAA;AACxD,IAAA,MAAM,EAAE,MAAA,EAAW,GAAA,IAAA,CAAK,cAAc,QAAQ,CAAA,CAAA;AAC9C,IAAM,MAAA,IAAA,GAAO,IAAK,CAAA,aAAA,CAAc,QAAQ,CAAA,CAAA;AAExC,IAAO,OAAA;AAAA,MACL,GAAG,IAAK,CAAA,uBAAA,CAAwB,QAAQ,CAAA;AAAA,MACxC,MAAA;AAAA,MACA,UAAA,EAAY,IAAK,CAAA,mBAAA,CAAoB,QAAQ,CAAA;AAAA,MAC7C,GAAI,IAAQ,IAAA,EAAE,IAAK,EAAA;AAAA,KACrB,CAAA;AAAA,GACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,qBAAqB,QAA+B,EAAA;AAC1D,IAAM,MAAA,YAAA,GAAe,IAAK,CAAA,eAAA,CAAgB,QAAQ,CAAA,CAAA;AAClD,IAAA,OAAO,YAAe,GAAA,mBAAA,CAAoB,YAAY,CAAA,GAAI,EAAC,CAAA;AAAA,GAC7D;AACF;;ACraA,SAAwB,sBACtB,IACsB,EAAA;AACtB,EAAO,OAAA;AAAA,IACL,UAAA,EAAY,CAAC,IAAI,CAAA;AAAA,GACnB,CAAA;AACF;;ACKA,MAAM,UAAA,GAAaJ,gCAAe,CAAC,CAAA,CAAA;AAQnB,SAAA,sBAAA,CACd,UACA,SACA,EAAA;AACA,EAAM,MAAA,UAAA,GAAa,qBAAsB,CAAA,QAAA,EAAU,SAAS,CAAA,CAAA;AAC5D,EAAM,MAAA,QAAA,GAAWC,6BAAY,UAAU,CAAA,CAAA;AAEvC,EAAM,MAAA,IAAA,GAAO,QAAS,CAAA,iBAAA,CAAkB,MAAM,CAAA,CAAA;AAE9C,EAAA,IAAI,IAAM,EAAA;AACR,IAAA,QAAA,CAAS,OAAO,IAAK,CAAA,EAAA;AAAA,MACnB,eAAA;AAAA,MACA,OAAO,QAAgB,QAAqB,KAAA;AAC1C,QAAM,MAAA,KAAA,GAAQO,uBAAO,CAAA,aAAA,EAAe,IAAI,CAAA,CAAA;AACxC,QAAM,MAAA,QAAA,CAAS,MAAM,KAAK,CAAA,CAAA;AAAA,OAC5B;AAAA,KACF,CAAA;AAAA,GACF;AACA,EAAO,OAAA,QAAA,CAAA;AACT,CAAA;AAQgB,SAAA,qBAAA,CACd,UACA,SACA,EAAA;AACA,EAAO,OAAA,mBAAA;AAAA,IACL,SAAS,GAAI,EAAA;AAAA,IACb;AAAA,MACE,UAAY,EAAA,qBAAA,CAAsB,QAAU,EAAA,CAAC,CAAC,SAAS,CAAA;AAAA,MACvD,gBAAkB,EAAA,IAAA;AAAA,KACpB;AAAA,IACA,SAAA;AAAA,GACF,CAAA;AACF,CAAA;AAQgB,SAAA,qBAAA,CACd,UACA,qBACkC,EAAA;AAClC,EAAM,MAAA,UAAA,GAAa,QAAS,CAAA,GAAA,CAAI,YAAY,CAAA,CAAA;AAC5C,EAAA,MAAM,kBACJ,GAAA,OAAO,UAAe,KAAA,QAAA,IAAY,UAAsB,YAAA,MAAA,CAAA;AAC1D,EAAM,MAAA,SAAA,GAAY,OAAO,qBAA0B,KAAA,SAAA,CAAA;AAEnD,EAAM,MAAA,2BAAA,GAA8B,SAChC,GAAA,kBAAA,GACA,qBAAyB,IAAA,kBAAA,CAAA;AAE7B,EAAO,OAAA,2BAAA,GACH,uBAAwB,CAAA,UAAoB,CAC5C,GAAA,UAAA,CAAA;AACN,CAAA;AAOO,SAAS,wBAAwB,gBAA0B,EAAA;AAChE,EAAA,MAAM,QAAQ,yBAA0B,EAAA,CAAA;AACxC,EAAA,OAAO,MAAM,gBAAgB,CAAA,CAAA;AAC/B,CAAA;AAEA,SAAS,yBAA4B,GAAA;AACnC,EAAI,IAAA;AACF,IAAO,OAAA,OAAA,CAAQ,sBAAsB,CAAE,CAAA,KAAA,CAAA;AAAA,WAChC,CAAG,EAAA;AACV,IAAM,MAAA,IAAIC,qBAAe,CAAA,0CAAA,EAA4C,CAAC,CAAA,CAAA;AAAA,GACxE;AACF,CAAA;AAQsB,eAAA,sBAAA,CACpB,aACG,SACH,EAAA;AACA,EAAM,MAAA,KAAA,GAAQ,uBAAuB,QAAU,EAAA;AAAA,IAC7C,UAAY,EAAA;AAAA,MACV,QAAU,EAAA,UAAA;AAAA,KACZ;AAAA,IACA,IAAM,EAAA;AAAA,MACJ,GAAK,EAAA,CAAA;AAAA,MACL,oBAAsB,EAAA,GAAA;AAAA,KACxB;AAAA,GACD,CAAA,CAAA;AAED,EAAI,IAAA;AACF,IAAM,MAAA,cAAA,GAAiB,OAAO,QAAqB,KAAA;AACjD,MAAM,MAAA,MAAA,GAAS,MAAM,KAAA,CAClB,IAAK,CAAA,aAAa,EAClB,KAAM,CAAA,SAAA,EAAW,QAAQ,CAAA,CACzB,KAAyC,EAAA,CAAA;AAE5C,MAAA,IAAI,SAAS,MAAO,CAAA,CAAC,EAAE,KAAO,EAAA,EAAE,IAAI,CAAG,EAAA;AACrC,QAAA,OAAA;AAAA,OACF;AAEA,MAAA,MAAM,KAAM,CAAA,GAAA,CAAI,CAAsB,kBAAA,CAAA,EAAA,CAAC,QAAQ,CAAC,CAAA,CAAA;AAAA,KAClD,CAAA;AAEA,IAAA,MAAM,OAAQ,CAAA,GAAA;AAAA,MACZ,SAAA,CAAU,GAAI,CAAA,OAAM,QAAY,KAAA;AAI9B,QAAA,IAAI,OAA6B,GAAA,KAAA,CAAA,CAAA;AACjC,QAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,CAAA,EAAG,CAAK,EAAA,EAAA;AAC1B,UAAI,IAAA;AACF,YAAA,OAAO,MAAM,UAAA,CAAW,MAAM,cAAA,CAAe,QAAQ,CAAC,CAAA,CAAA;AAAA,mBAC/C,GAAK,EAAA;AACZ,YAAU,OAAA,GAAA,GAAA,CAAA;AAAA,WACZ;AACA,UAAA,MAAM,IAAI,OAAQ,CAAA,CAAA,OAAA,KAAW,UAAW,CAAA,OAAA,EAAS,GAAG,CAAC,CAAA,CAAA;AAAA,SACvD;AACA,QAAM,MAAA,OAAA,CAAA;AAAA,OACP,CAAA;AAAA,KACH,CAAA;AAAA,GACA,SAAA;AACA,IAAA,MAAM,MAAM,OAAQ,EAAA,CAAA;AAAA,GACtB;AACF,CAAA;AAQsB,eAAA,oBAAA,CACpB,aACG,OACY,EAAA;AACf,EAAM,MAAA,KAAA,GAAQ,uBAAuB,QAAQ,CAAA,CAAA;AAC7C,EAAM,MAAA,IAAA,GAAO,QAAS,CAAA,iBAAA,CAAkB,MAAM,CAAA,CAAA;AAE9C,EAAI,IAAA;AACF,IAAM,MAAA,YAAA,GAAe,OAAO,QAAqB,KAAA;AAC/C,MAAA,IAAI,IAAM,EAAA;AACR,QAAM,MAAA,KAAA,CAAM,IAAI,CAAmD,+CAAA,CAAA,EAAA;AAAA,UACjE,QAAA;AAAA,UACA,IAAA;AAAA,SACD,CAAA,CAAA;AAAA,OACI,MAAA;AACL,QAAA,MAAM,KAAM,CAAA,GAAA,CAAI,CAAkC,8BAAA,CAAA,EAAA,CAAC,QAAQ,CAAC,CAAA,CAAA;AAAA,OAC9D;AAAA,KACF,CAAA;AAEA,IAAA,MAAM,OAAQ,CAAA,GAAA;AAAA,MACZ,OAAA,CAAQ,IAAI,CAAY,QAAA,KAAA,UAAA,CAAW,MAAM,YAAa,CAAA,QAAQ,CAAC,CAAC,CAAA;AAAA,KAClE,CAAA;AAAA,GACA,SAAA;AACA,IAAA,MAAM,MAAM,OAAQ,EAAA,CAAA;AAAA,GACtB;AACF,CAAA;AAQsB,eAAA,cAAA,CACpB,aACG,SACH,EAAA;AACA,EAAM,MAAA,KAAA,GAAQ,uBAAuB,QAAQ,CAAA,CAAA;AAC7C,EAAI,IAAA;AACF,IAAA,MAAM,OAAQ,CAAA,GAAA;AAAA,MACZ,SAAA,CAAU,GAAI,CAAA,OAAM,QAAY,KAAA;AAC9B,QAAM,MAAA,UAAA,CAAW,MAAM,KAAM,CAAA,GAAA,CAAI,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAA,CAAA;AAAA,OACjE,CAAA;AAAA,KACH,CAAA;AAAA,GACA,SAAA;AACA,IAAA,MAAM,MAAM,OAAQ,EAAA,CAAA;AAAA,GACtB;AACF,CAAA;AAKA,SAASL,aAAW,QAA0B,EAAA;AAC5C,EAAA,OAAO,UAAU,QAAQ,CAAA,CAAA,CAAA;AAC3B,CAAA;AAEA,SAASC,sBACP,UACsC,EAAA;AACtC,EAAA,IAAI,OAAO,UAAA,KAAe,WAAe,IAAA,UAAA,KAAe,IAAM,EAAA;AAC5D,IAAA,OAAO,EAAC,CAAA;AAAA,GACV;AAEA,EAAA,OAAO,OAAO,UAAe,KAAA,QAAA,IAAY,sBAAsB,MAC3D,GAAA,uBAAA,CAAwB,UAAoB,CAC5C,GAAA,UAAA,CAAA;AACN,CAAA;AAEO,MAAM,WAAiC,CAAA;AAAA,EAC5C,WAAA,CACmB,QACA,MACjB,EAAA;AAFiB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA,CAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA,CAAA;AAAA,GAChB;AAAA,EAEH,MAAM,SACJ,CAAA,QAAA,EACA,KAIe,EAAA;AACf,IAAA,MAAM,eAAe,IAAIC,mBAAA;AAAA,MACvB,IAAA,CAAK,mBAAmB,QAAQ,CAAA;AAAA,KAClC,CAAA;AAEA,IAAM,MAAA,YAAA,GAAe,IAAK,CAAA,eAAA,CAAgB,QAAQ,CAAA,CAAA;AAClD,IAAA,IAAI,YAAgB,IAAA,IAAA,CAAK,qBAAsB,CAAA,QAAQ,CAAG,EAAA;AACxD,MAAI,IAAA;AACF,QAAM,MAAA,sBAAA,CAAuB,cAAc,YAAY,CAAA,CAAA;AAAA,eAChD,KAAO,EAAA;AACd,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,qDAAA,EAAwD,YAAY,CAAA,UAAA,EAAa,KAAK,CAAA,CAAA;AAAA,SACxF,CAAA;AAAA,OACF;AAAA,KACF;AAEA,IAAI,IAAA,eAAA,CAAA;AACJ,IAAI,IAAA,IAAA,CAAK,2BAA4B,EAAA,KAAM,QAAU,EAAA;AACnD,MAAA,eAAA,GAAkB,sBAAsB,QAAQ,CAAA,CAAA;AAChD,MAAA,IACE,KAAK,2BAA4B,CAAA,QAAQ,KACzC,IAAK,CAAA,qBAAA,CAAsB,QAAQ,CACnC,EAAA;AACA,QAAI,IAAA;AACF,UAAM,MAAA,oBAAA,CAAqB,cAAc,QAAQ,CAAA,CAAA;AAAA,iBAC1C,KAAO,EAAA;AACd,UAAA,MAAM,IAAI,KAAA;AAAA,YACR,CAAA,uEAAA,EAA0E,QAAQ,CAAA,UAAA,EAAa,KAAK,CAAA,CAAA;AAAA,WACtG,CAAA;AAAA,SACF;AAAA,OACF;AAAA,KACF;AAEA,IAAA,MAAM,uBAA0B,GAAA,mBAAA;AAAA,MAC9B,EAAC;AAAA,MACD,IAAA,CAAK,qBAAqB,QAAQ,CAAA;AAAA,MAClC,eAAA;AAAA,KACF,CAAA;AAEA,IAAA,MAAM,MAAS,GAAA,sBAAA;AAAA,MACb,YAAA;AAAA,MACA,uBAAA;AAAA,KACF,CAAA;AAEA,IAAO,OAAA,MAAA,CAAA;AAAA,GACT;AAAA,EAEA,MAAM,gBAAgB,aAAwC,EAAA;AAC5D,IAAA,OAAO,MAAM,cAAA,CAAe,IAAK,CAAA,MAAA,EAAQ,GAAG,aAAa,CAAA,CAAA;AAAA,GAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcQ,gBAAgB,QAAsC,EAAA;AAC5D,IAAM,MAAA,UAAA,GAAa,IAAK,CAAA,mBAAA,CAAoB,QAAQ,CAAA,CAAA;AAEpD,IAAA,MAAM,eAAgB,UAAsC,EAAA,QAAA,CAAA;AAG5D,IAAI,IAAA,IAAA,CAAK,2BAA4B,EAAA,KAAM,QAAU,EAAA;AACnD,MAAO,OAAA,YAAA,CAAA;AAAA,KACT;AAGA,IAAA,OAAO,YAAgB,IAAA,CAAA,EAAG,IAAK,CAAA,MAAM,GAAG,QAAQ,CAAA,CAAA,CAAA;AAAA,GAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaQ,cAAc,QAGpB,EAAA;AACA,IAAM,MAAA,YAAA,GAAe,KAAK,MAAO,CAAA,iBAAA;AAAA,MAC/B,CAAA,EAAGF,YAAW,CAAA,QAAQ,CAAC,CAAA,OAAA,CAAA;AAAA,KACzB,CAAA;AAEA,IAAA,MAAM,UAAa,GAAA,IAAA,CAAK,MAAO,CAAA,SAAA,CAAU,QAAQ,CAAA,CAAA;AACjD,IAAA,MAAM,SAAS,YAAgB,IAAA,UAAA,CAAA;AAC/B,IAAO,OAAA;AAAA,MACL,MAAA;AAAA,MACA,YAAY,MAAW,KAAA,UAAA;AAAA,KACzB,CAAA;AAAA,GACF;AAAA,EAEQ,cAAc,QAAsC,EAAA;AAC1D,IAAA,OACE,IAAK,CAAA,MAAA,CAAO,iBAAkB,CAAA,CAAA,EAAGA,YAAW,CAAA,QAAQ,CAAC,CAAA,KAAA,CAAO,CAC5D,IAAA,IAAA,CAAK,MAAO,CAAA,iBAAA,CAAkB,MAAM,CAAA,CAAA;AAAA,GAExC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,wBAAwB,QAA0C,EAAA;AACxE,IAAM,MAAA,YAAA,GAAe,IAAK,CAAA,MAAA,CACvB,iBAAkB,CAAA,CAAA,EAAGA,aAAW,QAAQ,CAAC,CAAa,WAAA,CAAA,CAAA,EACrD,GAAgB,EAAA,CAAA;AAEpB,IAAA,MAAM,aAAa,IAAK,CAAA,MAAA,CACrB,iBAAkB,CAAA,YAAY,GAC7B,GAAgB,EAAA,CAAA;AAEpB,IAAO,OAAAN,YAAA,CAAM,YAAY,YAAY,CAAA,CAAA;AAAA,GACvC;AAAA,EAEQ,sBAAsB,QAA2B,EAAA;AACvD,IAAA,MAAM,UAAa,GAAA,IAAA,CAAK,MAAO,CAAA,kBAAA,CAAmB,cAAc,CAAK,IAAA,IAAA,CAAA;AACrE,IACE,OAAA,IAAA,CAAK,OAAO,kBAAmB,CAAA,CAAA,EAAGM,aAAW,QAAQ,CAAC,eAAe,CACrE,IAAA,UAAA,CAAA;AAAA,GAEJ;AAAA,EAEQ,4BAA4B,QAA2B,EAAA;AAC7D,IAAA,MAAM,UACJ,GAAA,IAAA,CAAK,MAAO,CAAA,kBAAA,CAAmB,oBAAoB,CAAK,IAAA,KAAA,CAAA;AAC1D,IAAA,OACE,KAAK,MAAO,CAAA,kBAAA;AAAA,MACV,CAAA,EAAGA,YAAW,CAAA,QAAQ,CAAC,CAAA,4BAAA,CAAA;AAAA,KACpB,IAAA,UAAA,CAAA;AAAA,GAET;AAAA,EAEQ,2BAAsC,GAAA;AAC5C,IAAA,OAAO,IAAK,CAAA,MAAA,CAAO,iBAAkB,CAAA,oBAAoB,CAAK,IAAA,UAAA,CAAA;AAAA,GAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYQ,oBAAoB,QAA+C,EAAA;AACzE,IAAA,MAAM,EAAE,UAAA,EAAe,GAAA,IAAA,CAAK,cAAc,QAAQ,CAAA,CAAA;AAElD,IAAA,IAAI,iBAAiBC,qBAAoB,CAAA,IAAA,CAAK,MAAO,CAAA,GAAA,CAAI,YAAY,CAAC,CAAA,CAAA;AAKtE,IAAI,IAAA,IAAA,CAAK,2BAA4B,EAAA,KAAM,QAAU,EAAA;AACnD,MAAiB,cAAA,GAAAE,WAAA,CAAK,gBAAgB,UAAU,CAAA,CAAA;AAAA,KAClD;AAGA,IAAA,MAAM,UAAa,GAAAF,qBAAA;AAAA,MACjB,KAAK,MAAO,CAAA,WAAA,CAAY,GAAGD,YAAW,CAAA,QAAQ,CAAC,CAAa,WAAA,CAAA,CAAA;AAAA,KAC9D,CAAA;AAEA,IACE,cAAA,CACA,gBAAqB,KAAA,CAAA,iBAAA,EAAoB,QAAQ,CAAA,CAAA,CAAA;AAEnD,IAAO,OAAA;AAAA;AAAA,MAEL,GAAI,UAAa,GAAA,EAAK,GAAA,cAAA;AAAA,MACtB,GAAG,UAAA;AAAA,KACL,CAAA;AAAA,GACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,mBAAmB,QAA+B,EAAA;AACxD,IAAA,MAAM,EAAE,MAAA,EAAW,GAAA,IAAA,CAAK,cAAc,QAAQ,CAAA,CAAA;AAC9C,IAAM,MAAA,IAAA,GAAO,IAAK,CAAA,aAAA,CAAc,QAAQ,CAAA,CAAA;AAExC,IAAO,OAAA;AAAA,MACL,GAAG,IAAK,CAAA,uBAAA,CAAwB,QAAQ,CAAA;AAAA,MACxC,MAAA;AAAA,MACA,UAAA,EAAY,IAAK,CAAA,mBAAA,CAAoB,QAAQ,CAAA;AAAA,MAC7C,GAAI,IAAQ,IAAA,EAAE,IAAK,EAAA;AAAA,KACrB,CAAA;AAAA,GACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,qBAAqB,QAA+B,EAAA;AAC1D,IAAM,MAAA,YAAA,GAAe,IAAK,CAAA,eAAA,CAAgB,QAAQ,CAAA,CAAA;AAClD,IAAA,OAAO,YAAe,GAAA,mBAAA,CAAoB,YAAY,CAAA,GAAI,EAAC,CAAA;AAAA,GAC7D;AACF;;AClcgB,SAAA,0BAAA,CACd,QACA,EAAA,SAAA,EACA,IAIA,EAAA;AACA,EAAM,MAAA,UAAA,GAAa,yBAA0B,CAAA,QAAA,EAAU,SAAS,CAAA,CAAA;AAChE,EAAA,MAAM,aAAa,UAAW,CAAA,UAAA,CAAA;AAE9B,EAAM,MAAA,QAAA,GAAW,WAAW,QAAY,IAAA,UAAA,CAAA;AAGxC,EAAA,IAAI,aAAa,UAAY,EAAA;AAC3B,IAAM,MAAA,SAAA,GAAYM,6BAAK,CAAA,OAAA,CAAQ,QAAQ,CAAA,CAAA;AACvC,IAAAC,gBAAA,CAAc,SAAS,CAAA,CAAA;AAAA,GACzB;AAEA,EAAI,IAAA,QAAA,CAAA;AAEJ,EAAI,IAAA,IAAA,IAAQ,aAAa,UAAY,EAAA;AAInC,IAAM,MAAA,QAAA,GAAWC,6BAAa,GAAI,EAAA,CAAA;AAElC,IAAA,IAAI,QAAU,EAAA;AACZ,MAAA,MAAM,OAAU,GAAA,CAAA,WAAA,EAAc,IAAK,CAAA,cAAA,CAAe,OAAO,CAAA,CAAA,CAAA;AAEzD,MAAA,MAAM,mBAAmB,YAAY;AAEnC,QAAA,MAAM,EAAE,IAAM,EAAA,QAAA,KAAa,MAAM,QAAA,CAAS,KAAK,OAAO,CAAA,CAAA;AAEtD,QAAO,OAAA;AAAA,UACL,GAAI,UAAW,CAAA,UAAA;AAAA,UACf,UAAU,QAAY,IAAA,UAAA;AAAA,SACxB,CAAA;AAAA,OACF,CAAA;AAEA,MAAA,QAAA,GAAWX,4BAAY,CAAA;AAAA,QACrB,GAAG,UAAA;AAAA,QACH,UAAA,EAAY,MAAO,CAAA,MAAA,CAAO,gBAAkB,EAAA;AAAA;AAAA,UAE1C,QAAU,EAAA,UAAA;AAAA,SACX,CAAA;AAAA,OACF,CAAA,CAAA;AAGD,MAAK,IAAA,CAAA,SAAA,CAAU,gBAAgB,YAAY;AACzC,QAAA,MAAM,UAAa,GAAA,MAAM,QAAS,CAAA,MAAA,CAAO,iBAAkB,EAAA,CAAA;AAC3D,QAAM,MAAA,IAAA,GAAO,WAAW,SAAU,EAAA,CAAA;AAClC,QAAM,MAAA,QAAA,CAAS,IAAK,CAAA,OAAA,EAAS,IAAI,CAAA,CAAA;AAAA,OAClC,CAAA,CAAA;AAAA,KACI,MAAA;AACL,MAAA,QAAA,GAAWA,6BAAY,UAAU,CAAA,CAAA;AAAA,KACnC;AAAA,GACK,MAAA;AACL,IAAA,QAAA,GAAWA,6BAAY,UAAU,CAAA,CAAA;AAAA,GACnC;AAEA,EAAA,QAAA,CAAS,OAAO,IAAK,CAAA,EAAA,CAAG,eAAiB,EAAA,CAAC,UAAe,QAAkB,KAAA;AACzE,IAAS,QAAA,CAAA,GAAA,CAAI,4BAA4B,MAAM;AAAA,KAAE,CAAA,CAAA;AAAA,GAClD,CAAA,CAAA;AAED,EAAO,OAAA,QAAA,CAAA;AACT,CAAA;AAQgB,SAAA,yBAAA,CACd,UACA,SACa,EAAA;AACb,EAAM,MAAA,UAAA,GAAa,SAAS,GAAiB,EAAA,CAAA;AAG7C,EAAI,IAAA,OAAO,UAAW,CAAA,UAAA,KAAe,QAAU,EAAA;AAC7C,IAAA,UAAA,CAAW,UAAa,GAAA,EAAE,QAAU,EAAA,UAAA,CAAW,UAAW,EAAA,CAAA;AAAA,GAC5D;AACA,EAAA,IAAI,SAAa,IAAA,OAAO,SAAU,CAAA,UAAA,KAAe,QAAU,EAAA;AACzD,IAAA,SAAA,CAAU,UAAa,GAAA,EAAE,QAAU,EAAA,SAAA,CAAU,UAAW,EAAA,CAAA;AAAA,GAC1D;AAEA,EAAA,MAAM,MAAsB,GAAA,mBAAA;AAAA,IAC1B;AAAA,MACE,YAAY,EAAC;AAAA,KACf;AAAA,IACA,UAAA;AAAA,IACA;AAAA,MACE,gBAAkB,EAAA,IAAA;AAAA,KACpB;AAAA,IACA,SAAA;AAAA,GACF,CAAA;AAEA,EAAO,OAAA,MAAA,CAAA;AACT,CAAA;AAKO,SAAS,yBAAyB,IAAoC,EAAA;AAC3E,EAAO,OAAA;AAAA,IACL,UAAA,EAAY,4BAA4B,IAAI,CAAA;AAAA,GAC9C,CAAA;AACF,CAAA;AAKO,SAAS,4BACd,IAC8B,EAAA;AAC9B,EAAO,OAAA;AAAA,IACL,QAAU,EAAA,IAAA;AAAA,GACZ,CAAA;AACF,CAAA;AAKA,SAASG,aAAW,QAA0B,EAAA;AAC5C,EAAA,OAAO,UAAU,QAAQ,CAAA,CAAA,CAAA;AAC3B,CAAA;AAEA,SAAS,oBACP,UACsC,EAAA;AACtC,EAAA,IAAI,OAAO,UAAA,KAAe,WAAe,IAAA,UAAA,KAAe,IAAM,EAAA;AAC5D,IAAA,OAAO,EAAC,CAAA;AAAA,GACV;AAEA,EAAA,OAAO,OAAO,UAAe,KAAA,QAAA,IAAY,sBAAsB,MAC3D,GAAA,2BAAA,CAA4B,UAAoB,CAChD,GAAA,UAAA,CAAA;AACN,CAAA;AAEO,MAAM,gBAAsC,CAAA;AAAA,EACjD,YAA6B,MAAgB,EAAA;AAAhB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA,CAAA;AAAA,GAAiB;AAAA,EAE9C,MAAM,SACJ,CAAA,QAAA,EACA,IAIe,EAAA;AACf,IAAA,MAAM,eAAe,IAAIE,mBAAA;AAAA,MACvB,IAAA,CAAK,mBAAmB,QAAQ,CAAA;AAAA,KAClC,CAAA;AAEA,IAAM,MAAA,kBAAA,GAAqB,KAAK,2BAA4B,EAAA,CAAA;AAC5D,IAAA,IAAI,uBAAuB,UAAY,EAAA;AACrC,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,4DAA4D,kBAAkB,CAAA,CAAA,CAAA;AAAA,OAChF,CAAA;AAAA,KACF;AAEA,IAAA,MAAM,uBAA0B,GAAA,mBAAA;AAAA,MAC9B,EAAC;AAAA,MACD,IAAA,CAAK,qBAAqB,QAAQ,CAAA;AAAA,KACpC,CAAA;AAEA,IAAA,MAAM,MAAS,GAAA,0BAAA;AAAA,MACb,YAAA;AAAA,MACA,uBAAA;AAAA,MACA,IAAA;AAAA,KACF,CAAA;AAEA,IAAO,OAAA,MAAA,CAAA;AAAA,GACT;AAAA,EAEA,MAAM,gBAAgB,cAAyC,EAAA;AAAA,GAE/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcQ,gBAAgB,QAAsC,EAAA;AAC5D,IAAM,MAAA,UAAA,GAAa,IAAK,CAAA,mBAAA,CAAoB,QAAQ,CAAA,CAAA;AAEpD,IAAA,MAAM,iBACJ,UACA,CAAA,QAAA,CAAA;AAEF,IAAA,IAAI,mBAAmB,UAAY,EAAA;AACjC,MAAO,OAAA,cAAA,CAAA;AAAA,KACT;AAEA,IAAM,MAAA,eAAA,GACH,WAAsC,SAAa,IAAA,GAAA,CAAA;AAEtD,IAAA,OAAOI,8BAAK,IAAK,CAAA,eAAA,EAAiB,cAAkB,IAAA,CAAA,EAAG,QAAQ,CAAS,OAAA,CAAA,CAAA,CAAA;AAAA,GAC1E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaQ,cAAc,QAGpB,EAAA;AACA,IAAM,MAAA,YAAA,GAAe,KAAK,MAAO,CAAA,iBAAA;AAAA,MAC/B,CAAA,EAAGN,YAAW,CAAA,QAAQ,CAAC,CAAA,OAAA,CAAA;AAAA,KACzB,CAAA;AAEA,IAAA,MAAM,UAAa,GAAA,IAAA,CAAK,MAAO,CAAA,SAAA,CAAU,QAAQ,CAAA,CAAA;AACjD,IAAA,MAAM,SAAS,YAAgB,IAAA,UAAA,CAAA;AAC/B,IAAO,OAAA;AAAA,MACL,MAAA;AAAA,MACA,YAAY,MAAW,KAAA,UAAA;AAAA,KACzB,CAAA;AAAA,GACF;AAAA,EAEQ,cAAc,QAAsC,EAAA;AAC1D,IAAA,OACE,IAAK,CAAA,MAAA,CAAO,iBAAkB,CAAA,CAAA,EAAGA,YAAW,CAAA,QAAQ,CAAC,CAAA,KAAA,CAAO,CAC5D,IAAA,IAAA,CAAK,MAAO,CAAA,iBAAA,CAAkB,MAAM,CAAA,CAAA;AAAA,GAExC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,wBAAwB,QAA0C,EAAA;AACxE,IAAM,MAAA,YAAA,GAAe,IAAK,CAAA,MAAA,CACvB,iBAAkB,CAAA,CAAA,EAAGA,aAAW,QAAQ,CAAC,CAAa,WAAA,CAAA,CAAA,EACrD,GAAgB,EAAA,CAAA;AAEpB,IAAA,MAAM,aAAa,IAAK,CAAA,MAAA,CACrB,iBAAkB,CAAA,YAAY,GAC7B,GAAgB,EAAA,CAAA;AAEpB,IAAO,OAAAN,YAAA,CAAM,YAAY,YAAY,CAAA,CAAA;AAAA,GACvC;AAAA,EAEQ,2BAAsC,GAAA;AAC5C,IAAA,OAAO,IAAK,CAAA,MAAA,CAAO,iBAAkB,CAAA,oBAAoB,CAAK,IAAA,UAAA,CAAA;AAAA,GAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaQ,oBAAoB,QAA+C,EAAA;AACzE,IAAA,MAAM,EAAE,MAAQ,EAAA,UAAA,EAAe,GAAA,IAAA,CAAK,cAAc,QAAQ,CAAA,CAAA;AAE1D,IAAA,IAAI,iBAAiB,mBAAoB,CAAA,IAAA,CAAK,MAAO,CAAA,GAAA,CAAI,YAAY,CAAC,CAAA,CAAA;AAEtE,IACE,IAAA,MAAA,CAAO,SAAS,SAAS,CAAA,IACzB,cAAc,cACd,IAAA,cAAA,CAAe,aAAa,UAC5B,EAAA;AACA,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,+JAAA;AAAA,OACF,CAAA;AAAA,KACF;AAMA,IAAI,IAAA,IAAA,CAAK,2BAA4B,EAAA,KAAM,QAAU,EAAA;AACnD,MAAiB,cAAA,GAAAS,WAAA,CAAK,gBAAgB,UAAU,CAAA,CAAA;AAAA,KAClD;AAGA,IAAA,MAAM,UAAa,GAAA,mBAAA;AAAA,MACjB,KAAK,MAAO,CAAA,WAAA,CAAY,GAAGH,YAAW,CAAA,QAAQ,CAAC,CAAa,WAAA,CAAA,CAAA;AAAA,KAC9D,CAAA;AAEA,IAAO,OAAA;AAAA;AAAA,MAEL,GAAI,UAAa,GAAA,EAAK,GAAA,cAAA;AAAA,MACtB,GAAG,UAAA;AAAA,KACL,CAAA;AAAA,GACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,mBAAmB,QAA+B,EAAA;AACxD,IAAA,MAAM,EAAE,MAAA,EAAW,GAAA,IAAA,CAAK,cAAc,QAAQ,CAAA,CAAA;AAC9C,IAAM,MAAA,IAAA,GAAO,IAAK,CAAA,aAAA,CAAc,QAAQ,CAAA,CAAA;AAExC,IAAO,OAAA;AAAA,MACL,GAAG,IAAK,CAAA,uBAAA,CAAwB,QAAQ,CAAA;AAAA,MACxC,MAAA;AAAA,MACA,UAAA,EAAY,IAAK,CAAA,mBAAA,CAAoB,QAAQ,CAAA;AAAA,MAC7C,GAAI,IAAQ,IAAA,EAAE,IAAK,EAAA;AAAA,KACrB,CAAA;AAAA,GACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,qBAAqB,QAA+B,EAAA;AAC1D,IAAM,MAAA,YAAA,GAAe,IAAK,CAAA,eAAA,CAAgB,QAAQ,CAAA,CAAA;AAClD,IAAA,OAAO,YAAe,GAAA,wBAAA,CAAyB,YAAY,CAAA,GAAI,EAAC,CAAA;AAAA,GAClE;AACF;;ACxVA,SAAS,WAAW,QAA0B,EAAA;AAC5C,EAAA,OAAO,UAAU,QAAQ,CAAA,CAAA,CAAA;AAC3B,CAAA;AAuBO,MAAM,mBAAyD,CAAA;AAAA,EACpE,YACmB,MACA,EAAA,UAAA,EACA,SACA,aAA4C,mBAAA,IAAI,KACjE,EAAA;AAJiB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA,CAAA;AACA,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA,CAAA;AACA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA,CAAA;AACA,IAAA,IAAA,CAAA,aAAA,GAAA,aAAA,CAAA;AAAA,GAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASH,SAAA,CACE,UACA,IAIuB,EAAA;AACvB,IAAA,MAAM,MAAS,GAAA,IAAA,CAAK,aAAc,CAAA,QAAQ,CAAE,CAAA,MAAA,CAAA;AAC5C,IAAM,MAAA,SAAA,GAAY,IAAK,CAAA,UAAA,CAAW,MAAM,CAAA,CAAA;AACxC,IAAA,IAAI,CAAC,SAAW,EAAA;AACd,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,kCAAA,EAAqC,MAAM,CAAA,wBAAA,EAA2B,QAAQ,CAAA,CAAA,CAAA;AAAA,OAChF,CAAA;AAAA,KACF;AACA,IAAA,MAAM,YAAY,MAAM,IAAA,CAAK,WAAY,CAAA,QAAA,EAAU,WAAW,IAAI,CAAA,CAAA;AAElE,IAAA,MAAM,OACJ,IAAK,CAAA,OAAA,EAAS,UAAY,EAAA,IAAA,IAC1B,KAAK,MAAO,CAAA,kBAAA;AAAA,MACV,2BAA2B,QAAQ,CAAA,eAAA,CAAA;AAAA,KAErC,IAAA,IAAA,CAAK,MAAO,CAAA,kBAAA,CAAmB,iCAAiC,CAChE,IAAA,KAAA,CAAA;AAEF,IAAA,OAAO,EAAE,SAAA,EAAW,UAAY,EAAA,EAAE,MAAO,EAAA,CAAA;AAAA,GAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaQ,cAAc,QAGpB,EAAA;AACA,IAAM,MAAA,YAAA,GAAe,KAAK,MAAO,CAAA,iBAAA;AAAA,MAC/B,CAAA,EAAG,UAAW,CAAA,QAAQ,CAAC,CAAA,OAAA,CAAA;AAAA,KACzB,CAAA;AAEA,IAAA,MAAM,UAAa,GAAA,IAAA,CAAK,MAAO,CAAA,SAAA,CAAU,QAAQ,CAAA,CAAA;AACjD,IAAA,MAAM,SAAS,YAAgB,IAAA,UAAA,CAAA;AAC/B,IAAO,OAAA;AAAA,MACL,MAAA;AAAA,MACA,YAAY,MAAW,KAAA,UAAA;AAAA,KACzB,CAAA;AAAA,GACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,WAAA,CACZ,QACA,EAAA,SAAA,EACA,IAIe,EAAA;AACf,IAAA,IAAI,IAAK,CAAA,aAAA,CAAc,GAAI,CAAA,QAAQ,CAAG,EAAA;AACpC,MAAO,OAAA,IAAA,CAAK,aAAc,CAAA,GAAA,CAAI,QAAQ,CAAA,CAAA;AAAA,KACxC;AAEA,IAAA,MAAM,aAAgB,GAAA,SAAA,CAAU,SAAU,CAAA,QAAA,EAAU,IAAI,CAAA,CAAA;AACxD,IAAK,IAAA,CAAA,aAAA,CAAc,GAAI,CAAA,QAAA,EAAU,aAAa,CAAA,CAAA;AAE9C,IAAI,IAAA,OAAA,CAAQ,GAAI,CAAA,QAAA,KAAa,MAAQ,EAAA;AACnC,MAAA,aAAA,CAAc,KAAK,CAAU,MAAA,KAAA,IAAA,CAAK,kBAAmB,CAAA,QAAA,EAAU,MAAM,CAAC,CAAA,CAAA;AAAA,KACxE;AAEA,IAAO,OAAA,aAAA,CAAA;AAAA,GACT;AAAA,EAEQ,kBAAA,CAAmB,UAAkB,MAAoB,EAAA;AAC/D,IAAA,IAAI,mBAAsB,GAAA,KAAA,CAAA;AAE1B,IAAA,WAAA,CAAY,MAAM;AAGhB,MAAQ,MAAA,EAAA,GAAA,CAAI,UAAU,CAAE,CAAA,IAAA;AAAA,QACtB,MAAM;AACJ,UAAsB,mBAAA,GAAA,KAAA,CAAA;AAAA,SACxB;AAAA,QACA,CAAC,KAAmB,KAAA;AAClB,UAAA,IAAI,CAAC,mBAAqB,EAAA;AACxB,YAAsB,mBAAA,GAAA,IAAA,CAAA;AACtB,YAAA,IAAA,CAAK,SAAS,MAAQ,EAAA,IAAA;AAAA,cACpB,CAAA,qCAAA,EAAwC,QAAQ,CAAK,EAAA,EAAAS,qBAAA;AAAA,gBACnD,KAAA;AAAA,eACD,CAAA,CAAA;AAAA,aACH,CAAA;AAAA,WACF;AAAA,SACF;AAAA,OACF,CAAA;AAAA,KACF,EAAG,KAAK,GAAI,CAAA,CAAA;AAAA,GACd;AACF,CAAA;AAeO,MAAM,eAAqD,CAAA;AAAA,EA6BxD,YAA6B,IAA2B,EAAA;AAA3B,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA,CAAA;AAAA,GAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAtBjE,OAAO,UACL,CAAA,MAAA,EACA,OACiB,EAAA;AACjB,IAAM,MAAA,cAAA,GAAiB,MAAO,CAAA,SAAA,CAAU,kBAAkB,CAAA,CAAA;AAC1D,IAAA,MAAM,MACJ,GAAA,cAAA,CAAe,iBAAkB,CAAA,QAAQ,CAAK,IAAA,mBAAA,CAAA;AAChD,IAAA,OAAO,IAAI,eAAA;AAAA,MACT,IAAI,mBAAA;AAAA,QACF,cAAA;AAAA,QACA;AAAA,UACE,EAAI,EAAA,IAAI,WAAY,CAAA,cAAA,EAAgB,MAAM,CAAA;AAAA,UAC1C,OAAA,EAAS,IAAI,gBAAA,CAAiB,cAAc,CAAA;AAAA,UAC5C,gBAAA,EAAkB,IAAI,gBAAA,CAAiB,cAAc,CAAA;AAAA,UACrD,KAAO,EAAA,IAAI,cAAe,CAAA,cAAA,EAAgB,MAAM,CAAA;AAAA,UAChD,MAAQ,EAAA,IAAI,cAAe,CAAA,cAAA,EAAgB,MAAM,CAAA;AAAA,SACnD;AAAA,QACA,OAAA;AAAA,OACF;AAAA,KACF,CAAA;AAAA,GACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,SAAA,CACE,UACA,IAIuB,EAAA;AACvB,IAAA,OAAO,IAAK,CAAA,IAAA,CAAK,SAAU,CAAA,QAAA,EAAU,IAAI,CAAA,CAAA;AAAA,GAC3C;AACF,CAAA;AAQsB,eAAA,YAAA,CACpB,aACG,aACY,EAAA;AACf,EAAM,MAAA,MAAA,GAAS,QAAS,CAAA,SAAA,CAAU,QAAQ,CAAA,CAAA;AAC1C,EAAA,MAAM,MAAS,GAAA,QAAA,CAAS,iBAAkB,CAAA,QAAQ,CAAK,IAAA,mBAAA,CAAA;AAEvD,EAAA,IAAI,WAAW,IAAM,EAAA;AACnB,IAAA,MAAM,IAAI,WAAY,CAAA,QAAA,EAAU,MAAM,CAAE,CAAA,YAAA,CAAa,GAAG,aAAa,CAAA,CAAA;AAAA,GAC5D,MAAA,IAAA,MAAA,KAAW,OAAW,IAAA,MAAA,KAAW,QAAU,EAAA;AACpD,IAAA,MAAM,IAAI,cAAe,CAAA,QAAA,EAAU,MAAM,CAAE,CAAA,YAAA,CAAa,GAAG,aAAa,CAAA,CAAA;AAAA,GAC1E;AACF;;ACrOO,MAAM,yBAAyBC,qCAAqB,CAAA;AAAA,EACzD,SAASC,6BAAa,CAAA,QAAA;AAAA,EACtB,IAAM,EAAA;AAAA,IACJ,QAAQA,6BAAa,CAAA,UAAA;AAAA,IACrB,WAAWA,6BAAa,CAAA,SAAA;AAAA,IACxB,gBAAgBA,6BAAa,CAAA,cAAA;AAAA,GAC/B;AAAA,EACA,MAAM,iBAAA,CAAkB,UAAEC,QAAA,EAAU,EAAA;AAClC,IAAO,OAAAA,QAAA,CAAO,YAAY,kBAAkB,CAAA,GACxC,gBAAgB,UAAW,CAAAA,QAAM,IACjC,eAAgB,CAAA,UAAA;AAAA,MACd,IAAIV,mBAAa,CAAA;AAAA,QACf,OAAS,EAAA;AAAA,UACP,QAAU,EAAA,EAAE,MAAQ,EAAA,gBAAA,EAAkB,YAAY,UAAW,EAAA;AAAA,SAC/D;AAAA,OACD,CAAA;AAAA,KACH,CAAA;AAAA,GACN;AAAA,EACA,MAAM,OAAQ,CAAA,EAAE,cAAgB,EAAA,SAAA,IAAa,eAAiB,EAAA;AAC5D,IAAA,OAAO,eAAgB,CAAA,SAAA,CAAU,cAAe,CAAA,KAAA,EAAS,EAAA;AAAA,MACvD,cAAA;AAAA,MACA,SAAA;AAAA,KACD,CAAA,CAAA;AAAA,GACH;AACF,CAAC;;;;;;"}
|
package/dist/database.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { Config } from '@backstage/config';
|
|
|
11
11
|
*
|
|
12
12
|
* @public
|
|
13
13
|
*/
|
|
14
|
-
declare const databaseServiceFactory: _backstage_backend_plugin_api.
|
|
14
|
+
declare const databaseServiceFactory: _backstage_backend_plugin_api.ServiceFactory<_backstage_backend_plugin_api.DatabaseService, "plugin", "singleton">;
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Creation options for {@link DatabaseManager}.
|
package/dist/discovery.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { Config } from '@backstage/config';
|
|
|
11
11
|
*
|
|
12
12
|
* @public
|
|
13
13
|
*/
|
|
14
|
-
declare const discoveryServiceFactory: _backstage_backend_plugin_api.
|
|
14
|
+
declare const discoveryServiceFactory: _backstage_backend_plugin_api.ServiceFactory<_backstage_backend_plugin_api.DiscoveryService, "plugin", "singleton">;
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* HostDiscovery is a basic PluginEndpointDiscovery implementation
|
package/dist/httpAuth.d.ts
CHANGED
|
@@ -10,6 +10,6 @@ import { HttpAuthService } from '@backstage/backend-plugin-api';
|
|
|
10
10
|
*
|
|
11
11
|
* @public
|
|
12
12
|
*/
|
|
13
|
-
declare const httpAuthServiceFactory: _backstage_backend_plugin_api.
|
|
13
|
+
declare const httpAuthServiceFactory: _backstage_backend_plugin_api.ServiceFactory<HttpAuthService, "plugin", "singleton">;
|
|
14
14
|
|
|
15
15
|
export { httpAuthServiceFactory };
|
package/dist/httpRouter.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { RequestHandler } from 'express';
|
|
|
12
12
|
*
|
|
13
13
|
* @public
|
|
14
14
|
*/
|
|
15
|
-
declare const httpRouterServiceFactory: _backstage_backend_plugin_api.
|
|
15
|
+
declare const httpRouterServiceFactory: _backstage_backend_plugin_api.ServiceFactory<_backstage_backend_plugin_api.HttpRouterService, "plugin", "singleton">;
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Options for {@link createLifecycleMiddleware}.
|