diff --git a/packages/frontend-app-api/src/apis/implementations/ComponentsApi/DefaultComponentsApi.test.tsx b/packages/frontend-app-api/src/apis/implementations/ComponentsApi/DefaultComponentsApi.test.tsx
index e2c7581e63..3d19fc413f 100644
--- a/packages/frontend-app-api/src/apis/implementations/ComponentsApi/DefaultComponentsApi.test.tsx
+++ b/packages/frontend-app-api/src/apis/implementations/ComponentsApi/DefaultComponentsApi.test.tsx
@@ -15,57 +15,22 @@
*/
import React from 'react';
-import {
- coreExtensionData,
- createComponentExtension,
- createComponentRef,
- createExtension,
- createExtensionOverrides,
-} from '@backstage/frontend-plugin-api';
-import { resolveAppNodeSpecs } from '../../../tree/resolveAppNodeSpecs';
-import { resolveAppTree } from '../../../tree/resolveAppTree';
-import { App } from '../../../extensions/App';
+import { createComponentRef } from '@backstage/frontend-plugin-api';
import { DefaultComponentsApi } from './DefaultComponentsApi';
import { render, screen } from '@testing-library/react';
-import { instantiateAppNodeTree } from '../../../tree/instantiateAppNodeTree';
const testRefA = createComponentRef({ id: 'test.a' });
const testRefB1 = createComponentRef({ id: 'test.b' });
const testRefB2 = createComponentRef({ id: 'test.b' });
-const baseOverrides = createExtensionOverrides({
- extensions: [
- App,
- createExtension({
- namespace: 'app',
- name: 'root',
- attachTo: { id: 'app', input: 'root' },
- output: [coreExtensionData.reactElement],
- factory: () => [coreExtensionData.reactElement(
root
)],
- }),
- ],
-});
-
describe('DefaultComponentsApi', () => {
it('should provide components', () => {
- const tree = resolveAppTree(
- 'app',
- resolveAppNodeSpecs({
- features: [
- baseOverrides,
- createExtensionOverrides({
- extensions: [
- createComponentExtension({
- ref: testRefA,
- loader: { sync: () => () => test.a
},
- }),
- ],
- }),
- ],
- }),
- );
- instantiateAppNodeTree(tree.root);
- const api = DefaultComponentsApi.fromTree(tree);
+ const api = DefaultComponentsApi.fromComponents([
+ {
+ ref: testRefA,
+ impl: () => test.a
,
+ },
+ ]);
const ComponentA = api.getComponent(testRefA);
render();
@@ -74,24 +39,12 @@ describe('DefaultComponentsApi', () => {
});
it('should key extension refs by ID', () => {
- const tree = resolveAppTree(
- 'app',
- resolveAppNodeSpecs({
- features: [
- baseOverrides,
- createExtensionOverrides({
- extensions: [
- createComponentExtension({
- ref: testRefB1,
- loader: { sync: () => () => test.b
},
- }),
- ],
- }),
- ],
- }),
- );
- instantiateAppNodeTree(tree.root);
- const api = DefaultComponentsApi.fromTree(tree);
+ const api = DefaultComponentsApi.fromComponents([
+ {
+ ref: testRefB1,
+ impl: () => test.b
,
+ },
+ ]);
const ComponentB1 = api.getComponent(testRefB1);
const ComponentB2 = api.getComponent(testRefB2);
diff --git a/packages/frontend-app-api/src/extensions/AppLanguageApi.ts b/packages/frontend-app-api/src/extensions/AppLanguageApi.ts
new file mode 100644
index 0000000000..ff12848d44
--- /dev/null
+++ b/packages/frontend-app-api/src/extensions/AppLanguageApi.ts
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2024 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// eslint-disable-next-line @backstage/no-relative-monorepo-imports
+import { AppLanguageSelector } from '../../../core-app-api/src/apis/implementations/AppLanguageApi';
+import { appLanguageApiRef } from '@backstage/core-plugin-api/alpha';
+import { ApiBlueprint, createApiFactory } from '@backstage/frontend-plugin-api';
+
+export const AppLanguageApi = ApiBlueprint.make({
+ name: 'app-language',
+ params: {
+ factory: createApiFactory(
+ appLanguageApiRef,
+ AppLanguageSelector.createWithStorage(),
+ ),
+ },
+});
diff --git a/packages/frontend-app-api/src/extensions/FeatureFlagsApi.ts b/packages/frontend-app-api/src/extensions/FeatureFlagsApi.ts
new file mode 100644
index 0000000000..3acc6e52be
--- /dev/null
+++ b/packages/frontend-app-api/src/extensions/FeatureFlagsApi.ts
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2024 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {
+ ApiBlueprint,
+ createApiFactory,
+ featureFlagsApiRef,
+} from '@backstage/frontend-plugin-api';
+// eslint-disable-next-line @backstage/no-relative-monorepo-imports
+import { LocalStorageFeatureFlags } from '../../../core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags';
+
+/**
+ * Contains the shareable icons installed into the app.
+ *
+ * @public
+ */
+export const FeatureFlagsApi = ApiBlueprint.make({
+ name: 'feature-flags',
+ params: {
+ // TODO: properly discovery feature flags, maybe rework the whole thing
+ factory: createApiFactory({
+ api: featureFlagsApiRef,
+ deps: {},
+ factory: () => new LocalStorageFeatureFlags(),
+ }),
+ },
+});
diff --git a/packages/frontend-app-api/src/extensions/TranslationsApi.ts b/packages/frontend-app-api/src/extensions/TranslationsApi.tsx
similarity index 100%
rename from packages/frontend-app-api/src/extensions/TranslationsApi.ts
rename to packages/frontend-app-api/src/extensions/TranslationsApi.tsx
diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx
index 13374e2e17..37594f74d4 100644
--- a/packages/frontend-app-api/src/wiring/createApp.tsx
+++ b/packages/frontend-app-api/src/wiring/createApp.tsx
@@ -55,14 +55,10 @@ import { AppThemeProvider } from '../../../core-app-api/src/app/AppThemeProvider
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
import { AppIdentityProxy } from '../../../core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy';
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
-import { LocalStorageFeatureFlags } from '../../../core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags';
-// eslint-disable-next-line @backstage/no-relative-monorepo-imports
import { defaultConfigLoaderSync } from '../../../core-app-api/src/app/defaultConfigLoader';
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
import { overrideBaseUrlConfigs } from '../../../core-app-api/src/app/overrideBaseUrlConfigs';
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
-import { AppLanguageSelector } from '../../../core-app-api/src/apis/implementations/AppLanguageApi/AppLanguageSelector';
-// eslint-disable-next-line @backstage/no-relative-monorepo-imports
import { resolveExtensionDefinition } from '../../../frontend-plugin-api/src/wiring/resolveExtensionDefinition';
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
import { apis as defaultApis } from '../../../app-defaults/src/defaults';
@@ -72,7 +68,7 @@ import {
alertDisplayAppRootElement,
} from '../extensions/elements';
import { extractRouteInfoFromAppNode } from '../routing/extractRouteInfoFromAppNode';
-import { appLanguageApiRef } from '@backstage/core-plugin-api/alpha';
+
import { CreateAppRouteBinder } from '../routing';
import { RouteResolver } from '../routing/RouteResolver';
import { resolveRouteBindings } from '../routing/resolveRouteBindings';
@@ -95,6 +91,8 @@ import { AppThemeApi, DarkTheme, LightTheme } from '../extensions/AppThemeApi';
import { IconsApi } from '../extensions/IconsApi';
import { TranslationsApi } from '../extensions/TranslationsApi';
import { ComponentsApi } from '../extensions/ComponentsApi';
+import { AppLanguageApi } from '../extensions/AppLanguageApi';
+import { FeatureFlagsApi } from '../extensions/FeatureFlagsApi';
const DefaultApis = defaultApis.map(factory =>
ApiBlueprint.make({ namespace: factory.api.id, params: { factory } }),
@@ -114,9 +112,11 @@ export const builtinExtensions = [
oauthRequestDialogAppRootElement,
alertDisplayAppRootElement,
AppThemeApi,
+ AppLanguageApi,
IconsApi,
TranslationsApi,
ComponentsApi,
+ FeatureFlagsApi,
...DefaultApis,
].map(def => resolveExtensionDefinition(def));
@@ -349,13 +349,6 @@ function createApiHolder(
factoryRegistry.register('default', factory);
}
- // TODO: properly discovery feature flags, maybe rework the whole thing
- factoryRegistry.register('default', {
- api: featureFlagsApiRef,
- deps: {},
- factory: () => new LocalStorageFeatureFlags(),
- });
-
factoryRegistry.register('static', {
api: identityApiRef,
deps: {},
@@ -376,12 +369,6 @@ function createApiHolder(
factory: () => routeResolutionApi,
});
- factoryRegistry.register('static', {
- api: appLanguageApiRef,
- deps: {},
- factory: () => AppLanguageSelector.createWithStorage(),
- });
-
factoryRegistry.register('static', {
api: configApiRef,
deps: {},