diff --git a/docs/auth/cloudflare/access.md b/docs/auth/cloudflare/access.md
index 05663aca30..51567e9a0f 100644
--- a/docs/auth/cloudflare/access.md
+++ b/docs/auth/cloudflare/access.md
@@ -100,7 +100,7 @@ const app = createApp({
},
/* highlight-add-end */
// ..
-})
+});
```
See [Sign-In with Proxy Providers](../index.md#sign-in-with-proxy-providers) for pointers on how to set up the sign-in page to also work smoothly for local development.
diff --git a/docs/auth/google/gcp-iap-auth.md b/docs/auth/google/gcp-iap-auth.md
index 138d795f0f..410008b22e 100644
--- a/docs/auth/google/gcp-iap-auth.md
+++ b/docs/auth/google/gcp-iap-auth.md
@@ -104,13 +104,13 @@ installed in `packages/app/src/App.tsx` like this:
import { ProxiedSignInPage } from '@backstage/core-components';
const app = createApp({
- /* highlight-add-start */
+ /* highlight-add-start */
components: {
SignInPage: props => ,
},
/* highlight-add-end */
// ..
-})
+});
```
See the [Sign-In with Proxy Providers](../index.md#sign-in-with-proxy-providers) section for more information.
diff --git a/docs/auth/index.md b/docs/auth/index.md
index 7f4511af24..abe7fb8db6 100644
--- a/docs/auth/index.md
+++ b/docs/auth/index.md
@@ -121,12 +121,15 @@ const app = createApp({
SignInPage: props => (
),
},
@@ -314,7 +317,7 @@ import {
export const apis: AnyApiFactory[] = [
/* highlight-add-next-line */
ScmAuth.createDefaultApiFactory(),
- // ...
+ // ...
];
```
diff --git a/docs/auth/microsoft/azure-easyauth.md b/docs/auth/microsoft/azure-easyauth.md
index fb0b897760..4daf0851f0 100644
--- a/docs/auth/microsoft/azure-easyauth.md
+++ b/docs/auth/microsoft/azure-easyauth.md
@@ -67,11 +67,13 @@ import { ProxiedSignInPage } from '@backstage/core-components';
const app = createApp({
/* highlight-add-start */
components: {
- SignInPage: props => ,
+ SignInPage: props => (
+
+ ),
},
/* highlight-add-end */
// ..
-})
+});
```
See the [Sign-In with Proxy Providers](../index.md#sign-in-with-proxy-providers) section for more information.
diff --git a/docs/auth/oauth2-proxy/provider.md b/docs/auth/oauth2-proxy/provider.md
index e3b5e89633..9c8f681138 100644
--- a/docs/auth/oauth2-proxy/provider.md
+++ b/docs/auth/oauth2-proxy/provider.md
@@ -70,11 +70,13 @@ import { ProxiedSignInPage } from '@backstage/core-components';
const app = createApp({
/* highlight-add-start */
components: {
- SignInPage: props => ,
+ SignInPage: props => (
+
+ ),
},
/* highlight-add-end */
// ..
-})
+});
```
See [Sign-In with Proxy Providers](../index.md#sign-in-with-proxy-providers) for pointers on how to set up the sign-in page to also work smoothly for local development.
diff --git a/docs/auth/oidc.md b/docs/auth/oidc.md
index 0a9e4417ed..9c681b7360 100644
--- a/docs/auth/oidc.md
+++ b/docs/auth/oidc.md
@@ -89,28 +89,23 @@ export const apis: AnyApiFactory[] = [
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
- },
- factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
- OAuth2.create({
- discoveryApi,
- oauthRequestApi,
- provider: {
- id: 'my-auth-provider',
- title: 'My custom auth provider',
- icon: () => null,
- },
- environment: configApi.getOptionalString('auth.environment'),
- defaultScopes: [
- 'openid',
- 'profile',
- 'email',
- ],
- }),
+ },
+ factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
+ OAuth2.create({
+ discoveryApi,
+ oauthRequestApi,
+ provider: {
+ id: 'my-auth-provider',
+ title: 'My custom auth provider',
+ icon: () => null,
+ },
+ environment: configApi.getOptionalString('auth.environment'),
+ defaultScopes: ['openid', 'profile', 'email'],
+ }),
}),
/* highlight-add-end */
// ..
-]
-
+];
```
Please note we're importing the `OAuth2` class from `@backstage/core-app-api` effectively
diff --git a/docs/backend-system/building-backends/08-migrating.md b/docs/backend-system/building-backends/08-migrating.md
index 358b6ae764..b4005b41b4 100644
--- a/docs/backend-system/building-backends/08-migrating.md
+++ b/docs/backend-system/building-backends/08-migrating.md
@@ -134,7 +134,10 @@ import { createBackend } from '@backstage/backend-defaults';
/* highlight-remove-next-line */
import { legacyPlugin } from '@backstage/backend-common';
/* highlight-add-start */
-import { makeLegacyPlugin, loggerToWinstonLogger } from '@backstage/backend-common';
+import {
+ makeLegacyPlugin,
+ loggerToWinstonLogger,
+} from '@backstage/backend-common';
import { coreServices } from '@backstage/backend-plugin-api';
/* highlight-add-end */
@@ -187,16 +190,16 @@ In this example, we'll assume that your added environment field is named
/* highlight-add-next-line */
import { exampleServiceRef } from ''; // if the definition is elsewhere
- const legacyPlugin = makeLegacyPlugin(
- {
- // ... the above core services still go here
- /* highlight-add-next-line */
- example: exampleServiceRef
- },
- {
- logger: log => loggerToWinstonLogger(log),
- },
- );
+const legacyPlugin = makeLegacyPlugin(
+ {
+ // ... the above core services still go here
+ /* highlight-add-next-line */
+ example: exampleServiceRef,
+ },
+ {
+ logger: log => loggerToWinstonLogger(log),
+ },
+);
```
After this, your backend will know how to instantiate your thing on demand and
@@ -282,7 +285,7 @@ import { createBackendModule } from '@backstage/backend-plugin-api';
/* highlight-add-start */
const catalogModuleCustomExtensions = createBackendModule({
- pluginId: 'catalog', // name of the plugin that the module is targeting
+ pluginId: 'catalog', // name of the plugin that the module is targeting
moduleId: 'customExtensions',
register(env) {
env.registerInit({
@@ -294,7 +297,7 @@ const catalogModuleCustomExtensions = createBackendModule({
// Here you have the opportunity to interact with the extension
// point before the plugin itself gets instantiated
catalog.addEntityProvider(new MyEntityProvider()); // just an example
- catalog.addProcessor(new MyProcessor()); // just an example
+ catalog.addProcessor(new MyProcessor()); // just an example
},
});
},
@@ -352,7 +355,7 @@ import { createBackendModule } from '@backstage/backend-plugin-api';
/* highlight-add-start */
const eventsModuleCustomExtensions = createBackendModule({
- pluginId: 'events', // name of the plugin that the module is targeting
+ pluginId: 'events', // name of the plugin that the module is targeting
moduleId: 'customExtensions',
register(env) {
env.registerInit({
@@ -420,7 +423,7 @@ import { createBackendModule } from '@backstage/backend-plugin-api';
/* highlight-add-start */
const scaffolderModuleCustomExtensions = createBackendModule({
- pluginId: 'scaffolder', // name of the plugin that the module is targeting
+ pluginId: 'scaffolder', // name of the plugin that the module is targeting
moduleId: 'customExtensions',
register(env) {
env.registerInit({
diff --git a/docs/features/kubernetes/installation.md b/docs/features/kubernetes/installation.md
index abc42ddbe0..ae7826a804 100644
--- a/docs/features/kubernetes/installation.md
+++ b/docs/features/kubernetes/installation.md
@@ -38,7 +38,7 @@ const serviceEntityPage = (
{/* highlight-add-end */}
-)
+);
```
**Notes:**
diff --git a/docs/features/search/how-to-guides.md b/docs/features/search/how-to-guides.md
index 7a00d10ede..5b28e259b5 100644
--- a/docs/features/search/how-to-guides.md
+++ b/docs/features/search/how-to-guides.md
@@ -20,30 +20,30 @@ to do that in two steps.
[interface](https://github.com/backstage/backstage/blob/db2666b980853c281b8fe77905d7639c5d255f13/plugins/search/src/apis.ts#L31)
according to your needs.
- ```typescript
- export class SearchClient implements SearchApi {
- // your implementation
- }
- ```
+ ```typescript
+ export class SearchClient implements SearchApi {
+ // your implementation
+ }
+ ```
2. Override the API ref `searchApiRef` with your new implemented API in the
`App.tsx` using `ApiFactories`.
[Read more about App APIs](https://backstage.io/docs/api/utility-apis#app-apis).
- ```typescript
- const app = createApp({
- apis: [
- // SearchApi
- createApiFactory({
- api: searchApiRef,
- deps: { discovery: discoveryApiRef },
- factory({ discovery }) {
- return new SearchClient({ discoveryApi: discovery });
- },
- }),
- ],
- });
- ```
+ ```typescript
+ const app = createApp({
+ apis: [
+ // SearchApi
+ createApiFactory({
+ api: searchApiRef,
+ deps: { discovery: discoveryApiRef },
+ factory({ discovery }) {
+ return new SearchClient({ discoveryApi: discovery });
+ },
+ }),
+ ],
+ });
+ ```
## How to index TechDocs documents
@@ -63,35 +63,35 @@ getting started guide.
1. Import the `DefaultTechDocsCollatorFactory` from
`@backstage/plugin-techdocs-backend`.
- ```typescript
- import { DefaultTechDocsCollatorFactory } from '@backstage/plugin-techdocs-backend';
- ```
+ ```typescript
+ import { DefaultTechDocsCollatorFactory } from '@backstage/plugin-techdocs-backend';
+ ```
2. If there isn't an existing schedule you'd like to run the collator on, be
sure to create it first. Something like...
- ```typescript
- import { Duration } from 'luxon';
+ ```typescript
+ import { Duration } from 'luxon';
- const every10MinutesSchedule = env.scheduler.createScheduledTaskRunner({
- frequency: Duration.fromObject({ seconds: 600 }),
- timeout: Duration.fromObject({ seconds: 900 }),
- initialDelay: Duration.fromObject({ seconds: 3 }),
- });
- ```
+ const every10MinutesSchedule = env.scheduler.createScheduledTaskRunner({
+ frequency: Duration.fromObject({ seconds: 600 }),
+ timeout: Duration.fromObject({ seconds: 900 }),
+ initialDelay: Duration.fromObject({ seconds: 3 }),
+ });
+ ```
3. Register the `DefaultTechDocsCollatorFactory` with the IndexBuilder.
- ```typescript
- indexBuilder.addCollator({
- schedule: every10MinutesSchedule,
- factory: DefaultTechDocsCollatorFactory.fromConfig(env.config, {
- discovery: env.discovery,
- logger: env.logger,
- tokenManager: env.tokenManager,
- }),
- });
- ```
+ ```typescript
+ indexBuilder.addCollator({
+ schedule: every10MinutesSchedule,
+ factory: DefaultTechDocsCollatorFactory.fromConfig(env.config, {
+ discovery: env.discovery,
+ logger: env.logger,
+ tokenManager: env.tokenManager,
+ }),
+ });
+ ```
You should now have your TechDocs documents indexed to your search engine of
choice!
@@ -125,7 +125,9 @@ You can either just simply amend default behaviour, or even to write completely
> `authorization` and `location` cannot be modified via a `entityTransformer`, `location` can be modified only through `locationTemplate`.
```ts title="packages/backend/src/plugins/search.ts"
-const entityTransformer: CatalogCollatorEntityTransformer = (entity: Entity) => {
+const entityTransformer: CatalogCollatorEntityTransformer = (
+ entity: Entity,
+) => {
if (entity.kind === 'SomeKind') {
return {
// customize here output for 'SomeKind' kind
@@ -173,7 +175,7 @@ indexBuilder.addCollator({
tokenManager: env.tokenManager,
/* highlight-add-start */
filter: {
- kind: ['API', 'Component', 'Domain', 'Group', 'System', 'User'],
+ kind: ['API', 'Component', 'Domain', 'Group', 'System', 'User'],
},
/* highlight-add-end */
}),
diff --git a/docs/features/software-catalog/external-integrations.md b/docs/features/software-catalog/external-integrations.md
index d8e4c2099a..6f957625bd 100644
--- a/docs/features/software-catalog/external-integrations.md
+++ b/docs/features/software-catalog/external-integrations.md
@@ -254,7 +254,9 @@ export default async function createPlugin(
/* highlight-add-start */
await env.scheduler.scheduleTask({
id: 'run_frobs_refresh',
- fn: async () => { await frobs.run(); },
+ fn: async () => {
+ await frobs.run();
+ },
frequency: { minutes: 30 },
timeout: { minutes: 10 },
});
diff --git a/docs/features/software-templates/testing-scaffolder-alpha.md b/docs/features/software-templates/testing-scaffolder-alpha.md
index 1791ab0822..c0b97e897c 100644
--- a/docs/features/software-templates/testing-scaffolder-alpha.md
+++ b/docs/features/software-templates/testing-scaffolder-alpha.md
@@ -46,7 +46,6 @@ The `ScaffolderPage` router has a completely different export for the `scaffolde
import { ScaffolderPage } from '@backstage/plugin-scaffolder';
/* highlight-add-next-line */
import { NextScaffolderPage } from '@backstage/plugin-scaffolder/alpha';
-
```
And this API should be the exact same as the previous Router, so you should be able to make a change like the following further down in this file:
@@ -136,7 +135,7 @@ export const EntityNamePicker = (
placeholder,
} = props;
// ..
-}
+};
```
There's another `/alpha` export that you need to replace `FieldExtensionComponentProps` with which is the `NextFieldExtensionComponentProps`.
@@ -167,7 +166,7 @@ export const EntityNamePicker = (
placeholder,
} = props;
// ..
-}
+};
```
You'll notice that there's an additional change here, which is that we're now defaulting the `uiSchema` to an empty object. This is because the `uiSchema` is now optional, and if you don't provide it, it will be `undefined` instead of an empty object. There's more around this in the [breaking changes](#breaking-changes) section.
@@ -218,20 +217,20 @@ Once we fully release the code that is in the `/alpha` exports right now onto th
Later releases of `react-jsonschema-form` have made the `uiSchema` optional, and if you don't provide it, it will be `undefined` instead of an empty object. This means that you will need to make sure that you're defaulting the `uiSchema` to an empty object if you're using it in your code.
```tsx
- const {
- onChange,
- required,
- schema: { title = 'Name', description = 'Unique name of the component' },
- rawErrors,
- formData,
- /* highlight-remove-next-line */
- uiSchema: { 'ui:autofocus': autoFocus },
- /* highlight-add-next-line */
- uiSchema: { 'ui:autofocus': autoFocus } = {},
- idSchema,
- placeholder,
- } = props;
- // ..
+const {
+ onChange,
+ required,
+ schema: { title = 'Name', description = 'Unique name of the component' },
+ rawErrors,
+ formData,
+ /* highlight-remove-next-line */
+ uiSchema: { 'ui:autofocus': autoFocus },
+ /* highlight-add-next-line */
+ uiSchema: { 'ui:autofocus': autoFocus } = {},
+ idSchema,
+ placeholder,
+} = props;
+// ..
```
### `formData` can also be `undefined`
@@ -239,18 +238,18 @@ Later releases of `react-jsonschema-form` have made the `uiSchema` optional, and
If you were using the `formData` and assuming that it was set to an empty object when building `Field Extensions` that return objects, then this will be `undefined` now due to a change in the `react-jsonschema-form` library.
```tsx
- const {
- onChange,
- required,
- schema: { title = 'Name', description = 'Unique name of the component' },
- rawErrors,
- /* highlight-remove-next-line */
- formData,
- /* highlight-add-next-line */
- formData = {}, // or maybe some other default value that you would prefer
- uiSchema: { 'ui:autofocus': autoFocus } = {},
- idSchema,
- placeholder,
- } = props;
- // ..
+const {
+ onChange,
+ required,
+ schema: { title = 'Name', description = 'Unique name of the component' },
+ rawErrors,
+ /* highlight-remove-next-line */
+ formData,
+ /* highlight-add-next-line */
+ formData = {}, // or maybe some other default value that you would prefer
+ uiSchema: { 'ui:autofocus': autoFocus } = {},
+ idSchema,
+ placeholder,
+} = props;
+// ..
```
diff --git a/docs/getting-started/app-custom-theme.md b/docs/getting-started/app-custom-theme.md
index fcb27c220d..697c58ac8f 100644
--- a/docs/getting-started/app-custom-theme.md
+++ b/docs/getting-started/app-custom-theme.md
@@ -346,19 +346,19 @@ You can add more icons, if the [default icons](https://github.com/backstage/back
2. Then you want to import your icon, add this to the rest of your imports: `import AlarmIcon from '@material-ui/icons/Alarm';`
3. Next you want to add the icon like this to your `createApp`:
- ```tsx title="packages/app/src/App.tsx"
- const app = createApp({
- apis: ...,
- plugins: ...,
- /* highlight-add-start */
- icons: {
- alert: AlarmIcon,
- },
- /* highlight-add-end */
- themes: ...,
- components: ...,
- });
- ```
+ ```tsx title="packages/app/src/App.tsx"
+ const app = createApp({
+ apis: ...,
+ plugins: ...,
+ /* highlight-add-start */
+ icons: {
+ alert: AlarmIcon,
+ },
+ /* highlight-add-end */
+ themes: ...,
+ components: ...,
+ });
+ ```
4. Now we can reference `alert` for our icon in our entity links like this:
@@ -413,71 +413,71 @@ For this example we'll show you how you can expand the sidebar with a sub-menu:
3. Then update the `@backstage/core-components` import like this:
- ```tsx
- import {
- Sidebar,
- sidebarConfig,
- SidebarDivider,
- SidebarGroup,
- SidebarItem,
- SidebarPage,
- SidebarScrollWrapper,
- SidebarSpace,
- useSidebarOpenState,
- Link,
- /* highlight-add-start */
- GroupIcon,
- SidebarSubmenu,
- SidebarSubmenuItem,
- /* highlight-add-end */
- } from '@backstage/core-components';
- ```
+ ```tsx
+ import {
+ Sidebar,
+ sidebarConfig,
+ SidebarDivider,
+ SidebarGroup,
+ SidebarItem,
+ SidebarPage,
+ SidebarScrollWrapper,
+ SidebarSpace,
+ useSidebarOpenState,
+ Link,
+ /* highlight-add-start */
+ GroupIcon,
+ SidebarSubmenu,
+ SidebarSubmenuItem,
+ /* highlight-add-end */
+ } from '@backstage/core-components';
+ ```
4. Finally replace `` with this:
- ```tsx
-
-
-
-
-
-
-
-
-
-
-
-
-
- ```
+ ```tsx
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ```
When you startup your Backstage app and hover over the Home option on the sidebar you'll now see a nice sub-menu appear with links to the various Kinds in your Catalog. It would look like this:
diff --git a/docs/getting-started/configure-app-with-plugins.md b/docs/getting-started/configure-app-with-plugins.md
index 54654366d8..e0c698d3a1 100644
--- a/docs/getting-started/configure-app-with-plugins.md
+++ b/docs/getting-started/configure-app-with-plugins.md
@@ -33,25 +33,25 @@ to an entity in the software catalog.
2. Add the `EntityCircleCIContent` extension to the entity pages in the app:
- ```tsx title="packages/app/src/components/catalog/EntityPage.tsx"
- /* highlight-add-start */
- import {
- EntityCircleCIContent,
- isCircleCIAvailable,
- } from '@backstage/plugin-circleci';
- /* highlight-add-end */
+ ```tsx title="packages/app/src/components/catalog/EntityPage.tsx"
+ /* highlight-add-start */
+ import {
+ EntityCircleCIContent,
+ isCircleCIAvailable,
+ } from '@backstage/plugin-circleci';
+ /* highlight-add-end */
- const cicdContent = (
-
- {/* ... */}
- {/* highlight-add-next-line */}
-
-
- ;
- {/* highlight-add-end */}
-
- );
- ```
+ const cicdContent = (
+
+ {/* ... */}
+ {/* highlight-add-next-line */}
+
+
+
+ ;{/* highlight-add-end */}
+
+ );
+ ```
This is just one example, but each Backstage instance may integrate content or
cards to suit their needs on different pages, tabs, etc. In addition, while some
diff --git a/docs/getting-started/homepage.md b/docs/getting-started/homepage.md
index 29b427bad8..63a97ec54f 100644
--- a/docs/getting-started/homepage.md
+++ b/docs/getting-started/homepage.md
@@ -58,7 +58,7 @@ const routes = (
{/* ... */}
-)
+);
```
Let's replace the `` line and use the new component we created in the previous step as the new homepage.
@@ -80,7 +80,7 @@ const routes = (
{/* highlight-add-end */}
{/* ... */}
-)
+);
```
#### 4. Update sidebar items
@@ -122,7 +122,7 @@ export const Root = ({ children }: PropsWithChildren<{}>) => (
-)
+);
```
That's it! You should now have _(although slightly boring)_ a homepage!
diff --git a/docs/integrations/azure/discovery.md b/docs/integrations/azure/discovery.md
index d4ded290c3..d1309a80eb 100644
--- a/docs/integrations/azure/discovery.md
+++ b/docs/integrations/azure/discovery.md
@@ -128,7 +128,11 @@ export default async function createPlugin(
): Promise {
const builder = await CatalogBuilder.create(env);
/* highlight-add-next-line */
- builder.addProcessor(AzureDevOpsDiscoveryProcessor.fromConfig(env.config, { logger: env.logger }));
+ builder.addProcessor(
+ AzureDevOpsDiscoveryProcessor.fromConfig(env.config, {
+ logger: env.logger,
+ }),
+ );
// ..
}
diff --git a/docs/integrations/azure/org.md b/docs/integrations/azure/org.md
index 403f0042a9..f855b29bb9 100644
--- a/docs/integrations/azure/org.md
+++ b/docs/integrations/azure/org.md
@@ -44,7 +44,7 @@ For large organizations, this plugin can take a long time, so be careful setting
import { MicrosoftGraphOrgEntityProvider } from '@backstage/plugin-catalog-backend-module-msgraph';
export default async function createPlugin(
- env: PluginEnvironment,
+ env: PluginEnvironment,
): Promise {
const builder = await CatalogBuilder.create(env);
@@ -55,7 +55,7 @@ export default async function createPlugin(
schedule: env.scheduler.createScheduledTaskRunner({
frequency: { hours: 1 },
timeout: { minutes: 50 },
- initialDelay: { seconds: 15}
+ initialDelay: { seconds: 15 },
}),
}),
);
diff --git a/docs/integrations/bitbucketCloud/discovery.md b/docs/integrations/bitbucketCloud/discovery.md
index 7074fcac1b..c5a7eee4a0 100644
--- a/docs/integrations/bitbucketCloud/discovery.md
+++ b/docs/integrations/bitbucketCloud/discovery.md
@@ -105,8 +105,8 @@ export default async function createCatalogEventBasedProviders(
}),
);
/* highlight-add-end */
- return providers.flat();
- }
+ return providers.flat();
+}
```
**Attention:**
diff --git a/docs/integrations/github/discovery.md b/docs/integrations/github/discovery.md
index 499cb32812..fb65173b28 100644
--- a/docs/integrations/github/discovery.md
+++ b/docs/integrations/github/discovery.md
@@ -44,7 +44,7 @@ export default async function createPlugin(
schedule: env.scheduler.createScheduledTaskRunner({
frequency: { minutes: 30 },
timeout: { minutes: 3 },
- }),
+ }),
// optional: alternatively, use schedule
scheduler: env.scheduler,
}),
@@ -88,14 +88,14 @@ export default async function createCatalogEventBasedProviders(
/* highlight-add-start */
providers.push(
GithubEntityProvider.fromConfig(env.config, {
- logger: env.logger,
- // optional: alternatively, use scheduler with schedule defined in app-config.yaml
- schedule: env.scheduler.createScheduledTaskRunner({
- frequency: { minutes: 30 },
- timeout: { minutes: 3 },
- }),
- // optional: alternatively, use schedule
- scheduler: env.scheduler,
+ logger: env.logger,
+ // optional: alternatively, use scheduler with schedule defined in app-config.yaml
+ schedule: env.scheduler.createScheduledTaskRunner({
+ frequency: { minutes: 30 },
+ timeout: { minutes: 3 },
+ }),
+ // optional: alternatively, use schedule
+ scheduler: env.scheduler,
}),
);
/* highlight-add-end */
@@ -269,7 +269,7 @@ import {
} from '@backstage/plugin-catalog-backend-module-github';
import {
ScmIntegrations,
- DefaultGithubCredentialsProvider
+ DefaultGithubCredentialsProvider,
} from '@backstage/integration';
/* highlight-add-end */
diff --git a/docs/integrations/github/org.md b/docs/integrations/github/org.md
index 4600d65466..8f67e2a43f 100644
--- a/docs/integrations/github/org.md
+++ b/docs/integrations/github/org.md
@@ -88,7 +88,7 @@ import { PluginEnvironment } from '../types';
export default async function createCatalogEventBasedProviders(
/* highlight-remove-next-line */
_: PluginEnvironment,
- /* highlight-add-next-line */
+ /* highlight-add-next-line */
env: PluginEnvironment,
): Promise> {
const providers: Array<
diff --git a/docs/integrations/gitlab/discovery.md b/docs/integrations/gitlab/discovery.md
index 8c95243b04..6d0bb7e2e2 100644
--- a/docs/integrations/gitlab/discovery.md
+++ b/docs/integrations/gitlab/discovery.md
@@ -99,7 +99,7 @@ export default async function createPlugin(
const builder = await CatalogBuilder.create(env);
/* highlight-add-start */
builder.addProcessor(
- GitLabDiscoveryProcessor.fromConfig(env.config, { logger: env.logger })
+ GitLabDiscoveryProcessor.fromConfig(env.config, { logger: env.logger }),
);
/* highlight-add-end */
diff --git a/docs/permissions/getting-started.md b/docs/permissions/getting-started.md
index bb6c9a558e..8cb6dd953e 100644
--- a/docs/permissions/getting-started.md
+++ b/docs/permissions/getting-started.md
@@ -46,67 +46,67 @@ The permissions framework uses a new `permission-backend` plugin to accept autho
1. Add `@backstage/plugin-permission-backend` as a dependency of your Backstage backend:
- ```bash
- # From your Backstage root directory
- $ yarn add --cwd packages/backend @backstage/plugin-permission-backend
- ```
+ ```bash
+ # From your Backstage root directory
+ $ yarn add --cwd packages/backend @backstage/plugin-permission-backend
+ ```
2. Add the following to a new file, `packages/backend/src/plugins/permission.ts`. This adds the permission-backend router, and configures it with a policy which allows everything.
- ```typescript title="packages/backend/src/plugins/permission.ts"
- import { createRouter } from '@backstage/plugin-permission-backend';
- import {
- AuthorizeResult,
- PolicyDecision,
- } from '@backstage/plugin-permission-common';
- import { PermissionPolicy } from '@backstage/plugin-permission-node';
- import { Router } from 'express';
- import { PluginEnvironment } from '../types';
+ ```typescript title="packages/backend/src/plugins/permission.ts"
+ import { createRouter } from '@backstage/plugin-permission-backend';
+ import {
+ AuthorizeResult,
+ PolicyDecision,
+ } from '@backstage/plugin-permission-common';
+ import { PermissionPolicy } from '@backstage/plugin-permission-node';
+ import { Router } from 'express';
+ import { PluginEnvironment } from '../types';
- class TestPermissionPolicy implements PermissionPolicy {
- async handle(): Promise {
- return { result: AuthorizeResult.ALLOW };
- }
- }
+ class TestPermissionPolicy implements PermissionPolicy {
+ async handle(): Promise {
+ return { result: AuthorizeResult.ALLOW };
+ }
+ }
- export default async function createPlugin(
- env: PluginEnvironment,
- ): Promise {
- return await createRouter({
- config: env.config,
- logger: env.logger,
- discovery: env.discovery,
- policy: new TestPermissionPolicy(),
- identity: env.identity,
- });
- }
- ```
+ export default async function createPlugin(
+ env: PluginEnvironment,
+ ): Promise {
+ return await createRouter({
+ config: env.config,
+ logger: env.logger,
+ discovery: env.discovery,
+ policy: new TestPermissionPolicy(),
+ identity: env.identity,
+ });
+ }
+ ```
3. Wire up the permission policy in `packages/backend/src/index.ts`. [The index in the example backend](https://github.com/backstage/backstage/blob/master/packages/backend/src/index.ts) shows how to do this. You’ll need to import the module from the previous step, create a plugin environment, and add the router to the express app:
- ```ts title="packages/backend/src/index.ts"
- import proxy from './plugins/proxy';
- import techdocs from './plugins/techdocs';
- import search from './plugins/search';
- /* highlight-add-next-line */
- import permission from './plugins/permission';
+ ```ts title="packages/backend/src/index.ts"
+ import proxy from './plugins/proxy';
+ import techdocs from './plugins/techdocs';
+ import search from './plugins/search';
+ /* highlight-add-next-line */
+ import permission from './plugins/permission';
- async function main() {
- const techdocsEnv = useHotMemoize(module, () => createEnv('techdocs'));
- const searchEnv = useHotMemoize(module, () => createEnv('search'));
- const appEnv = useHotMemoize(module, () => createEnv('app'));
- /* highlight-add-next-line */
- const permissionEnv = useHotMemoize(module, () => createEnv('permission'));
- // ..
+ async function main() {
+ const techdocsEnv = useHotMemoize(module, () => createEnv('techdocs'));
+ const searchEnv = useHotMemoize(module, () => createEnv('search'));
+ const appEnv = useHotMemoize(module, () => createEnv('app'));
+ /* highlight-add-next-line */
+ const permissionEnv = useHotMemoize(module, () => createEnv('permission'));
+ // ..
- apiRouter.use('/techdocs', await techdocs(techdocsEnv));
- apiRouter.use('/proxy', await proxy(proxyEnv));
- apiRouter.use('/search', await search(searchEnv));
- /* highlight-add-next-line */
- apiRouter.use('/permission', await permission(permissionEnv));
- // ..
- }
- ```
+ apiRouter.use('/techdocs', await techdocs(techdocsEnv));
+ apiRouter.use('/proxy', await proxy(proxyEnv));
+ apiRouter.use('/search', await search(searchEnv));
+ /* highlight-add-next-line */
+ apiRouter.use('/permission', await permission(permissionEnv));
+ // ..
+ }
+ ```
### 2. Enable and test the permissions system
@@ -114,46 +114,46 @@ Now that the permission backend is running, it’s time to enable the permission
1. Set the property `permission.enabled` to `true` in `app-config.yaml`.
- ```yaml title="app-config.yaml"
- permission:
- enabled: true
- ```
+ ```yaml title="app-config.yaml"
+ permission:
+ enabled: true
+ ```
2. Update the PermissionPolicy in `packages/backend/src/plugins/permission.ts` to disable a permission that’s easy for us to test. This policy rejects any attempt to delete a catalog entity:
- ```ts title="packages/backend/src/plugins/permission.ts"
- import { createRouter } from '@backstage/plugin-permission-backend';
- import {
- AuthorizeResult,
- PolicyDecision,
- } from '@backstage/plugin-permission-common';
- /* highlight-remove-next-line */
- import { PermissionPolicy } from '@backstage/plugin-permission-node';
- /* highlight-add-start */
- import {
- PermissionPolicy,
- PolicyQuery,
- } from '@backstage/plugin-permission-node';
- /* highlight-add-end */
- import { Router } from 'express';
- import { PluginEnvironment } from '../types';
+ ```ts title="packages/backend/src/plugins/permission.ts"
+ import { createRouter } from '@backstage/plugin-permission-backend';
+ import {
+ AuthorizeResult,
+ PolicyDecision,
+ } from '@backstage/plugin-permission-common';
+ /* highlight-remove-next-line */
+ import { PermissionPolicy } from '@backstage/plugin-permission-node';
+ /* highlight-add-start */
+ import {
+ PermissionPolicy,
+ PolicyQuery,
+ } from '@backstage/plugin-permission-node';
+ /* highlight-add-end */
+ import { Router } from 'express';
+ import { PluginEnvironment } from '../types';
- class TestPermissionPolicy implements PermissionPolicy {
- /* highlight-remove-next-line */
- async handle(): Promise {
- /* highlight-add-start */
- async handle(request: PolicyQuery): Promise {
- if (request.permission.name === 'catalog.entity.delete') {
- return {
- result: AuthorizeResult.DENY,
- };
- }
- /* highlight-add-end */
+ class TestPermissionPolicy implements PermissionPolicy {
+ /* highlight-remove-next-line */
+ async handle(): Promise {
+ /* highlight-add-start */
+ async handle(request: PolicyQuery): Promise {
+ if (request.permission.name === 'catalog.entity.delete') {
+ return {
+ result: AuthorizeResult.DENY,
+ };
+ }
+ /* highlight-add-end */
- return { result: AuthorizeResult.ALLOW };
- }
- }
- ```
+ return { result: AuthorizeResult.ALLOW };
+ }
+ }
+ ```
3. Now that you’ve made this change, you should find that the unregister entity menu option on the catalog entity page is disabled.
diff --git a/docs/permissions/plugin-authors/01-setup.md b/docs/permissions/plugin-authors/01-setup.md
index 46673ed307..6827096900 100644
--- a/docs/permissions/plugin-authors/01-setup.md
+++ b/docs/permissions/plugin-authors/01-setup.md
@@ -20,99 +20,99 @@ The source code is available here:
1. Copy-paste the three folders into the plugins folder of your backstage application repository (removing the `example-` prefix from each folder) or run the following script from the root of your backstage application:
- ```bash
- $ cd $(mktemp -d)
- git clone --depth 1 --quiet --no-checkout --filter=blob:none https://github.com/backstage/backstage.git .
- git checkout master -- plugins/example-todo-list/
- git checkout master -- plugins/example-todo-list-backend/
- git checkout master -- plugins/example-todo-list-common/
- sed -i '' 's/workspace:\^/\*/g' plugins/example-todo-list/package.json
- sed -i '' 's/workspace:\^/\*/g' plugins/example-todo-list-backend/package.json
- sed -i '' 's/workspace:\^/\*/g' plugins/example-todo-list-common/package.json
- for file in plugins/*; do mv "$file" "$OLDPWD/${file/example-todo/todo}"; done
- cd -
- ```
+ ```bash
+ $ cd $(mktemp -d)
+ git clone --depth 1 --quiet --no-checkout --filter=blob:none https://github.com/backstage/backstage.git .
+ git checkout master -- plugins/example-todo-list/
+ git checkout master -- plugins/example-todo-list-backend/
+ git checkout master -- plugins/example-todo-list-common/
+ sed -i '' 's/workspace:\^/\*/g' plugins/example-todo-list/package.json
+ sed -i '' 's/workspace:\^/\*/g' plugins/example-todo-list-backend/package.json
+ sed -i '' 's/workspace:\^/\*/g' plugins/example-todo-list-common/package.json
+ for file in plugins/*; do mv "$file" "$OLDPWD/${file/example-todo/todo}"; done
+ cd -
+ ```
- The `plugins` directory of your project should now include `todo-list`, `todo-list-backend`, and `todo-list-common`.
+ The `plugins` directory of your project should now include `todo-list`, `todo-list-backend`, and `todo-list-common`.
- **Important**: if you are on **Windows**, make sure you have WSL and git installed on your machine before executing the script above.
+ **Important**: if you are on **Windows**, make sure you have WSL and git installed on your machine before executing the script above.
2. Add these packages as dependencies for your Backstage app:
- ```sh
- # From your Backstage root directory
- $ yarn add --cwd packages/backend @internal/plugin-todo-list-backend @internal/plugin-todo-list-common
- $ yarn add --cwd packages/app @internal/plugin-todo-list
- ```
+ ```sh
+ # From your Backstage root directory
+ $ yarn add --cwd packages/backend @internal/plugin-todo-list-backend @internal/plugin-todo-list-common
+ $ yarn add --cwd packages/app @internal/plugin-todo-list
+ ```
3. Include the backend and frontend plugin in your application:
- Create a new `packages/backend/src/plugins/todolist.ts` with the following content:
+ Create a new `packages/backend/src/plugins/todolist.ts` with the following content:
- ```typescript title="packages/backend/src/plugins/todolist.ts"
- import { DefaultIdentityClient } from '@backstage/plugin-auth-node';
- import { createRouter } from '@internal/plugin-todo-list-backend';
- import { Router } from 'express';
- import { PluginEnvironment } from '../types';
+ ```typescript title="packages/backend/src/plugins/todolist.ts"
+ import { DefaultIdentityClient } from '@backstage/plugin-auth-node';
+ import { createRouter } from '@internal/plugin-todo-list-backend';
+ import { Router } from 'express';
+ import { PluginEnvironment } from '../types';
- export default async function createPlugin({
- logger,
- discovery,
- }: PluginEnvironment): Promise {
- return await createRouter({
- logger,
- identity: DefaultIdentityClient.create({
- discovery,
- issuer: await discovery.getExternalBaseUrl('auth'),
- }),
- });
- }
- ```
+ export default async function createPlugin({
+ logger,
+ discovery,
+ }: PluginEnvironment): Promise {
+ return await createRouter({
+ logger,
+ identity: DefaultIdentityClient.create({
+ discovery,
+ issuer: await discovery.getExternalBaseUrl('auth'),
+ }),
+ });
+ }
+ ```
- Apply the following changes to `packages/backend/src/index.ts`:
+ Apply the following changes to `packages/backend/src/index.ts`:
- ```ts title="packages/backend/src/index.ts"
- import techdocs from './plugins/techdocs';
- /* highlight-add-next-line */
- import todoList from './plugins/todolist';
- import search from './plugins/search';
+ ```ts title="packages/backend/src/index.ts"
+ import techdocs from './plugins/techdocs';
+ /* highlight-add-next-line */
+ import todoList from './plugins/todolist';
+ import search from './plugins/search';
- async function main() {
- const searchEnv = useHotMemoize(module, () => createEnv('search'));
- const appEnv = useHotMemoize(module, () => createEnv('app'));
- /* highlight-add-next-line */
- const todoListEnv = useHotMemoize(module, () => createEnv('todolist'));
- // ..
+ async function main() {
+ const searchEnv = useHotMemoize(module, () => createEnv('search'));
+ const appEnv = useHotMemoize(module, () => createEnv('app'));
+ /* highlight-add-next-line */
+ const todoListEnv = useHotMemoize(module, () => createEnv('todolist'));
+ // ..
- apiRouter.use('/proxy', await proxy(proxyEnv));
- apiRouter.use('/search', await search(searchEnv));
- apiRouter.use('/permission', await permission(permissionEnv));
- /* highlight-add-next-line */
- apiRouter.use('/todolist', await todoList(todoListEnv));
- // Add backends ABOVE this line; this 404 handler is the catch-all fallback
- apiRouter.use(notFoundHandler());
- // ..
- }
- ```
+ apiRouter.use('/proxy', await proxy(proxyEnv));
+ apiRouter.use('/search', await search(searchEnv));
+ apiRouter.use('/permission', await permission(permissionEnv));
+ /* highlight-add-next-line */
+ apiRouter.use('/todolist', await todoList(todoListEnv));
+ // Add backends ABOVE this line; this 404 handler is the catch-all fallback
+ apiRouter.use(notFoundHandler());
+ // ..
+ }
+ ```
- Apply the following changes to `packages/app/src/App.tsx`:
+ Apply the following changes to `packages/app/src/App.tsx`:
- ```tsx title="packages/app/src/App.tsx"
- /* highlight-add-next-line */
- import { TodoListPage } from '@internal/plugin-todo-list';
+ ```tsx title="packages/app/src/App.tsx"
+ /* highlight-add-next-line */
+ import { TodoListPage } from '@internal/plugin-todo-list';
- const routes = (
-
- }>
- {searchPage}
-
- } />
- {/* highlight-add-next-line */}
- } />
- {/* ... */}
-
- );
- ```
+ const routes = (
+
+ }>
+ {searchPage}
+
+ } />
+ {/* highlight-add-next-line */}
+ } />
+ {/* ... */}
+
+ );
+ ```
Now if you start your application you should be able to reach the `/todo-list` page:
diff --git a/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md b/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md
index ed4fb74573..e714301ded 100644
--- a/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md
+++ b/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md
@@ -32,7 +32,10 @@ export const todoListUpdatePermission = createPermission({
/* highlight-remove-next-line */
export const todoListPermissions = [todoListCreatePermission];
/* highlight-add-next-line */
-export const todoListPermissions = [todoListCreatePermission, todoListUpdatePermission];
+export const todoListPermissions = [
+ todoListCreatePermission,
+ todoListUpdatePermission,
+];
```
Notice that unlike `todoListCreatePermission`, the `todoListUpdatePermission` permission contains a `resourceType` field. This field indicates to the permission framework that this permission is intended to be authorized in the context of a resource with type `'todo-item'`. You can use whatever string you like as the resource type, as long as you use the same value consistently for each type of resource.
@@ -45,7 +48,10 @@ To start, let's edit `plugins/todo-list-backend/src/service/router.ts` in the sa
/* highlight-remove-next-line */
import { todoListCreatePermission } from '@internal/plugin-todo-list-common';
/* highlight-add-next-line */
-import { todoListCreatePermission, todoListUpdatePermission } from '@internal/plugin-todo-list-common';
+import {
+ todoListCreatePermission,
+ todoListUpdatePermission,
+} from '@internal/plugin-todo-list-common';
router.put('/todos', async (req, res) => {
/* highlight-add-start */
diff --git a/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data.md b/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data.md
index 4b12e9e407..bd56afc971 100644
--- a/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data.md
+++ b/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data.md
@@ -14,11 +14,14 @@ router.get('/todos', async (req, res) => {
const token = IdentityClient.getBearerToken(req.header('authorization'));
/* highlight-remove-next-line */
- res.json(getAll())
+ res.json(getAll());
/* highlight-add-start */
const items = getAll();
const decisions = await permissions.authorize(
- items.map(({ id }) => ({ permission: todoListReadPermission, resourceRef: id })),
+ items.map(({ id }) => ({
+ permission: todoListReadPermission,
+ resourceRef: id,
+ })),
);
const filteredItems = decisions.filter(
@@ -64,9 +67,16 @@ export const todoListReadPermission = createPermission({
/* highlight-add-end */
/* highlight-add-next-line */
-export const todoListPermissions = [todoListCreatePermission, todoListUpdatePermission];
+export const todoListPermissions = [
+ todoListCreatePermission,
+ todoListUpdatePermission,
+];
/* highlight-add-next-line */
-export const todoListPermissions = [todoListCreatePermission, todoListUpdatePermission, todoListReadPermission];
+export const todoListPermissions = [
+ todoListCreatePermission,
+ todoListUpdatePermission,
+ todoListReadPermission,
+];
```
## Using conditional policy decisions
diff --git a/docs/permissions/plugin-authors/05-frontend-authorization.md b/docs/permissions/plugin-authors/05-frontend-authorization.md
index 235495e13f..92d855698f 100644
--- a/docs/permissions/plugin-authors/05-frontend-authorization.md
+++ b/docs/permissions/plugin-authors/05-frontend-authorization.md
@@ -36,7 +36,9 @@ import { todoListCreatePermission } from '@internal/plugin-todo-list-common';
function AddTodo({ onAdd }: { onAdd: (title: string) => any }) {
const title = useRef('');
/* highlight-add-next-line */
- const { loading: loadingPermission, allowed: canAddTodo } = usePermission({ permission: todoListCreatePermission });
+ const { loading: loadingPermission, allowed: canAddTodo } = usePermission({
+ permission: todoListCreatePermission,
+ });
return (
<>
@@ -78,7 +80,6 @@ Here we are using the [`usePermission` hook](https://backstage.io/docs/reference
It's really that simple! Let's change our policy to test the disabled button:
```ts title="packages/backend/src/plugins/permission.ts"
-
if (isPermission(request.permission, todoListCreatePermission)) {
return {
/* highlight-remove-next-line */
@@ -117,10 +118,7 @@ export const TodoListPage = () => {
{/* highlight-remove-end */}
{/* highlight-add-start */}
- >}
- >
+ >}>
@@ -129,13 +127,15 @@ export const TodoListPage = () => {
-
-}
+ ;
+};
function AddTodo({ onAdd }: { onAdd: (title: string) => any }) {
const title = useRef('');
/* highlight-remove-next-line */
- const { loading: loadingPermission, allowed: canAddTodo } = usePermission({ permission: todoListCreatePermission });
+ const { loading: loadingPermission, allowed: canAddTodo } = usePermission({
+ permission: todoListCreatePermission,
+ });
return (
<>
diff --git a/docs/tutorials/react-router-stable-migration.md b/docs/tutorials/react-router-stable-migration.md
index 24dba3c244..017f69ba4f 100644
--- a/docs/tutorials/react-router-stable-migration.md
+++ b/docs/tutorials/react-router-stable-migration.md
@@ -181,10 +181,14 @@ It's crucial that you update to `RequirePermission` at the same time as you upda
When migrating over to React Router v6 stable, you might also see browser console warnings for the `Navigate` component. This will need to be wrapped up in a `Route` component with the `Navigate` component in the `element` prop.
```tsx
-{/* highlight-remove-next-line */}
-
-{/* highlight-add-next-line */}
-} />
+{
+ /* highlight-remove-next-line */
+}
+;
+{
+ /* highlight-add-next-line */
+}
+} />;
```
### `NavLink`