@backstage/backend-app-api 0.5.3-next.1 → 0.5.3-next.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of @backstage/backend-app-api might be problematic. Click here for more details.
- package/CHANGELOG.md +41 -0
- package/alpha/package.json +1 -1
- package/dist/alpha.cjs.js +48 -19
- package/dist/alpha.cjs.js.map +1 -1
- package/dist/index.cjs.js +143 -52
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/package.json +13 -13
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
# @backstage/backend-app-api
|
|
2
2
|
|
|
3
|
+
## 0.5.3-next.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 154632d8753b: Add support for discovering additional service factories during startup.
|
|
8
|
+
- cb7fc410ed99: The experimental backend feature discovery now only considers default exports from packages. It no longer filters packages to include based on the package role, except that `'cli'` packages are ignored. However, the `"backstage"` field is still required in `package.json`.
|
|
9
|
+
- 3b30b179cb38: Add support for installing features as package imports, for example `backend.add(import('my-plugin'))`.
|
|
10
|
+
- Updated dependencies
|
|
11
|
+
- @backstage/config@1.1.0-next.2
|
|
12
|
+
- @backstage/errors@1.2.2-next.0
|
|
13
|
+
- @backstage/types@1.1.1-next.0
|
|
14
|
+
- @backstage/plugin-permission-node@0.7.14-next.3
|
|
15
|
+
- @backstage/backend-plugin-api@0.6.3-next.3
|
|
16
|
+
- @backstage/backend-common@0.19.5-next.3
|
|
17
|
+
- @backstage/backend-tasks@0.5.8-next.3
|
|
18
|
+
- @backstage/cli-common@0.1.12
|
|
19
|
+
- @backstage/cli-node@0.1.4-next.0
|
|
20
|
+
- @backstage/config-loader@1.5.0-next.3
|
|
21
|
+
- @backstage/plugin-auth-node@0.3.0-next.3
|
|
22
|
+
|
|
23
|
+
## 0.5.3-next.2
|
|
24
|
+
|
|
25
|
+
### Patch Changes
|
|
26
|
+
|
|
27
|
+
- 37a20c7f14aa: Adds include and exclude configuration to feature discovery of backend packages
|
|
28
|
+
Adds alpha modules to feature discovery
|
|
29
|
+
- 3fc64b9e2f8f: Extension points are now tracked via their ID rather than reference, in order to support package duplication.
|
|
30
|
+
- b219d097b3f4: Backend startup will now fail if any circular service dependencies are detected.
|
|
31
|
+
- Updated dependencies
|
|
32
|
+
- @backstage/config-loader@1.5.0-next.2
|
|
33
|
+
- @backstage/config@1.1.0-next.1
|
|
34
|
+
- @backstage/backend-tasks@0.5.8-next.2
|
|
35
|
+
- @backstage/backend-common@0.19.5-next.2
|
|
36
|
+
- @backstage/plugin-auth-node@0.3.0-next.2
|
|
37
|
+
- @backstage/plugin-permission-node@0.7.14-next.2
|
|
38
|
+
- @backstage/backend-plugin-api@0.6.3-next.2
|
|
39
|
+
- @backstage/cli-common@0.1.12
|
|
40
|
+
- @backstage/cli-node@0.1.3
|
|
41
|
+
- @backstage/errors@1.2.1
|
|
42
|
+
- @backstage/types@1.1.0
|
|
43
|
+
|
|
3
44
|
## 0.5.3-next.1
|
|
4
45
|
|
|
5
46
|
### Patch Changes
|
package/alpha/package.json
CHANGED
package/dist/alpha.cjs.js
CHANGED
|
@@ -11,7 +11,6 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
|
|
|
11
11
|
|
|
12
12
|
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
|
|
13
13
|
|
|
14
|
-
const LOADED_PACKAGE_ROLES = ["backend-plugin", "backend-module"];
|
|
15
14
|
async function findClosestPackageDir(searchDir) {
|
|
16
15
|
let path$1 = searchDir;
|
|
17
16
|
for (let i = 0; i < 1e3; i++) {
|
|
@@ -31,38 +30,67 @@ async function findClosestPackageDir(searchDir) {
|
|
|
31
30
|
);
|
|
32
31
|
}
|
|
33
32
|
class PackageDiscoveryService {
|
|
34
|
-
constructor(config) {
|
|
33
|
+
constructor(config, logger) {
|
|
35
34
|
this.config = config;
|
|
35
|
+
this.logger = logger;
|
|
36
|
+
}
|
|
37
|
+
getDependencyNames(path) {
|
|
38
|
+
const { dependencies } = require(path);
|
|
39
|
+
const packagesConfig = this.config.getOptional("backend.packages");
|
|
40
|
+
const dependencyNames = Object.keys(dependencies || {});
|
|
41
|
+
if (packagesConfig === "all") {
|
|
42
|
+
return dependencyNames;
|
|
43
|
+
}
|
|
44
|
+
const includedPackagesConfig = this.config.getOptionalStringArray(
|
|
45
|
+
"backend.packages.include"
|
|
46
|
+
);
|
|
47
|
+
const includedPackages = includedPackagesConfig ? new Set(includedPackagesConfig) : dependencyNames;
|
|
48
|
+
const excludedPackagesSet = new Set(
|
|
49
|
+
this.config.getOptionalStringArray("backend.packages.exclude")
|
|
50
|
+
);
|
|
51
|
+
return [...includedPackages].filter((name) => !excludedPackagesSet.has(name));
|
|
36
52
|
}
|
|
37
53
|
async getBackendFeatures() {
|
|
38
|
-
var _a
|
|
39
|
-
|
|
54
|
+
var _a;
|
|
55
|
+
const packagesConfig = this.config.getOptional("backend.packages");
|
|
56
|
+
if (!packagesConfig || Object.keys(packagesConfig).length === 0) {
|
|
40
57
|
return { features: [] };
|
|
41
58
|
}
|
|
42
59
|
const packageDir = await findClosestPackageDir(process.argv[1]);
|
|
43
60
|
if (!packageDir) {
|
|
44
61
|
throw new Error("Package discovery failed to find package.json");
|
|
45
62
|
}
|
|
46
|
-
const
|
|
47
|
-
packageDir,
|
|
48
|
-
|
|
49
|
-
));
|
|
50
|
-
const dependencyNames = Object.keys(dependencies || {});
|
|
63
|
+
const dependencyNames = this.getDependencyNames(
|
|
64
|
+
path.resolve(packageDir, "package.json")
|
|
65
|
+
);
|
|
51
66
|
const features = [];
|
|
52
67
|
for (const name of dependencyNames) {
|
|
53
68
|
const depPkg = require(require.resolve(`${name}/package.json`, {
|
|
54
69
|
paths: [packageDir]
|
|
55
70
|
}));
|
|
56
|
-
if (!
|
|
71
|
+
if (!(depPkg == null ? void 0 : depPkg.backstage) || ((_a = depPkg == null ? void 0 : depPkg.backstage) == null ? void 0 : _a.role) === "cli") {
|
|
57
72
|
continue;
|
|
58
73
|
}
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
74
|
+
const exportedModulePaths = [
|
|
75
|
+
require.resolve(name, {
|
|
76
|
+
paths: [packageDir]
|
|
77
|
+
})
|
|
78
|
+
];
|
|
79
|
+
try {
|
|
80
|
+
exportedModulePaths.push(
|
|
81
|
+
require.resolve(`${name}/alpha`, { paths: [packageDir] })
|
|
82
|
+
);
|
|
83
|
+
} catch {
|
|
84
|
+
}
|
|
85
|
+
for (const modulePath of exportedModulePaths) {
|
|
86
|
+
const mod = require(modulePath);
|
|
87
|
+
if (isBackendFeature(mod.default)) {
|
|
88
|
+
this.logger.info(`Detected: ${name}`);
|
|
89
|
+
features.push(mod.default);
|
|
63
90
|
}
|
|
64
|
-
if (isBackendFeatureFactory(
|
|
65
|
-
|
|
91
|
+
if (isBackendFeatureFactory(mod.default)) {
|
|
92
|
+
this.logger.info(`Detected: ${name}`);
|
|
93
|
+
features.push(mod.default());
|
|
66
94
|
}
|
|
67
95
|
}
|
|
68
96
|
}
|
|
@@ -72,10 +100,11 @@ class PackageDiscoveryService {
|
|
|
72
100
|
const featureDiscoveryServiceFactory = backendPluginApi.createServiceFactory({
|
|
73
101
|
service: alpha.featureDiscoveryServiceRef,
|
|
74
102
|
deps: {
|
|
75
|
-
config: backendPluginApi.coreServices.rootConfig
|
|
103
|
+
config: backendPluginApi.coreServices.rootConfig,
|
|
104
|
+
logger: backendPluginApi.coreServices.rootLogger
|
|
76
105
|
},
|
|
77
|
-
factory({ config }) {
|
|
78
|
-
return new PackageDiscoveryService(config);
|
|
106
|
+
factory({ config, logger }) {
|
|
107
|
+
return new PackageDiscoveryService(config, logger);
|
|
79
108
|
}
|
|
80
109
|
});
|
|
81
110
|
function isBackendFeature(value) {
|
package/dist/alpha.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alpha.cjs.js","sources":["../src/alpha/featureDiscoveryServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2023 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 RootConfigService,\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport {\n featureDiscoveryServiceRef,\n FeatureDiscoveryService,\n} from '@backstage/backend-plugin-api/alpha';\nimport { resolve as resolvePath, dirname } from 'path';\nimport fs from 'fs-extra';\nimport { BackstagePackageJson } from '@backstage/cli-node';\n\
|
|
1
|
+
{"version":3,"file":"alpha.cjs.js","sources":["../src/alpha/featureDiscoveryServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2023 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 RootConfigService,\n RootLoggerService,\n coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport {\n featureDiscoveryServiceRef,\n FeatureDiscoveryService,\n} from '@backstage/backend-plugin-api/alpha';\nimport { resolve as resolvePath, dirname } from 'path';\nimport fs from 'fs-extra';\nimport { BackstagePackageJson } from '@backstage/cli-node';\n\n/** @internal */\nasync function findClosestPackageDir(\n searchDir: string,\n): Promise<string | undefined> {\n let path = searchDir;\n\n // Some confidence check to avoid infinite loop\n for (let i = 0; i < 1000; i++) {\n const packagePath = resolvePath(path, 'package.json');\n const exists = await fs.pathExists(packagePath);\n if (exists) {\n return path;\n }\n\n const newPath = dirname(path);\n if (newPath === path) {\n return undefined;\n }\n path = newPath;\n }\n\n throw new Error(\n `Iteration limit reached when searching for root package.json at ${searchDir}`,\n );\n}\n\n/** @internal */\nclass PackageDiscoveryService implements FeatureDiscoveryService {\n constructor(\n private readonly config: RootConfigService,\n private readonly logger: RootLoggerService,\n ) {}\n\n getDependencyNames(path: string) {\n const { dependencies } = require(path) as BackstagePackageJson;\n const packagesConfig = this.config.getOptional('backend.packages');\n\n const dependencyNames = Object.keys(dependencies || {});\n\n if (packagesConfig === 'all') {\n return dependencyNames;\n }\n\n const includedPackagesConfig = this.config.getOptionalStringArray(\n 'backend.packages.include',\n );\n\n const includedPackages = includedPackagesConfig\n ? new Set(includedPackagesConfig)\n : dependencyNames;\n const excludedPackagesSet = new Set(\n this.config.getOptionalStringArray('backend.packages.exclude'),\n );\n\n return [...includedPackages].filter(name => !excludedPackagesSet.has(name));\n }\n\n async getBackendFeatures(): Promise<{ features: Array<BackendFeature> }> {\n const packagesConfig = this.config.getOptional('backend.packages');\n if (!packagesConfig || Object.keys(packagesConfig).length === 0) {\n return { features: [] };\n }\n\n const packageDir = await findClosestPackageDir(process.argv[1]);\n if (!packageDir) {\n throw new Error('Package discovery failed to find package.json');\n }\n const dependencyNames = this.getDependencyNames(\n resolvePath(packageDir, 'package.json'),\n );\n\n const features: BackendFeature[] = [];\n\n for (const name of dependencyNames) {\n const depPkg = require(require.resolve(`${name}/package.json`, {\n paths: [packageDir],\n })) as BackstagePackageJson;\n if (!depPkg?.backstage || depPkg?.backstage?.role === 'cli') {\n continue; // Not a backstage package, ignore\n }\n\n const exportedModulePaths = [\n require.resolve(name, {\n paths: [packageDir],\n }),\n ];\n\n // Find modules exported as alpha\n try {\n exportedModulePaths.push(\n require.resolve(`${name}/alpha`, { paths: [packageDir] }),\n );\n } catch {\n /* ignore */\n }\n\n for (const modulePath of exportedModulePaths) {\n const mod = require(modulePath);\n\n if (isBackendFeature(mod.default)) {\n this.logger.info(`Detected: ${name}`);\n features.push(mod.default);\n }\n if (isBackendFeatureFactory(mod.default)) {\n this.logger.info(`Detected: ${name}`);\n features.push(mod.default());\n }\n }\n }\n\n return { features };\n }\n}\n\n/** @alpha */\nexport const featureDiscoveryServiceFactory = createServiceFactory({\n service: featureDiscoveryServiceRef,\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.rootLogger,\n },\n factory({ config, logger }) {\n return new PackageDiscoveryService(config, logger);\n },\n});\n\nfunction isBackendFeature(value: unknown): value is BackendFeature {\n return (\n !!value &&\n typeof value === 'object' &&\n (value as BackendFeature).$$type === '@backstage/BackendFeature'\n );\n}\n\nfunction isBackendFeatureFactory(\n value: unknown,\n): value is () => BackendFeature {\n return (\n !!value &&\n typeof value === 'function' &&\n (value as any).$$type === '@backstage/BackendFeatureFactory'\n );\n}\n"],"names":["path","resolvePath","fs","dirname","createServiceFactory","featureDiscoveryServiceRef","coreServices"],"mappings":"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"}
|
package/dist/index.cjs.js
CHANGED
|
@@ -1093,7 +1093,11 @@ var __privateSet$4 = (obj, member, value, setter) => {
|
|
|
1093
1093
|
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
1094
1094
|
return value;
|
|
1095
1095
|
};
|
|
1096
|
-
var
|
|
1096
|
+
var __privateMethod$3 = (obj, member, method) => {
|
|
1097
|
+
__accessCheck$4(obj, member, "access private method");
|
|
1098
|
+
return method;
|
|
1099
|
+
};
|
|
1100
|
+
var _nodeIds, _cycleKeys, _getCycleKey, getCycleKey_fn, _nodes, _allProvided;
|
|
1097
1101
|
class Node {
|
|
1098
1102
|
constructor(value, consumes, provides) {
|
|
1099
1103
|
this.value = value;
|
|
@@ -1108,6 +1112,33 @@ class Node {
|
|
|
1108
1112
|
);
|
|
1109
1113
|
}
|
|
1110
1114
|
}
|
|
1115
|
+
const _CycleKeySet = class _CycleKeySet {
|
|
1116
|
+
constructor(nodes) {
|
|
1117
|
+
__privateAdd$4(this, _getCycleKey);
|
|
1118
|
+
__privateAdd$4(this, _nodeIds, void 0);
|
|
1119
|
+
__privateAdd$4(this, _cycleKeys, void 0);
|
|
1120
|
+
__privateSet$4(this, _nodeIds, new Map(nodes.map((n, i) => [n.value, i])));
|
|
1121
|
+
__privateSet$4(this, _cycleKeys, /* @__PURE__ */ new Set());
|
|
1122
|
+
}
|
|
1123
|
+
static from(nodes) {
|
|
1124
|
+
return new _CycleKeySet(nodes);
|
|
1125
|
+
}
|
|
1126
|
+
tryAdd(path) {
|
|
1127
|
+
const cycleKey = __privateMethod$3(this, _getCycleKey, getCycleKey_fn).call(this, path);
|
|
1128
|
+
if (__privateGet$4(this, _cycleKeys).has(cycleKey)) {
|
|
1129
|
+
return false;
|
|
1130
|
+
}
|
|
1131
|
+
__privateGet$4(this, _cycleKeys).add(cycleKey);
|
|
1132
|
+
return true;
|
|
1133
|
+
}
|
|
1134
|
+
};
|
|
1135
|
+
_nodeIds = new WeakMap();
|
|
1136
|
+
_cycleKeys = new WeakMap();
|
|
1137
|
+
_getCycleKey = new WeakSet();
|
|
1138
|
+
getCycleKey_fn = function(path) {
|
|
1139
|
+
return path.map((n) => __privateGet$4(this, _nodeIds).get(n)).sort().join(",");
|
|
1140
|
+
};
|
|
1141
|
+
let CycleKeySet = _CycleKeySet;
|
|
1111
1142
|
const _DependencyGraph = class _DependencyGraph {
|
|
1112
1143
|
constructor(nodes) {
|
|
1113
1144
|
__privateAdd$4(this, _nodes, void 0);
|
|
@@ -1135,7 +1166,9 @@ const _DependencyGraph = class _DependencyGraph {
|
|
|
1135
1166
|
}
|
|
1136
1167
|
return new _DependencyGraph(nodes);
|
|
1137
1168
|
}
|
|
1138
|
-
|
|
1169
|
+
/**
|
|
1170
|
+
* Find all nodes that consume dependencies that are not provided by any other node.
|
|
1171
|
+
*/
|
|
1139
1172
|
findUnsatisfiedDeps() {
|
|
1140
1173
|
const unsatisfiedDependencies = [];
|
|
1141
1174
|
for (const node of __privateGet$4(this, _nodes).values()) {
|
|
@@ -1148,9 +1181,19 @@ const _DependencyGraph = class _DependencyGraph {
|
|
|
1148
1181
|
}
|
|
1149
1182
|
return unsatisfiedDependencies;
|
|
1150
1183
|
}
|
|
1151
|
-
|
|
1152
|
-
|
|
1184
|
+
/**
|
|
1185
|
+
* Detect the first circular dependency within the graph, returning the path of nodes that
|
|
1186
|
+
* form a cycle, with the same node as the first and last element of the array.
|
|
1187
|
+
*/
|
|
1153
1188
|
detectCircularDependency() {
|
|
1189
|
+
return this.detectCircularDependencies().next().value;
|
|
1190
|
+
}
|
|
1191
|
+
/**
|
|
1192
|
+
* Detect circular dependencies within the graph, returning the path of nodes that
|
|
1193
|
+
* form a cycle, with the same node as the first and last element of the array.
|
|
1194
|
+
*/
|
|
1195
|
+
*detectCircularDependencies() {
|
|
1196
|
+
const cycleKeys = CycleKeySet.from(__privateGet$4(this, _nodes));
|
|
1154
1197
|
for (const startNode of __privateGet$4(this, _nodes)) {
|
|
1155
1198
|
const visited = /* @__PURE__ */ new Set();
|
|
1156
1199
|
const stack = new Array([
|
|
@@ -1163,16 +1206,19 @@ const _DependencyGraph = class _DependencyGraph {
|
|
|
1163
1206
|
continue;
|
|
1164
1207
|
}
|
|
1165
1208
|
visited.add(node);
|
|
1166
|
-
for (const
|
|
1167
|
-
const
|
|
1168
|
-
(other) => other.
|
|
1209
|
+
for (const consumed of node.consumes) {
|
|
1210
|
+
const providerNodes = __privateGet$4(this, _nodes).filter(
|
|
1211
|
+
(other) => other.provides.has(consumed)
|
|
1169
1212
|
);
|
|
1170
|
-
for (const
|
|
1171
|
-
if (
|
|
1172
|
-
|
|
1213
|
+
for (const provider of providerNodes) {
|
|
1214
|
+
if (provider === startNode) {
|
|
1215
|
+
if (cycleKeys.tryAdd(path)) {
|
|
1216
|
+
yield [...path, startNode.value];
|
|
1217
|
+
}
|
|
1218
|
+
break;
|
|
1173
1219
|
}
|
|
1174
|
-
if (!visited.has(
|
|
1175
|
-
stack.push([
|
|
1220
|
+
if (!visited.has(provider)) {
|
|
1221
|
+
stack.push([provider, [...path, provider.value]]);
|
|
1176
1222
|
}
|
|
1177
1223
|
}
|
|
1178
1224
|
}
|
|
@@ -1260,7 +1306,7 @@ var __privateMethod$2 = (obj, member, method) => {
|
|
|
1260
1306
|
__accessCheck$3(obj, member, "access private method");
|
|
1261
1307
|
return method;
|
|
1262
1308
|
};
|
|
1263
|
-
var _providedFactories, _loadedDefaultFactories, _implementations, _rootServiceImplementations, _resolveFactory, resolveFactory_fn, _checkForMissingDeps, checkForMissingDeps_fn;
|
|
1309
|
+
var _providedFactories, _loadedDefaultFactories, _implementations, _rootServiceImplementations, _addedFactoryIds, _instantiatedFactories, _resolveFactory, resolveFactory_fn, _checkForMissingDeps, checkForMissingDeps_fn;
|
|
1264
1310
|
function toInternalServiceFactory(factory) {
|
|
1265
1311
|
const f = factory;
|
|
1266
1312
|
if (f.$$type !== "@backstage/BackendFeature") {
|
|
@@ -1278,7 +1324,7 @@ const pluginMetadataServiceFactory = backendPluginApi.createServiceFactory(
|
|
|
1278
1324
|
factory: async () => ({ getId: () => options == null ? void 0 : options.pluginId })
|
|
1279
1325
|
})
|
|
1280
1326
|
);
|
|
1281
|
-
class
|
|
1327
|
+
const _ServiceRegistry = class _ServiceRegistry {
|
|
1282
1328
|
constructor(factories) {
|
|
1283
1329
|
__privateAdd$3(this, _resolveFactory);
|
|
1284
1330
|
__privateAdd$3(this, _checkForMissingDeps);
|
|
@@ -1286,17 +1332,62 @@ class ServiceRegistry {
|
|
|
1286
1332
|
__privateAdd$3(this, _loadedDefaultFactories, void 0);
|
|
1287
1333
|
__privateAdd$3(this, _implementations, void 0);
|
|
1288
1334
|
__privateAdd$3(this, _rootServiceImplementations, /* @__PURE__ */ new Map());
|
|
1335
|
+
__privateAdd$3(this, _addedFactoryIds, /* @__PURE__ */ new Set());
|
|
1336
|
+
__privateAdd$3(this, _instantiatedFactories, /* @__PURE__ */ new Set());
|
|
1289
1337
|
__privateSet$3(this, _providedFactories, new Map(
|
|
1290
1338
|
factories.map((sf) => [sf.service.id, toInternalServiceFactory(sf)])
|
|
1291
1339
|
));
|
|
1292
1340
|
__privateSet$3(this, _loadedDefaultFactories, /* @__PURE__ */ new Map());
|
|
1293
1341
|
__privateSet$3(this, _implementations, /* @__PURE__ */ new Map());
|
|
1294
1342
|
}
|
|
1343
|
+
static create(factories) {
|
|
1344
|
+
const registry = new _ServiceRegistry(factories);
|
|
1345
|
+
registry.checkForCircularDeps();
|
|
1346
|
+
return registry;
|
|
1347
|
+
}
|
|
1348
|
+
checkForCircularDeps() {
|
|
1349
|
+
const graph = DependencyGraph.fromIterable(
|
|
1350
|
+
Array.from(__privateGet$3(this, _providedFactories)).map(
|
|
1351
|
+
([serviceId, serviceFactory]) => ({
|
|
1352
|
+
value: serviceId,
|
|
1353
|
+
provides: [serviceId],
|
|
1354
|
+
consumes: Object.values(serviceFactory.deps).map((d) => d.id)
|
|
1355
|
+
})
|
|
1356
|
+
)
|
|
1357
|
+
);
|
|
1358
|
+
const circularDependencies = Array.from(graph.detectCircularDependencies());
|
|
1359
|
+
if (circularDependencies.length) {
|
|
1360
|
+
const cycles = circularDependencies.map((c) => c.map((id) => `'${id}'`).join(" -> ")).join("\n ");
|
|
1361
|
+
throw new errors.ConflictError(`Circular dependencies detected:
|
|
1362
|
+
${cycles}`);
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
add(factory) {
|
|
1366
|
+
const factoryId = factory.service.id;
|
|
1367
|
+
if (factoryId === backendPluginApi.coreServices.pluginMetadata.id) {
|
|
1368
|
+
throw new Error(
|
|
1369
|
+
`The ${backendPluginApi.coreServices.pluginMetadata.id} service cannot be overridden`
|
|
1370
|
+
);
|
|
1371
|
+
}
|
|
1372
|
+
if (__privateGet$3(this, _addedFactoryIds).has(factoryId)) {
|
|
1373
|
+
throw new Error(
|
|
1374
|
+
`Duplicate service implementations provided for ${factoryId}`
|
|
1375
|
+
);
|
|
1376
|
+
}
|
|
1377
|
+
if (__privateGet$3(this, _instantiatedFactories).has(factoryId)) {
|
|
1378
|
+
throw new Error(
|
|
1379
|
+
`Unable to set service factory with id ${factoryId}, service has already been instantiated`
|
|
1380
|
+
);
|
|
1381
|
+
}
|
|
1382
|
+
__privateGet$3(this, _addedFactoryIds).add(factoryId);
|
|
1383
|
+
__privateGet$3(this, _providedFactories).set(factoryId, toInternalServiceFactory(factory));
|
|
1384
|
+
}
|
|
1295
1385
|
getServiceRefs() {
|
|
1296
1386
|
return Array.from(__privateGet$3(this, _providedFactories).values()).map((f) => f.service);
|
|
1297
1387
|
}
|
|
1298
1388
|
get(ref, pluginId) {
|
|
1299
1389
|
var _a;
|
|
1390
|
+
__privateGet$3(this, _instantiatedFactories).add(ref.id);
|
|
1300
1391
|
return (_a = __privateMethod$2(this, _resolveFactory, resolveFactory_fn).call(this, ref, pluginId)) == null ? void 0 : _a.then((factory) => {
|
|
1301
1392
|
if (factory.service.scope === "root") {
|
|
1302
1393
|
let existing = __privateGet$3(this, _rootServiceImplementations).get(factory);
|
|
@@ -1367,11 +1458,13 @@ class ServiceRegistry {
|
|
|
1367
1458
|
return result;
|
|
1368
1459
|
});
|
|
1369
1460
|
}
|
|
1370
|
-
}
|
|
1461
|
+
};
|
|
1371
1462
|
_providedFactories = new WeakMap();
|
|
1372
1463
|
_loadedDefaultFactories = new WeakMap();
|
|
1373
1464
|
_implementations = new WeakMap();
|
|
1374
1465
|
_rootServiceImplementations = new WeakMap();
|
|
1466
|
+
_addedFactoryIds = new WeakMap();
|
|
1467
|
+
_instantiatedFactories = new WeakMap();
|
|
1375
1468
|
_resolveFactory = new WeakSet();
|
|
1376
1469
|
resolveFactory_fn = function(ref, pluginId) {
|
|
1377
1470
|
if (ref.id === backendPluginApi.coreServices.pluginMetadata.id) {
|
|
@@ -1420,6 +1513,7 @@ checkForMissingDeps_fn = function(factory, pluginId) {
|
|
|
1420
1513
|
);
|
|
1421
1514
|
}
|
|
1422
1515
|
};
|
|
1516
|
+
let ServiceRegistry = _ServiceRegistry;
|
|
1423
1517
|
|
|
1424
1518
|
var __accessCheck$2 = (obj, member, msg) => {
|
|
1425
1519
|
if (!member.has(obj))
|
|
@@ -1443,7 +1537,7 @@ var __privateMethod$1 = (obj, member, method) => {
|
|
|
1443
1537
|
__accessCheck$2(obj, member, "access private method");
|
|
1444
1538
|
return method;
|
|
1445
1539
|
};
|
|
1446
|
-
var _startPromise, _features, _extensionPoints,
|
|
1540
|
+
var _startPromise, _features, _extensionPoints, _serviceRegistry, _registeredFeatures, _getInitDeps, getInitDeps_fn, _addFeature, addFeature_fn, _doStart, doStart_fn, _getRootLifecycleImpl, getRootLifecycleImpl_fn, _getPluginLifecycleImpl, getPluginLifecycleImpl_fn;
|
|
1447
1541
|
class BackendInitializer {
|
|
1448
1542
|
constructor(defaultApiFactories) {
|
|
1449
1543
|
__privateAdd$2(this, _getInitDeps);
|
|
@@ -1455,16 +1549,15 @@ class BackendInitializer {
|
|
|
1455
1549
|
__privateAdd$2(this, _startPromise, void 0);
|
|
1456
1550
|
__privateAdd$2(this, _features, new Array());
|
|
1457
1551
|
__privateAdd$2(this, _extensionPoints, /* @__PURE__ */ new Map());
|
|
1458
|
-
__privateAdd$2(this,
|
|
1459
|
-
__privateAdd$2(this,
|
|
1460
|
-
|
|
1461
|
-
__privateSet$2(this, _defaultApiFactories, defaultApiFactories);
|
|
1552
|
+
__privateAdd$2(this, _serviceRegistry, void 0);
|
|
1553
|
+
__privateAdd$2(this, _registeredFeatures, new Array());
|
|
1554
|
+
__privateSet$2(this, _serviceRegistry, ServiceRegistry.create([...defaultApiFactories]));
|
|
1462
1555
|
}
|
|
1463
1556
|
add(feature) {
|
|
1464
1557
|
if (__privateGet$2(this, _startPromise)) {
|
|
1465
1558
|
throw new Error("feature can not be added after the backend has started");
|
|
1466
1559
|
}
|
|
1467
|
-
|
|
1560
|
+
__privateGet$2(this, _registeredFeatures).push(Promise.resolve(feature));
|
|
1468
1561
|
}
|
|
1469
1562
|
async start() {
|
|
1470
1563
|
if (__privateGet$2(this, _startPromise)) {
|
|
@@ -1503,15 +1596,14 @@ class BackendInitializer {
|
|
|
1503
1596
|
_startPromise = new WeakMap();
|
|
1504
1597
|
_features = new WeakMap();
|
|
1505
1598
|
_extensionPoints = new WeakMap();
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
_defaultApiFactories = new WeakMap();
|
|
1599
|
+
_serviceRegistry = new WeakMap();
|
|
1600
|
+
_registeredFeatures = new WeakMap();
|
|
1509
1601
|
_getInitDeps = new WeakSet();
|
|
1510
1602
|
getInitDeps_fn = async function(deps, pluginId) {
|
|
1511
1603
|
const result = /* @__PURE__ */ new Map();
|
|
1512
1604
|
const missingRefs = /* @__PURE__ */ new Set();
|
|
1513
1605
|
for (const [name, ref] of Object.entries(deps)) {
|
|
1514
|
-
const ep = __privateGet$2(this, _extensionPoints).get(ref);
|
|
1606
|
+
const ep = __privateGet$2(this, _extensionPoints).get(ref.id);
|
|
1515
1607
|
if (ep) {
|
|
1516
1608
|
if (ep.pluginId !== pluginId) {
|
|
1517
1609
|
throw new Error(
|
|
@@ -1520,7 +1612,7 @@ getInitDeps_fn = async function(deps, pluginId) {
|
|
|
1520
1612
|
}
|
|
1521
1613
|
result.set(name, ep.impl);
|
|
1522
1614
|
} else {
|
|
1523
|
-
const impl = await __privateGet$2(this,
|
|
1615
|
+
const impl = await __privateGet$2(this, _serviceRegistry).get(
|
|
1524
1616
|
ref,
|
|
1525
1617
|
pluginId
|
|
1526
1618
|
);
|
|
@@ -1547,19 +1639,7 @@ addFeature_fn = function(feature) {
|
|
|
1547
1639
|
);
|
|
1548
1640
|
}
|
|
1549
1641
|
if (isServiceFactory(feature)) {
|
|
1550
|
-
|
|
1551
|
-
throw new Error(
|
|
1552
|
-
`The ${backendPluginApi.coreServices.pluginMetadata.id} service cannot be overridden`
|
|
1553
|
-
);
|
|
1554
|
-
}
|
|
1555
|
-
if (__privateGet$2(this, _providedServiceFactories).find(
|
|
1556
|
-
(sf) => sf.service.id === feature.service.id
|
|
1557
|
-
)) {
|
|
1558
|
-
throw new Error(
|
|
1559
|
-
`Duplicate service implementations provided for ${feature.service.id}`
|
|
1560
|
-
);
|
|
1561
|
-
}
|
|
1562
|
-
__privateGet$2(this, _providedServiceFactories).push(feature);
|
|
1642
|
+
__privateGet$2(this, _serviceRegistry).add(feature);
|
|
1563
1643
|
} else if (isInternalBackendFeature(feature)) {
|
|
1564
1644
|
if (feature.version !== "v1") {
|
|
1565
1645
|
throw new Error(
|
|
@@ -1575,11 +1655,11 @@ addFeature_fn = function(feature) {
|
|
|
1575
1655
|
};
|
|
1576
1656
|
_doStart = new WeakSet();
|
|
1577
1657
|
doStart_fn = async function() {
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
const featureDiscovery = await __privateGet$2(this,
|
|
1658
|
+
__privateGet$2(this, _serviceRegistry).checkForCircularDeps();
|
|
1659
|
+
for (const feature of __privateGet$2(this, _registeredFeatures)) {
|
|
1660
|
+
__privateMethod$1(this, _addFeature, addFeature_fn).call(this, await feature);
|
|
1661
|
+
}
|
|
1662
|
+
const featureDiscovery = await __privateGet$2(this, _serviceRegistry).get(
|
|
1583
1663
|
alpha.featureDiscoveryServiceRef,
|
|
1584
1664
|
"root"
|
|
1585
1665
|
);
|
|
@@ -1588,10 +1668,11 @@ doStart_fn = async function() {
|
|
|
1588
1668
|
for (const feature of features) {
|
|
1589
1669
|
__privateMethod$1(this, _addFeature, addFeature_fn).call(this, feature);
|
|
1590
1670
|
}
|
|
1671
|
+
__privateGet$2(this, _serviceRegistry).checkForCircularDeps();
|
|
1591
1672
|
}
|
|
1592
|
-
for (const ref of __privateGet$2(this,
|
|
1673
|
+
for (const ref of __privateGet$2(this, _serviceRegistry).getServiceRefs()) {
|
|
1593
1674
|
if (ref.scope === "root") {
|
|
1594
|
-
await __privateGet$2(this,
|
|
1675
|
+
await __privateGet$2(this, _serviceRegistry).get(ref, "root");
|
|
1595
1676
|
}
|
|
1596
1677
|
}
|
|
1597
1678
|
const pluginInits = /* @__PURE__ */ new Map();
|
|
@@ -1601,12 +1682,12 @@ doStart_fn = async function() {
|
|
|
1601
1682
|
const provides = /* @__PURE__ */ new Set();
|
|
1602
1683
|
if (r.type === "plugin" || r.type === "module") {
|
|
1603
1684
|
for (const [extRef, extImpl] of r.extensionPoints) {
|
|
1604
|
-
if (__privateGet$2(this, _extensionPoints).has(extRef)) {
|
|
1685
|
+
if (__privateGet$2(this, _extensionPoints).has(extRef.id)) {
|
|
1605
1686
|
throw new Error(
|
|
1606
1687
|
`ExtensionPoint with ID '${extRef.id}' is already registered`
|
|
1607
1688
|
);
|
|
1608
1689
|
}
|
|
1609
|
-
__privateGet$2(this, _extensionPoints).set(extRef, {
|
|
1690
|
+
__privateGet$2(this, _extensionPoints).set(extRef.id, {
|
|
1610
1691
|
impl: extImpl,
|
|
1611
1692
|
pluginId: r.pluginId
|
|
1612
1693
|
});
|
|
@@ -1693,7 +1774,7 @@ doStart_fn = async function() {
|
|
|
1693
1774
|
const lifecycleService = await __privateMethod$1(this, _getRootLifecycleImpl, getRootLifecycleImpl_fn).call(this);
|
|
1694
1775
|
await lifecycleService.startup();
|
|
1695
1776
|
if (process.env.NODE_ENV !== "test") {
|
|
1696
|
-
const rootLogger = await __privateGet$2(this,
|
|
1777
|
+
const rootLogger = await __privateGet$2(this, _serviceRegistry).get(
|
|
1697
1778
|
backendPluginApi.coreServices.rootLogger,
|
|
1698
1779
|
"root"
|
|
1699
1780
|
);
|
|
@@ -1709,7 +1790,7 @@ doStart_fn = async function() {
|
|
|
1709
1790
|
};
|
|
1710
1791
|
_getRootLifecycleImpl = new WeakSet();
|
|
1711
1792
|
getRootLifecycleImpl_fn = async function() {
|
|
1712
|
-
const lifecycleService = await __privateGet$2(this,
|
|
1793
|
+
const lifecycleService = await __privateGet$2(this, _serviceRegistry).get(
|
|
1713
1794
|
backendPluginApi.coreServices.rootLifecycle,
|
|
1714
1795
|
"root"
|
|
1715
1796
|
);
|
|
@@ -1720,7 +1801,7 @@ getRootLifecycleImpl_fn = async function() {
|
|
|
1720
1801
|
};
|
|
1721
1802
|
_getPluginLifecycleImpl = new WeakSet();
|
|
1722
1803
|
getPluginLifecycleImpl_fn = async function(pluginId) {
|
|
1723
|
-
const lifecycleService = await __privateGet$2(this,
|
|
1804
|
+
const lifecycleService = await __privateGet$2(this, _serviceRegistry).get(
|
|
1724
1805
|
backendPluginApi.coreServices.lifecycle,
|
|
1725
1806
|
pluginId
|
|
1726
1807
|
);
|
|
@@ -1761,7 +1842,11 @@ class BackstageBackend {
|
|
|
1761
1842
|
__privateSet$1(this, _initializer, new BackendInitializer(defaultServiceFactories));
|
|
1762
1843
|
}
|
|
1763
1844
|
add(feature) {
|
|
1764
|
-
|
|
1845
|
+
if (isPromise(feature)) {
|
|
1846
|
+
__privateGet$1(this, _initializer).add(feature.then((f) => unwrapFeature(f.default)));
|
|
1847
|
+
} else {
|
|
1848
|
+
__privateGet$1(this, _initializer).add(unwrapFeature(feature));
|
|
1849
|
+
}
|
|
1765
1850
|
}
|
|
1766
1851
|
async start() {
|
|
1767
1852
|
await __privateGet$1(this, _initializer).start();
|
|
@@ -1771,6 +1856,12 @@ class BackstageBackend {
|
|
|
1771
1856
|
}
|
|
1772
1857
|
}
|
|
1773
1858
|
_initializer = new WeakMap();
|
|
1859
|
+
function isPromise(value) {
|
|
1860
|
+
return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
|
|
1861
|
+
}
|
|
1862
|
+
function unwrapFeature(feature) {
|
|
1863
|
+
return typeof feature === "function" ? feature() : feature;
|
|
1864
|
+
}
|
|
1774
1865
|
|
|
1775
1866
|
function createSpecializedBackend(options) {
|
|
1776
1867
|
const services = options.defaultServiceFactories.map(
|