backend-app-api: nicer error messaging when service deps are missing

Co-authored-by: Fredrik Adelöw <freben@gmail.com>
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2022-09-02 11:24:17 +02:00
parent f52a9e0a60
commit 1f384c5644
3 changed files with 43 additions and 6 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-app-api': patch
---
Improved error messaging when failing to instantiate services.
@@ -220,4 +220,24 @@ describe('ServiceRegistry', () => {
expect(innerFactory).toHaveBeenCalledWith('catalog');
expect(innerFactory).toHaveBeenCalledWith('scaffolder');
});
it('should throw if dependencies are not available', async () => {
const myFactory = createServiceFactory({
service: ref1,
deps: { dep: ref2 },
async factory({ dep }) {
return async pluginId => {
const d = await dep(pluginId);
return { x: d.x, pluginId };
};
},
});
const registry = new ServiceRegistry([myFactory]);
const factory = registry.get(ref1)!;
await expect(factory('catalog')).rejects.toThrow(
"Failed to instantiate service '1' for 'catalog'. The following dependent services are missing: '2'",
);
});
});
@@ -56,12 +56,24 @@ export class ServiceRegistry {
let implementation = this.#implementations.get(factory);
if (!implementation) {
const factoryDeps = Object.fromEntries(
Object.entries(factory.deps).map(([name, serviceRef]) => [
name,
this.get(serviceRef)!, // TODO: throw
]),
);
const missingRefs = new Array<ServiceRef<unknown>>();
const factoryDeps: { [name in string]: FactoryFunc<unknown> } = {};
for (const [name, serviceRef] of Object.entries(factory.deps)) {
const target = this.get(serviceRef);
if (!target) {
missingRefs.push(serviceRef);
} else {
factoryDeps[name] = target;
}
}
if (missingRefs.length) {
const missing = missingRefs.map(r => `'${r.id}'`).join(', ');
throw new Error(
`Failed to instantiate service '${ref.id}' for '${pluginId}'. The following dependent services are missing: ${missing}`,
);
}
implementation = {
factoryFunc: factory.factory(factoryDeps),