@backstage/backend-test-utils 1.11.4-next.1 → 1.11.4

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 CHANGED
@@ -1,5 +1,19 @@
1
1
  # @backstage/backend-test-utils
2
2
 
3
+ ## 1.11.4
4
+
5
+ ### Patch Changes
6
+
7
+ - 2e895ea: Internal refactor.
8
+ - 2d181c0: Increased MySQL connection and pool timeouts to reduce flaky `connect ETIMEDOUT` failures in CI. The test MySQL container now also uses `mysql_native_password` for cheaper connection handshakes and disables binary logging.
9
+ - 06a2035: Updated `MockActionsRegistry` to support the new secrets schema. The mock now validates secrets against the declared schema, rejects missing secrets for actions that require them, and forwards secrets to the action handler.
10
+ - Updated dependencies
11
+ - @backstage/backend-defaults@0.17.3
12
+ - @backstage/backend-app-api@1.7.1
13
+ - @backstage/backend-plugin-api@1.9.2
14
+ - @backstage/plugin-auth-node@0.7.2
15
+ - @backstage/plugin-events-node@0.4.23
16
+
3
17
  ## 1.11.4-next.1
4
18
 
5
19
  ### Patch Changes
@@ -18,7 +18,9 @@ function createPluginMetadataServiceFactory(pluginId) {
18
18
  return backendPluginApi.createServiceFactory({
19
19
  service: backendPluginApi.coreServices.pluginMetadata,
20
20
  deps: {},
21
- factory: async () => ({ getId: () => pluginId })
21
+ factory: async () => ({
22
+ getId: () => pluginId
23
+ })
22
24
  });
23
25
  }
