From 0c4ee1876f1f8773cda2ba2fc69e9873d066bb53 Mon Sep 17 00:00:00 2001 From: Jussi Hallila Date: Fri, 27 Aug 2021 15:34:33 +0200 Subject: [PATCH 1/4] Modify app impl to contain a reference to apiRegistry. Store additional, late registered and lazy loaded APIs in the registry as well. Route paths, route objs and others are collected already on late reg, this adds APIs to be collected also. Signed-off-by: Jussi Hallila --- .changeset/great-humans-return.md | 7 +++++ packages/core-app-api/src/app/App.tsx | 40 ++++++++++++++++++--------- 2 files changed, 34 insertions(+), 13 deletions(-) create mode 100644 .changeset/great-humans-return.md diff --git a/.changeset/great-humans-return.md b/.changeset/great-humans-return.md new file mode 100644 index 0000000000..bb35069161 --- /dev/null +++ b/.changeset/great-humans-return.md @@ -0,0 +1,7 @@ +--- +'@backstage/core-app-api': patch +--- + +Store additional, late registered and lazy loaded APIs in the registry as well. +Route paths, route objs and others are collected already on late reg, this adds APIs to be collected also. +Enables late registration of plugins into the application and updates ApiHolder when additional plugins have been added in. diff --git a/packages/core-app-api/src/app/App.tsx b/packages/core-app-api/src/app/App.tsx index 7857c8b35f..21d79e6926 100644 --- a/packages/core-app-api/src/app/App.tsx +++ b/packages/core-app-api/src/app/App.tsx @@ -198,6 +198,7 @@ export class PrivateAppImpl implements BackstageApp { private readonly bindRoutes: AppOptions['bindRoutes']; private readonly identityApi = new AppIdentity(); + private readonly apiFactoryRegistry: ApiFactoryRegistry; constructor(options: FullAppOptions) { this.apis = options.apis; @@ -208,6 +209,7 @@ export class PrivateAppImpl implements BackstageApp { this.configLoader = options.configLoader; this.defaultApis = options.defaultApis; this.bindRoutes = options.bindRoutes; + this.apiFactoryRegistry = new ApiFactoryRegistry(); } getPlugins(): BackstagePlugin[] { @@ -388,17 +390,27 @@ export class PrivateAppImpl implements BackstageApp { private getApiHolder(): ApiHolder { if (this.apiHolder) { + // Register additional plugins if they have been added. + // Routes and other config options are updated above when children change + for (const plugin of this.plugins) { + for (const factory of plugin.getApis()) { + if (!this.apiFactoryRegistry.get(factory.api)) { + this.apiFactoryRegistry.register('default', factory); + } + } + } + ApiResolver.validateFactories( + this.apiFactoryRegistry, + this.apiFactoryRegistry.getAllApis(), + ); return this.apiHolder; } - - const registry = new ApiFactoryRegistry(); - - registry.register('static', { + this.apiFactoryRegistry.register('static', { api: appThemeApiRef, deps: {}, factory: () => AppThemeSelector.createWithStorage(this.themes), }); - registry.register('static', { + this.apiFactoryRegistry.register('static', { api: configApiRef, deps: {}, factory: () => { @@ -410,7 +422,7 @@ export class PrivateAppImpl implements BackstageApp { return this.configApi; }, }); - registry.register('static', { + this.apiFactoryRegistry.register('static', { api: identityApiRef, deps: {}, factory: () => this.identityApi, @@ -418,18 +430,18 @@ export class PrivateAppImpl implements BackstageApp { // It's possible to replace the feature flag API, but since we must have at least // one implementation we add it here directly instead of through the defaultApis. - registry.register('default', { + this.apiFactoryRegistry.register('default', { api: featureFlagsApiRef, deps: {}, factory: () => new LocalStorageFeatureFlags(), }); for (const factory of this.defaultApis) { - registry.register('default', factory); + this.apiFactoryRegistry.register('default', factory); } for (const plugin of this.plugins) { for (const factory of plugin.getApis()) { - if (!registry.register('default', factory)) { + if (!this.apiFactoryRegistry.register('default', factory)) { throw new Error( `Plugin ${plugin.getId()} tried to register duplicate or forbidden API factory for ${ factory.api @@ -440,17 +452,19 @@ export class PrivateAppImpl implements BackstageApp { } for (const factory of this.apis) { - if (!registry.register('app', factory)) { + if (!this.apiFactoryRegistry.register('app', factory)) { throw new Error( `Duplicate or forbidden API factory for ${factory.api} in app`, ); } } - ApiResolver.validateFactories(registry, registry.getAllApis()); - - this.apiHolder = new ApiResolver(registry); + ApiResolver.validateFactories( + this.apiFactoryRegistry, + this.apiFactoryRegistry.getAllApis(), + ); + this.apiHolder = new ApiResolver(this.apiFactoryRegistry); return this.apiHolder; } From ab4e129ca53b91aa89d0e2ced86d6f2ee02ded29 Mon Sep 17 00:00:00 2001 From: Jussi Hallila Date: Fri, 24 Sep 2021 13:56:42 +0200 Subject: [PATCH 2/4] Tweak comment. Signed-off-by: Jussi Hallila --- packages/core-app-api/src/app/App.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core-app-api/src/app/App.tsx b/packages/core-app-api/src/app/App.tsx index 21d79e6926..f5fec7e624 100644 --- a/packages/core-app-api/src/app/App.tsx +++ b/packages/core-app-api/src/app/App.tsx @@ -391,7 +391,7 @@ export class PrivateAppImpl implements BackstageApp { private getApiHolder(): ApiHolder { if (this.apiHolder) { // Register additional plugins if they have been added. - // Routes and other config options are updated above when children change + // Routes paths, objects and others are already updated in the provider when children of it change for (const plugin of this.plugins) { for (const factory of plugin.getApis()) { if (!this.apiFactoryRegistry.get(factory.api)) { From e13bc6909982b7096bcae748acee7ea5baa8ad34 Mon Sep 17 00:00:00 2001 From: Jussi Hallila Date: Fri, 24 Sep 2021 13:59:40 +0200 Subject: [PATCH 3/4] Fix English text in changeset. Signed-off-by: Jussi Hallila --- .changeset/great-humans-return.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/great-humans-return.md b/.changeset/great-humans-return.md index bb35069161..1a7c2ee5da 100644 --- a/.changeset/great-humans-return.md +++ b/.changeset/great-humans-return.md @@ -3,5 +3,5 @@ --- Store additional, late registered and lazy loaded APIs in the registry as well. -Route paths, route objs and others are collected already on late reg, this adds APIs to be collected also. +Route paths, route objects and others are collected already on late registration, this adds APIs to be collected also. Enables late registration of plugins into the application and updates ApiHolder when additional plugins have been added in. From 98ff0f47756b18085a7768bbe95a62a89ac795d8 Mon Sep 17 00:00:00 2001 From: Jussi Hallila Date: Tue, 28 Sep 2021 08:34:11 +0200 Subject: [PATCH 4/4] Modify wording in changeset. Signed-off-by: Jussi Hallila --- .changeset/great-humans-return.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.changeset/great-humans-return.md b/.changeset/great-humans-return.md index 1a7c2ee5da..dd1cda0f5a 100644 --- a/.changeset/great-humans-return.md +++ b/.changeset/great-humans-return.md @@ -2,6 +2,4 @@ '@backstage/core-app-api': patch --- -Store additional, late registered and lazy loaded APIs in the registry as well. -Route paths, route objects and others are collected already on late registration, this adds APIs to be collected also. -Enables late registration of plugins into the application and updates ApiHolder when additional plugins have been added in. +Enables late registration of plugins into the application by updating ApiHolder when additional plugins have been added in.