Remove deprecated createPublicSignInApp from @backstage/frontend-defaults

The function was deprecated in favor of using `createApp` with the
`appModulePublicSignIn` module from `@backstage/plugin-app/alpha`.
This removes the function, its tests, and updates the documentation
to use the recommended approach.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2026-03-05 10:33:45 +01:00
parent d0b53e39fd
commit 33de79d5dd
6 changed files with 9 additions and 162 deletions
@@ -0,0 +1,5 @@
---
'@backstage/frontend-defaults': minor
---
**BREAKING**: Removed the deprecated `createPublicSignInApp` function. Use `createApp` from `@backstage/frontend-defaults` with `appModulePublicSignIn` from `@backstage/plugin-app/alpha` instead.
+4 -3
View File
@@ -107,10 +107,11 @@ If your app uses the new frontend system, you can still use the public entry poi
```tsx title="in packages/app/src/index-public-experimental.tsx"
import ReactDOM from 'react-dom/client';
import { signInPageModule } from './overrides/SignInPage';
import { createPublicSignInApp } from '@backstage/frontend-defaults';
import { appModulePublicSignIn } from '@backstage/plugin-app/alpha';
import { createApp } from '@backstage/frontend-defaults';
const app = createPublicSignInApp({
features: [signInPageModule],
const app = createApp({
features: [signInPageModule, appModulePublicSignIn],
});
ReactDOM.createRoot(document.getElementById('root')!).render(app.createRoot());
-5
View File
@@ -37,11 +37,6 @@ export interface CreateAppOptions {
features?: (FrontendFeature | FrontendFeatureLoader)[];
}
// @public @deprecated (undocumented)
export function createPublicSignInApp(options?: CreateAppOptions): {
createRoot(): JSX_2;
};
// @public (undocumented)
export function discoverAvailableFeatures(config: Config): {
features: (FrontendFeature | FrontendFeatureLoader)[];
@@ -1,124 +0,0 @@
/*
* 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 { createFrontendModule } from '@backstage/frontend-plugin-api';
import { SignInPageBlueprint } from '@backstage/plugin-app-react';
import { render, screen, waitFor } from '@testing-library/react';
import { useEffect } from 'react';
import { createPublicSignInApp } from './createPublicSignInApp';
import { mockApis } from '@backstage/test-utils';
describe('createPublicSignInApp', () => {
beforeEach(() => {
jest.resetAllMocks();
});
it('should render a sign-in page', async () => {
const app = createPublicSignInApp({
advanced: {
configLoader: async () => ({ config: mockApis.config() }),
},
features: [
createFrontendModule({
pluginId: 'app',
extensions: [
SignInPageBlueprint.make({
params: {
loader: async () => () => <div>Sign in page</div>,
},
}),
],
}),
],
});
render(app.createRoot());
await expect(
screen.findByText('Sign in page'),
).resolves.toBeInTheDocument();
});
it('should render the form redirect on sign-in', async () => {
const submitSpy = jest
.spyOn(HTMLFormElement.prototype, 'submit')
.mockReturnValue();
const app = createPublicSignInApp({
advanced: {
configLoader: async () => ({ config: mockApis.config() }),
},
features: [
createFrontendModule({
pluginId: 'app',
extensions: [
SignInPageBlueprint.make({
params: {
loader:
async () =>
({ onSignInSuccess }) => {
useEffect(() => {
onSignInSuccess(
mockApis.identity({ token: 'mock-token' }),
);
}, [onSignInSuccess]);
return <div />;
},
},
}),
],
}),
],
});
const { baseElement } = render(app.createRoot());
await waitFor(() => {
expect(submitSpy).toHaveBeenCalled();
});
expect(baseElement).toMatchInlineSnapshot(`
<body
data-theme-mode="light"
data-theme-name="backstage"
data-unified-theme-stack="[{"mode":"light","name":"backstage"}]"
>
<div>
<form
action="http://localhost/"
method="POST"
style="visibility: hidden;"
>
<input
name="type"
type="hidden"
value="sign-in"
/>
<input
name="token"
type="hidden"
value="mock-token"
/>
<input
type="submit"
value="Continue"
/>
</form>
</div>
</body>
`);
});
});
@@ -1,29 +0,0 @@
/*
* Copyright 2025 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 { appModulePublicSignIn } from '@backstage/plugin-app/alpha';
import { CreateAppOptions, createApp } from './createApp';
/**
* @public
* @deprecated Use {@link @backstage/plugin-app/alpha#appModulePublicSignIn} instead.
*/
export function createPublicSignInApp(options?: CreateAppOptions) {
return createApp({
...options,
features: [...(options?.features ?? []), appModulePublicSignIn],
});
}
-1
View File
@@ -21,7 +21,6 @@
*/
export { createApp, type CreateAppOptions } from './createApp';
export { createPublicSignInApp } from './createPublicSignInApp';
export { discoverAvailableFeatures } from './discovery';
export { resolveAsyncFeatures } from './resolution';
export { maybeCreateErrorPage } from './maybeCreateErrorPage';