@backstage/backend-app-api 1.7.1-next.0 → 1.7.2-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/config.schema.json +95 -0
- package/dist/backend-internal/src/wiring/helpers.cjs.js +18 -0
- package/dist/backend-internal/src/wiring/helpers.cjs.js.map +1 -0
- package/dist/wiring/BackendInitializer.cjs.js +58 -3
- package/dist/wiring/BackendInitializer.cjs.js.map +1 -1
- package/dist/wiring/BackstageBackend.cjs.js +3 -5
- package/dist/wiring/BackstageBackend.cjs.js.map +1 -1
- package/dist/wiring/ServiceRegistry.cjs.js +3 -1
- package/dist/wiring/ServiceRegistry.cjs.js.map +1 -1
- package/dist/wiring/helpers.cjs.js +0 -10
- package/dist/wiring/helpers.cjs.js.map +1 -1
- package/dist/wiring/withDeclaredConnections.cjs.js +22 -0
- package/dist/wiring/withDeclaredConnections.cjs.js.map +1 -0
- package/package.json +9 -7
- package/config.d.ts +0 -74
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @backstage/backend-app-api
|
|
2
2
|
|
|
3
|
+
## 1.7.2-next.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
- @backstage/backend-plugin-api@1.9.3-next.0
|
|
9
|
+
- @backstage/connections@0.1.1-next.0
|
|
10
|
+
|
|
11
|
+
## 1.7.1
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- 2e895ea: Internal refactor.
|
|
16
|
+
- Updated dependencies
|
|
17
|
+
- @backstage/connections@0.1.0
|
|
18
|
+
- @backstage/backend-plugin-api@1.9.2
|
|
19
|
+
|
|
3
20
|
## 1.7.1-next.0
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"properties": {
|
|
5
|
+
"backend": {
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"packages": {
|
|
9
|
+
"anyOf": [
|
|
10
|
+
{
|
|
11
|
+
"type": "string",
|
|
12
|
+
"const": "all"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"type": "object",
|
|
16
|
+
"properties": {
|
|
17
|
+
"include": {
|
|
18
|
+
"type": "array",
|
|
19
|
+
"items": {
|
|
20
|
+
"type": "string"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"exclude": {
|
|
24
|
+
"type": "array",
|
|
25
|
+
"items": {
|
|
26
|
+
"type": "string"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
"description": "Used by the feature discovery service"
|
|
33
|
+
},
|
|
34
|
+
"startup": {
|
|
35
|
+
"type": "object",
|
|
36
|
+
"properties": {
|
|
37
|
+
"default": {
|
|
38
|
+
"type": "object",
|
|
39
|
+
"properties": {
|
|
40
|
+
"onPluginBootFailure": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"enum": [
|
|
43
|
+
"continue",
|
|
44
|
+
"abort"
|
|
45
|
+
],
|
|
46
|
+
"description": "The default value for `onPluginBootFailure` if not specified for a particular plugin. This defaults to 'abort', which means `onPluginBootFailure: continue` must be specified for backend startup to continue on plugin boot failure. This can also be set to 'continue', which flips the logic for individual plugins so that they must be set to `onPluginBootFailure: abort` to be required."
|
|
47
|
+
},
|
|
48
|
+
"onPluginModuleBootFailure": {
|
|
49
|
+
"type": "string",
|
|
50
|
+
"enum": [
|
|
51
|
+
"continue",
|
|
52
|
+
"abort"
|
|
53
|
+
],
|
|
54
|
+
"description": "The default value for `onPluginModuleBootFailure` if not specified for a particular plugin module. This defaults to 'abort', which means `onPluginModuleBootFailure: continue` must be specified for backend startup to continue on plugin module boot failure. This can also be set to 'continue', which flips the logic for individual plugin modules so that they must be set to `onPluginModuleBootFailure: abort` to be required."
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"plugins": {
|
|
59
|
+
"type": "object",
|
|
60
|
+
"additionalProperties": {
|
|
61
|
+
"type": "object",
|
|
62
|
+
"properties": {
|
|
63
|
+
"onPluginBootFailure": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"enum": [
|
|
66
|
+
"continue",
|
|
67
|
+
"abort"
|
|
68
|
+
],
|
|
69
|
+
"description": "Used to control backend startup behavior when this plugin fails to boot up. Setting this to `continue` allows the backend to continue starting up, even if this plugin fails. This can enable leaving a crashing plugin installed, but still permit backend startup, which may help troubleshoot data-dependent issues. Plugin failures for plugins set to `abort` are fatal (this is the default unless overridden by the `default` setting)."
|
|
70
|
+
},
|
|
71
|
+
"modules": {
|
|
72
|
+
"type": "object",
|
|
73
|
+
"additionalProperties": {
|
|
74
|
+
"type": "object",
|
|
75
|
+
"properties": {
|
|
76
|
+
"onPluginModuleBootFailure": {
|
|
77
|
+
"type": "string",
|
|
78
|
+
"enum": [
|
|
79
|
+
"continue",
|
|
80
|
+
"abort"
|
|
81
|
+
],
|
|
82
|
+
"description": "Used to control backend startup behavior when this plugin module fails to boot up. Setting this to `continue` allows the backend to continue starting up, even if this plugin module fails. This can enable leaving a crashing plugin installed, but still permit backend startup, which may help troubleshoot data-dependent issues. Plugin module failures for plugin modules set to `abort` are fatal (this is the default unless overridden by the `default` setting)."
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -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;;;;;"}
|
|
@@ -5,10 +5,13 @@ var errors = require('@backstage/errors');
|
|
|
5
5
|
var DependencyGraph = require('../lib/DependencyGraph.cjs.js');
|
|
6
6
|
var ServiceRegistry = require('./ServiceRegistry.cjs.js');
|
|
7
7
|
var createInitializationResultCollector = require('./createInitializationResultCollector.cjs.js');
|
|
8
|
-
var helpers = require('./helpers.cjs.js');
|
|
8
|
+
var helpers$1 = require('./helpers.cjs.js');
|
|
9
9
|
var BackendStartupError = require('./BackendStartupError.cjs.js');
|
|
10
10
|
var createAllowBootFailurePredicate = require('./createAllowBootFailurePredicate.cjs.js');
|
|
11
|
+
var connections = require('@backstage/connections');
|
|
12
|
+
var withDeclaredConnections = require('./withDeclaredConnections.cjs.js');
|
|
11
13
|
var OpaqueExtensionPointFactoryMiddleware = require('../backend-internal/src/wiring/OpaqueExtensionPointFactoryMiddleware.cjs.js');
|
|
14
|
+
var helpers = require('../backend-internal/src/wiring/helpers.cjs.js');
|
|
12
15
|
|
|
13
16
|
const instanceRegistry = new class InstanceRegistry {
|
|
14
17
|
#registered = false;
|
|
@@ -47,6 +50,28 @@ const instanceRegistry = new class InstanceRegistry {
|
|
|
47
50
|
}
|
|
48
51
|
};
|
|
49
52
|
}();
|
|
53
|
+
function callerKey(pluginId, moduleId) {
|
|
54
|
+
return moduleId ? `${pluginId}\0${moduleId}` : pluginId;
|
|
55
|
+
}
|
|
56
|
+
function collectCallerConnectionRegistrations(registrations) {
|
|
57
|
+
const byCaller = /* @__PURE__ */ new Map();
|
|
58
|
+
for (const registration of registrations) {
|
|
59
|
+
const declared = "connections" in registration && Array.isArray(registration.connections) ? registration.connections : [];
|
|
60
|
+
if (declared.length === 0) continue;
|
|
61
|
+
const key = "moduleId" in registration ? callerKey(registration.pluginId, registration.moduleId) : callerKey(registration.pluginId);
|
|
62
|
+
const target = byCaller.get(key) ?? (() => {
|
|
63
|
+
const list = [];
|
|
64
|
+
byCaller.set(key, list);
|
|
65
|
+
return list;
|
|
66
|
+
})();
|
|
67
|
+
for (const decl of declared) {
|
|
68
|
+
if (!target.some((c) => c.type === decl.type)) {
|
|
69
|
+
target.push({ ...decl });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return byCaller;
|
|
74
|
+
}
|
|
50
75
|
function createRootInstanceMetadataServiceFactory(rawRegistrations) {
|
|
51
76
|
const installedPlugins = /* @__PURE__ */ new Map();
|
|
52
77
|
const registrations = rawRegistrations.filter((registration) => registration.featureType === "registrations").flatMap((registration) => registration.getRegistrations());
|
|
@@ -78,7 +103,7 @@ function createRootInstanceMetadataServiceFactory(rawRegistrations) {
|
|
|
78
103
|
service: backendPluginApi.coreServices.rootInstanceMetadata,
|
|
79
104
|
deps: {},
|
|
80
105
|
factory: async () => {
|
|
81
|
-
const readonlyInstalledPlugins = helpers.deepFreeze([
|
|
106
|
+
const readonlyInstalledPlugins = helpers$1.deepFreeze([
|
|
82
107
|
...installedPlugins.values()
|
|
83
108
|
]);
|
|
84
109
|
const instanceMetadata = {
|
|
@@ -97,6 +122,21 @@ class BackendInitializer {
|
|
|
97
122
|
#registeredFeatures = new Array();
|
|
98
123
|
#registeredFeatureLoaders = new Array();
|
|
99
124
|
#extensionPointFactoryMiddleware;
|
|
125
|
+
#callerConnectionRegistrations = /* @__PURE__ */ new Map();
|
|
126
|
+
#getConnectionRegistrations(pluginId, moduleId) {
|
|
127
|
+
if (moduleId) {
|
|
128
|
+
return this.#callerConnectionRegistrations.get(
|
|
129
|
+
callerKey(pluginId, moduleId)
|
|
130
|
+
) ?? [];
|
|
131
|
+
}
|
|
132
|
+
const result = [];
|
|
133
|
+
for (const [key, registrations] of this.#callerConnectionRegistrations) {
|
|
134
|
+
if (key === pluginId) {
|
|
135
|
+
result.push(...registrations);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
100
140
|
#unhandledRejectionHandler;
|
|
101
141
|
#uncaughtExceptionHandler;
|
|
102
142
|
constructor(defaultApiFactories, extensionPointFactoryMiddleware) {
|
|
@@ -137,7 +177,21 @@ class BackendInitializer {
|
|
|
137
177
|
pluginId
|
|
138
178
|
);
|
|
139
179
|
if (impl) {
|
|
140
|
-
|
|
180
|
+
if (ref.id === connections.connectionsServiceRef.id) {
|
|
181
|
+
const registrations = this.#getConnectionRegistrations(
|
|
182
|
+
pluginId,
|
|
183
|
+
moduleId
|
|
184
|
+
);
|
|
185
|
+
result.set(
|
|
186
|
+
name,
|
|
187
|
+
withDeclaredConnections.withDeclaredConnections(
|
|
188
|
+
impl,
|
|
189
|
+
registrations
|
|
190
|
+
)
|
|
191
|
+
);
|
|
192
|
+
} else {
|
|
193
|
+
result.set(name, impl);
|
|
194
|
+
}
|
|
141
195
|
} else {
|
|
142
196
|
missingRefs.add(ref);
|
|
143
197
|
}
|
|
@@ -217,6 +271,7 @@ class BackendInitializer {
|
|
|
217
271
|
const allRegistrations = this.#registrations.flatMap(
|
|
218
272
|
(f) => f.getRegistrations()
|
|
219
273
|
);
|
|
274
|
+
this.#callerConnectionRegistrations = collectCallerConnectionRegistrations(allRegistrations);
|
|
220
275
|
const allPluginIds = [
|
|
221
276
|
...new Set(
|
|
222
277
|
allRegistrations.flatMap(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BackendInitializer.cjs.js","sources":["../../src/wiring/BackendInitializer.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 BackendFeature,\n ExtensionPoint,\n coreServices,\n ServiceRef,\n ServiceFactory,\n LifecycleService,\n RootLifecycleService,\n createServiceFactory,\n ExtensionPointFactoryContext,\n} from '@backstage/backend-plugin-api';\nimport {\n ExtensionPointFactoryMiddleware,\n ServiceOrExtensionPoint,\n} from './types';\nimport { OpaqueExtensionPointFactoryMiddleware } from '@internal/backend';\n// Direct internal import to avoid duplication\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport type {\n InternalBackendFeature,\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';\nimport { ConflictError, ForwardedError, toError } from '@backstage/errors';\nimport { DependencyGraph } from '../lib/DependencyGraph';\nimport { ServiceRegistry } from './ServiceRegistry';\nimport { createInitializationResultCollector } from './createInitializationResultCollector';\nimport { deepFreeze, unwrapFeature } from './helpers';\nimport type { RootInstanceMetadataServicePluginInfo } from '@backstage/backend-plugin-api';\nimport { BackendStartupResult } from './types';\nimport { BackendStartupError } from './BackendStartupError';\nimport { createAllowBootFailurePredicate } from './createAllowBootFailurePredicate';\n\nexport interface BackendRegisterInit {\n consumes: Set<ServiceOrExtensionPoint>;\n provides: Set<ServiceOrExtensionPoint>;\n init: {\n deps: { [name: string]: ServiceOrExtensionPoint };\n func: (deps: { [name: string]: unknown }) => Promise<void>;\n };\n}\n\n/**\n * A registry of backend instances, used to manage process shutdown hooks across all instances.\n */\nconst instanceRegistry = new (class InstanceRegistry {\n #registered = false;\n #instances = new Set<BackendInitializer>();\n\n register(instance: BackendInitializer) {\n if (!this.#registered) {\n this.#registered = true;\n\n process.addListener('SIGTERM', this.#exitHandler);\n process.addListener('SIGINT', this.#exitHandler);\n process.addListener('beforeExit', this.#exitHandler);\n }\n\n this.#instances.add(instance);\n }\n\n unregister(instance: BackendInitializer) {\n this.#instances.delete(instance);\n }\n\n #exitHandler = async () => {\n try {\n const results = await Promise.allSettled(\n Array.from(this.#instances).map(b => b.stop()),\n );\n const errors = results.flatMap(r =>\n r.status === 'rejected' ? [r.reason] : [],\n );\n\n if (errors.length > 0) {\n for (const error of errors) {\n console.error(error);\n }\n process.exit(1);\n } else {\n process.exit(0);\n }\n } catch (error) {\n console.error(error);\n process.exit(1);\n }\n };\n})();\n\nfunction createRootInstanceMetadataServiceFactory(\n rawRegistrations: InternalBackendRegistrations[],\n) {\n const installedPlugins: Map<string, RootInstanceMetadataServicePluginInfo> =\n new Map();\n const registrations = rawRegistrations\n .filter(registration => registration.featureType === 'registrations')\n .flatMap(registration => registration.getRegistrations());\n const plugins = registrations.filter(\n registration =>\n registration.type === 'plugin' || registration.type === 'plugin-v1.1',\n );\n const modules = registrations.filter(\n registration =>\n registration.type === 'module' || registration.type === 'module-v1.1',\n );\n for (const plugin of plugins) {\n const { pluginId } = plugin;\n if (!installedPlugins.get(pluginId)) {\n installedPlugins.set(pluginId, {\n pluginId,\n modules: [],\n });\n }\n }\n for (const module of modules) {\n const { pluginId, moduleId } = module;\n const installedPlugin = installedPlugins.get(pluginId);\n if (installedPlugin) {\n (installedPlugin.modules as Array<{ moduleId: string }>).push({\n moduleId,\n });\n }\n }\n\n return createServiceFactory({\n service: coreServices.rootInstanceMetadata,\n deps: {},\n factory: async () => {\n const readonlyInstalledPlugins = deepFreeze([\n ...installedPlugins.values(),\n ]);\n const instanceMetadata = {\n getInstalledPlugins: () => Promise.resolve(readonlyInstalledPlugins),\n };\n\n return instanceMetadata;\n },\n });\n}\n\nexport class BackendInitializer {\n #startPromise?: Promise<{ result: BackendStartupResult }>;\n #stopPromise?: Promise<void>;\n #registrations = new Array<InternalBackendRegistrations>();\n #extensionPoints = new Map<\n string,\n {\n pluginId: string;\n factory: (context: ExtensionPointFactoryContext) => unknown;\n }\n >();\n #serviceRegistry: ServiceRegistry;\n #registeredFeatures = new Array<Promise<BackendFeature>>();\n #registeredFeatureLoaders = new Array<InternalBackendFeatureLoader>();\n #extensionPointFactoryMiddleware: ExtensionPointFactoryMiddleware[];\n #unhandledRejectionHandler?: (reason: Error) => void;\n #uncaughtExceptionHandler?: (error: Error) => void;\n\n constructor(\n defaultApiFactories: ServiceFactory[],\n extensionPointFactoryMiddleware?: ExtensionPointFactoryMiddleware[],\n ) {\n this.#serviceRegistry = ServiceRegistry.create([...defaultApiFactories]);\n this.#extensionPointFactoryMiddleware =\n extensionPointFactoryMiddleware ?? [];\n }\n\n async #getInitDeps(\n deps: { [name: string]: ServiceOrExtensionPoint },\n resultCollector: ReturnType<typeof createInitializationResultCollector>,\n pluginId: string,\n moduleId?: string,\n ) {\n const result = new Map<string, unknown>();\n const missingRefs = new Set<ServiceOrExtensionPoint>();\n\n for (const [name, ref] of Object.entries(deps)) {\n const ep = this.#extensionPoints.get(ref.id);\n if (ep) {\n if (ep.pluginId !== pluginId) {\n throw new Error(\n `Illegal dependency: Module '${moduleId}' for plugin '${pluginId}' attempted to depend on extension point '${ref.id}' for plugin '${ep.pluginId}'. Extension points can only be used within their plugin's scope.`,\n );\n }\n if (!moduleId) {\n throw new Error(\n `Rejected dependency on extension point ${ref.id} from outside of a module`,\n );\n }\n let epImpl = ep.factory({\n reportModuleStartupFailure: ({ error }) => {\n resultCollector.amendPluginModuleResult(pluginId, moduleId, error);\n },\n });\n for (const mw of this.#extensionPointFactoryMiddleware) {\n const internal = OpaqueExtensionPointFactoryMiddleware.toInternal(mw);\n if (internal.extensionPointId === ref.id) {\n epImpl = await internal.middleware(epImpl);\n }\n }\n result.set(name, epImpl);\n } else {\n const impl = await this.#serviceRegistry.get(\n ref as ServiceRef<unknown>,\n pluginId,\n );\n if (impl) {\n result.set(name, impl);\n } else {\n missingRefs.add(ref);\n }\n }\n }\n\n if (missingRefs.size > 0) {\n const missing = Array.from(missingRefs).join(', ');\n const target = moduleId\n ? `module '${moduleId}' for plugin '${pluginId}'`\n : `plugin '${pluginId}'`;\n throw new Error(\n `Service or extension point dependencies of ${target} are missing for the following ref(s): ${missing}`,\n );\n }\n\n return Object.fromEntries(result);\n }\n\n add(feature: BackendFeature | Promise<BackendFeature>) {\n if (this.#startPromise) {\n throw new Error('feature can not be added after the backend has started');\n }\n this.#registeredFeatures.push(Promise.resolve(feature));\n }\n\n #addFeature(feature: BackendFeature) {\n if (isServiceFactory(feature)) {\n this.#serviceRegistry.add(feature);\n } else if (isBackendFeatureLoader(feature)) {\n this.#registeredFeatureLoaders.push(feature);\n } else if (isBackendRegistrations(feature)) {\n this.#registrations.push(feature);\n } else {\n throw new Error(\n `Failed to add feature, invalid feature ${JSON.stringify(feature)}`,\n );\n }\n }\n\n async start(): Promise<{ result: BackendStartupResult }> {\n if (this.#startPromise) {\n throw new Error('Backend has already started');\n }\n if (this.#stopPromise) {\n throw new Error('Backend has already stopped');\n }\n\n instanceRegistry.register(this);\n\n this.#startPromise = this.#doStart();\n return await this.#startPromise;\n }\n\n async #doStart(): Promise<{ result: BackendStartupResult }> {\n this.#serviceRegistry.checkForCircularDeps();\n\n for (const feature of this.#registeredFeatures) {\n this.#addFeature(await feature);\n }\n\n await this.#applyBackendFeatureLoaders(this.#registeredFeatureLoaders);\n\n this.#serviceRegistry.add(\n createRootInstanceMetadataServiceFactory(this.#registrations),\n );\n\n // This makes sure that any uncaught errors or unhandled rejections are\n // caught and logged, rather than terminating the process. We register these\n // as early as possible while still using the root logger service, the\n // tradeoff that if there are any unhandled errors as part of the that\n // instationation, it will cause the process to crash. If there are multiple\n // backend instances, each instance will log the error, because we can't\n // determine which instance the error came from.\n if (process.env.NODE_ENV !== 'test') {\n const rootLogger = await this.#serviceRegistry.get(\n coreServices.rootLogger,\n 'root',\n );\n this.#unhandledRejectionHandler = (reason: Error) => {\n rootLogger\n ?.child({ type: 'unhandledRejection' })\n ?.error('Unhandled rejection', reason);\n };\n this.#uncaughtExceptionHandler = (error: Error) => {\n rootLogger\n ?.child({ type: 'uncaughtException' })\n ?.error('Uncaught exception', error);\n };\n process.on('unhandledRejection', this.#unhandledRejectionHandler);\n process.on('uncaughtException', this.#uncaughtExceptionHandler);\n }\n\n // Initialize all root scoped services\n await this.#serviceRegistry.initializeEagerServicesWithScope('root');\n\n const rootConfig = await this.#serviceRegistry.get(\n coreServices.rootConfig,\n 'root',\n );\n const rootLogger = await this.#serviceRegistry.get(\n coreServices.rootLogger,\n 'root',\n );\n\n const allRegistrations = this.#registrations.flatMap(f =>\n f.getRegistrations(),\n );\n\n const allPluginIds = [\n ...new Set(\n allRegistrations.flatMap(r =>\n 'pluginId' in r && typeof r.pluginId === 'string' ? [r.pluginId] : [],\n ),\n ),\n ];\n\n const resultCollector = createInitializationResultCollector({\n pluginIds: allPluginIds,\n logger: rootLogger,\n allowBootFailurePredicate: createAllowBootFailurePredicate(rootConfig),\n });\n\n const { pluginInits, moduleInits } = this.#enumerateRegistrations(\n allRegistrations,\n resultCollector,\n );\n\n // All plugins are initialized in parallel\n await Promise.all(\n [...pluginInits.keys()].map(async pluginId => {\n try {\n // Initialize all eager services\n await this.#serviceRegistry.initializeEagerServicesWithScope(\n 'plugin',\n pluginId,\n );\n\n // Modules are initialized before plugins, so that they can provide extension to the plugin\n const modules = moduleInits.get(pluginId);\n if (modules) {\n const tree = DependencyGraph.fromIterable(\n Array.from(modules).map(([moduleId, moduleInit]) => ({\n value: { moduleId, moduleInit },\n // Relationships are reversed at this point since we're only interested in the extension points.\n // If a modules provides extension point A we want it to be initialized AFTER all modules\n // that depend on extension point A, so that they can provide their extensions.\n consumes: Array.from(moduleInit.provides).map(p => p.id),\n provides: Array.from(moduleInit.consumes).map(c => c.id),\n })),\n );\n const circular = tree.detectCircularDependency();\n if (circular) {\n throw new ConflictError(\n `Circular dependency detected for modules of plugin '${pluginId}', ${circular\n .map(({ moduleId }) => `'${moduleId}'`)\n .join(' -> ')}`,\n );\n }\n await tree.parallelTopologicalTraversal(\n async ({ moduleId, moduleInit }) => {\n try {\n const moduleDeps = await this.#getInitDeps(\n moduleInit.init.deps,\n resultCollector,\n pluginId,\n moduleId,\n );\n await moduleInit.init.func(moduleDeps);\n resultCollector.onPluginModuleResult(pluginId, moduleId);\n } catch (error: unknown) {\n const err = toError(error);\n resultCollector.onPluginModuleResult(pluginId, moduleId, err);\n }\n },\n );\n }\n\n // Once all modules have been initialized, we can initialize the plugin itself\n const pluginInit = pluginInits.get(pluginId);\n // We allow modules to be installed without the accompanying plugin, so the plugin may not exist\n if (pluginInit) {\n const pluginDeps = await this.#getInitDeps(\n pluginInit.init.deps,\n resultCollector,\n pluginId,\n );\n await pluginInit.init.func(pluginDeps);\n }\n\n resultCollector.onPluginResult(pluginId);\n\n // Once the plugin and all modules have been initialized, we can signal that the plugin has stared up successfully\n const lifecycleService = await this.#getPluginLifecycleImpl(pluginId);\n await lifecycleService.startup();\n } catch (error: unknown) {\n const err = toError(error);\n resultCollector.onPluginResult(pluginId, err);\n }\n }),\n ).catch(error => {\n throw new ForwardedError(\n 'Unexpected uncaught backend startup error',\n error,\n );\n });\n\n const result = resultCollector.finalize();\n if (result.outcome === 'failure') {\n throw new BackendStartupError(result);\n }\n\n // Once all plugins and modules have been initialized, we can signal that the backend has started up successfully\n const lifecycleService = await this.#getRootLifecycleImpl();\n await lifecycleService.startup();\n\n return { result };\n }\n\n #enumerateRegistrations(\n allRegistrations: ReturnType<\n InternalBackendRegistrations['getRegistrations']\n >,\n resultCollector: ReturnType<typeof createInitializationResultCollector>,\n ): {\n pluginInits: Map<string, BackendRegisterInit>;\n moduleInits: Map<string, Map<string, BackendRegisterInit>>;\n } {\n const pluginInits = new Map<string, BackendRegisterInit>();\n const moduleInits = new Map<string, Map<string, BackendRegisterInit>>();\n\n for (const r of allRegistrations) {\n const addedExtensionPointIds: string[] = [];\n try {\n const provides = new Set<ExtensionPoint<unknown>>();\n\n if (r.type === 'plugin' || r.type === 'module') {\n // Handle v1 format: Array<readonly [ExtensionPoint<unknown>, unknown]>\n for (const [extRef, extImpl] of r.extensionPoints) {\n if (this.#extensionPoints.has(extRef.id)) {\n throw new Error(\n `ExtensionPoint with ID '${extRef.id}' is already registered`,\n );\n }\n this.#extensionPoints.set(extRef.id, {\n pluginId: r.pluginId,\n factory: () => extImpl,\n });\n addedExtensionPointIds.push(extRef.id);\n provides.add(extRef);\n }\n } else if (r.type === 'plugin-v1.1' || r.type === 'module-v1.1') {\n // Handle v1.1 format: Array<ExtensionPointRegistration>\n for (const extReg of r.extensionPoints) {\n if (this.#extensionPoints.has(extReg.extensionPoint.id)) {\n throw new Error(\n `ExtensionPoint with ID '${extReg.extensionPoint.id}' is already registered`,\n );\n }\n this.#extensionPoints.set(extReg.extensionPoint.id, {\n pluginId: r.pluginId,\n factory: extReg.factory,\n });\n addedExtensionPointIds.push(extReg.extensionPoint.id);\n provides.add(extReg.extensionPoint);\n }\n }\n\n if (r.type === 'plugin' || r.type === 'plugin-v1.1') {\n if (pluginInits.has(r.pluginId)) {\n throw new Error(`Plugin '${r.pluginId}' is already registered`);\n }\n pluginInits.set(r.pluginId, {\n provides,\n consumes: new Set(Object.values(r.init.deps)),\n init: r.init,\n });\n } else if (r.type === 'module' || r.type === 'module-v1.1') {\n let modules = moduleInits.get(r.pluginId);\n if (!modules) {\n modules = new Map();\n moduleInits.set(r.pluginId, modules);\n }\n if (modules.has(r.moduleId)) {\n throw new Error(\n `Module '${r.moduleId}' for plugin '${r.pluginId}' is already registered`,\n );\n }\n modules.set(r.moduleId, {\n provides,\n consumes: new Set(Object.values(r.init.deps)),\n init: r.init,\n });\n } else {\n throw new Error(`Invalid registration type '${(r as any).type}'`);\n }\n } catch (error: unknown) {\n const err = toError(error);\n // Clean up partially registered extension points\n for (const id of addedExtensionPointIds) {\n this.#extensionPoints.delete(id);\n }\n if ('pluginId' in r && 'moduleId' in r) {\n resultCollector.onPluginModuleResult(r.pluginId, r.moduleId, err);\n } else if ('pluginId' in r) {\n pluginInits.delete(r.pluginId);\n moduleInits.delete(r.pluginId);\n resultCollector.onPluginResult(r.pluginId, err);\n } else {\n throw err;\n }\n }\n }\n\n return { pluginInits, moduleInits };\n }\n\n // It's fine to call .stop() multiple times, which for example can happen with manual stop + process exit\n async stop(): Promise<void> {\n instanceRegistry.unregister(this);\n\n if (!this.#stopPromise) {\n this.#stopPromise = this.#doStop();\n }\n await this.#stopPromise;\n }\n\n async #doStop(): Promise<void> {\n if (!this.#startPromise) {\n return;\n }\n\n try {\n await this.#startPromise;\n } catch (error) {\n // The startup failed, but we may still want to do cleanup so we continue silently\n }\n\n const rootLifecycleService = await this.#getRootLifecycleImpl();\n\n // Root services like the health one need to immediately be notified of the shutdown\n await rootLifecycleService.beforeShutdown();\n\n // Get all plugins.\n const allPlugins = new Set<string>();\n for (const feature of this.#registrations) {\n for (const r of feature.getRegistrations()) {\n if (r.type === 'plugin' || r.type === 'plugin-v1.1') {\n allPlugins.add(r.pluginId);\n }\n }\n }\n\n // Iterate through all plugins and run their shutdown hooks.\n await Promise.allSettled(\n [...allPlugins].map(async pluginId => {\n const lifecycleService = await this.#getPluginLifecycleImpl(pluginId);\n await lifecycleService.shutdown();\n }),\n );\n\n // Once all plugin shutdown hooks are done, run root shutdown hooks.\n await rootLifecycleService.shutdown();\n\n // Clean up process event listeners to prevent memory leaks and duplicate logging\n if (this.#unhandledRejectionHandler) {\n process.off('unhandledRejection', this.#unhandledRejectionHandler);\n this.#unhandledRejectionHandler = undefined;\n }\n if (this.#uncaughtExceptionHandler) {\n process.off('uncaughtException', this.#uncaughtExceptionHandler);\n this.#uncaughtExceptionHandler = undefined;\n }\n }\n\n // Bit of a hacky way to grab the lifecycle services, potentially find a nicer way to do this\n async #getRootLifecycleImpl(): Promise<\n RootLifecycleService & {\n startup(): Promise<void>;\n beforeShutdown(): Promise<void>;\n shutdown(): Promise<void>;\n }\n > {\n const lifecycleService = await this.#serviceRegistry.get(\n coreServices.rootLifecycle,\n 'root',\n );\n\n const service = lifecycleService as any;\n if (\n service &&\n typeof service.startup === 'function' &&\n typeof service.shutdown === 'function'\n ) {\n return service;\n }\n\n throw new Error('Unexpected root lifecycle service implementation');\n }\n\n async #getPluginLifecycleImpl(\n pluginId: string,\n ): Promise<\n LifecycleService & { startup(): Promise<void>; shutdown(): Promise<void> }\n > {\n const lifecycleService = await this.#serviceRegistry.get(\n coreServices.lifecycle,\n pluginId,\n );\n\n const service = lifecycleService as any;\n if (\n service &&\n typeof service.startup === 'function' &&\n typeof service.shutdown === 'function'\n ) {\n return service;\n }\n\n throw new Error('Unexpected plugin lifecycle service implementation');\n }\n\n async #applyBackendFeatureLoaders(loaders: InternalBackendFeatureLoader[]) {\n const servicesAddedByLoaders = new Map<\n string,\n InternalBackendFeatureLoader\n >();\n\n for (const loader of loaders) {\n const deps = new Map<string, unknown>();\n const missingRefs = new Set<ServiceOrExtensionPoint>();\n\n for (const [name, ref] of Object.entries(loader.deps ?? {})) {\n if (ref.scope !== 'root') {\n throw new Error(\n `Feature loaders can only depend on root scoped services, but '${name}' is scoped to '${ref.scope}'. Offending loader is ${loader.description}`,\n );\n }\n const impl = await this.#serviceRegistry.get(\n ref as ServiceRef<unknown>,\n 'root',\n );\n if (impl) {\n deps.set(name, impl);\n } else {\n missingRefs.add(ref);\n }\n }\n\n if (missingRefs.size > 0) {\n const missing = Array.from(missingRefs).join(', ');\n throw new Error(\n `No service available for the following ref(s): ${missing}, depended on by feature loader ${loader.description}`,\n );\n }\n\n const result = await loader\n .loader(Object.fromEntries(deps))\n .then(features => features.map(unwrapFeature))\n .catch(error => {\n throw new ForwardedError(\n `Feature loader ${loader.description} failed`,\n error,\n );\n });\n\n let didAddServiceFactory = false;\n const newLoaders = new Array<InternalBackendFeatureLoader>();\n\n for await (const feature of result) {\n if (isBackendFeatureLoader(feature)) {\n newLoaders.push(feature);\n } else {\n // This block makes sure that feature loaders do not provide duplicate\n // implementations for the same service, but at the same time allows\n // service factories provided by feature loaders to be overridden by\n // ones that are explicitly installed with backend.add(serviceFactory).\n //\n // If a factory has already been explicitly installed, the service\n // factory provided by the loader will simply be ignored.\n if (isServiceFactory(feature) && !feature.service.multiton) {\n const conflictingLoader = servicesAddedByLoaders.get(\n feature.service.id,\n );\n if (conflictingLoader) {\n throw new Error(\n `Duplicate service implementations provided for ${feature.service.id} by both feature loader ${loader.description} and feature loader ${conflictingLoader.description}`,\n );\n }\n\n // Check that this service wasn't already explicitly added by backend.add(serviceFactory)\n if (!this.#serviceRegistry.hasBeenAdded(feature.service)) {\n didAddServiceFactory = true;\n servicesAddedByLoaders.set(feature.service.id, loader);\n this.#addFeature(feature);\n }\n } else {\n this.#addFeature(feature);\n }\n }\n }\n\n // Every time we add a new service factory we need to make sure that we don't have circular dependencies\n if (didAddServiceFactory) {\n this.#serviceRegistry.checkForCircularDeps();\n }\n\n // Apply loaders recursively, depth-first\n if (newLoaders.length > 0) {\n await this.#applyBackendFeatureLoaders(newLoaders);\n }\n }\n }\n}\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 isServiceFactory(\n feature: BackendFeature,\n): feature is InternalServiceFactory {\n const internal = toInternalBackendFeature(feature);\n if (internal.featureType === 'service') {\n return true;\n }\n // Backwards compatibility for v1 registrations that use duck typing\n return 'service' in internal;\n}\n\nfunction isBackendRegistrations(\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\nfunction isBackendFeatureLoader(\n feature: BackendFeature,\n): feature is InternalBackendFeatureLoader {\n return toInternalBackendFeature(feature).featureType === 'loader';\n}\n"],"names":["createServiceFactory","coreServices","deepFreeze","ServiceRegistry","OpaqueExtensionPointFactoryMiddleware","rootLogger","createInitializationResultCollector","createAllowBootFailurePredicate","DependencyGraph","ConflictError","toError","lifecycleService","ForwardedError","BackendStartupError","unwrapFeature"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BackendInitializer.cjs.js","sources":["../../src/wiring/BackendInitializer.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 BackendFeature,\n ExtensionPoint,\n coreServices,\n ServiceRef,\n ServiceFactory,\n LifecycleService,\n RootLifecycleService,\n createServiceFactory,\n ExtensionPointFactoryContext,\n} from '@backstage/backend-plugin-api';\nimport type { ConnectionRegistration } from '@backstage/backend-plugin-api/alpha';\nimport {\n ExtensionPointFactoryMiddleware,\n ServiceOrExtensionPoint,\n} from './types';\nimport {\n OpaqueExtensionPointFactoryMiddleware,\n unwrapFeature,\n} from '@internal/backend';\n// Direct internal import to avoid duplication\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport type {\n InternalBackendFeature,\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';\nimport { ConflictError, ForwardedError, toError } from '@backstage/errors';\nimport { DependencyGraph } from '../lib/DependencyGraph';\nimport { ServiceRegistry } from './ServiceRegistry';\nimport { createInitializationResultCollector } from './createInitializationResultCollector';\nimport { deepFreeze } from './helpers';\nimport type { RootInstanceMetadataServicePluginInfo } from '@backstage/backend-plugin-api';\nimport { BackendStartupResult } from './types';\nimport { BackendStartupError } from './BackendStartupError';\nimport { createAllowBootFailurePredicate } from './createAllowBootFailurePredicate';\nimport {\n connectionsServiceRef,\n type ConnectionsService,\n} from '@backstage/connections';\nimport { withDeclaredConnections } from './withDeclaredConnections';\n\nexport interface BackendRegisterInit {\n consumes: Set<ServiceOrExtensionPoint>;\n provides: Set<ServiceOrExtensionPoint>;\n init: {\n deps: { [name: string]: ServiceOrExtensionPoint };\n func: (deps: { [name: string]: unknown }) => Promise<void>;\n };\n}\n\n/**\n * A registry of backend instances, used to manage process shutdown hooks across all instances.\n */\nconst instanceRegistry = new (class InstanceRegistry {\n #registered = false;\n #instances = new Set<BackendInitializer>();\n\n register(instance: BackendInitializer) {\n if (!this.#registered) {\n this.#registered = true;\n\n process.addListener('SIGTERM', this.#exitHandler);\n process.addListener('SIGINT', this.#exitHandler);\n process.addListener('beforeExit', this.#exitHandler);\n }\n\n this.#instances.add(instance);\n }\n\n unregister(instance: BackendInitializer) {\n this.#instances.delete(instance);\n }\n\n #exitHandler = async () => {\n try {\n const results = await Promise.allSettled(\n Array.from(this.#instances).map(b => b.stop()),\n );\n const errors = results.flatMap(r =>\n r.status === 'rejected' ? [r.reason] : [],\n );\n\n if (errors.length > 0) {\n for (const error of errors) {\n console.error(error);\n }\n process.exit(1);\n } else {\n process.exit(0);\n }\n } catch (error) {\n console.error(error);\n process.exit(1);\n }\n };\n})();\n\nfunction callerKey(pluginId: string, moduleId?: string): string {\n return moduleId ? `${pluginId}\\0${moduleId}` : pluginId;\n}\n\nfunction collectCallerConnectionRegistrations(\n registrations: ReturnType<InternalBackendRegistrations['getRegistrations']>,\n): Map<string, ConnectionRegistration[]> {\n const byCaller = new Map<string, ConnectionRegistration[]>();\n\n for (const registration of registrations) {\n const declared =\n 'connections' in registration && Array.isArray(registration.connections)\n ? registration.connections\n : [];\n if (declared.length === 0) continue;\n\n const key =\n 'moduleId' in registration\n ? callerKey(registration.pluginId, registration.moduleId)\n : callerKey(registration.pluginId);\n\n const target =\n byCaller.get(key) ??\n (() => {\n const list: ConnectionRegistration[] = [];\n byCaller.set(key, list);\n return list;\n })();\n\n for (const decl of declared) {\n if (!target.some(c => c.type === decl.type)) {\n target.push({ ...decl });\n }\n }\n }\n\n return byCaller;\n}\n\nfunction createRootInstanceMetadataServiceFactory(\n rawRegistrations: InternalBackendRegistrations[],\n) {\n const installedPlugins: Map<string, RootInstanceMetadataServicePluginInfo> =\n new Map();\n const registrations = rawRegistrations\n .filter(registration => registration.featureType === 'registrations')\n .flatMap(registration => registration.getRegistrations());\n const plugins = registrations.filter(\n registration =>\n registration.type === 'plugin' || registration.type === 'plugin-v1.1',\n );\n const modules = registrations.filter(\n registration =>\n registration.type === 'module' || registration.type === 'module-v1.1',\n );\n for (const plugin of plugins) {\n const { pluginId } = plugin;\n if (!installedPlugins.get(pluginId)) {\n installedPlugins.set(pluginId, {\n pluginId,\n modules: [],\n });\n }\n }\n for (const module of modules) {\n const { pluginId, moduleId } = module;\n const installedPlugin = installedPlugins.get(pluginId);\n if (installedPlugin) {\n (installedPlugin.modules as Array<{ moduleId: string }>).push({\n moduleId,\n });\n }\n }\n\n return createServiceFactory({\n service: coreServices.rootInstanceMetadata,\n deps: {},\n factory: async () => {\n const readonlyInstalledPlugins = deepFreeze([\n ...installedPlugins.values(),\n ]);\n const instanceMetadata = {\n getInstalledPlugins: () => Promise.resolve(readonlyInstalledPlugins),\n };\n\n return instanceMetadata;\n },\n });\n}\n\nexport class BackendInitializer {\n #startPromise?: Promise<{ result: BackendStartupResult }>;\n #stopPromise?: Promise<void>;\n #registrations = new Array<InternalBackendRegistrations>();\n #extensionPoints = new Map<\n string,\n {\n pluginId: string;\n factory: (context: ExtensionPointFactoryContext) => unknown;\n }\n >();\n #serviceRegistry: ServiceRegistry;\n #registeredFeatures = new Array<Promise<BackendFeature>>();\n #registeredFeatureLoaders = new Array<InternalBackendFeatureLoader>();\n #extensionPointFactoryMiddleware: ExtensionPointFactoryMiddleware[];\n #callerConnectionRegistrations = new Map<string, ConnectionRegistration[]>();\n\n #getConnectionRegistrations(\n pluginId: string,\n moduleId?: string,\n ): ConnectionRegistration[] {\n if (moduleId) {\n return (\n this.#callerConnectionRegistrations.get(\n callerKey(pluginId, moduleId),\n ) ?? []\n );\n }\n // Aggregate registrations from the plugin\n const result: ConnectionRegistration[] = [];\n for (const [key, registrations] of this.#callerConnectionRegistrations) {\n if (key === pluginId) {\n result.push(...registrations);\n }\n }\n return result;\n }\n\n #unhandledRejectionHandler?: (reason: Error) => void;\n #uncaughtExceptionHandler?: (error: Error) => void;\n\n constructor(\n defaultApiFactories: ServiceFactory[],\n extensionPointFactoryMiddleware?: ExtensionPointFactoryMiddleware[],\n ) {\n this.#serviceRegistry = ServiceRegistry.create([...defaultApiFactories]);\n this.#extensionPointFactoryMiddleware =\n extensionPointFactoryMiddleware ?? [];\n }\n\n async #getInitDeps(\n deps: { [name: string]: ServiceOrExtensionPoint },\n resultCollector: ReturnType<typeof createInitializationResultCollector>,\n pluginId: string,\n moduleId?: string,\n ) {\n const result = new Map<string, unknown>();\n const missingRefs = new Set<ServiceOrExtensionPoint>();\n\n for (const [name, ref] of Object.entries(deps)) {\n const ep = this.#extensionPoints.get(ref.id);\n if (ep) {\n if (ep.pluginId !== pluginId) {\n throw new Error(\n `Illegal dependency: Module '${moduleId}' for plugin '${pluginId}' attempted to depend on extension point '${ref.id}' for plugin '${ep.pluginId}'. Extension points can only be used within their plugin's scope.`,\n );\n }\n if (!moduleId) {\n throw new Error(\n `Rejected dependency on extension point ${ref.id} from outside of a module`,\n );\n }\n let epImpl = ep.factory({\n reportModuleStartupFailure: ({ error }) => {\n resultCollector.amendPluginModuleResult(pluginId, moduleId, error);\n },\n });\n for (const mw of this.#extensionPointFactoryMiddleware) {\n const internal = OpaqueExtensionPointFactoryMiddleware.toInternal(mw);\n if (internal.extensionPointId === ref.id) {\n epImpl = await internal.middleware(epImpl);\n }\n }\n result.set(name, epImpl);\n } else {\n const impl = await this.#serviceRegistry.get(\n ref as ServiceRef<unknown>,\n pluginId,\n );\n if (impl) {\n if (ref.id === connectionsServiceRef.id) {\n const registrations = this.#getConnectionRegistrations(\n pluginId,\n moduleId,\n );\n result.set(\n name,\n withDeclaredConnections(\n impl as ConnectionsService,\n registrations,\n ),\n );\n } else {\n result.set(name, impl);\n }\n } else {\n missingRefs.add(ref);\n }\n }\n }\n\n if (missingRefs.size > 0) {\n const missing = Array.from(missingRefs).join(', ');\n const target = moduleId\n ? `module '${moduleId}' for plugin '${pluginId}'`\n : `plugin '${pluginId}'`;\n throw new Error(\n `Service or extension point dependencies of ${target} are missing for the following ref(s): ${missing}`,\n );\n }\n\n return Object.fromEntries(result);\n }\n\n add(feature: BackendFeature | Promise<BackendFeature>) {\n if (this.#startPromise) {\n throw new Error('feature can not be added after the backend has started');\n }\n this.#registeredFeatures.push(Promise.resolve(feature));\n }\n\n #addFeature(feature: BackendFeature) {\n if (isServiceFactory(feature)) {\n this.#serviceRegistry.add(feature);\n } else if (isBackendFeatureLoader(feature)) {\n this.#registeredFeatureLoaders.push(feature);\n } else if (isBackendRegistrations(feature)) {\n this.#registrations.push(feature);\n } else {\n throw new Error(\n `Failed to add feature, invalid feature ${JSON.stringify(feature)}`,\n );\n }\n }\n\n async start(): Promise<{ result: BackendStartupResult }> {\n if (this.#startPromise) {\n throw new Error('Backend has already started');\n }\n if (this.#stopPromise) {\n throw new Error('Backend has already stopped');\n }\n\n instanceRegistry.register(this);\n\n this.#startPromise = this.#doStart();\n return await this.#startPromise;\n }\n\n async #doStart(): Promise<{ result: BackendStartupResult }> {\n this.#serviceRegistry.checkForCircularDeps();\n\n for (const feature of this.#registeredFeatures) {\n this.#addFeature(await feature);\n }\n\n await this.#applyBackendFeatureLoaders(this.#registeredFeatureLoaders);\n\n this.#serviceRegistry.add(\n createRootInstanceMetadataServiceFactory(this.#registrations),\n );\n\n // This makes sure that any uncaught errors or unhandled rejections are\n // caught and logged, rather than terminating the process. We register these\n // as early as possible while still using the root logger service, the\n // tradeoff that if there are any unhandled errors as part of the that\n // instationation, it will cause the process to crash. If there are multiple\n // backend instances, each instance will log the error, because we can't\n // determine which instance the error came from.\n if (process.env.NODE_ENV !== 'test') {\n const rootLogger = await this.#serviceRegistry.get(\n coreServices.rootLogger,\n 'root',\n );\n this.#unhandledRejectionHandler = (reason: Error) => {\n rootLogger\n ?.child({ type: 'unhandledRejection' })\n ?.error('Unhandled rejection', reason);\n };\n this.#uncaughtExceptionHandler = (error: Error) => {\n rootLogger\n ?.child({ type: 'uncaughtException' })\n ?.error('Uncaught exception', error);\n };\n process.on('unhandledRejection', this.#unhandledRejectionHandler);\n process.on('uncaughtException', this.#uncaughtExceptionHandler);\n }\n\n // Initialize all root scoped services\n await this.#serviceRegistry.initializeEagerServicesWithScope('root');\n\n const rootConfig = await this.#serviceRegistry.get(\n coreServices.rootConfig,\n 'root',\n );\n const rootLogger = await this.#serviceRegistry.get(\n coreServices.rootLogger,\n 'root',\n );\n\n const allRegistrations = this.#registrations.flatMap(f =>\n f.getRegistrations(),\n );\n\n this.#callerConnectionRegistrations =\n collectCallerConnectionRegistrations(allRegistrations);\n\n const allPluginIds = [\n ...new Set(\n allRegistrations.flatMap(r =>\n 'pluginId' in r && typeof r.pluginId === 'string' ? [r.pluginId] : [],\n ),\n ),\n ];\n\n const resultCollector = createInitializationResultCollector({\n pluginIds: allPluginIds,\n logger: rootLogger,\n allowBootFailurePredicate: createAllowBootFailurePredicate(rootConfig),\n });\n\n const { pluginInits, moduleInits } = this.#enumerateRegistrations(\n allRegistrations,\n resultCollector,\n );\n\n // All plugins are initialized in parallel\n await Promise.all(\n [...pluginInits.keys()].map(async pluginId => {\n try {\n // Initialize all eager services\n await this.#serviceRegistry.initializeEagerServicesWithScope(\n 'plugin',\n pluginId,\n );\n\n // Modules are initialized before plugins, so that they can provide extension to the plugin\n const modules = moduleInits.get(pluginId);\n if (modules) {\n const tree = DependencyGraph.fromIterable(\n Array.from(modules).map(([moduleId, moduleInit]) => ({\n value: { moduleId, moduleInit },\n // Relationships are reversed at this point since we're only interested in the extension points.\n // If a modules provides extension point A we want it to be initialized AFTER all modules\n // that depend on extension point A, so that they can provide their extensions.\n consumes: Array.from(moduleInit.provides).map(p => p.id),\n provides: Array.from(moduleInit.consumes).map(c => c.id),\n })),\n );\n const circular = tree.detectCircularDependency();\n if (circular) {\n throw new ConflictError(\n `Circular dependency detected for modules of plugin '${pluginId}', ${circular\n .map(({ moduleId }) => `'${moduleId}'`)\n .join(' -> ')}`,\n );\n }\n await tree.parallelTopologicalTraversal(\n async ({ moduleId, moduleInit }) => {\n try {\n const moduleDeps = await this.#getInitDeps(\n moduleInit.init.deps,\n resultCollector,\n pluginId,\n moduleId,\n );\n await moduleInit.init.func(moduleDeps);\n resultCollector.onPluginModuleResult(pluginId, moduleId);\n } catch (error: unknown) {\n const err = toError(error);\n resultCollector.onPluginModuleResult(pluginId, moduleId, err);\n }\n },\n );\n }\n\n // Once all modules have been initialized, we can initialize the plugin itself\n const pluginInit = pluginInits.get(pluginId);\n // We allow modules to be installed without the accompanying plugin, so the plugin may not exist\n if (pluginInit) {\n const pluginDeps = await this.#getInitDeps(\n pluginInit.init.deps,\n resultCollector,\n pluginId,\n );\n await pluginInit.init.func(pluginDeps);\n }\n\n resultCollector.onPluginResult(pluginId);\n\n // Once the plugin and all modules have been initialized, we can signal that the plugin has stared up successfully\n const lifecycleService = await this.#getPluginLifecycleImpl(pluginId);\n await lifecycleService.startup();\n } catch (error: unknown) {\n const err = toError(error);\n resultCollector.onPluginResult(pluginId, err);\n }\n }),\n ).catch(error => {\n throw new ForwardedError(\n 'Unexpected uncaught backend startup error',\n error,\n );\n });\n\n const result = resultCollector.finalize();\n if (result.outcome === 'failure') {\n throw new BackendStartupError(result);\n }\n\n // Once all plugins and modules have been initialized, we can signal that the backend has started up successfully\n const lifecycleService = await this.#getRootLifecycleImpl();\n await lifecycleService.startup();\n\n return { result };\n }\n\n #enumerateRegistrations(\n allRegistrations: ReturnType<\n InternalBackendRegistrations['getRegistrations']\n >,\n resultCollector: ReturnType<typeof createInitializationResultCollector>,\n ): {\n pluginInits: Map<string, BackendRegisterInit>;\n moduleInits: Map<string, Map<string, BackendRegisterInit>>;\n } {\n const pluginInits = new Map<string, BackendRegisterInit>();\n const moduleInits = new Map<string, Map<string, BackendRegisterInit>>();\n\n for (const r of allRegistrations) {\n const addedExtensionPointIds: string[] = [];\n try {\n const provides = new Set<ExtensionPoint<unknown>>();\n\n if (r.type === 'plugin' || r.type === 'module') {\n // Handle v1 format: Array<readonly [ExtensionPoint<unknown>, unknown]>\n for (const [extRef, extImpl] of r.extensionPoints) {\n if (this.#extensionPoints.has(extRef.id)) {\n throw new Error(\n `ExtensionPoint with ID '${extRef.id}' is already registered`,\n );\n }\n this.#extensionPoints.set(extRef.id, {\n pluginId: r.pluginId,\n factory: () => extImpl,\n });\n addedExtensionPointIds.push(extRef.id);\n provides.add(extRef);\n }\n } else if (r.type === 'plugin-v1.1' || r.type === 'module-v1.1') {\n // Handle v1.1 format: Array<ExtensionPointRegistration>\n for (const extReg of r.extensionPoints) {\n if (this.#extensionPoints.has(extReg.extensionPoint.id)) {\n throw new Error(\n `ExtensionPoint with ID '${extReg.extensionPoint.id}' is already registered`,\n );\n }\n this.#extensionPoints.set(extReg.extensionPoint.id, {\n pluginId: r.pluginId,\n factory: extReg.factory,\n });\n addedExtensionPointIds.push(extReg.extensionPoint.id);\n provides.add(extReg.extensionPoint);\n }\n }\n\n if (r.type === 'plugin' || r.type === 'plugin-v1.1') {\n if (pluginInits.has(r.pluginId)) {\n throw new Error(`Plugin '${r.pluginId}' is already registered`);\n }\n pluginInits.set(r.pluginId, {\n provides,\n consumes: new Set(Object.values(r.init.deps)),\n init: r.init,\n });\n } else if (r.type === 'module' || r.type === 'module-v1.1') {\n let modules = moduleInits.get(r.pluginId);\n if (!modules) {\n modules = new Map();\n moduleInits.set(r.pluginId, modules);\n }\n if (modules.has(r.moduleId)) {\n throw new Error(\n `Module '${r.moduleId}' for plugin '${r.pluginId}' is already registered`,\n );\n }\n modules.set(r.moduleId, {\n provides,\n consumes: new Set(Object.values(r.init.deps)),\n init: r.init,\n });\n } else {\n throw new Error(`Invalid registration type '${(r as any).type}'`);\n }\n } catch (error: unknown) {\n const err = toError(error);\n // Clean up partially registered extension points\n for (const id of addedExtensionPointIds) {\n this.#extensionPoints.delete(id);\n }\n if ('pluginId' in r && 'moduleId' in r) {\n resultCollector.onPluginModuleResult(r.pluginId, r.moduleId, err);\n } else if ('pluginId' in r) {\n pluginInits.delete(r.pluginId);\n moduleInits.delete(r.pluginId);\n resultCollector.onPluginResult(r.pluginId, err);\n } else {\n throw err;\n }\n }\n }\n\n return { pluginInits, moduleInits };\n }\n\n // It's fine to call .stop() multiple times, which for example can happen with manual stop + process exit\n async stop(): Promise<void> {\n instanceRegistry.unregister(this);\n\n if (!this.#stopPromise) {\n this.#stopPromise = this.#doStop();\n }\n await this.#stopPromise;\n }\n\n async #doStop(): Promise<void> {\n if (!this.#startPromise) {\n return;\n }\n\n try {\n await this.#startPromise;\n } catch (error) {\n // The startup failed, but we may still want to do cleanup so we continue silently\n }\n\n const rootLifecycleService = await this.#getRootLifecycleImpl();\n\n // Root services like the health one need to immediately be notified of the shutdown\n await rootLifecycleService.beforeShutdown();\n\n // Get all plugins.\n const allPlugins = new Set<string>();\n for (const feature of this.#registrations) {\n for (const r of feature.getRegistrations()) {\n if (r.type === 'plugin' || r.type === 'plugin-v1.1') {\n allPlugins.add(r.pluginId);\n }\n }\n }\n\n // Iterate through all plugins and run their shutdown hooks.\n await Promise.allSettled(\n [...allPlugins].map(async pluginId => {\n const lifecycleService = await this.#getPluginLifecycleImpl(pluginId);\n await lifecycleService.shutdown();\n }),\n );\n\n // Once all plugin shutdown hooks are done, run root shutdown hooks.\n await rootLifecycleService.shutdown();\n\n // Clean up process event listeners to prevent memory leaks and duplicate logging\n if (this.#unhandledRejectionHandler) {\n process.off('unhandledRejection', this.#unhandledRejectionHandler);\n this.#unhandledRejectionHandler = undefined;\n }\n if (this.#uncaughtExceptionHandler) {\n process.off('uncaughtException', this.#uncaughtExceptionHandler);\n this.#uncaughtExceptionHandler = undefined;\n }\n }\n\n // Bit of a hacky way to grab the lifecycle services, potentially find a nicer way to do this\n async #getRootLifecycleImpl(): Promise<\n RootLifecycleService & {\n startup(): Promise<void>;\n beforeShutdown(): Promise<void>;\n shutdown(): Promise<void>;\n }\n > {\n const lifecycleService = await this.#serviceRegistry.get(\n coreServices.rootLifecycle,\n 'root',\n );\n\n const service = lifecycleService as any;\n if (\n service &&\n typeof service.startup === 'function' &&\n typeof service.shutdown === 'function'\n ) {\n return service;\n }\n\n throw new Error('Unexpected root lifecycle service implementation');\n }\n\n async #getPluginLifecycleImpl(\n pluginId: string,\n ): Promise<\n LifecycleService & { startup(): Promise<void>; shutdown(): Promise<void> }\n > {\n const lifecycleService = await this.#serviceRegistry.get(\n coreServices.lifecycle,\n pluginId,\n );\n\n const service = lifecycleService as any;\n if (\n service &&\n typeof service.startup === 'function' &&\n typeof service.shutdown === 'function'\n ) {\n return service;\n }\n\n throw new Error('Unexpected plugin lifecycle service implementation');\n }\n\n async #applyBackendFeatureLoaders(loaders: InternalBackendFeatureLoader[]) {\n const servicesAddedByLoaders = new Map<\n string,\n InternalBackendFeatureLoader\n >();\n\n for (const loader of loaders) {\n const deps = new Map<string, unknown>();\n const missingRefs = new Set<ServiceOrExtensionPoint>();\n\n for (const [name, ref] of Object.entries(loader.deps ?? {})) {\n if (ref.scope !== 'root') {\n throw new Error(\n `Feature loaders can only depend on root scoped services, but '${name}' is scoped to '${ref.scope}'. Offending loader is ${loader.description}`,\n );\n }\n const impl = await this.#serviceRegistry.get(\n ref as ServiceRef<unknown>,\n 'root',\n );\n if (impl) {\n deps.set(name, impl);\n } else {\n missingRefs.add(ref);\n }\n }\n\n if (missingRefs.size > 0) {\n const missing = Array.from(missingRefs).join(', ');\n throw new Error(\n `No service available for the following ref(s): ${missing}, depended on by feature loader ${loader.description}`,\n );\n }\n\n const result = await loader\n .loader(Object.fromEntries(deps))\n .then(features => features.map(unwrapFeature))\n .catch(error => {\n throw new ForwardedError(\n `Feature loader ${loader.description} failed`,\n error,\n );\n });\n\n let didAddServiceFactory = false;\n const newLoaders = new Array<InternalBackendFeatureLoader>();\n\n for await (const feature of result) {\n if (isBackendFeatureLoader(feature)) {\n newLoaders.push(feature);\n } else {\n // This block makes sure that feature loaders do not provide duplicate\n // implementations for the same service, but at the same time allows\n // service factories provided by feature loaders to be overridden by\n // ones that are explicitly installed with backend.add(serviceFactory).\n //\n // If a factory has already been explicitly installed, the service\n // factory provided by the loader will simply be ignored.\n if (isServiceFactory(feature) && !feature.service.multiton) {\n const conflictingLoader = servicesAddedByLoaders.get(\n feature.service.id,\n );\n if (conflictingLoader) {\n throw new Error(\n `Duplicate service implementations provided for ${feature.service.id} by both feature loader ${loader.description} and feature loader ${conflictingLoader.description}`,\n );\n }\n\n // Check that this service wasn't already explicitly added by backend.add(serviceFactory)\n if (!this.#serviceRegistry.hasBeenAdded(feature.service)) {\n didAddServiceFactory = true;\n servicesAddedByLoaders.set(feature.service.id, loader);\n this.#addFeature(feature);\n }\n } else {\n this.#addFeature(feature);\n }\n }\n }\n\n // Every time we add a new service factory we need to make sure that we don't have circular dependencies\n if (didAddServiceFactory) {\n this.#serviceRegistry.checkForCircularDeps();\n }\n\n // Apply loaders recursively, depth-first\n if (newLoaders.length > 0) {\n await this.#applyBackendFeatureLoaders(newLoaders);\n }\n }\n }\n}\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 isServiceFactory(\n feature: BackendFeature,\n): feature is InternalServiceFactory {\n const internal = toInternalBackendFeature(feature);\n if (internal.featureType === 'service') {\n return true;\n }\n // Backwards compatibility for v1 registrations that use duck typing\n return 'service' in internal;\n}\n\nfunction isBackendRegistrations(\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\nfunction isBackendFeatureLoader(\n feature: BackendFeature,\n): feature is InternalBackendFeatureLoader {\n return toInternalBackendFeature(feature).featureType === 'loader';\n}\n"],"names":["createServiceFactory","coreServices","deepFreeze","ServiceRegistry","OpaqueExtensionPointFactoryMiddleware","connectionsServiceRef","withDeclaredConnections","rootLogger","createInitializationResultCollector","createAllowBootFailurePredicate","DependencyGraph","ConflictError","toError","lifecycleService","ForwardedError","BackendStartupError","unwrapFeature"],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var BackendInitializer = require('./BackendInitializer.cjs.js');
|
|
4
|
-
var helpers = require('
|
|
4
|
+
var helpers = require('../backend-internal/src/wiring/helpers.cjs.js');
|
|
5
|
+
require('../backend-internal/src/wiring/OpaqueExtensionPointFactoryMiddleware.cjs.js');
|
|
5
6
|
|
|
6
7
|
class BackstageBackend {
|
|
7
8
|
#initializer;
|
|
@@ -12,7 +13,7 @@ class BackstageBackend {
|
|
|
12
13
|
);
|
|
13
14
|
}
|
|
14
15
|
add(feature) {
|
|
15
|
-
if (isPromise(feature)) {
|
|
16
|
+
if (helpers.isPromise(feature)) {
|
|
16
17
|
this.#initializer.add(feature.then((f) => helpers.unwrapFeature(f.default)));
|
|
17
18
|
} else {
|
|
18
19
|
this.#initializer.add(helpers.unwrapFeature(feature));
|
|
@@ -25,9 +26,6 @@ class BackstageBackend {
|
|
|
25
26
|
await this.#initializer.stop();
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
|
-
function isPromise(value) {
|
|
29
|
-
return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
|
|
30
|
-
}
|
|
31
29
|
|
|
32
30
|
exports.BackstageBackend = BackstageBackend;
|
|
33
31
|
//# sourceMappingURL=BackstageBackend.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BackstageBackend.cjs.js","sources":["../../src/wiring/BackstageBackend.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 { BackendFeature, ServiceFactory } from '@backstage/backend-plugin-api';\nimport {
|
|
1
|
+
{"version":3,"file":"BackstageBackend.cjs.js","sources":["../../src/wiring/BackstageBackend.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 { BackendFeature, ServiceFactory } from '@backstage/backend-plugin-api';\nimport { isPromise, unwrapFeature } from '@internal/backend';\nimport { BackendInitializer } from './BackendInitializer';\nimport {\n Backend,\n BackendStartupResult,\n ExtensionPointFactoryMiddleware,\n} from './types';\n\nexport class BackstageBackend implements Backend {\n #initializer: BackendInitializer;\n\n constructor(\n defaultServiceFactories: ServiceFactory[],\n extensionPointFactoryMiddleware?: ExtensionPointFactoryMiddleware[],\n ) {\n this.#initializer = new BackendInitializer(\n defaultServiceFactories,\n extensionPointFactoryMiddleware,\n );\n }\n\n add(feature: BackendFeature | Promise<{ default: BackendFeature }>): void {\n if (isPromise(feature)) {\n this.#initializer.add(feature.then(f => unwrapFeature(f.default)));\n } else {\n this.#initializer.add(unwrapFeature(feature));\n }\n }\n\n async start(): Promise<{ result: BackendStartupResult }> {\n return await this.#initializer.start();\n }\n\n async stop(): Promise<void> {\n await this.#initializer.stop();\n }\n}\n"],"names":["BackendInitializer","isPromise","unwrapFeature"],"mappings":";;;;;;AAyBO,MAAM,gBAAA,CAAoC;AAAA,EAC/C,YAAA;AAAA,EAEA,WAAA,CACE,yBACA,+BAAA,EACA;AACA,IAAA,IAAA,CAAK,eAAe,IAAIA,qCAAA;AAAA,MACtB,uBAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAAA,EAEA,IAAI,OAAA,EAAsE;AACxE,IAAA,IAAIC,iBAAA,CAAU,OAAO,CAAA,EAAG;AACtB,MAAA,IAAA,CAAK,YAAA,CAAa,IAAI,OAAA,CAAQ,IAAA,CAAK,OAAKC,qBAAA,CAAc,CAAA,CAAE,OAAO,CAAC,CAAC,CAAA;AAAA,IACnE,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,YAAA,CAAa,GAAA,CAAIA,qBAAA,CAAc,OAAO,CAAC,CAAA;AAAA,IAC9C;AAAA,EACF;AAAA,EAEA,MAAM,KAAA,GAAmD;AACvD,IAAA,OAAO,MAAM,IAAA,CAAK,YAAA,CAAa,KAAA,EAAM;AAAA,EACvC;AAAA,EAEA,MAAM,IAAA,GAAsB;AAC1B,IAAA,MAAM,IAAA,CAAK,aAAa,IAAA,EAAK;AAAA,EAC/B;AACF;;;;"}
|
|
@@ -18,7 +18,9 @@ function createPluginMetadataServiceFactory(pluginId) {
|
|
|
18
18
|
return backendPluginApi.createServiceFactory({
|
|
19
19
|
service: backendPluginApi.coreServices.pluginMetadata,
|
|
20
20
|
deps: {},
|
|
21
|
-
factory: async () => ({
|
|
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":["../../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":["../../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,14 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
function unwrapFeature(feature) {
|
|
4
|
-
if ("$$type" in feature) {
|
|
5
|
-
return feature;
|
|
6
|
-
}
|
|
7
|
-
if ("default" in feature) {
|
|
8
|
-
return feature.default;
|
|
9
|
-
}
|
|
10
|
-
return feature;
|
|
11
|
-
}
|
|
12
3
|
function deepFreeze(obj) {
|
|
13
4
|
Object.values(obj).forEach(
|
|
14
5
|
(value) => Object.isFrozen(value) || deepFreeze(value)
|
|
@@ -17,5 +8,4 @@ function deepFreeze(obj) {
|
|
|
17
8
|
}
|
|
18
9
|
|
|
19
10
|
exports.deepFreeze = deepFreeze;
|
|
20
|
-
exports.unwrapFeature = unwrapFeature;
|
|
21
11
|
//# sourceMappingURL=helpers.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.cjs.js","sources":["../../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\
|
|
1
|
+
{"version":3,"file":"helpers.cjs.js","sources":["../../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\n/** @internal */\nexport type DeepReadonly<T> = {\n readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];\n};\n\n/**\n * Deeply freezes an object by recursively freezing all of its properties.\n * From https://gist.github.com/tkrotoff/e997cd6ff8d6cf6e51e6bb6146407fc3 +\n * https://stackoverflow.com/a/69656011\n */\nexport function deepFreeze<T>(obj: T) {\n // Can cause: \"Type instantiation is excessively deep and possibly infinite.\"\n // @ts-expect-error\n Object.values(obj).forEach(\n value => Object.isFrozen(value) || deepFreeze(value),\n );\n return Object.freeze(obj) as DeepReadonly<T>;\n}\n"],"names":[],"mappings":";;AA0BO,SAAS,WAAc,GAAA,EAAQ;AAGpC,EAAA,MAAA,CAAO,MAAA,CAAO,GAAG,CAAA,CAAE,OAAA;AAAA,IACjB,WAAS,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,IAAK,WAAW,KAAK;AAAA,GACrD;AACA,EAAA,OAAO,MAAA,CAAO,OAAO,GAAG,CAAA;AAC1B;;;;"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var errors = require('@backstage/errors');
|
|
4
|
+
|
|
5
|
+
function withDeclaredConnections(service, registrations) {
|
|
6
|
+
const assertDeclared = (type) => {
|
|
7
|
+
if (!registrations.some(({ type: registeredType }) => registeredType === type)) {
|
|
8
|
+
throw new errors.InputError(
|
|
9
|
+
`Plugin attempted to look up an undeclared connection of type "${type}". Declare it during register() with declareConnection(reg, { type: "${type}" }).`
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
return {
|
|
14
|
+
async find(options) {
|
|
15
|
+
assertDeclared(options.type);
|
|
16
|
+
return service.find(options);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
exports.withDeclaredConnections = withDeclaredConnections;
|
|
22
|
+
//# sourceMappingURL=withDeclaredConnections.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withDeclaredConnections.cjs.js","sources":["../../src/wiring/withDeclaredConnections.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 type { ConnectionRegistration } from '@backstage/backend-plugin-api/alpha';\nimport type { ConnectionsService } from '@backstage/connections';\nimport { InputError } from '@backstage/errors';\n\n/** @internal */\nexport function withDeclaredConnections(\n service: ConnectionsService,\n registrations: ReadonlyArray<ConnectionRegistration>,\n): ConnectionsService {\n const assertDeclared = (type: string) => {\n if (\n !registrations.some(({ type: registeredType }) => registeredType === type)\n ) {\n throw new InputError(\n `Plugin attempted to look up an undeclared connection of type \"${type}\". Declare it during register() with declareConnection(reg, { type: \"${type}\" }).`,\n );\n }\n };\n return {\n async find(options) {\n assertDeclared(options.type);\n return service.find(options);\n },\n };\n}\n"],"names":["InputError"],"mappings":";;;;AAoBO,SAAS,uBAAA,CACd,SACA,aAAA,EACoB;AACpB,EAAA,MAAM,cAAA,GAAiB,CAAC,IAAA,KAAiB;AACvC,IAAA,IACE,CAAC,aAAA,CAAc,IAAA,CAAK,CAAC,EAAE,MAAM,cAAA,EAAe,KAAM,cAAA,KAAmB,IAAI,CAAA,EACzE;AACA,MAAA,MAAM,IAAIA,iBAAA;AAAA,QACR,CAAA,8DAAA,EAAiE,IAAI,CAAA,qEAAA,EAAwE,IAAI,CAAA,KAAA;AAAA,OACnJ;AAAA,IACF;AAAA,EACF,CAAA;AACA,EAAA,OAAO;AAAA,IACL,MAAM,KAAK,OAAA,EAAS;AAClB,MAAA,cAAA,CAAe,QAAQ,IAAI,CAAA;AAC3B,MAAA,OAAO,OAAA,CAAQ,KAAK,OAAO,CAAA;AAAA,IAC7B;AAAA,GACF;AACF;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/backend-app-api",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.2-next.0",
|
|
4
4
|
"description": "Core API used by Backstage backend apps",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "node-library"
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"files": [
|
|
39
39
|
"dist",
|
|
40
|
-
"config.
|
|
40
|
+
"config.schema.json",
|
|
41
41
|
"migrations/**/*.{js,d.ts}"
|
|
42
42
|
],
|
|
43
43
|
"scripts": {
|
|
@@ -50,14 +50,16 @@
|
|
|
50
50
|
"test": "backstage-cli package test"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@backstage/backend-plugin-api": "1.9.
|
|
53
|
+
"@backstage/backend-plugin-api": "1.9.3-next.0",
|
|
54
54
|
"@backstage/config": "1.3.8",
|
|
55
|
+
"@backstage/connections": "0.1.1-next.0",
|
|
55
56
|
"@backstage/errors": "1.3.1"
|
|
56
57
|
},
|
|
57
58
|
"devDependencies": {
|
|
58
|
-
"@backstage/backend-defaults": "0.17.
|
|
59
|
-
"@backstage/backend-test-utils": "1.11.
|
|
60
|
-
"@backstage/cli": "0.36.
|
|
59
|
+
"@backstage/backend-defaults": "0.17.4-next.0",
|
|
60
|
+
"@backstage/backend-test-utils": "1.11.5-next.0",
|
|
61
|
+
"@backstage/cli": "0.36.4-next.0",
|
|
62
|
+
"@backstage/types": "1.2.2"
|
|
61
63
|
},
|
|
62
|
-
"configSchema": "config.
|
|
64
|
+
"configSchema": "config.schema.json"
|
|
63
65
|
}
|
package/config.d.ts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2020 The Backstage Authors
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
export interface Config {
|
|
18
|
-
backend?: {
|
|
19
|
-
/** Used by the feature discovery service */
|
|
20
|
-
packages?:
|
|
21
|
-
| 'all'
|
|
22
|
-
| {
|
|
23
|
-
include?: string[];
|
|
24
|
-
exclude?: string[];
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
startup?: {
|
|
28
|
-
default?: {
|
|
29
|
-
/**
|
|
30
|
-
* The default value for `onPluginBootFailure` if not specified for a particular plugin.
|
|
31
|
-
* This defaults to 'abort', which means `onPluginBootFailure: continue` must be specified
|
|
32
|
-
* for backend startup to continue on plugin boot failure. This can also be set to
|
|
33
|
-
* 'continue', which flips the logic for individual plugins so that they must be set to
|
|
34
|
-
* `onPluginBootFailure: abort` to be required.
|
|
35
|
-
*/
|
|
36
|
-
onPluginBootFailure?: 'continue' | 'abort';
|
|
37
|
-
/**
|
|
38
|
-
* The default value for `onPluginModuleBootFailure` if not specified for a particular plugin module.
|
|
39
|
-
* This defaults to 'abort', which means `onPluginModuleBootFailure: continue` must be specified
|
|
40
|
-
* for backend startup to continue on plugin module boot failure. This can also be set to
|
|
41
|
-
* 'continue', which flips the logic for individual plugin modules so that they must be set to
|
|
42
|
-
* `onPluginModuleBootFailure: abort` to be required.
|
|
43
|
-
*/
|
|
44
|
-
onPluginModuleBootFailure?: 'continue' | 'abort';
|
|
45
|
-
};
|
|
46
|
-
plugins?: {
|
|
47
|
-
[pluginId: string]: {
|
|
48
|
-
/**
|
|
49
|
-
* Used to control backend startup behavior when this plugin fails to boot up. Setting
|
|
50
|
-
* this to `continue` allows the backend to continue starting up, even if this plugin
|
|
51
|
-
* fails. This can enable leaving a crashing plugin installed, but still permit backend
|
|
52
|
-
* startup, which may help troubleshoot data-dependent issues. Plugin failures for plugins
|
|
53
|
-
* set to `abort` are fatal (this is the default unless overridden by the `default`
|
|
54
|
-
* setting).
|
|
55
|
-
*/
|
|
56
|
-
onPluginBootFailure?: 'continue' | 'abort';
|
|
57
|
-
modules?: {
|
|
58
|
-
[moduleId: string]: {
|
|
59
|
-
/**
|
|
60
|
-
* Used to control backend startup behavior when this plugin module fails to boot up. Setting
|
|
61
|
-
* this to `continue` allows the backend to continue starting up, even if this plugin
|
|
62
|
-
* module fails. This can enable leaving a crashing plugin installed, but still permit backend
|
|
63
|
-
* startup, which may help troubleshoot data-dependent issues. Plugin module failures for plugin modules
|
|
64
|
-
* set to `abort` are fatal (this is the default unless overridden by the `default`
|
|
65
|
-
* setting).
|
|
66
|
-
*/
|
|
67
|
-
onPluginModuleBootFailure?: 'continue' | 'abort';
|
|
68
|
-
};
|
|
69
|
-
};
|
|
70
|
-
};
|
|
71
|
-
};
|
|
72
|
-
};
|
|
73
|
-
};
|
|
74
|
-
}
|