24
26
  class ServiceRegistry {
@@ -1 +1 @@
1
- {"version":3,"file":"ServiceRegistry.cjs.js","sources":["../../../../../backend-app-api/src/wiring/ServiceRegistry.ts"],"sourcesContent":["/*\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 ServiceFactory,\n ServiceRef,\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { ConflictError, stringifyError } from '@backstage/errors';\n// Direct internal import to avoid duplication\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { InternalServiceFactory } from '../../../backend-plugin-api/src/services/system/types';\nimport { DependencyGraph } from '../lib/DependencyGraph';\n/**\n * Keep in sync with `@backstage/backend-plugin-api/src/services/system/types.ts`\n * @internal\n */\nexport type InternalServiceRef = ServiceRef<unknown> & {\n __defaultFactory?: (\n service: ServiceRef<unknown>,\n ) => Promise<ServiceFactory | (() => ServiceFactory)>;\n};\n\nfunction toInternalServiceFactory<TService, TScope extends 'plugin' | 'root'>(\n factory: ServiceFactory<TService, TScope>,\n): InternalServiceFactory<TService, TScope> {\n const f = factory as InternalServiceFactory<TService, TScope>;\n if (f.$$type !== '@backstage/BackendFeature') {\n throw new Error(`Invalid service factory, bad type '${f.$$type}'`);\n }\n if (f.version !== 'v1') {\n throw new Error(`Invalid service factory, bad version '${f.version}'`);\n }\n return f;\n}\n\nfunction createPluginMetadataServiceFactory(pluginId: string) {\n return createServiceFactory({\n service: coreServices.pluginMetadata,\n deps: {},\n factory: async () => ({ getId: () => pluginId }),\n });\n}\n\nexport class ServiceRegistry {\n static create(factories: Array<ServiceFactory>): ServiceRegistry {\n const factoryMap = new Map<string, InternalServiceFactory[]>();\n for (const factory of factories) {\n if (factory.service.multiton) {\n const existing = factoryMap.get(factory.service.id) ?? [];\n factoryMap.set(\n factory.service.id,\n existing.concat(toInternalServiceFactory(factory)),\n );\n } else {\n factoryMap.set(factory.service.id, [toInternalServiceFactory(factory)]);\n }\n }\n const registry = new ServiceRegistry(factoryMap);\n registry.checkForCircularDeps();\n return registry;\n }\n\n readonly #providedFactories: Map<string, InternalServiceFactory[]>;\n readonly #loadedDefaultFactories: Map<\n Function,\n Promise<InternalServiceFactory>\n >;\n readonly #implementations: Map<\n InternalServiceFactory,\n {\n context: Promise<unknown>;\n byPlugin: Map<string, Promise<unknown>>;\n }\n >;\n readonly #rootServiceImplementations = new Map<\n InternalServiceFactory,\n Promise<unknown>\n >();\n readonly #addedFactoryIds = new Set<string>();\n readonly #instantiatedFactories = new Set<string>();\n\n private constructor(factories: Map<string, InternalServiceFactory[]>) {\n this.#providedFactories = factories;\n this.#loadedDefaultFactories = new Map();\n this.#implementations = new Map();\n }\n\n #resolveFactory(\n ref: ServiceRef<unknown>,\n pluginId: string,\n ): Promise<InternalServiceFactory[]> | undefined {\n // Special case handling of the plugin metadata service, generating a custom factory for it each time\n if (ref.id === coreServices.pluginMetadata.id) {\n return Promise.resolve([\n toInternalServiceFactory(createPluginMetadataServiceFactory(pluginId)),\n ]);\n }\n\n let resolvedFactory:\n | Promise<InternalServiceFactory[]>\n | InternalServiceFactory[]\n | undefined = this.#providedFactories.get(ref.id);\n const { __defaultFactory: defaultFactory } = ref as InternalServiceRef;\n if (!resolvedFactory && !defaultFactory) {\n return undefined;\n }\n\n if (!resolvedFactory) {\n let loadedFactory = this.#loadedDefaultFactories.get(defaultFactory!);\n if (!loadedFactory) {\n loadedFactory = Promise.resolve()\n .then(() => defaultFactory!(ref))\n .then(f =>\n toInternalServiceFactory(typeof f === 'function' ? f() : f),\n );\n this.#loadedDefaultFactories.set(defaultFactory!, loadedFactory);\n }\n resolvedFactory = loadedFactory.then(\n factory => [factory],\n error => {\n throw new Error(\n `Failed to instantiate service '${\n ref.id\n }' because the default factory loader threw an error, ${stringifyError(\n error,\n )}`,\n );\n },\n );\n }\n\n return Promise.resolve(resolvedFactory);\n }\n\n #checkForMissingDeps(factory: InternalServiceFactory, pluginId: string) {\n const missingDeps = Object.values(factory.deps).filter(ref => {\n if (ref.id === coreServices.pluginMetadata.id) {\n return false;\n }\n if (this.#providedFactories.get(ref.id)) {\n return false;\n }\n if (ref.multiton) {\n return false;\n }\n\n return !(ref as InternalServiceRef).__defaultFactory;\n });\n\n if (missingDeps.length) {\n const missing = missingDeps.map(r => `'${r.id}'`).join(', ');\n throw new Error(\n `Failed to instantiate service '${factory.service.id}' for '${pluginId}' because the following dependent services are missing: ${missing}`,\n );\n }\n }\n\n checkForCircularDeps(): void {\n const graph = DependencyGraph.fromIterable(\n Array.from(this.#providedFactories).map(([serviceId, factories]) => ({\n value: serviceId,\n provides: [serviceId],\n consumes: factories.flatMap(factory =>\n Object.values(factory.deps).map(d => d.id),\n ),\n })),\n );\n const circularDependencies = Array.from(graph.detectCircularDependencies());\n\n if (circularDependencies.length) {\n const cycles = circularDependencies\n .map(c => c.map(id => `'${id}'`).join(' -> '))\n .join('\\n ');\n\n throw new ConflictError(`Circular dependencies detected:\\n ${cycles}`);\n }\n }\n\n hasBeenAdded(ref: ServiceRef<any>) {\n if (ref.id === coreServices.pluginMetadata.id) {\n return true;\n }\n return this.#addedFactoryIds.has(ref.id);\n }\n\n add(factory: ServiceFactory) {\n const factoryId = factory.service.id;\n if (factoryId === coreServices.pluginMetadata.id) {\n throw new Error(\n `The ${coreServices.pluginMetadata.id} service cannot be overridden`,\n );\n }\n\n if (this.#instantiatedFactories.has(factoryId)) {\n throw new Error(\n `Unable to set service factory with id ${factoryId}, service has already been instantiated`,\n );\n }\n\n if (factory.service.multiton) {\n const newFactories = (\n this.#providedFactories.get(factoryId) ?? []\n ).concat(toInternalServiceFactory(factory));\n this.#providedFactories.set(factoryId, newFactories);\n } else {\n if (this.#addedFactoryIds.has(factoryId)) {\n throw new Error(\n `Duplicate service implementations provided for ${factoryId}`,\n );\n }\n\n this.#addedFactoryIds.add(factoryId);\n this.#providedFactories.set(factoryId, [\n toInternalServiceFactory(factory),\n ]);\n }\n }\n\n async initializeEagerServicesWithScope(\n scope: 'root' | 'plugin',\n pluginId: string = 'root',\n ) {\n for (const [factory] of this.#providedFactories.values()) {\n if (factory.service.scope === scope) {\n // Root-scoped services are eager by default, plugin-scoped are lazy by default\n if (scope === 'root' && factory.initialization !== 'lazy') {\n await this.get(factory.service, pluginId);\n } else if (scope === 'plugin' && factory.initialization === 'always') {\n await this.get(factory.service, pluginId);\n }\n }\n }\n }\n\n get<T, TInstances extends 'singleton' | 'multiton'>(\n ref: ServiceRef<T, 'plugin' | 'root', TInstances>,\n pluginId: string,\n ): Promise<TInstances extends 'multiton' ? T[] : T> | undefined {\n this.#instantiatedFactories.add(ref.id);\n\n const resolvedFactory = this.#resolveFactory(ref, pluginId);\n\n if (!resolvedFactory) {\n return ref.multiton\n ? (Promise.resolve([]) as\n | Promise<TInstances extends 'multiton' ? T[] : T>\n | undefined)\n : undefined;\n }\n\n return resolvedFactory\n .then(factories => {\n return Promise.all(\n factories.map(factory => {\n if (factory.service.scope === 'root') {\n let existing = this.#rootServiceImplementations.get(factory);\n if (!existing) {\n this.#checkForMissingDeps(factory, pluginId);\n const rootDeps = new Array<\n Promise<[name: string, impl: unknown]>\n >();\n\n for (const [name, serviceRef] of Object.entries(factory.deps)) {\n if (serviceRef.scope !== 'root') {\n throw new Error(\n `Failed to instantiate 'root' scoped service '${ref.id}' because it depends on '${serviceRef.scope}' scoped service '${serviceRef.id}'.`,\n );\n }\n const target = this.get(serviceRef, pluginId)!;\n rootDeps.push(target.then(impl => [name, impl]));\n }\n\n existing = Promise.all(rootDeps).then(entries =>\n factory.factory(Object.fromEntries(entries), undefined),\n );\n this.#rootServiceImplementations.set(factory, existing);\n }\n return existing as Promise<T>;\n }\n\n let implementation = this.#implementations.get(factory);\n if (!implementation) {\n this.#checkForMissingDeps(factory, pluginId);\n const rootDeps = new Array<\n Promise<[name: string, impl: unknown]>\n >();\n\n for (const [name, serviceRef] of Object.entries(factory.deps)) {\n if (serviceRef.scope === 'root') {\n const target = this.get(serviceRef, pluginId)!;\n rootDeps.push(target.then(impl => [name, impl]));\n }\n }\n\n implementation = {\n context: Promise.all(rootDeps)\n .then(entries =>\n factory.createRootContext?.(Object.fromEntries(entries)),\n )\n .catch(error => {\n const cause = stringifyError(error);\n throw new Error(\n `Failed to instantiate service '${ref.id}' because createRootContext threw an error, ${cause}`,\n );\n }),\n byPlugin: new Map(),\n };\n\n this.#implementations.set(factory, implementation);\n }\n\n let result = implementation.byPlugin.get(pluginId) as Promise<any>;\n if (!result) {\n const allDeps = new Array<\n Promise<[name: string, impl: unknown]>\n >();\n\n for (const [name, serviceRef] of Object.entries(factory.deps)) {\n const target = this.get(serviceRef, pluginId)!;\n allDeps.push(target.then(impl => [name, impl]));\n }\n\n result = implementation.context\n .then(context =>\n Promise.all(allDeps).then(entries =>\n factory.factory(Object.fromEntries(entries), context),\n ),\n )\n .catch(error => {\n const cause = stringifyError(error);\n throw new Error(\n `Failed to instantiate service '${ref.id}' for '${pluginId}' because the factory function threw an error, ${cause}`,\n );\n });\n implementation.byPlugin.set(pluginId, result);\n }\n return result;\n }),\n );\n })\n .then(results => (ref.multiton ? results : results[0]));\n }\n}\n"],"names":["createServiceFactory","coreServices","stringifyError","DependencyGraph","ConflictError"],"mappings":"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"}
1
+ {"version":3,"file":"ServiceRegistry.cjs.js","sources":["../../../../../backend-app-api/src/wiring/ServiceRegistry.ts"],"sourcesContent":["/*\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 ServiceFactory,\n ServiceRef,\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { ConflictError, stringifyError } from '@backstage/errors';\n// Direct internal import to avoid duplication\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { InternalServiceFactory } from '../../../backend-plugin-api/src/services/system/types';\nimport { DependencyGraph } from '../lib/DependencyGraph';\n/**\n * Keep in sync with `@backstage/backend-plugin-api/src/services/system/types.ts`\n * @internal\n */\nexport type InternalServiceRef = ServiceRef<unknown> & {\n __defaultFactory?: (\n service: ServiceRef<unknown>,\n ) => Promise<ServiceFactory | (() => ServiceFactory)>;\n};\n\nfunction toInternalServiceFactory<TService, TScope extends 'plugin' | 'root'>(\n factory: ServiceFactory<TService, TScope>,\n): InternalServiceFactory<TService, TScope> {\n const f = factory as InternalServiceFactory<TService, TScope>;\n if (f.$$type !== '@backstage/BackendFeature') {\n throw new Error(`Invalid service factory, bad type '${f.$$type}'`);\n }\n if (f.version !== 'v1') {\n throw new Error(`Invalid service factory, bad version '${f.version}'`);\n }\n return f;\n}\n\nfunction createPluginMetadataServiceFactory(pluginId: string) {\n return createServiceFactory({\n service: coreServices.pluginMetadata,\n deps: {},\n factory: async () => ({\n getId: () => pluginId,\n }),\n });\n}\n\nexport class ServiceRegistry {\n static create(factories: Array<ServiceFactory>): ServiceRegistry {\n const factoryMap = new Map<string, InternalServiceFactory[]>();\n for (const factory of factories) {\n if (factory.service.multiton) {\n const existing = factoryMap.get(factory.service.id) ?? [];\n factoryMap.set(\n factory.service.id,\n existing.concat(toInternalServiceFactory(factory)),\n );\n } else {\n factoryMap.set(factory.service.id, [toInternalServiceFactory(factory)]);\n }\n }\n const registry = new ServiceRegistry(factoryMap);\n registry.checkForCircularDeps();\n return registry;\n }\n\n readonly #providedFactories: Map<string, InternalServiceFactory[]>;\n readonly #loadedDefaultFactories: Map<\n Function,\n Promise<InternalServiceFactory>\n >;\n readonly #implementations: Map<\n InternalServiceFactory,\n {\n context: Promise<unknown>;\n byPlugin: Map<string, Promise<unknown>>;\n }\n >;\n readonly #rootServiceImplementations = new Map<\n InternalServiceFactory,\n Promise<unknown>\n >();\n readonly #addedFactoryIds = new Set<string>();\n readonly #instantiatedFactories = new Set<string>();\n\n private constructor(factories: Map<string, InternalServiceFactory[]>) {\n this.#providedFactories = factories;\n this.#loadedDefaultFactories = new Map();\n this.#implementations = new Map();\n }\n\n #resolveFactory(\n ref: ServiceRef<unknown>,\n pluginId: string,\n ): Promise<InternalServiceFactory[]> | undefined {\n // Special case handling of the plugin metadata service, generating a custom factory for it each time\n if (ref.id === coreServices.pluginMetadata.id) {\n return Promise.resolve([\n toInternalServiceFactory(createPluginMetadataServiceFactory(pluginId)),\n ]);\n }\n\n let resolvedFactory:\n | Promise<InternalServiceFactory[]>\n | InternalServiceFactory[]\n | undefined = this.#providedFactories.get(ref.id);\n const { __defaultFactory: defaultFactory } = ref as InternalServiceRef;\n if (!resolvedFactory && !defaultFactory) {\n return undefined;\n }\n\n if (!resolvedFactory) {\n let loadedFactory = this.#loadedDefaultFactories.get(defaultFactory!);\n if (!loadedFactory) {\n loadedFactory = Promise.resolve()\n .then(() => defaultFactory!(ref))\n .then(f =>\n toInternalServiceFactory(typeof f === 'function' ? f() : f),\n );\n this.#loadedDefaultFactories.set(defaultFactory!, loadedFactory);\n }\n resolvedFactory = loadedFactory.then(\n factory => [factory],\n error => {\n throw new Error(\n `Failed to instantiate service '${\n ref.id\n }' because the default factory loader threw an error, ${stringifyError(\n error,\n )}`,\n );\n },\n );\n }\n\n return Promise.resolve(resolvedFactory);\n }\n\n #checkForMissingDeps(factory: InternalServiceFactory, pluginId: string) {\n const missingDeps = Object.values(factory.deps).filter(ref => {\n if (ref.id === coreServices.pluginMetadata.id) {\n return false;\n }\n if (this.#providedFactories.get(ref.id)) {\n return false;\n }\n if (ref.multiton) {\n return false;\n }\n\n return !(ref as InternalServiceRef).__defaultFactory;\n });\n\n if (missingDeps.length) {\n const missing = missingDeps.map(r => `'${r.id}'`).join(', ');\n throw new Error(\n `Failed to instantiate service '${factory.service.id}' for '${pluginId}' because the following dependent services are missing: ${missing}`,\n );\n }\n }\n\n checkForCircularDeps(): void {\n const graph = DependencyGraph.fromIterable(\n Array.from(this.#providedFactories).map(([serviceId, factories]) => ({\n value: serviceId,\n provides: [serviceId],\n consumes: factories.flatMap(factory =>\n Object.values(factory.deps).map(d => d.id),\n ),\n })),\n );\n const circularDependencies = Array.from(graph.detectCircularDependencies());\n\n if (circularDependencies.length) {\n const cycles = circularDependencies\n .map(c => c.map(id => `'${id}'`).join(' -> '))\n .join('\\n ');\n\n throw new ConflictError(`Circular dependencies detected:\\n ${cycles}`);\n }\n }\n\n hasBeenAdded(ref: ServiceRef<any>) {\n if (ref.id === coreServices.pluginMetadata.id) {\n return true;\n }\n return this.#addedFactoryIds.has(ref.id);\n }\n\n add(factory: ServiceFactory) {\n const factoryId = factory.service.id;\n if (factoryId === coreServices.pluginMetadata.id) {\n throw new Error(\n `The ${coreServices.pluginMetadata.id} service cannot be overridden`,\n );\n }\n\n if (this.#instantiatedFactories.has(factoryId)) {\n throw new Error(\n `Unable to set service factory with id ${factoryId}, service has already been instantiated`,\n );\n }\n\n if (factory.service.multiton) {\n const newFactories = (\n this.#providedFactories.get(factoryId) ?? []\n ).concat(toInternalServiceFactory(factory));\n this.#providedFactories.set(factoryId, newFactories);\n } else {\n if (this.#addedFactoryIds.has(factoryId)) {\n throw new Error(\n `Duplicate service implementations provided for ${factoryId}`,\n );\n }\n\n this.#addedFactoryIds.add(factoryId);\n this.#providedFactories.set(factoryId, [\n toInternalServiceFactory(factory),\n ]);\n }\n }\n\n async initializeEagerServicesWithScope(\n scope: 'root' | 'plugin',\n pluginId: string = 'root',\n ) {\n for (const [factory] of this.#providedFactories.values()) {\n if (factory.service.scope === scope) {\n // Root-scoped services are eager by default, plugin-scoped are lazy by default\n if (scope === 'root' && factory.initialization !== 'lazy') {\n await this.get(factory.service, pluginId);\n } else if (scope === 'plugin' && factory.initialization === 'always') {\n await this.get(factory.service, pluginId);\n }\n }\n }\n }\n\n get<T, TInstances extends 'singleton' | 'multiton'>(\n ref: ServiceRef<T, 'plugin' | 'root', TInstances>,\n pluginId: string,\n ): Promise<TInstances extends 'multiton' ? T[] : T> | undefined {\n this.#instantiatedFactories.add(ref.id);\n\n const resolvedFactory = this.#resolveFactory(ref, pluginId);\n\n if (!resolvedFactory) {\n return ref.multiton\n ? (Promise.resolve([]) as\n | Promise<TInstances extends 'multiton' ? T[] : T>\n | undefined)\n : undefined;\n }\n\n return resolvedFactory\n .then(factories => {\n return Promise.all(\n factories.map(factory => {\n if (factory.service.scope === 'root') {\n let existing = this.#rootServiceImplementations.get(factory);\n if (!existing) {\n this.#checkForMissingDeps(factory, pluginId);\n const rootDeps = new Array<\n Promise<[name: string, impl: unknown]>\n >();\n\n for (const [name, serviceRef] of Object.entries(factory.deps)) {\n if (serviceRef.scope !== 'root') {\n throw new Error(\n `Failed to instantiate 'root' scoped service '${ref.id}' because it depends on '${serviceRef.scope}' scoped service '${serviceRef.id}'.`,\n );\n }\n const target = this.get(serviceRef, pluginId)!;\n rootDeps.push(target.then(impl => [name, impl]));\n }\n\n existing = Promise.all(rootDeps).then(entries =>\n factory.factory(Object.fromEntries(entries), undefined),\n );\n this.#rootServiceImplementations.set(factory, existing);\n }\n return existing as Promise<T>;\n }\n\n let implementation = this.#implementations.get(factory);\n if (!implementation) {\n this.#checkForMissingDeps(factory, pluginId);\n const rootDeps = new Array<\n Promise<[name: string, impl: unknown]>\n >();\n\n for (const [name, serviceRef] of Object.entries(factory.deps)) {\n if (serviceRef.scope === 'root') {\n const target = this.get(serviceRef, pluginId)!;\n rootDeps.push(target.then(impl => [name, impl]));\n }\n }\n\n implementation = {\n context: Promise.all(rootDeps)\n .then(entries =>\n factory.createRootContext?.(Object.fromEntries(entries)),\n )\n .catch(error => {\n const cause = stringifyError(error);\n throw new Error(\n `Failed to instantiate service '${ref.id}' because createRootContext threw an error, ${cause}`,\n );\n }),\n byPlugin: new Map(),\n };\n\n this.#implementations.set(factory, implementation);\n }\n\n let result = implementation.byPlugin.get(pluginId) as Promise<any>;\n if (!result) {\n const allDeps = new Array<\n Promise<[name: string, impl: unknown]>\n >();\n\n for (const [name, serviceRef] of Object.entries(factory.deps)) {\n const target = this.get(serviceRef, pluginId)!;\n allDeps.push(target.then(impl => [name, impl]));\n }\n\n result = implementation.context\n .then(context =>\n Promise.all(allDeps).then(entries =>\n factory.factory(Object.fromEntries(entries), context),\n ),\n )\n .catch(error => {\n const cause = stringifyError(error);\n throw new Error(\n `Failed to instantiate service '${ref.id}' for '${pluginId}' because the factory function threw an error, ${cause}`,\n );\n });\n implementation.byPlugin.set(pluginId, result);\n }\n return result;\n }),\n );\n })\n .then(results => (ref.multiton ? results : results[0]));\n }\n}\n"],"names":["createServiceFactory","coreServices","stringifyError","DependencyGraph","ConflictError"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ var OpaqueType = require('../../../opaque-internal/src/OpaqueType.cjs.js');
4
+
5
+ OpaqueType.OpaqueType.create({
6
+ type: "@backstage/ExtensionPointFactoryMiddleware",
7
+ versions: ["v1"]
8
+ });
9
+ //# sourceMappingURL=OpaqueExtensionPointFactoryMiddleware.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OpaqueExtensionPointFactoryMiddleware.cjs.js","sources":["../../../../../backend-internal/src/wiring/OpaqueExtensionPointFactoryMiddleware.ts"],"sourcesContent":["/*\n * Copyright 2026 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 { OpaqueType } from '@internal/opaque';\n\nexport const OpaqueExtensionPointFactoryMiddleware = OpaqueType.create<{\n public: { $$type: '@backstage/ExtensionPointFactoryMiddleware' };\n versions: {\n readonly version: 'v1';\n readonly extensionPointId: string;\n readonly middleware: (original: unknown) => Promise<unknown>;\n };\n}>({\n type: '@backstage/ExtensionPointFactoryMiddleware',\n versions: ['v1'],\n});\n"],"names":["OpaqueType"],"mappings":";;;;AAkBqDA,sBAAW,MAAA,CAO7D;AAAA,EACD,IAAA,EAAM,4CAAA;AAAA,EACN,QAAA,EAAU,CAAC,IAAI;AACjB,CAAC;;"}
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ function isPromise(value) {
4
+ return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
5
+ }
6
+ function unwrapFeature(feature) {
7
+ if ("$$type" in feature) {
8
+ return feature;
9
+ }
10
+ if ("default" in feature) {
11
+ return feature.default;
12
+ }
13
+ return feature;
14
+ }
15
+
16
+ exports.isPromise = isPromise;
17
+ exports.unwrapFeature = unwrapFeature;
18
+ //# sourceMappingURL=helpers.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.cjs.js","sources":["../../../../../backend-internal/src/wiring/helpers.ts"],"sourcesContent":["/*\n * Copyright 2024 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 { BackendFeature } from '@backstage/backend-plugin-api';\n\n/** @internal */\nexport function isPromise<T>(value: unknown | Promise<T>): value is Promise<T> {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'then' in value &&\n typeof value.then === 'function'\n );\n}\n\n/**\n * Unwraps a backend feature from a possibly double-nested default export.\n * This is a workaround where default exports get transpiled to\n * `exports['default'] = ...` in CommonJS modules, which in turn results\n * in a double `{ default: { default: ... } }` nesting when importing\n * using a dynamic import.\n *\n * @internal\n */\nexport function unwrapFeature(\n feature: BackendFeature | { default: BackendFeature },\n): BackendFeature {\n if ('$$type' in feature) {\n return feature;\n }\n\n if ('default' in feature) {\n return feature.default;\n }\n\n return feature;\n}\n"],"names":[],"mappings":";;AAmBO,SAAS,UAAa,KAAA,EAAkD;AAC7E,EAAA,OACE,OAAO,UAAU,QAAA,IACjB,KAAA,KAAU,QACV,MAAA,IAAU,KAAA,IACV,OAAO,KAAA,CAAM,IAAA,KAAS,UAAA;AAE1B;AAWO,SAAS,cACd,OAAA,EACgB;AAChB,EAAA,IAAI,YAAY,OAAA,EAAS;AACvB,IAAA,OAAO,OAAA;AAAA,EACT;AAEA,EAAA,IAAI,aAAa,OAAA,EAAS;AACxB,IAAA,OAAO,OAAA,CAAQ,OAAA;AAAA,EACjB;AAEA,EAAA,OAAO,OAAA;AACT;;;;;"}
@@ -0,0 +1,105 @@
1
+ 'use strict';
2
+
3
+ class OpaqueType {
4
+ /**
5
+ * Creates a new opaque type.
6
+ *
7
+ * @param options.type The type identifier of the opaque type
8
+ * @param options.versions The available versions of the opaque type
9
+ * @returns A new opaque type helper
10
+ */
11
+ static create(options) {
12
+ return new OpaqueType(options.type, new Set(options.versions));
13
+ }
14
+ #type;
15
+ #versions;
16
+ constructor(type, versions) {
17
+ this.#type = type;
18
+ this.#versions = versions;
19
+ }
20
+ /**
21
+ * The internal version of the opaque type, used like this: `typeof MyOpaqueType.TPublic`
22
+ *
23
+ * @remarks
24
+ *
25
+ * This property is only useful for type checking, its runtime value is `undefined`.
26
+ */
27
+ TPublic = void 0;
28
+ /**
29
+ * The internal version of the opaque type, used like this: `typeof MyOpaqueType.TInternal`
30
+ *
31
+ * @remarks
32
+ *
33
+ * This property is only useful for type checking, its runtime value is `undefined`.
34
+ */
35
+ TInternal = void 0;
36
+ /**
37
+ * @param value Input value expected to be an instance of this opaque type
38
+ * @returns True if the value matches this opaque type
39
+ */
40
+ isType = (value) => {
41
+ return this.#isThisInternalType(value);
42
+ };
43
+ /**
44
+ * @param value Input value expected to be an instance of this opaque type
45
+ * @throws If the value is not an instance of this opaque type or is of an unsupported version
46
+ * @returns The internal version of the opaque type
47
+ */
48
+ toInternal = (value) => {
49
+ if (!this.#isThisInternalType(value)) {
50
+ throw new TypeError(
51
+ `Invalid opaque type, expected '${this.#type}', but got '${this.#stringifyUnknown(value)}'`
52
+ );
53
+ }
54
+ if (!this.#versions.has(value.version)) {
55
+ const versions = Array.from(this.#versions).map(this.#stringifyVersion);
56
+ if (versions.length > 1) {
57
+ versions[versions.length - 1] = `or ${versions[versions.length - 1]}`;
58
+ }
59
+ const expected = versions.length > 2 ? versions.join(", ") : versions.join(" ");
60
+ throw new TypeError(
61
+ `Invalid opaque type instance, got version ${this.#stringifyVersion(
62
+ value.version
63
+ )}, expected ${expected}`
64
+ );
65
+ }
66
+ return value;
67
+ };
68
+ /**
69
+ * Creates an instance of the opaque type, returning the public type.
70
+ *
71
+ * @param version The version of the instance to create
72
+ * @param value The remaining public and internal properties of the instance
73
+ * @returns An instance of the opaque type
74
+ */
75
+ createInstance(version, props) {
76
+ return Object.assign(props, {
77
+ $$type: this.#type,
78
+ ...version && { version }
79
+ });
80
+ }
81
+ #isThisInternalType(value) {
82
+ if (value === null || typeof value !== "object") {
83
+ return false;
84
+ }
85
+ return value.$$type === this.#type;
86
+ }
87
+ #stringifyUnknown(value) {
88
+ if (typeof value !== "object") {
89
+ return `<${typeof value}>`;
90
+ }
91
+ if (value === null) {
92
+ return "<null>";
93
+ }
94
+ if ("$$type" in value) {
95
+ return String(value.$$type);
96
+ }
97
+ return String(value);
98
+ }
99
+ #stringifyVersion = (version) => {
100
+ return version ? `'${version}'` : "undefined";
101
+ };
102
+ }
103
+
104
+ exports.OpaqueType = OpaqueType;
105
+ //# sourceMappingURL=OpaqueType.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OpaqueType.cjs.js","sources":["../../../../opaque-internal/src/OpaqueType.ts"],"sourcesContent":["/*\n * Copyright 2024 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\n// TODO(Rugvip): This lives here temporarily, but should be moved to a more\n// central location. It's useful for backend packages too so we'll need to have\n// it in a common package, but it might also be that we want to make it\n// available publicly too in which case it would make sense to have this be part\n// of @backstage/version-bridge. The problem with exporting it from there is\n// that it would need to be very stable at that point, so it might be a bit\n// early to put it there already.\n\n/**\n * A helper for working with opaque types.\n */\nexport class OpaqueType<\n T extends {\n public: { $$type: string };\n versions: { version: string | undefined };\n },\n> {\n /**\n * Creates a new opaque type.\n *\n * @param options.type The type identifier of the opaque type\n * @param options.versions The available versions of the opaque type\n * @returns A new opaque type helper\n */\n static create<\n T extends {\n public: { $$type: string };\n versions: { version: string | undefined };\n },\n >(options: {\n type: T['public']['$$type'];\n versions: Array<T['versions']['version']>;\n }) {\n return new OpaqueType<T>(options.type, new Set(options.versions));\n }\n\n #type: string;\n #versions: Set<string | undefined>;\n\n private constructor(type: string, versions: Set<string | undefined>) {\n this.#type = type;\n this.#versions = versions;\n }\n\n /**\n * The internal version of the opaque type, used like this: `typeof MyOpaqueType.TPublic`\n *\n * @remarks\n *\n * This property is only useful for type checking, its runtime value is `undefined`.\n */\n TPublic: T['public'] = undefined as any;\n\n /**\n * The internal version of the opaque type, used like this: `typeof MyOpaqueType.TInternal`\n *\n * @remarks\n *\n * This property is only useful for type checking, its runtime value is `undefined`.\n */\n TInternal: T['public'] & T['versions'] = undefined as any;\n\n /**\n * @param value Input value expected to be an instance of this opaque type\n * @returns True if the value matches this opaque type\n */\n isType = (value: unknown): value is T['public'] => {\n return this.#isThisInternalType(value);\n };\n\n /**\n * @param value Input value expected to be an instance of this opaque type\n * @throws If the value is not an instance of this opaque type or is of an unsupported version\n * @returns The internal version of the opaque type\n */\n toInternal = (value: unknown): T['public'] & T['versions'] => {\n if (!this.#isThisInternalType(value)) {\n throw new TypeError(\n `Invalid opaque type, expected '${\n this.#type\n }', but got '${this.#stringifyUnknown(value)}'`,\n );\n }\n\n if (!this.#versions.has(value.version)) {\n const versions = Array.from(this.#versions).map(this.#stringifyVersion);\n if (versions.length > 1) {\n versions[versions.length - 1] = `or ${versions[versions.length - 1]}`;\n }\n const expected =\n versions.length > 2 ? versions.join(', ') : versions.join(' ');\n throw new TypeError(\n `Invalid opaque type instance, got version ${this.#stringifyVersion(\n value.version,\n )}, expected ${expected}`,\n );\n }\n\n return value;\n };\n\n /**\n * Creates an instance of the opaque type, returning the public type.\n *\n * @param version The version of the instance to create\n * @param value The remaining public and internal properties of the instance\n * @returns An instance of the opaque type\n */\n createInstance<\n TVersion extends T['versions']['version'],\n TPublic extends T['public'],\n >(\n version: TVersion,\n props: Omit<T['public'], '$$type'> &\n (T['versions'] extends infer UVersion\n ? UVersion extends { version: TVersion }\n ? Omit<UVersion, 'version'>\n : never\n : never) &\n Object, // & Object to allow for object properties too, e.g. toString()\n ): TPublic {\n return Object.assign(props as object, {\n $$type: this.#type,\n ...(version && { version }),\n }) as unknown as TPublic;\n }\n\n #isThisInternalType(value: unknown): value is T['public'] & T['versions'] {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n return (value as T['public']).$$type === this.#type;\n }\n\n #stringifyUnknown(value: unknown) {\n if (typeof value !== 'object') {\n return `<${typeof value}>`;\n }\n if (value === null) {\n return '<null>';\n }\n if ('$$type' in value) {\n return String(value.$$type);\n }\n return String(value);\n }\n\n #stringifyVersion = (version: string | undefined) => {\n return version ? `'${version}'` : 'undefined';\n };\n}\n"],"names":[],"mappings":"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"}
@@ -15,6 +15,8 @@ require('zod-to-json-schema');
15
15
  var ActionsServiceMock = require('../alpha/services/ActionsServiceMock.cjs.js');
16
16
  var MetricsServiceMock = require('../alpha/services/MetricsServiceMock.cjs.js');
17
17
  var TracingServiceMock = require('../alpha/services/TracingServiceMock.cjs.js');
18
+ var helpers = require('../backend-internal/src/wiring/helpers.cjs.js');
19
+ require('../backend-internal/src/wiring/OpaqueExtensionPointFactoryMiddleware.cjs.js');
18
20
 
19
21
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
20
22
 
@@ -131,28 +133,16 @@ function createExtensionPointTestModules(features, extensionPointTuples) {
131
133
  }
132
134
  return modules;
133
135
  }
