frontend-plugin-api: move app blueprints to new app-react package

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2026-01-16 10:58:04 +01:00
parent d15524f895
commit 9ccf84e219
33 changed files with 653 additions and 34 deletions
+3 -1
View File
@@ -7,7 +7,8 @@
"pluginPackages": [
"@backstage/plugin-app",
"@backstage/plugin-app-backend",
"@backstage/plugin-app-node"
"@backstage/plugin-app-node",
"@backstage/plugin-app-react"
]
},
"publishConfig": {
@@ -54,6 +55,7 @@
"@backstage/core-plugin-api": "workspace:^",
"@backstage/frontend-plugin-api": "workspace:^",
"@backstage/integration-react": "workspace:^",
"@backstage/plugin-app-react": "workspace:^",
"@backstage/plugin-permission-react": "workspace:^",
"@backstage/theme": "workspace:^",
"@backstage/types": "workspace:^",
+8
View File
@@ -94,6 +94,14 @@ export const AppNav = createExtension({
},
output: [coreExtensionData.reactElement],
*factory({ inputs }) {
if (inputs.content && inputs.content.node.spec.plugin?.id !== 'app') {
// eslint-disable-next-line no-console
console.warn(
`DEPRECATION WARNING: NavContent should only be installed as an extension in the app plugin. ` +
`You can either use appPlugin.override(), or a module for the app plugin. The following extension will be ignored in the future: ${inputs.content.node.spec.id}`,
);
}
const Content =
inputs.content?.get(NavContentBlueprint.dataRefs.component) ??
DefaultNavContent;
+16
View File
@@ -74,6 +74,22 @@ export const AppRoot = createExtension({
},
output: [coreExtensionData.reactElement],
factory({ inputs, apis }) {
if (inputs.router && inputs.router.node.spec.plugin?.id !== 'app') {
// eslint-disable-next-line no-console
console.warn(
`DEPRECATION WARNING: Router should only be installed as an extension in the app plugin. ` +
`You can either use appPlugin.override(), or a module for the app plugin. The following extension will be ignored in the future: ${inputs.router.node.spec.id}`,
);
}
if (inputs.signInPage && inputs.signInPage.node.spec.plugin?.id !== 'app') {
// eslint-disable-next-line no-console
console.warn(
`DEPRECATION WARNING: SignInPage should only be installed as an extension in the app plugin. ` +
`You can either use appPlugin.override(), or a module for the app plugin. The following extension will be ignored in the future: ${inputs.signInPage.node.spec.id}`,
);
}
if (isProtectedApp()) {
const identityApi = apis.get(identityApiRef);
if (!identityApi) {
+17 -3
View File
@@ -44,10 +44,24 @@ export const AppThemeApi = ApiBlueprint.makeWithOverrides({
defineParams({
api: appThemeApiRef,
deps: {},
factory: () =>
AppThemeSelector.createWithStorage(
factory: () => {
const nonAppExtensions = inputs.themes.filter(
i => i.node.spec.plugin?.id !== 'app',
);
if (nonAppExtensions.length > 0) {
const list = nonAppExtensions.map(i => i.node.spec.id).join(', ');
// eslint-disable-next-line no-console
console.warn(
`DEPRECATION WARNING: Theme should only be installed as an extension in the app plugin. ` +
`You can either use appPlugin.override(), or a module for the app plugin. The following extension will be ignored in the future: ${list}`,
);
}
return AppThemeSelector.createWithStorage(
inputs.themes.map(i => i.get(ThemeBlueprint.dataRefs.theme)),
),
);
},
}),
);
},
+17 -3
View File
@@ -40,12 +40,26 @@ export const IconsApi = ApiBlueprint.makeWithOverrides({
defineParams({
api: iconsApiRef,
deps: {},
factory: () =>
new DefaultIconsApi(
factory: () => {
const nonAppExtensions = inputs.icons.filter(
i => i.node.spec.plugin?.id !== 'app',
);
if (nonAppExtensions.length > 0) {
const list = nonAppExtensions.map(i => i.node.spec.id).join(', ');
// eslint-disable-next-line no-console
console.warn(
`DEPRECATION WARNING: IconBundle should only be installed as an extension in the app plugin. ` +
`You can either use appPlugin.override(), or a module for the app plugin. The following extension will be ignored in the future: ${list}`,
);
}
return new DefaultIconsApi(
inputs.icons
.map(i => i.get(IconBundleBlueprint.dataRefs.icons))
.reduce((acc, bundle) => ({ ...acc, ...bundle }), defaultIcons),
),
);
},
}),
);
},
+17 -3
View File
@@ -42,13 +42,27 @@ export const TranslationsApi = ApiBlueprint.makeWithOverrides({
defineParams({
api: translationApiRef,
deps: { languageApi: appLanguageApiRef },
factory: ({ languageApi }) =>
I18nextTranslationApi.create({
factory: ({ languageApi }) => {
const nonAppExtensions = inputs.translations.filter(
i => i.node.spec.plugin?.id !== 'app',
);
if (nonAppExtensions.length > 0) {
const list = nonAppExtensions.map(i => i.node.spec.id).join(', ');
// eslint-disable-next-line no-console
console.warn(
`DEPRECATION WARNING: Translations should only be installed as an extension in the app plugin. ` +
`You can either use appPlugin.override(), or a module for the app plugin. The following extension will be ignored in the future: ${list}`,
);
}
return I18nextTranslationApi.create({
languageApi,
resources: inputs.translations.map(i =>
i.get(TranslationBlueprint.dataRefs.translation),
),
}),
});
},
}),
);
},