@backstage/backend-app-api 1.7.3-next.0 → 1.7.3

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.
@@ -3,14 +3,25 @@
3
3
  var backendPluginApi = require('@backstage/backend-plugin-api');
4
4
  var errors = require('@backstage/errors');
5
5
  var DependencyGraph = require('../lib/DependencyGraph.cjs.js');
6
+ var validateBackendFeature = require('./validateBackendFeature.cjs.js');
6
7
 
7
- function toInternalServiceFactory(factory) {
8
+ function toInternalServiceFactory(factory, path) {
9
+ validateBackendFeature.assertObjectLike(factory, path);
8
10
  const f = factory;
9
11
  if (f.$$type !== "@backstage/BackendFeature") {
10
- throw new Error(`Invalid service factory, bad type '${f.$$type}'`);
12
+ validateBackendFeature.throwInvalidBackendFeature(
13
+ `${path}.$$type`,
14
+ '"@backstage/BackendFeature"',
15
+ f.$$type
16
+ );
11
17
  }
12
18
  if (f.version !== "v1") {
13
- throw new Error(`Invalid service factory, bad version '${f.version}'`);
19
+ validateBackendFeature.throwInvalidBackendFeature(`${path}.version`, '"v1"', f.version);
20
+ }
21
+ validateBackendFeature.validateServiceRef(f.service, `${path}.service`);
22
+ validateBackendFeature.assertObject(f.deps, `${path}.deps`, "a dependency object");
23
+ for (const [name, ref] of Object.entries(f.deps)) {
24
+ validateBackendFeature.validateServiceRef(ref, `${path}.deps.${name}`);
14
25
  }
15
26
  return f;
16
27
  }
@@ -26,15 +37,14 @@ function createPluginMetadataServiceFactory(pluginId) {
26
37
  class ServiceRegistry {
27
38
  static create(factories) {
28
39
  const factoryMap = /* @__PURE__ */ new Map();
29
- for (const factory of factories) {
40
+ for (let index = 0; index < factories.length; index++) {
41
+ const source = validateBackendFeature.describeBackendFeature(factories[index]) ?? `default service factories[${index}]`;
42
+ const factory = toInternalServiceFactory(factories[index], source);
30
43
  if (factory.service.multiton) {
31
44
  const existing = factoryMap.get(factory.service.id) ?? [];
32
- factoryMap.set(
33
- factory.service.id,
34
- existing.concat(toInternalServiceFactory(factory))
35
- );
45
+ factoryMap.set(factory.service.id, existing.concat(factory));
36
46
  } else {
37
- factoryMap.set(factory.service.id, [toInternalServiceFactory(factory)]);
47
+ factoryMap.set(factory.service.id, [factory]);
38
48
  }
39
49
  }
40
50
  const registry = new ServiceRegistry(factoryMap);
@@ -55,7 +65,10 @@ class ServiceRegistry {
55
65
  #resolveFactory(ref, pluginId) {
56
66
  if (ref.id === backendPluginApi.coreServices.pluginMetadata.id) {
57
67
  return Promise.resolve([
58
- toInternalServiceFactory(createPluginMetadataServiceFactory(pluginId))
68
+ toInternalServiceFactory(
69
+ createPluginMetadataServiceFactory(pluginId),
70
+ "plugin metadata service factory"
71
+ )
59
72
  ]);
60
73
  }
61
74
  let resolvedFactory = this.#providedFactories.get(ref.id);
@@ -67,7 +80,10 @@ class ServiceRegistry {
67
80
  let loadedFactory = this.#loadedDefaultFactories.get(defaultFactory);
68
81
  if (!loadedFactory) {
69
82
  loadedFactory = Promise.resolve().then(() => defaultFactory(ref)).then(
70
- (f) => toInternalServiceFactory(typeof f === "function" ? f() : f)
83
+ (f) => toInternalServiceFactory(
84
+ typeof f === "function" ? f() : f,
85
+ `default factory for service ${JSON.stringify(ref.id)}`
86
+ )
71
87
  );
72
88
  this.#loadedDefaultFactories.set(defaultFactory, loadedFactory);
73
89
  }
@@ -127,8 +143,10 @@ class ServiceRegistry {
127
143
  }
128
144
  return this.#addedFactoryIds.has(ref.id);
129
145
  }
130
- add(factory) {
131
- const factoryId = factory.service.id;
146
+ add(factory, source) {
147
+ const factorySource = source ?? validateBackendFeature.describeBackendFeature(factory) ?? "service factory";
148
+ const internalFactory = toInternalServiceFactory(factory, factorySource);
149
+ const factoryId = internalFactory.service.id;
132
150
  if (factoryId === backendPluginApi.coreServices.pluginMetadata.id) {
133
151
  throw new Error(
134
152
  `The ${backendPluginApi.coreServices.pluginMetadata.id} service cannot be overridden`
@@ -139,8 +157,8 @@ class ServiceRegistry {
139
157
  `Unable to set service factory with id ${factoryId}, service has already been instantiated`
140
158
  );
141
159
  }
142
- if (factory.service.multiton) {
143
- const newFactories = (this.#providedFactories.get(factoryId) ?? []).concat(toInternalServiceFactory(factory));
160
+ if (internalFactory.service.multiton) {
161
+ const newFactories = (this.#providedFactories.get(factoryId) ?? []).concat(internalFactory);
144
162
  this.#providedFactories.set(factoryId, newFactories);
145
163
  } else {
146
164
  if (this.#addedFactoryIds.has(factoryId)) {
@@ -149,9 +167,7 @@ class ServiceRegistry {
149
167
  );
150
168
  }
151
169
  this.#addedFactoryIds.add(factoryId);
152
- this.#providedFactories.set(factoryId, [
153
- toInternalServiceFactory(factory)
154
- ]);
170
+ this.#providedFactories.set(factoryId, [internalFactory]);
155
171
  }
156
172
  }
157
173
  async initializeEagerServicesWithScope(scope, pluginId = "root") {
@@ -1 +1 @@
1
- {"version":3,"file":"ServiceRegistry.cjs.js","sources":["../../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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"}
1
+ {"version":3,"file":"ServiceRegistry.cjs.js","sources":["../../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';\nimport {\n assertObject,\n assertObjectLike,\n describeBackendFeature,\n throwInvalidBackendFeature,\n validateServiceRef,\n} from './validateBackendFeature';\n\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 path: string,\n): InternalServiceFactory<TService, TScope> {\n assertObjectLike(factory, path);\n const f = factory as unknown as InternalServiceFactory<TService, TScope>;\n if (f.$$type !== '@backstage/BackendFeature') {\n throwInvalidBackendFeature(\n `${path}.$$type`,\n '\"@backstage/BackendFeature\"',\n f.$$type,\n );\n }\n if (f.version !== 'v1') {\n throwInvalidBackendFeature(`${path}.version`, '\"v1\"', f.version);\n }\n\n validateServiceRef(f.service, `${path}.service`);\n assertObject(f.deps, `${path}.deps`, 'a dependency object');\n for (const [name, ref] of Object.entries(f.deps)) {\n validateServiceRef(ref, `${path}.deps.${name}`);\n }\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 (let index = 0; index < factories.length; index++) {\n const source =\n describeBackendFeature(factories[index]) ??\n `default service factories[${index}]`;\n const factory = toInternalServiceFactory(factories[index], source);\n if (factory.service.multiton) {\n const existing = factoryMap.get(factory.service.id) ?? [];\n factoryMap.set(factory.service.id, existing.concat(factory));\n } else {\n factoryMap.set(factory.service.id, [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(\n createPluginMetadataServiceFactory(pluginId),\n 'plugin metadata service factory',\n ),\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(\n typeof f === 'function' ? f() : f,\n `default factory for service ${JSON.stringify(ref.id)}`,\n ),\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, source?: string) {\n const factorySource =\n source ?? describeBackendFeature(factory) ?? 'service factory';\n const internalFactory = toInternalServiceFactory(factory, factorySource);\n const factoryId = internalFactory.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 (internalFactory.service.multiton) {\n const newFactories = (\n this.#providedFactories.get(factoryId) ?? []\n ).concat(internalFactory);\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, [internalFactory]);\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":["assertObjectLike","throwInvalidBackendFeature","validateServiceRef","assertObject","createServiceFactory","coreServices","describeBackendFeature","stringifyError","DependencyGraph","ConflictError"],"mappings":"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"}
@@ -0,0 +1,215 @@
1
+ 'use strict';
2
+
3
+ var errors = require('@backstage/errors');
4
+
5
+ function describeValue(value) {
6
+ if (value === void 0) {
7
+ return "undefined";
8
+ }
9
+ if (value === null) {
10
+ return "null";
11
+ }
12
+ if (typeof value === "string") {
13
+ return JSON.stringify(value);
14
+ }
15
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
16
+ return String(value);
17
+ }
18
+ if (typeof value === "function") {
19
+ return "a function";
20
+ }
21
+ if (Array.isArray(value)) {
22
+ return "an array";
23
+ }
24
+ return "an object";
25
+ }
26
+ function throwInvalidBackendFeature(path, expected, value) {
27
+ throw new errors.InputError(
28
+ `Invalid backend feature at ${path}, expected ${expected}, received ${describeValue(
29
+ value
30
+ )}`
31
+ );
32
+ }
33
+ function assertObject(value, path, expected = "an object") {
34
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
35
+ throwInvalidBackendFeature(path, expected, value);
36
+ }
37
+ }
38
+ function assertObjectLike(value, path) {
39
+ if ((typeof value !== "object" || value === null) && typeof value !== "function") {
40
+ throwInvalidBackendFeature(path, "an object or function", value);
41
+ }
42
+ }
43
+ function assertString(value, path) {
44
+ if (typeof value !== "string") {
45
+ throwInvalidBackendFeature(path, "a string", value);
46
+ }
47
+ }
48
+ function assertFunction(value, path) {
49
+ if (typeof value !== "function") {
50
+ throwInvalidBackendFeature(path, "a function", value);
51
+ }
52
+ }
53
+ function assertArray(value, path) {
54
+ if (!Array.isArray(value)) {
55
+ throwInvalidBackendFeature(path, "an array", value);
56
+ }
57
+ }
58
+ function validateServiceRef(value, path) {
59
+ assertObject(value, path, "a service reference object");
60
+ assertString(value.id, `${path}.id`);
61
+ if (value.scope !== "root" && value.scope !== "plugin") {
62
+ throwInvalidBackendFeature(
63
+ `${path}.scope`,
64
+ '"root" or "plugin"',
65
+ value.scope
66
+ );
67
+ }
68
+ }
69
+ function validateExtensionPoint(value, path) {
70
+ assertObject(value, path, "an extension point reference object");
71
+ assertString(value.id, `${path}.id`);
72
+ }
73
+ function validateBackendRegistrations(feature, source) {
74
+ assertFunction(feature.getRegistrations, `${source}.getRegistrations`);
75
+ const registrations = feature.getRegistrations();
76
+ assertArray(registrations, `${source}.getRegistrations()`);
77
+ for (let index = 0; index < registrations.length; index++) {
78
+ const path = `${source}.getRegistrations()[${index}]`;
79
+ const registration = registrations[index];
80
+ assertObject(registration, path, "a registration object");
81
+ if (registration.type === "plugin" || registration.type === "module" || registration.type === "plugin-v1.1" || registration.type === "module-v1.1") {
82
+ assertString(registration.pluginId, `${path}.pluginId`);
83
+ }
84
+ if (registration.type === "module" || registration.type === "module-v1.1") {
85
+ const modulePath = typeof registration.pluginId === "string" ? `module registration for plugin ${JSON.stringify(
86
+ registration.pluginId
87
+ )}` : path;
88
+ assertString(registration.moduleId, `${modulePath}.moduleId`);
89
+ }
90
+ }
91
+ return registrations;
92
+ }
93
+ function validateBackendRegistration(registration) {
94
+ let registrationPath = "registration";
95
+ if ("moduleId" in registration) {
96
+ registrationPath = `module ${JSON.stringify(
97
+ registration.moduleId
98
+ )} for plugin ${JSON.stringify(registration.pluginId)}`;
99
+ } else if ("pluginId" in registration) {
100
+ registrationPath = `plugin ${JSON.stringify(registration.pluginId)}`;
101
+ }
102
+ if (registration.type === "plugin" || registration.type === "module") {
103
+ assertArray(
104
+ registration.extensionPoints,
105
+ `${registrationPath}.extensionPoints`
106
+ );
107
+ for (let index = 0; index < registration.extensionPoints.length; index++) {
108
+ const itemPath = `${registrationPath}.extensionPoints[${index}]`;
109
+ const item = registration.extensionPoints[index];
110
+ assertArray(item, itemPath);
111
+ validateExtensionPoint(item[0], `${itemPath}[0]`);
112
+ }
113
+ } else if (registration.type === "plugin-v1.1" || registration.type === "module-v1.1") {
114
+ assertArray(
115
+ registration.extensionPoints,
116
+ `${registrationPath}.extensionPoints`
117
+ );
118
+ for (let index = 0; index < registration.extensionPoints.length; index++) {
119
+ const itemPath = `${registrationPath}.extensionPoints[${index}]`;
120
+ const item = registration.extensionPoints[index];
121
+ assertObject(item, itemPath, "an extension point registration object");
122
+ validateExtensionPoint(item.extensionPoint, `${itemPath}.extensionPoint`);
123
+ }
124
+ }
125
+ if (registration.type === "plugin" || registration.type === "module" || registration.type === "plugin-v1.1" || registration.type === "module-v1.1") {
126
+ assertObject(
127
+ registration.init,
128
+ `${registrationPath}.init`,
129
+ "an init registration object"
130
+ );
131
+ assertObject(
132
+ registration.init.deps,
133
+ `${registrationPath}.init.deps`,
134
+ "a dependency object"
135
+ );
136
+ for (const [name, ref] of Object.entries(registration.init.deps)) {
137
+ const path = `${registrationPath}.init.deps.${name}`;
138
+ if ((registration.type === "module" || registration.type === "module-v1.1") && typeof ref === "object" && ref !== null && ref.$$type === "@backstage/ExtensionPoint") {
139
+ validateExtensionPoint(ref, path);
140
+ } else {
141
+ validateServiceRef(ref, path);
142
+ }
143
+ }
144
+ }
145
+ }
146
+ function describeBackendFeature(value) {
147
+ if ((typeof value !== "object" || value === null) && typeof value !== "function") {
148
+ return void 0;
149
+ }
150
+ const feature = value;
151
+ const service = feature.service;
152
+ if (typeof service === "object" && service !== null && "id" in service) {
153
+ const serviceId = service.id;
154
+ if (typeof serviceId === "string") {
155
+ return `service factory for ${JSON.stringify(serviceId)}`;
156
+ }
157
+ }
158
+ if (feature.featureType === "loader" && typeof feature.description === "string") {
159
+ return `feature loader ${feature.description}`;
160
+ }
161
+ if (typeof feature.description === "string") {
162
+ return `backend feature ${feature.description}`;
163
+ }
164
+ return void 0;
165
+ }
166
+ function validateBackendFeature(value, path) {
167
+ assertObjectLike(value, path);
168
+ if (value.$$type !== "@backstage/BackendFeature") {
169
+ throwInvalidBackendFeature(
170
+ `${path}.$$type`,
171
+ '"@backstage/BackendFeature"',
172
+ value.$$type
173
+ );
174
+ }
175
+ if (value.version !== "v1") {
176
+ throwInvalidBackendFeature(`${path}.version`, '"v1"', value.version);
177
+ }
178
+ if (value.featureType === "service" || "service" in value) {
179
+ return {
180
+ type: "service",
181
+ feature: value
182
+ };
183
+ }
184
+ if (value.featureType === "loader") {
185
+ return {
186
+ type: "loader",
187
+ feature: value
188
+ };
189
+ }
190
+ if (value.featureType === "registrations" || "getRegistrations" in value) {
191
+ return {
192
+ type: "registrations",
193
+ feature: value
194
+ };
195
+ }
196
+ return throwInvalidBackendFeature(
197
+ `${path}.featureType`,
198
+ '"service", "registrations", or "loader"',
199
+ value.featureType
200
+ );
201
+ }
202
+
203
+ exports.assertArray = assertArray;
204
+ exports.assertFunction = assertFunction;
205
+ exports.assertObject = assertObject;
206
+ exports.assertObjectLike = assertObjectLike;
207
+ exports.assertString = assertString;
208
+ exports.describeBackendFeature = describeBackendFeature;
209
+ exports.throwInvalidBackendFeature = throwInvalidBackendFeature;
210
+ exports.validateBackendFeature = validateBackendFeature;
211
+ exports.validateBackendRegistration = validateBackendRegistration;
212
+ exports.validateBackendRegistrations = validateBackendRegistrations;
213
+ exports.validateExtensionPoint = validateExtensionPoint;
214
+ exports.validateServiceRef = validateServiceRef;
215
+ //# sourceMappingURL=validateBackendFeature.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateBackendFeature.cjs.js","sources":["../../src/wiring/validateBackendFeature.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 { InputError } from '@backstage/errors';\n// Direct internal import to avoid duplication\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport type {\n InternalBackendFeatureLoader,\n InternalBackendRegistrations,\n} from '../../../backend-plugin-api/src/wiring/types';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport type { InternalServiceFactory } from '../../../backend-plugin-api/src/services/system/types';\n\nexport type ValidatedBackendFeature =\n | { type: 'service'; feature: InternalServiceFactory }\n | { type: 'loader'; feature: InternalBackendFeatureLoader }\n | { type: 'registrations'; feature: InternalBackendRegistrations };\n\nfunction describeValue(value: unknown): string {\n if (value === undefined) {\n return 'undefined';\n }\n if (value === null) {\n return 'null';\n }\n if (typeof value === 'string') {\n return JSON.stringify(value);\n }\n if (\n typeof value === 'number' ||\n typeof value === 'boolean' ||\n typeof value === 'bigint'\n ) {\n return String(value);\n }\n if (typeof value === 'function') {\n return 'a function';\n }\n if (Array.isArray(value)) {\n return 'an array';\n }\n return 'an object';\n}\n\nexport function throwInvalidBackendFeature(\n path: string,\n expected: string,\n value: unknown,\n): never {\n throw new InputError(\n `Invalid backend feature at ${path}, expected ${expected}, received ${describeValue(\n value,\n )}`,\n );\n}\n\nexport function assertObject(\n value: unknown,\n path: string,\n expected = 'an object',\n): asserts value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throwInvalidBackendFeature(path, expected, value);\n }\n}\n\nexport function assertObjectLike(\n value: unknown,\n path: string,\n): asserts value is Record<string, unknown> {\n if (\n (typeof value !== 'object' || value === null) &&\n typeof value !== 'function'\n ) {\n throwInvalidBackendFeature(path, 'an object or function', value);\n }\n}\n\nexport function assertString(\n value: unknown,\n path: string,\n): asserts value is string {\n if (typeof value !== 'string') {\n throwInvalidBackendFeature(path, 'a string', value);\n }\n}\n\nexport function assertFunction(\n value: unknown,\n path: string,\n): asserts value is (...args: any[]) => unknown {\n if (typeof value !== 'function') {\n throwInvalidBackendFeature(path, 'a function', value);\n }\n}\n\nexport function assertArray(\n value: unknown,\n path: string,\n): asserts value is unknown[] {\n if (!Array.isArray(value)) {\n throwInvalidBackendFeature(path, 'an array', value);\n }\n}\n\nexport function validateServiceRef(value: unknown, path: string): void {\n assertObject(value, path, 'a service reference object');\n assertString(value.id, `${path}.id`);\n if (value.scope !== 'root' && value.scope !== 'plugin') {\n throwInvalidBackendFeature(\n `${path}.scope`,\n '\"root\" or \"plugin\"',\n value.scope,\n );\n }\n}\n\nexport function validateExtensionPoint(value: unknown, path: string): void {\n assertObject(value, path, 'an extension point reference object');\n assertString(value.id, `${path}.id`);\n}\n\n/**\n * Reads the registrations from a backend feature and validates the outer\n * registration objects and their identifying fields.\n *\n * Nested registration data is validated later by\n * {@link validateBackendRegistration}, when each registration is enumerated.\n */\nexport function validateBackendRegistrations(\n feature: InternalBackendRegistrations,\n source: string,\n): ReturnType<InternalBackendRegistrations['getRegistrations']> {\n assertFunction(feature.getRegistrations, `${source}.getRegistrations`);\n const registrations: unknown = feature.getRegistrations();\n assertArray(registrations, `${source}.getRegistrations()`);\n\n for (let index = 0; index < registrations.length; index++) {\n const path = `${source}.getRegistrations()[${index}]`;\n const registration = registrations[index];\n assertObject(registration, path, 'a registration object');\n\n if (\n registration.type === 'plugin' ||\n registration.type === 'module' ||\n registration.type === 'plugin-v1.1' ||\n registration.type === 'module-v1.1'\n ) {\n assertString(registration.pluginId, `${path}.pluginId`);\n }\n if (registration.type === 'module' || registration.type === 'module-v1.1') {\n const modulePath =\n typeof registration.pluginId === 'string'\n ? `module registration for plugin ${JSON.stringify(\n registration.pluginId,\n )}`\n : path;\n assertString(registration.moduleId, `${modulePath}.moduleId`);\n }\n }\n\n return registrations as ReturnType<\n InternalBackendRegistrations['getRegistrations']\n >;\n}\n\n/**\n * Validates the nested extension point and dependency data consumed while a\n * single plugin or module registration is enumerated.\n *\n * The registration object and its identifying fields have already been\n * validated by {@link validateBackendRegistrations}. Duplicate and conflicting\n * registrations are handled separately by the backend initializer.\n */\nexport function validateBackendRegistration(\n registration: ReturnType<\n InternalBackendRegistrations['getRegistrations']\n >[number],\n): void {\n let registrationPath = 'registration';\n if ('moduleId' in registration) {\n registrationPath = `module ${JSON.stringify(\n registration.moduleId,\n )} for plugin ${JSON.stringify(registration.pluginId)}`;\n } else if ('pluginId' in registration) {\n registrationPath = `plugin ${JSON.stringify(registration.pluginId)}`;\n }\n\n if (registration.type === 'plugin' || registration.type === 'module') {\n assertArray(\n registration.extensionPoints,\n `${registrationPath}.extensionPoints`,\n );\n for (let index = 0; index < registration.extensionPoints.length; index++) {\n const itemPath = `${registrationPath}.extensionPoints[${index}]`;\n const item: unknown = registration.extensionPoints[index];\n assertArray(item, itemPath);\n validateExtensionPoint(item[0], `${itemPath}[0]`);\n }\n } else if (\n registration.type === 'plugin-v1.1' ||\n registration.type === 'module-v1.1'\n ) {\n assertArray(\n registration.extensionPoints,\n `${registrationPath}.extensionPoints`,\n );\n for (let index = 0; index < registration.extensionPoints.length; index++) {\n const itemPath = `${registrationPath}.extensionPoints[${index}]`;\n const item: unknown = registration.extensionPoints[index];\n assertObject(item, itemPath, 'an extension point registration object');\n validateExtensionPoint(item.extensionPoint, `${itemPath}.extensionPoint`);\n }\n }\n\n if (\n registration.type === 'plugin' ||\n registration.type === 'module' ||\n registration.type === 'plugin-v1.1' ||\n registration.type === 'module-v1.1'\n ) {\n assertObject(\n registration.init,\n `${registrationPath}.init`,\n 'an init registration object',\n );\n assertObject(\n registration.init.deps,\n `${registrationPath}.init.deps`,\n 'a dependency object',\n );\n for (const [name, ref] of Object.entries(registration.init.deps)) {\n const path = `${registrationPath}.init.deps.${name}`;\n if (\n (registration.type === 'module' ||\n registration.type === 'module-v1.1') &&\n typeof ref === 'object' &&\n ref !== null &&\n (ref as { $$type?: unknown }).$$type === '@backstage/ExtensionPoint'\n ) {\n validateExtensionPoint(ref, path);\n } else {\n validateServiceRef(ref, path);\n }\n }\n }\n}\n\nexport function describeBackendFeature(value: unknown): string | undefined {\n if (\n (typeof value !== 'object' || value === null) &&\n typeof value !== 'function'\n ) {\n return undefined;\n }\n\n const feature = value as Record<string, unknown>;\n const service = feature.service;\n if (typeof service === 'object' && service !== null && 'id' in service) {\n const serviceId = service.id;\n if (typeof serviceId === 'string') {\n return `service factory for ${JSON.stringify(serviceId)}`;\n }\n }\n\n if (\n feature.featureType === 'loader' &&\n typeof feature.description === 'string'\n ) {\n return `feature loader ${feature.description}`;\n }\n\n if (typeof feature.description === 'string') {\n return `backend feature ${feature.description}`;\n }\n\n return undefined;\n}\n\nexport function validateBackendFeature(\n value: unknown,\n path: string,\n): ValidatedBackendFeature {\n assertObjectLike(value, path);\n if (value.$$type !== '@backstage/BackendFeature') {\n throwInvalidBackendFeature(\n `${path}.$$type`,\n '\"@backstage/BackendFeature\"',\n value.$$type,\n );\n }\n if (value.version !== 'v1') {\n throwInvalidBackendFeature(`${path}.version`, '\"v1\"', value.version);\n }\n\n if (value.featureType === 'service' || 'service' in value) {\n return {\n type: 'service',\n feature: value as unknown as InternalServiceFactory,\n };\n }\n if (value.featureType === 'loader') {\n return {\n type: 'loader',\n feature: value as unknown as InternalBackendFeatureLoader,\n };\n }\n if (value.featureType === 'registrations' || 'getRegistrations' in value) {\n return {\n type: 'registrations',\n feature: value as unknown as InternalBackendRegistrations,\n };\n }\n\n return throwInvalidBackendFeature(\n `${path}.featureType`,\n '\"service\", \"registrations\", or \"loader\"',\n value.featureType,\n );\n}\n"],"names":["InputError"],"mappings":";;;;AA+BA,SAAS,cAAc,KAAA,EAAwB;AAC7C,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA,OAAO,WAAA;AAAA,EACT;AACA,EAAA,IAAI,UAAU,IAAA,EAAM;AAClB,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,OAAO,IAAA,CAAK,UAAU,KAAK,CAAA;AAAA,EAC7B;AACA,EAAA,IACE,OAAO,UAAU,QAAA,IACjB,OAAO,UAAU,SAAA,IACjB,OAAO,UAAU,QAAA,EACjB;AACA,IAAA,OAAO,OAAO,KAAK,CAAA;AAAA,EACrB;AACA,EAAA,IAAI,OAAO,UAAU,UAAA,EAAY;AAC/B,IAAA,OAAO,YAAA;AAAA,EACT;AACA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,IAAA,OAAO,UAAA;AAAA,EACT;AACA,EAAA,OAAO,WAAA;AACT;AAEO,SAAS,0BAAA,CACd,IAAA,EACA,QAAA,EACA,KAAA,EACO;AACP,EAAA,MAAM,IAAIA,iBAAA;AAAA,IACR,CAAA,2BAAA,EAA8B,IAAI,CAAA,WAAA,EAAc,QAAQ,CAAA,WAAA,EAAc,aAAA;AAAA,MACpE;AAAA,KACD,CAAA;AAAA,GACH;AACF;AAEO,SAAS,YAAA,CACd,KAAA,EACA,IAAA,EACA,QAAA,GAAW,WAAA,EAC+B;AAC1C,EAAA,IAAI,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACvE,IAAA,0BAAA,CAA2B,IAAA,EAAM,UAAU,KAAK,CAAA;AAAA,EAClD;AACF;AAEO,SAAS,gBAAA,CACd,OACA,IAAA,EAC0C;AAC1C,EAAA,IAAA,CACG,OAAO,KAAA,KAAU,QAAA,IAAY,UAAU,IAAA,KACxC,OAAO,UAAU,UAAA,EACjB;AACA,IAAA,0BAAA,CAA2B,IAAA,EAAM,yBAAyB,KAAK,CAAA;AAAA,EACjE;AACF;AAEO,SAAS,YAAA,CACd,OACA,IAAA,EACyB;AACzB,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,0BAAA,CAA2B,IAAA,EAAM,YAAY,KAAK,CAAA;AAAA,EACpD;AACF;AAEO,SAAS,cAAA,CACd,OACA,IAAA,EAC8C;AAC9C,EAAA,IAAI,OAAO,UAAU,UAAA,EAAY;AAC/B,IAAA,0BAAA,CAA2B,IAAA,EAAM,cAAc,KAAK,CAAA;AAAA,EACtD;AACF;AAEO,SAAS,WAAA,CACd,OACA,IAAA,EAC4B;AAC5B,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACzB,IAAA,0BAAA,CAA2B,IAAA,EAAM,YAAY,KAAK,CAAA;AAAA,EACpD;AACF;AAEO,SAAS,kBAAA,CAAmB,OAAgB,IAAA,EAAoB;AACrE,EAAA,YAAA,CAAa,KAAA,EAAO,MAAM,4BAA4B,CAAA;AACtD,EAAA,YAAA,CAAa,KAAA,CAAM,EAAA,EAAI,CAAA,EAAG,IAAI,CAAA,GAAA,CAAK,CAAA;AACnC,EAAA,IAAI,KAAA,CAAM,KAAA,KAAU,MAAA,IAAU,KAAA,CAAM,UAAU,QAAA,EAAU;AACtD,IAAA,0BAAA;AAAA,MACE,GAAG,IAAI,CAAA,MAAA,CAAA;AAAA,MACP,oBAAA;AAAA,MACA,KAAA,CAAM;AAAA,KACR;AAAA,EACF;AACF;AAEO,SAAS,sBAAA,CAAuB,OAAgB,IAAA,EAAoB;AACzE,EAAA,YAAA,CAAa,KAAA,EAAO,MAAM,qCAAqC,CAAA;AAC/D,EAAA,YAAA,CAAa,KAAA,CAAM,EAAA,EAAI,CAAA,EAAG,IAAI,CAAA,GAAA,CAAK,CAAA;AACrC;AASO,SAAS,4BAAA,CACd,SACA,MAAA,EAC8D;AAC9D,EAAA,cAAA,CAAe,OAAA,CAAQ,gBAAA,EAAkB,CAAA,EAAG,MAAM,CAAA,iBAAA,CAAmB,CAAA;AACrE,EAAA,MAAM,aAAA,GAAyB,QAAQ,gBAAA,EAAiB;AACxD,EAAA,WAAA,CAAY,aAAA,EAAe,CAAA,EAAG,MAAM,CAAA,mBAAA,CAAqB,CAAA;AAEzD,EAAA,KAAA,IAAS,KAAA,GAAQ,CAAA,EAAG,KAAA,GAAQ,aAAA,CAAc,QAAQ,KAAA,EAAA,EAAS;AACzD,IAAA,MAAM,IAAA,GAAO,CAAA,EAAG,MAAM,CAAA,oBAAA,EAAuB,KAAK,CAAA,CAAA,CAAA;AAClD,IAAA,MAAM,YAAA,GAAe,cAAc,KAAK,CAAA;AACxC,IAAA,YAAA,CAAa,YAAA,EAAc,MAAM,uBAAuB,CAAA;AAExD,IAAA,IACE,YAAA,CAAa,IAAA,KAAS,QAAA,IACtB,YAAA,CAAa,IAAA,KAAS,QAAA,IACtB,YAAA,CAAa,IAAA,KAAS,aAAA,IACtB,YAAA,CAAa,IAAA,KAAS,aAAA,EACtB;AACA,MAAA,YAAA,CAAa,YAAA,CAAa,QAAA,EAAU,CAAA,EAAG,IAAI,CAAA,SAAA,CAAW,CAAA;AAAA,IACxD;AACA,IAAA,IAAI,YAAA,CAAa,IAAA,KAAS,QAAA,IAAY,YAAA,CAAa,SAAS,aAAA,EAAe;AACzE,MAAA,MAAM,aACJ,OAAO,YAAA,CAAa,QAAA,KAAa,QAAA,GAC7B,kCAAkC,IAAA,CAAK,SAAA;AAAA,QACrC,YAAA,CAAa;AAAA,OACd,CAAA,CAAA,GACD,IAAA;AACN,MAAA,YAAA,CAAa,YAAA,CAAa,QAAA,EAAU,CAAA,EAAG,UAAU,CAAA,SAAA,CAAW,CAAA;AAAA,IAC9D;AAAA,EACF;AAEA,EAAA,OAAO,aAAA;AAGT;AAUO,SAAS,4BACd,YAAA,EAGM;AACN,EAAA,IAAI,gBAAA,GAAmB,cAAA;AACvB,EAAA,IAAI,cAAc,YAAA,EAAc;AAC9B,IAAA,gBAAA,GAAmB,UAAU,IAAA,CAAK,SAAA;AAAA,MAChC,YAAA,CAAa;AAAA,KACd,CAAA,YAAA,EAAe,IAAA,CAAK,SAAA,CAAU,YAAA,CAAa,QAAQ,CAAC,CAAA,CAAA;AAAA,EACvD,CAAA,MAAA,IAAW,cAAc,YAAA,EAAc;AACrC,IAAA,gBAAA,GAAmB,CAAA,OAAA,EAAU,IAAA,CAAK,SAAA,CAAU,YAAA,CAAa,QAAQ,CAAC,CAAA,CAAA;AAAA,EACpE;AAEA,EAAA,IAAI,YAAA,CAAa,IAAA,KAAS,QAAA,IAAY,YAAA,CAAa,SAAS,QAAA,EAAU;AACpE,IAAA,WAAA;AAAA,MACE,YAAA,CAAa,eAAA;AAAA,MACb,GAAG,gBAAgB,CAAA,gBAAA;AAAA,KACrB;AACA,IAAA,KAAA,IAAS,QAAQ,CAAA,EAAG,KAAA,GAAQ,YAAA,CAAa,eAAA,CAAgB,QAAQ,KAAA,EAAA,EAAS;AACxE,MAAA,MAAM,QAAA,GAAW,CAAA,EAAG,gBAAgB,CAAA,iBAAA,EAAoB,KAAK,CAAA,CAAA,CAAA;AAC7D,MAAA,MAAM,IAAA,GAAgB,YAAA,CAAa,eAAA,CAAgB,KAAK,CAAA;AACxD,MAAA,WAAA,CAAY,MAAM,QAAQ,CAAA;AAC1B,MAAA,sBAAA,CAAuB,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,EAAG,QAAQ,CAAA,GAAA,CAAK,CAAA;AAAA,IAClD;AAAA,EACF,WACE,YAAA,CAAa,IAAA,KAAS,aAAA,IACtB,YAAA,CAAa,SAAS,aAAA,EACtB;AACA,IAAA,WAAA;AAAA,MACE,YAAA,CAAa,eAAA;AAAA,MACb,GAAG,gBAAgB,CAAA,gBAAA;AAAA,KACrB;AACA,IAAA,KAAA,IAAS,QAAQ,CAAA,EAAG,KAAA,GAAQ,YAAA,CAAa,eAAA,CAAgB,QAAQ,KAAA,EAAA,EAAS;AACxE,MAAA,MAAM,QAAA,GAAW,CAAA,EAAG,gBAAgB,CAAA,iBAAA,EAAoB,KAAK,CAAA,CAAA,CAAA;AAC7D,MAAA,MAAM,IAAA,GAAgB,YAAA,CAAa,eAAA,CAAgB,KAAK,CAAA;AACxD,MAAA,YAAA,CAAa,IAAA,EAAM,UAAU,wCAAwC,CAAA;AACrE,MAAA,sBAAA,CAAuB,IAAA,CAAK,cAAA,EAAgB,CAAA,EAAG,QAAQ,CAAA,eAAA,CAAiB,CAAA;AAAA,IAC1E;AAAA,EACF;AAEA,EAAA,IACE,YAAA,CAAa,IAAA,KAAS,QAAA,IACtB,YAAA,CAAa,IAAA,KAAS,QAAA,IACtB,YAAA,CAAa,IAAA,KAAS,aAAA,IACtB,YAAA,CAAa,IAAA,KAAS,aAAA,EACtB;AACA,IAAA,YAAA;AAAA,MACE,YAAA,CAAa,IAAA;AAAA,MACb,GAAG,gBAAgB,CAAA,KAAA,CAAA;AAAA,MACnB;AAAA,KACF;AACA,IAAA,YAAA;AAAA,MACE,aAAa,IAAA,CAAK,IAAA;AAAA,MAClB,GAAG,gBAAgB,CAAA,UAAA,CAAA;AAAA,MACnB;AAAA,KACF;AACA,IAAA,KAAA,MAAW,CAAC,MAAM,GAAG,CAAA,IAAK,OAAO,OAAA,CAAQ,YAAA,CAAa,IAAA,CAAK,IAAI,CAAA,EAAG;AAChE,MAAA,MAAM,IAAA,GAAO,CAAA,EAAG,gBAAgB,CAAA,WAAA,EAAc,IAAI,CAAA,CAAA;AAClD,MAAA,IAAA,CACG,YAAA,CAAa,IAAA,KAAS,QAAA,IACrB,YAAA,CAAa,IAAA,KAAS,aAAA,KACxB,OAAO,GAAA,KAAQ,QAAA,IACf,GAAA,KAAQ,IAAA,IACP,GAAA,CAA6B,WAAW,2BAAA,EACzC;AACA,QAAA,sBAAA,CAAuB,KAAK,IAAI,CAAA;AAAA,MAClC,CAAA,MAAO;AACL,QAAA,kBAAA,CAAmB,KAAK,IAAI,CAAA;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,uBAAuB,KAAA,EAAoC;AACzE,EAAA,IAAA,CACG,OAAO,KAAA,KAAU,QAAA,IAAY,UAAU,IAAA,KACxC,OAAO,UAAU,UAAA,EACjB;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,OAAA,GAAU,KAAA;AAChB,EAAA,MAAM,UAAU,OAAA,CAAQ,OAAA;AACxB,EAAA,IAAI,OAAO,OAAA,KAAY,QAAA,IAAY,OAAA,KAAY,IAAA,IAAQ,QAAQ,OAAA,EAAS;AACtE,IAAA,MAAM,YAAY,OAAA,CAAQ,EAAA;AAC1B,IAAA,IAAI,OAAO,cAAc,QAAA,EAAU;AACjC,MAAA,OAAO,CAAA,oBAAA,EAAuB,IAAA,CAAK,SAAA,CAAU,SAAS,CAAC,CAAA,CAAA;AAAA,IACzD;AAAA,EACF;AAEA,EAAA,IACE,QAAQ,WAAA,KAAgB,QAAA,IACxB,OAAO,OAAA,CAAQ,gBAAgB,QAAA,EAC/B;AACA,IAAA,OAAO,CAAA,eAAA,EAAkB,QAAQ,WAAW,CAAA,CAAA;AAAA,EAC9C;AAEA,EAAA,IAAI,OAAO,OAAA,CAAQ,WAAA,KAAgB,QAAA,EAAU;AAC3C,IAAA,OAAO,CAAA,gBAAA,EAAmB,QAAQ,WAAW,CAAA,CAAA;AAAA,EAC/C;AAEA,EAAA,OAAO,MAAA;AACT;AAEO,SAAS,sBAAA,CACd,OACA,IAAA,EACyB;AACzB,EAAA,gBAAA,CAAiB,OAAO,IAAI,CAAA;AAC5B,EAAA,IAAI,KAAA,CAAM,WAAW,2BAAA,EAA6B;AAChD,IAAA,0BAAA;AAAA,MACE,GAAG,IAAI,CAAA,OAAA,CAAA;AAAA,MACP,6BAAA;AAAA,MACA,KAAA,CAAM;AAAA,KACR;AAAA,EACF;AACA,EAAA,IAAI,KAAA,CAAM,YAAY,IAAA,EAAM;AAC1B,IAAA,0BAAA,CAA2B,CAAA,EAAG,IAAI,CAAA,QAAA,CAAA,EAAY,MAAA,EAAQ,MAAM,OAAO,CAAA;AAAA,EACrE;AAEA,EAAA,IAAI,KAAA,CAAM,WAAA,KAAgB,SAAA,IAAa,SAAA,IAAa,KAAA,EAAO;AACzD,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,SAAA;AAAA,MACN,OAAA,EAAS;AAAA,KACX;AAAA,EACF;AACA,EAAA,IAAI,KAAA,CAAM,gBAAgB,QAAA,EAAU;AAClC,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,QAAA;AAAA,MACN,OAAA,EAAS;AAAA,KACX;AAAA,EACF;AACA,EAAA,IAAI,KAAA,CAAM,WAAA,KAAgB,eAAA,IAAmB,kBAAA,IAAsB,KAAA,EAAO;AACxE,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,eAAA;AAAA,MACN,OAAA,EAAS;AAAA,KACX;AAAA,EACF;AAEA,EAAA,OAAO,0BAAA;AAAA,IACL,GAAG,IAAI,CAAA,YAAA,CAAA;AAAA,IACP,yCAAA;AAAA,IACA,KAAA,CAAM;AAAA,GACR;AACF;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/backend-app-api",
3
- "version": "1.7.3-next.0",
3
+ "version": "1.7.3",
4
4
  "description": "Core API used by Backstage backend apps",
5
5
  "backstage": {
6
6
  "role": "node-library"
@@ -50,17 +50,17 @@
50
50
  "test": "backstage-cli package test"
51
51
  },
52
52
  "dependencies": {
53
- "@backstage/backend-plugin-api": "1.10.0-next.0",
54
- "@backstage/config": "1.3.8",
55
- "@backstage/connections": "0.3.0-next.0",
56
- "@backstage/errors": "1.3.1",
57
- "@backstage/types": "1.2.2",
53
+ "@backstage/backend-plugin-api": "^1.10.0",
54
+ "@backstage/config": "^1.3.8",
55
+ "@backstage/connections": "^0.3.0",
56
+ "@backstage/errors": "^1.3.1",
57
+ "@backstage/types": "^1.2.2",
58
58
  "zod": "^3.25.76 || ^4.0.0"
59
59
  },
60
60
  "devDependencies": {
61
- "@backstage/backend-defaults": "0.17.6-next.0",
62
- "@backstage/backend-test-utils": "1.11.6-next.0",
63
- "@backstage/cli": "0.36.4"
61
+ "@backstage/backend-defaults": "^0.17.7",
62
+ "@backstage/backend-test-utils": "^1.11.6",
63
+ "@backstage/cli": "^0.36.5"
64
64
  },
65
65
  "configSchema": "config.schema.json"
66
66
  }
@@ -1,26 +0,0 @@
1
- 'use strict';
2
-
3
- function combineConnectionSources(legacy, fromConfig, logger) {
4
- const typeOf = (c) => c.type;
5
- const typesInConfig = new Set(fromConfig.map(typeOf));
6
- const warned = /* @__PURE__ */ new Set();
7
- const result = [];
8
- for (const legacyConn of legacy) {
9
- const type = typeOf(legacyConn);
10
- if (typesInConfig.has(type)) {
11
- if (!warned.has(type)) {
12
- warned.add(type);
13
- logger.warn(
14
- `Connection type "${type}" is defined in both legacy integrations and connections config; legacy integrations of this type are ignored.`
15
- );
16
- }
17
- continue;
18
- }
19
- result.push(legacyConn);
20
- }
21
- result.push(...fromConfig);
22
- return result;
23
- }
24
-
25
- exports.combineConnectionSources = combineConnectionSources;
26
- //# sourceMappingURL=combineConnectionSources.cjs.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"combineConnectionSources.cjs.js","sources":["../../../../connections-node/src/combineConnectionSources.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 */\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport type { RootConnection } from './types';\n\n/**\n * Merges connections derived from legacy `integrations.*` config with\n * connections defined explicitly in `connections:` config.\n *\n * If any entry in `fromConfig` declares a given connection type, all legacy\n * entries of that type are discarded — the connections config fully takes\n * over for that type. A single warning is logged per discarded type.\n */\nexport function combineConnectionSources(\n legacy: RootConnection[],\n fromConfig: RootConnection[],\n logger: LoggerService,\n): RootConnection[] {\n const typeOf = (c: RootConnection) => c.type as string;\n const typesInConfig = new Set(fromConfig.map(typeOf));\n\n const warned = new Set<string>();\n const result: RootConnection[] = [];\n\n for (const legacyConn of legacy) {\n const type = typeOf(legacyConn);\n if (typesInConfig.has(type)) {\n if (!warned.has(type)) {\n warned.add(type);\n logger.warn(\n `Connection type \"${type}\" is defined in both legacy integrations and connections config; legacy integrations of this type are ignored.`,\n );\n }\n continue;\n }\n result.push(legacyConn);\n }\n\n result.push(...fromConfig);\n\n return result;\n}\n"],"names":[],"mappings":";;AA0BO,SAAS,wBAAA,CACd,MAAA,EACA,UAAA,EACA,MAAA,EACkB;AAClB,EAAA,MAAM,MAAA,GAAS,CAAC,CAAA,KAAsB,CAAA,CAAE,IAAA;AACxC,EAAA,MAAM,gBAAgB,IAAI,GAAA,CAAI,UAAA,CAAW,GAAA,CAAI,MAAM,CAAC,CAAA;AAEpD,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAY;AAC/B,EAAA,MAAM,SAA2B,EAAC;AAElC,EAAA,KAAA,MAAW,cAAc,MAAA,EAAQ;AAC/B,IAAA,MAAM,IAAA,GAAO,OAAO,UAAU,CAAA;AAC9B,IAAA,IAAI,aAAA,CAAc,GAAA,CAAI,IAAI,CAAA,EAAG;AAC3B,MAAA,IAAI,CAAC,MAAA,CAAO,GAAA,CAAI,IAAI,CAAA,EAAG;AACrB,QAAA,MAAA,CAAO,IAAI,IAAI,CAAA;AACf,QAAA,MAAA,CAAO,IAAA;AAAA,UACL,oBAAoB,IAAI,CAAA,8GAAA;AAAA,SAC1B;AAAA,MACF;AACA,MAAA;AAAA,IACF;AACA,IAAA,MAAA,CAAO,KAAK,UAAU,CAAA;AAAA,EACxB;AAEA,EAAA,MAAA,CAAO,IAAA,CAAK,GAAG,UAAU,CAAA;AAEzB,EAAA,OAAO,MAAA;AACT;;;;"}