134
- function isPromise(value) {
135
- return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
136
- }
137
- function unwrapFeature(feature) {
138
- if ("$$type" in feature) {
139
- return feature;
140
- }
141
- if ("default" in feature) {
142
- return feature.default;
143
- }
144
- return feature;
145
- }
146
136
  const backendInstancesToCleanUp = new Array();
147
137
  async function startTestBackend(options) {
148
138
  const { extensionPoints, ...otherOptions } = options;
149
139
  const features = await Promise.all(
150
140
  options.features?.map(async (val) => {
151
- if (isPromise(val)) {
141
+ if (helpers.isPromise(val)) {
152
142
  const { default: feature } = await val;
153
- return unwrapFeature(feature);
143
+ return helpers.unwrapFeature(feature);
154
144
  }
155
- return unwrapFeature(val);
145
+ return helpers.unwrapFeature(val);
156
146
  }) ?? []
157
147
  );
158
148
  let server;
@@ -1 +1 @@
1
- {"version":3,"file":"TestBackend.cjs.js","sources":["../../src/wiring/TestBackend.ts"],"sourcesContent":["/*\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 { Backend, createSpecializedBackend } from '@backstage/backend-app-api';\nimport {\n createServiceFactory,\n BackendFeature,\n ExtensionPoint,\n coreServices,\n createBackendModule,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { mockServices } from '../services';\nimport { ConfigReader } from '@backstage/config';\nimport express from 'express';\n// Direct internal import to avoid duplication\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport {\n InternalBackendFeature,\n InternalBackendRegistrations,\n} from '../../../backend-plugin-api/src/wiring/types';\nimport {\n DefaultRootHttpRouter,\n ExtendedHttpServer,\n MiddlewareFactory,\n createHealthRouter,\n createHttpServer,\n} from '@backstage/backend-defaults/rootHttpRouter';\nimport { HostDiscovery } from '@backstage/backend-defaults/discovery';\nimport {\n actionsRegistryServiceMock,\n actionsServiceMock,\n metricsServiceMock,\n tracingServiceMock,\n} from '../alpha/services';\n\n/** @public */\nexport interface TestBackendOptions<TExtensionPoints extends any[]> {\n extensionPoints?: readonly [\n ...{\n [index in keyof TExtensionPoints]: [\n ExtensionPoint<TExtensionPoints[index]>,\n Partial<TExtensionPoints[index]>,\n ];\n },\n ];\n features?: Array<BackendFeature | Promise<{ default: BackendFeature }>>;\n}\n\n/** @public */\nexport interface TestBackend extends Backend {\n /**\n * Provides access to the underling HTTP server for use with utilities\n * such as `supertest`.\n *\n * If the root http router service has been replaced, this will throw an error.\n */\n readonly server: ExtendedHttpServer;\n}\n\nexport const defaultServiceFactories = [\n mockServices.auth.factory(),\n mockServices.auditor.factory(),\n mockServices.cache.factory(),\n mockServices.rootConfig.factory(),\n mockServices.database.factory(),\n mockServices.httpAuth.factory(),\n mockServices.httpRouter.factory(),\n mockServices.lifecycle.factory(),\n mockServices.logger.factory(),\n mockServices.permissions.factory(),\n mockServices.permissionsRegistry.factory(),\n mockServices.rootHealth.factory(),\n mockServices.rootLifecycle.factory(),\n mockServices.rootLogger.factory(),\n mockServices.scheduler.factory(),\n mockServices.userInfo.factory(),\n mockServices.urlReader.factory(),\n mockServices.events.factory(),\n\n // Alpha services\n actionsRegistryServiceMock.factory(),\n actionsServiceMock.factory(),\n metricsServiceMock.factory(),\n tracingServiceMock.factory(),\n];\n\n/**\n * Given a set of features, return an array of plugins that ensures that each\n * module in the provided set of features has a corresponding plugin.\n * @internal\n */\nfunction createPluginsForOrphanModules(features: Array<BackendFeature>) {\n const pluginIds = new Set<string>();\n const modulePluginIds = new Set<string>();\n\n for (const feature of features) {\n if (isInternalBackendRegistrations(feature)) {\n const registrations = feature.getRegistrations();\n for (const registration of registrations) {\n if (\n registration.type === 'plugin' ||\n registration.type === 'plugin-v1.1'\n ) {\n pluginIds.add(registration.pluginId);\n } else if (\n registration.type === 'module' ||\n registration.type === 'module-v1.1'\n ) {\n modulePluginIds.add(registration.pluginId);\n }\n }\n }\n }\n\n for (const pluginId of pluginIds) {\n modulePluginIds.delete(pluginId);\n }\n\n return Array.from(modulePluginIds).map(pluginId =>\n createBackendPlugin({\n pluginId,\n register(reg) {\n reg.registerInit({ deps: {}, async init() {} });\n },\n }),\n );\n}\n\n/**\n * Given a set of extension points and features, find the extension\n * points that we mock and tie them to the correct plugin ID.\n * @returns\n */\nfunction createExtensionPointTestModules(\n features: Array<BackendFeature>,\n extensionPointTuples?: readonly [\n ref: ExtensionPoint<unknown>,\n impl: unknown,\n ][],\n): Array<BackendFeature> {\n if (!extensionPointTuples) {\n return [];\n }\n\n const registrations = features.flatMap(feature => {\n if (isInternalBackendRegistrations(feature)) {\n return feature.getRegistrations();\n }\n return [];\n });\n\n const extensionPointMap = new Map(\n extensionPointTuples.map(ep => [ep[0].id, ep]),\n );\n const extensionPointsToSort = new Set(extensionPointMap.keys());\n const extensionPointsByPlugin = new Map<string, string[]>();\n\n for (const registration of registrations) {\n if (registration.type === 'module' || registration.type === 'module-v1.1') {\n const testDep = Object.values(registration.init.deps).filter(dep =>\n extensionPointsToSort.has(dep.id),\n );\n if (testDep.length > 0) {\n let points = extensionPointsByPlugin.get(registration.pluginId);\n if (!points) {\n points = [];\n extensionPointsByPlugin.set(registration.pluginId, points);\n }\n for (const { id } of testDep) {\n points.push(id);\n extensionPointsToSort.delete(id);\n }\n }\n }\n }\n\n if (extensionPointsToSort.size > 0) {\n const list = Array.from(extensionPointsToSort)\n .map(id => `'${id}'`)\n .join(', ');\n throw new Error(\n `Unable to determine the plugin ID of extension point(s) ${list}. ` +\n 'Tested extension points must be depended on by one or more tested modules.',\n );\n }\n\n const modules = [];\n\n for (const [pluginId, pluginExtensionPointIds] of extensionPointsByPlugin) {\n modules.push(\n createBackendModule({\n pluginId,\n moduleId: 'test-extension-point-registration',\n register(reg) {\n for (const id of pluginExtensionPointIds) {\n const tuple = extensionPointMap.get(id)!;\n reg.registerExtensionPoint(...tuple);\n }\n\n reg.registerInit({ deps: {}, async init() {} });\n },\n }),\n );\n }\n\n return modules;\n}\n\nfunction isPromise<T>(value: unknown | Promise<T>): value is Promise<T> {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'then' in value &&\n typeof value.then === 'function'\n );\n}\n\n// Same as in the backend-app-api, handles double defaults from dynamic imports\nfunction unwrapFeature(\n feature: BackendFeature | { default: BackendFeature },\n): BackendFeature {\n if ('$$type' in feature) {\n return feature;\n }\n\n if ('default' in feature) {\n return feature.default;\n }\n\n return feature;\n}\n\nconst backendInstancesToCleanUp = new Array<Backend>();\n\n/** @public */\nexport async function startTestBackend<TExtensionPoints extends any[]>(\n options: TestBackendOptions<TExtensionPoints>,\n): Promise<TestBackend> {\n const { extensionPoints, ...otherOptions } = options;\n\n // Unpack input into awaited plain BackendFeatures\n const features: BackendFeature[] = await Promise.all(\n options.features?.map(async val => {\n if (isPromise(val)) {\n const { default: feature } = await val;\n return unwrapFeature(feature);\n }\n return unwrapFeature(val);\n }) ?? [],\n );\n\n let server: ExtendedHttpServer;\n\n const rootHttpRouterFactory = createServiceFactory({\n service: coreServices.rootHttpRouter,\n deps: {\n config: coreServices.rootConfig,\n lifecycle: coreServices.rootLifecycle,\n rootLogger: coreServices.rootLogger,\n health: coreServices.rootHealth,\n },\n async factory({ config, lifecycle, rootLogger, health }) {\n const router = DefaultRootHttpRouter.create();\n const logger = rootLogger.child({ service: 'rootHttpRouter' });\n\n const app = express();\n\n const middleware = MiddlewareFactory.create({ config, logger });\n const healthRouter = createHealthRouter({ config, health });\n\n app.use(healthRouter);\n app.use(router.handler());\n app.use(middleware.notFound());\n app.use(middleware.error());\n\n server = await createHttpServer(\n app,\n { listen: { host: '', port: 0 } },\n { logger },\n );\n\n lifecycle.addShutdownHook(() => server.stop(), { logger });\n\n await server.start();\n\n return router;\n },\n });\n\n const discoveryFactory = createServiceFactory({\n service: coreServices.discovery,\n deps: {\n rootHttpRouter: coreServices.rootHttpRouter,\n },\n async factory() {\n if (!server) {\n throw new Error('Test server not started yet');\n }\n const port = server.port();\n const discovery = HostDiscovery.fromConfig(\n new ConfigReader({\n backend: { baseUrl: `http://localhost:${port}`, listen: { port } },\n }),\n );\n return discovery;\n },\n });\n\n const backend = createSpecializedBackend({\n ...otherOptions,\n defaultServiceFactories: [\n ...defaultServiceFactories,\n rootHttpRouterFactory,\n discoveryFactory,\n ],\n });\n\n backendInstancesToCleanUp.push(backend);\n\n for (const m of createExtensionPointTestModules(features, extensionPoints)) {\n backend.add(m);\n }\n for (const p of createPluginsForOrphanModules(features)) {\n backend.add(p);\n }\n for (const feature of features) {\n backend.add(feature);\n }\n\n await backend.start();\n\n return Object.assign(backend, {\n get server() {\n if (!server) {\n throw new Error('TestBackend server is not available');\n }\n return server;\n },\n });\n}\n\nlet registered = false;\nfunction registerTestHooks() {\n if (typeof afterAll !== 'function') {\n return;\n }\n if (registered) {\n return;\n }\n registered = true;\n\n afterAll(async () => {\n await Promise.all(\n backendInstancesToCleanUp.map(async backend => {\n try {\n await backend.stop();\n } catch (error) {\n console.error(`Failed to stop backend after tests, ${error}`);\n }\n }),\n );\n backendInstancesToCleanUp.length = 0;\n });\n}\n\nregisterTestHooks();\n\nfunction toInternalBackendFeature(\n feature: BackendFeature,\n): InternalBackendFeature {\n if (feature.$$type !== '@backstage/BackendFeature') {\n throw new Error(`Invalid BackendFeature, bad type '${feature.$$type}'`);\n }\n const internal = feature as InternalBackendFeature;\n if (internal.version !== 'v1') {\n throw new Error(\n `Invalid BackendFeature, bad version '${internal.version}'`,\n );\n }\n return internal;\n}\n\nfunction isInternalBackendRegistrations(\n feature: BackendFeature,\n): feature is InternalBackendRegistrations {\n const internal = toInternalBackendFeature(feature);\n if (internal.featureType === 'registrations') {\n return true;\n }\n // Backwards compatibility for v1 registrations that use duck typing\n return 'getRegistrations' in internal;\n}\n"],"names":["mockServices","actionsRegistryServiceMock","actionsServiceMock","metricsServiceMock","tracingServiceMock","createBackendPlugin","createBackendModule","createServiceFactory","coreServices","DefaultRootHttpRouter","express","MiddlewareFactory","createHealthRouter","createHttpServer","discovery","HostDiscovery","ConfigReader","createSpecializedBackend"],"mappings":"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"}
1
+ {"version":3,"file":"TestBackend.cjs.js","sources":["../../src/wiring/TestBackend.ts"],"sourcesContent":["/*\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 { Backend, createSpecializedBackend } from '@backstage/backend-app-api';\nimport {\n createServiceFactory,\n BackendFeature,\n ExtensionPoint,\n coreServices,\n createBackendModule,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { mockServices } from '../services';\nimport { ConfigReader } from '@backstage/config';\nimport express from 'express';\nimport { isPromise, unwrapFeature } from '@internal/backend';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport {\n InternalBackendFeature,\n InternalBackendRegistrations,\n} from '../../../backend-plugin-api/src/wiring/types';\nimport {\n DefaultRootHttpRouter,\n ExtendedHttpServer,\n MiddlewareFactory,\n createHealthRouter,\n createHttpServer,\n} from '@backstage/backend-defaults/rootHttpRouter';\nimport { HostDiscovery } from '@backstage/backend-defaults/discovery';\nimport {\n actionsRegistryServiceMock,\n actionsServiceMock,\n metricsServiceMock,\n tracingServiceMock,\n} from '../alpha/services';\n\n/** @public */\nexport interface TestBackendOptions<TExtensionPoints extends any[]> {\n extensionPoints?: readonly [\n ...{\n [index in keyof TExtensionPoints]: [\n ExtensionPoint<TExtensionPoints[index]>,\n Partial<TExtensionPoints[index]>,\n ];\n },\n ];\n features?: Array<BackendFeature | Promise<{ default: BackendFeature }>>;\n}\n\n/** @public */\nexport interface TestBackend extends Backend {\n /**\n * Provides access to the underling HTTP server for use with utilities\n * such as `supertest`.\n *\n * If the root http router service has been replaced, this will throw an error.\n */\n readonly server: ExtendedHttpServer;\n}\n\nexport const defaultServiceFactories = [\n mockServices.auth.factory(),\n mockServices.auditor.factory(),\n mockServices.cache.factory(),\n mockServices.rootConfig.factory(),\n mockServices.database.factory(),\n mockServices.httpAuth.factory(),\n mockServices.httpRouter.factory(),\n mockServices.lifecycle.factory(),\n mockServices.logger.factory(),\n mockServices.permissions.factory(),\n mockServices.permissionsRegistry.factory(),\n mockServices.rootHealth.factory(),\n mockServices.rootLifecycle.factory(),\n mockServices.rootLogger.factory(),\n mockServices.scheduler.factory(),\n mockServices.userInfo.factory(),\n mockServices.urlReader.factory(),\n mockServices.events.factory(),\n\n // Alpha services\n actionsRegistryServiceMock.factory(),\n actionsServiceMock.factory(),\n metricsServiceMock.factory(),\n tracingServiceMock.factory(),\n];\n\n/**\n * Given a set of features, return an array of plugins that ensures that each\n * module in the provided set of features has a corresponding plugin.\n * @internal\n */\nfunction createPluginsForOrphanModules(features: Array<BackendFeature>) {\n const pluginIds = new Set<string>();\n const modulePluginIds = new Set<string>();\n\n for (const feature of features) {\n if (isInternalBackendRegistrations(feature)) {\n const registrations = feature.getRegistrations();\n for (const registration of registrations) {\n if (\n registration.type === 'plugin' ||\n registration.type === 'plugin-v1.1'\n ) {\n pluginIds.add(registration.pluginId);\n } else if (\n registration.type === 'module' ||\n registration.type === 'module-v1.1'\n ) {\n modulePluginIds.add(registration.pluginId);\n }\n }\n }\n }\n\n for (const pluginId of pluginIds) {\n modulePluginIds.delete(pluginId);\n }\n\n return Array.from(modulePluginIds).map(pluginId =>\n createBackendPlugin({\n pluginId,\n register(reg) {\n reg.registerInit({ deps: {}, async init() {} });\n },\n }),\n );\n}\n\n/**\n * Given a set of extension points and features, find the extension\n * points that we mock and tie them to the correct plugin ID.\n * @returns\n */\nfunction createExtensionPointTestModules(\n features: Array<BackendFeature>,\n extensionPointTuples?: readonly [\n ref: ExtensionPoint<unknown>,\n impl: unknown,\n ][],\n): Array<BackendFeature> {\n if (!extensionPointTuples) {\n return [];\n }\n\n const registrations = features.flatMap(feature => {\n if (isInternalBackendRegistrations(feature)) {\n return feature.getRegistrations();\n }\n return [];\n });\n\n const extensionPointMap = new Map(\n extensionPointTuples.map(ep => [ep[0].id, ep]),\n );\n const extensionPointsToSort = new Set(extensionPointMap.keys());\n const extensionPointsByPlugin = new Map<string, string[]>();\n\n for (const registration of registrations) {\n if (registration.type === 'module' || registration.type === 'module-v1.1') {\n const testDep = Object.values(registration.init.deps).filter(dep =>\n extensionPointsToSort.has(dep.id),\n );\n if (testDep.length > 0) {\n let points = extensionPointsByPlugin.get(registration.pluginId);\n if (!points) {\n points = [];\n extensionPointsByPlugin.set(registration.pluginId, points);\n }\n for (const { id } of testDep) {\n points.push(id);\n extensionPointsToSort.delete(id);\n }\n }\n }\n }\n\n if (extensionPointsToSort.size > 0) {\n const list = Array.from(extensionPointsToSort)\n .map(id => `'${id}'`)\n .join(', ');\n throw new Error(\n `Unable to determine the plugin ID of extension point(s) ${list}. ` +\n 'Tested extension points must be depended on by one or more tested modules.',\n );\n }\n\n const modules = [];\n\n for (const [pluginId, pluginExtensionPointIds] of extensionPointsByPlugin) {\n modules.push(\n createBackendModule({\n pluginId,\n moduleId: 'test-extension-point-registration',\n register(reg) {\n for (const id of pluginExtensionPointIds) {\n const tuple = extensionPointMap.get(id)!;\n reg.registerExtensionPoint(...tuple);\n }\n\n reg.registerInit({ deps: {}, async init() {} });\n },\n }),\n );\n }\n\n return modules;\n}\n\nconst backendInstancesToCleanUp = new Array<Backend>();\n\n/** @public */\nexport async function startTestBackend<TExtensionPoints extends any[]>(\n options: TestBackendOptions<TExtensionPoints>,\n): Promise<TestBackend> {\n const { extensionPoints, ...otherOptions } = options;\n\n // Unpack input into awaited plain BackendFeatures\n const features: BackendFeature[] = await Promise.all(\n options.features?.map(async val => {\n if (isPromise(val)) {\n const { default: feature } = await val;\n return unwrapFeature(feature);\n }\n return unwrapFeature(val);\n }) ?? [],\n );\n\n let server: ExtendedHttpServer;\n\n const rootHttpRouterFactory = createServiceFactory({\n service: coreServices.rootHttpRouter,\n deps: {\n config: coreServices.rootConfig,\n lifecycle: coreServices.rootLifecycle,\n rootLogger: coreServices.rootLogger,\n health: coreServices.rootHealth,\n },\n async factory({ config, lifecycle, rootLogger, health }) {\n const router = DefaultRootHttpRouter.create();\n const logger = rootLogger.child({ service: 'rootHttpRouter' });\n\n const app = express();\n\n const middleware = MiddlewareFactory.create({ config, logger });\n const healthRouter = createHealthRouter({ config, health });\n\n app.use(healthRouter);\n app.use(router.handler());\n app.use(middleware.notFound());\n app.use(middleware.error());\n\n server = await createHttpServer(\n app,\n { listen: { host: '', port: 0 } },\n { logger },\n );\n\n lifecycle.addShutdownHook(() => server.stop(), { logger });\n\n await server.start();\n\n return router;\n },\n });\n\n const discoveryFactory = createServiceFactory({\n service: coreServices.discovery,\n deps: {\n rootHttpRouter: coreServices.rootHttpRouter,\n },\n async factory() {\n if (!server) {\n throw new Error('Test server not started yet');\n }\n const port = server.port();\n const discovery = HostDiscovery.fromConfig(\n new ConfigReader({\n backend: { baseUrl: `http://localhost:${port}`, listen: { port } },\n }),\n );\n return discovery;\n },\n });\n\n const backend = createSpecializedBackend({\n ...otherOptions,\n defaultServiceFactories: [\n ...defaultServiceFactories,\n rootHttpRouterFactory,\n discoveryFactory,\n ],\n });\n\n backendInstancesToCleanUp.push(backend);\n\n for (const m of createExtensionPointTestModules(features, extensionPoints)) {\n backend.add(m);\n }\n for (const p of createPluginsForOrphanModules(features)) {\n backend.add(p);\n }\n for (const feature of features) {\n backend.add(feature);\n }\n\n await backend.start();\n\n return Object.assign(backend, {\n get server() {\n if (!server) {\n throw new Error('TestBackend server is not available');\n }\n return server;\n },\n });\n}\n\nlet registered = false;\nfunction registerTestHooks() {\n if (typeof afterAll !== 'function') {\n return;\n }\n if (registered) {\n return;\n }\n registered = true;\n\n afterAll(async () => {\n await Promise.all(\n backendInstancesToCleanUp.map(async backend => {\n try {\n await backend.stop();\n } catch (error) {\n console.error(`Failed to stop backend after tests, ${error}`);\n }\n }),\n );\n backendInstancesToCleanUp.length = 0;\n });\n}\n\nregisterTestHooks();\n\nfunction toInternalBackendFeature(\n feature: BackendFeature,\n): InternalBackendFeature {\n if (feature.$$type !== '@backstage/BackendFeature') {\n throw new Error(`Invalid BackendFeature, bad type '${feature.$$type}'`);\n }\n const internal = feature as InternalBackendFeature;\n if (internal.version !== 'v1') {\n throw new Error(\n `Invalid BackendFeature, bad version '${internal.version}'`,\n );\n }\n return internal;\n}\n\nfunction isInternalBackendRegistrations(\n feature: BackendFeature,\n): feature is InternalBackendRegistrations {\n const internal = toInternalBackendFeature(feature);\n if (internal.featureType === 'registrations') {\n return true;\n }\n // Backwards compatibility for v1 registrations that use duck typing\n return 'getRegistrations' in internal;\n}\n"],"names":["mockServices","actionsRegistryServiceMock","actionsServiceMock","metricsServiceMock","tracingServiceMock","createBackendPlugin","createBackendModule","isPromise","unwrapFeature","createServiceFactory","coreServices","DefaultRootHttpRouter","express","MiddlewareFactory","createHealthRouter","createHttpServer","discovery","HostDiscovery","ConfigReader","createSpecializedBackend"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/backend-test-utils",
3
- "version": "1.11.4-next.1",
3
+ "version": "1.11.4",
4
4
  "description": "Test helpers library for Backstage backends",
5
5
  "backstage": {
6
6
  "role": "node-library"
@@ -57,15 +57,15 @@
57
57
  "test": "backstage-cli package test"
58
58
  },
59
59
  "dependencies": {
60
- "@backstage/backend-app-api": "1.7.1-next.0",
61
- "@backstage/backend-defaults": "0.17.3-next.1",
62
- "@backstage/backend-plugin-api": "1.9.2-next.1",
63
- "@backstage/config": "1.3.8",
64
- "@backstage/errors": "1.3.1",
65
- "@backstage/plugin-auth-node": "0.7.2-next.0",
66
- "@backstage/plugin-events-node": "0.4.23-next.0",
67
- "@backstage/plugin-permission-common": "0.9.9",
68
- "@backstage/types": "1.2.2",
60
+ "@backstage/backend-app-api": "^1.7.1",
61
+ "@backstage/backend-defaults": "^0.17.3",
62
+ "@backstage/backend-plugin-api": "^1.9.2",
63
+ "@backstage/config": "^1.3.8",
64
+ "@backstage/errors": "^1.3.1",
65
+ "@backstage/plugin-auth-node": "^0.7.2",
66
+ "@backstage/plugin-events-node": "^0.4.23",
67
+ "@backstage/plugin-permission-common": "^0.9.9",
68
+ "@backstage/types": "^1.2.2",
69
69
  "@keyv/memcache": "^2.0.1",
70
70
  "@keyv/redis": "^4.0.1",
71
71
  "@keyv/valkey": "^1.0.1",
@@ -90,7 +90,7 @@
90
90
  "zod-to-json-schema": "^3.25.1"
91
91
  },
92
92
  "devDependencies": {
93
- "@backstage/cli": "0.36.3-next.1",
93
+ "@backstage/cli": "^0.36.3",
94
94
  "@types/jest": "*",
95
95
  "@types/lodash": "^4.14.151",
96
96
  "@types/supertest": "^2.0.8",