@backstage/create-app 0.4.11 → 0.4.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +583 -0
- package/dist/index.cjs.js +76 -68
- package/dist/index.cjs.js.map +1 -1
- package/package.json +2 -2
- package/templates/default-app/package.json.hbs +2 -1
- package/templates/default-app/packages/app/package.json.hbs +3 -2
- package/templates/default-app/packages/app/src/App.tsx +5 -1
- package/templates/default-app/packages/app/src/components/Root/Root.tsx +34 -18
- package/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx +44 -2
- package/templates/default-app/packages/app/src/components/search/SearchPage.tsx +31 -0
- package/templates/default-app/packages/backend/package.json.hbs +2 -0
- package/templates/default-app/packages/backend/src/index.ts +6 -0
- package/templates/default-app/packages/backend/src/plugins/app.ts +2 -0
- package/templates/default-app/packages/backend/src/plugins/search.ts +4 -0
- package/templates/default-app/packages/backend/src/types.ts +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,588 @@
|
|
|
1
1
|
# @backstage/create-app
|
|
2
2
|
|
|
3
|
+
## 0.4.15
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 01b27d547c: Added three additional required properties to the search-backend `createRouter` function to support filtering search results based on permissions. To make this change to an existing app, add the required parameters to the `createRouter` call in `packages/backend/src/plugins/search.ts`:
|
|
8
|
+
|
|
9
|
+
```diff
|
|
10
|
+
export default async function createPlugin({
|
|
11
|
+
logger,
|
|
12
|
+
+ permissions,
|
|
13
|
+
discovery,
|
|
14
|
+
config,
|
|
15
|
+
tokenManager,
|
|
16
|
+
}: PluginEnvironment) {
|
|
17
|
+
/* ... */
|
|
18
|
+
|
|
19
|
+
return await createRouter({
|
|
20
|
+
engine: indexBuilder.getSearchEngine(),
|
|
21
|
+
+ types: indexBuilder.getDocumentTypes(),
|
|
22
|
+
+ permissions,
|
|
23
|
+
+ config,
|
|
24
|
+
logger,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
- a0d446c8ec: Replaced EntitySystemDiagramCard with EntityCatalogGraphCard
|
|
30
|
+
|
|
31
|
+
To make this change to an existing app:
|
|
32
|
+
|
|
33
|
+
Add `@backstage/catalog-graph-plugin` as a `dependency` in `packages/app/package.json`
|
|
34
|
+
|
|
35
|
+
Apply the following changes to the `packages/app/src/components/catalog/EntityPage.tsx` file:
|
|
36
|
+
|
|
37
|
+
```diff
|
|
38
|
+
+ import {
|
|
39
|
+
+ Direction,
|
|
40
|
+
+ EntityCatalogGraphCard,
|
|
41
|
+
+ } from '@backstage/plugin-catalog-graph';
|
|
42
|
+
+ import {
|
|
43
|
+
+ RELATION_API_CONSUMED_BY,
|
|
44
|
+
+ RELATION_API_PROVIDED_BY,
|
|
45
|
+
+ RELATION_CONSUMES_API,
|
|
46
|
+
+ RELATION_DEPENDENCY_OF,
|
|
47
|
+
+ RELATION_DEPENDS_ON,
|
|
48
|
+
+ RELATION_HAS_PART,
|
|
49
|
+
+ RELATION_PART_OF,
|
|
50
|
+
+ RELATION_PROVIDES_API,
|
|
51
|
+
+ } from '@backstage/catalog-model';
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
```diff
|
|
55
|
+
<EntityLayout.Route path="/diagram" title="Diagram">
|
|
56
|
+
- <EntitySystemDiagramCard />
|
|
57
|
+
+ <EntityCatalogGraphCard
|
|
58
|
+
+ variant="gridItem"
|
|
59
|
+
+ direction={Direction.TOP_BOTTOM}
|
|
60
|
+
+ title="System Diagram"
|
|
61
|
+
+ height={700}
|
|
62
|
+
+ relations={[
|
|
63
|
+
+ RELATION_PART_OF,
|
|
64
|
+
+ RELATION_HAS_PART,
|
|
65
|
+
+ RELATION_API_CONSUMED_BY,
|
|
66
|
+
+ RELATION_API_PROVIDED_BY,
|
|
67
|
+
+ RELATION_CONSUMES_API,
|
|
68
|
+
+ RELATION_PROVIDES_API,
|
|
69
|
+
+ RELATION_DEPENDENCY_OF,
|
|
70
|
+
+ RELATION_DEPENDS_ON,
|
|
71
|
+
+ ]}
|
|
72
|
+
+ unidirectional={false}
|
|
73
|
+
+ />
|
|
74
|
+
</EntityLayout.Route>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
```diff
|
|
78
|
+
const cicdContent = (
|
|
79
|
+
<Grid item md={6}>
|
|
80
|
+
<EntityAboutCard variant="gridItem" />
|
|
81
|
+
</Grid>
|
|
82
|
+
+ <Grid item md={6} xs={12}>
|
|
83
|
+
+ <EntityCatalogGraphCard variant="gridItem" height={400} />
|
|
84
|
+
+ </Grid>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Add the above component in `overviewContent`, `apiPage` , `systemPage` and domainPage` as well.
|
|
88
|
+
|
|
89
|
+
- 4aca2a5307: An example instance of a `<SearchFilter.Select />` with asynchronously loaded values was added to the composed `SearchPage.tsx`, allowing searches bound to the `techdocs` type to be filtered by entity name.
|
|
90
|
+
|
|
91
|
+
This is an entirely optional change; if you wish to adopt it, you can make the following (or similar) changes to your search page layout:
|
|
92
|
+
|
|
93
|
+
```diff
|
|
94
|
+
--- a/packages/app/src/components/search/SearchPage.tsx
|
|
95
|
+
+++ b/packages/app/src/components/search/SearchPage.tsx
|
|
96
|
+
@@ -2,6 +2,10 @@ import React from 'react';
|
|
97
|
+
import { makeStyles, Theme, Grid, List, Paper } from '@material-ui/core';
|
|
98
|
+
|
|
99
|
+
import { CatalogResultListItem } from '@backstage/plugin-catalog';
|
|
100
|
+
+import {
|
|
101
|
+
+ catalogApiRef,
|
|
102
|
+
+ CATALOG_FILTER_EXISTS,
|
|
103
|
+
+} from '@backstage/plugin-catalog-react';
|
|
104
|
+
import { DocsResultListItem } from '@backstage/plugin-techdocs';
|
|
105
|
+
|
|
106
|
+
import {
|
|
107
|
+
@@ -10,6 +14,7 @@ import {
|
|
108
|
+
SearchResult,
|
|
109
|
+
SearchType,
|
|
110
|
+
DefaultResultListItem,
|
|
111
|
+
+ useSearch,
|
|
112
|
+
} from '@backstage/plugin-search';
|
|
113
|
+
import {
|
|
114
|
+
CatalogIcon,
|
|
115
|
+
@@ -18,6 +23,7 @@ import {
|
|
116
|
+
Header,
|
|
117
|
+
Page,
|
|
118
|
+
} from '@backstage/core-components';
|
|
119
|
+
+import { useApi } from '@backstage/core-plugin-api';
|
|
120
|
+
|
|
121
|
+
const useStyles = makeStyles((theme: Theme) => ({
|
|
122
|
+
bar: {
|
|
123
|
+
@@ -36,6 +42,8 @@ const useStyles = makeStyles((theme: Theme) => ({
|
|
124
|
+
|
|
125
|
+
const SearchPage = () => {
|
|
126
|
+
const classes = useStyles();
|
|
127
|
+
+ const { types } = useSearch();
|
|
128
|
+
+ const catalogApi = useApi(catalogApiRef);
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
<Page themeId="home">
|
|
132
|
+
@@ -65,6 +73,27 @@ const SearchPage = () => {
|
|
133
|
+
]}
|
|
134
|
+
/>
|
|
135
|
+
<Paper className={classes.filters}>
|
|
136
|
+
+ {types.includes('techdocs') && (
|
|
137
|
+
+ <SearchFilter.Select
|
|
138
|
+
+ className={classes.filter}
|
|
139
|
+
+ label="Entity"
|
|
140
|
+
+ name="name"
|
|
141
|
+
+ values={async () => {
|
|
142
|
+
+ // Return a list of entities which are documented.
|
|
143
|
+
+ const { items } = await catalogApi.getEntities({
|
|
144
|
+
+ fields: ['metadata.name'],
|
|
145
|
+
+ filter: {
|
|
146
|
+
+ 'metadata.annotations.backstage.io/techdocs-ref':
|
|
147
|
+
+ CATALOG_FILTER_EXISTS,
|
|
148
|
+
+ },
|
|
149
|
+
+ });
|
|
150
|
+
+
|
|
151
|
+
+ const names = items.map(entity => entity.metadata.name);
|
|
152
|
+
+ names.sort();
|
|
153
|
+
+ return names;
|
|
154
|
+
+ }}
|
|
155
|
+
+ />
|
|
156
|
+
+ )}
|
|
157
|
+
<SearchFilter.Select
|
|
158
|
+
className={classes.filter}
|
|
159
|
+
name="kind"
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
- 1dbe63ec39: A `label` prop was added to `<SearchFilter.* />` components in order to allow
|
|
163
|
+
user-friendly label strings (as well as the option to omit a label). In order
|
|
164
|
+
to maintain labels on your existing filters, add a `label` prop to them in your
|
|
165
|
+
`SearchPage.tsx`.
|
|
166
|
+
|
|
167
|
+
```diff
|
|
168
|
+
--- a/packages/app/src/components/search/SearchPage.tsx
|
|
169
|
+
+++ b/packages/app/src/components/search/SearchPage.tsx
|
|
170
|
+
@@ -96,11 +96,13 @@ const SearchPage = () => {
|
|
171
|
+
)}
|
|
172
|
+
<SearchFilter.Select
|
|
173
|
+
className={classes.filter}
|
|
174
|
+
+ label="Kind"
|
|
175
|
+
name="kind"
|
|
176
|
+
values={['Component', 'Template']}
|
|
177
|
+
/>
|
|
178
|
+
<SearchFilter.Checkbox
|
|
179
|
+
className={classes.filter}
|
|
180
|
+
+ label="Lifecycle"
|
|
181
|
+
name="lifecycle"
|
|
182
|
+
values={['experimental', 'production']}
|
|
183
|
+
/>
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## 0.4.14
|
|
187
|
+
|
|
188
|
+
### Patch Changes
|
|
189
|
+
|
|
190
|
+
- d4941024bc: Rebind external route for catalog import plugin from `scaffolderPlugin.routes.root` to `catalogImportPlugin.routes.importPage`.
|
|
191
|
+
|
|
192
|
+
To make this change to an existing app, make the following change to `packages/app/src/App.tsx`
|
|
193
|
+
|
|
194
|
+
```diff
|
|
195
|
+
const App = createApp({
|
|
196
|
+
...
|
|
197
|
+
bindRoutes({ bind }) {
|
|
198
|
+
...
|
|
199
|
+
bind(apiDocsPlugin.externalRoutes, {
|
|
200
|
+
- createComponent: scaffolderPlugin.routes.root,
|
|
201
|
+
+ registerApi: catalogImportPlugin.routes.importPage,
|
|
202
|
+
});
|
|
203
|
+
...
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
- b5402d6d72: Migrated the app template to React 17.
|
|
209
|
+
|
|
210
|
+
To apply this change to an existing app, make sure you have updated to the latest version of `@backstage/cli`, and make the following change to `packages/app/package.json`:
|
|
211
|
+
|
|
212
|
+
```diff
|
|
213
|
+
"history": "^5.0.0",
|
|
214
|
+
- "react": "^16.13.1",
|
|
215
|
+
- "react-dom": "^16.13.1",
|
|
216
|
+
+ "react": "^17.0.2",
|
|
217
|
+
+ "react-dom": "^17.0.2",
|
|
218
|
+
"react-router": "6.0.0-beta.0",
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Since we have recently moved over all `react` and `react-dom` dependencies to `peerDependencies` of all packages, and included React 17 in the version range, this should be all you need to do. If you end up with duplicate React installations, first make sure that all of your plugins are up-to-date, including ones for example from `@roadiehq`. If that doesn't work, you may need to fall back to adding [Yarn resolutions](https://classic.yarnpkg.com/lang/en/docs/selective-version-resolutions/) in the `package.json` of your project root:
|
|
222
|
+
|
|
223
|
+
```diff
|
|
224
|
+
+ "resolutions": {
|
|
225
|
+
+ "react": "^17.0.2",
|
|
226
|
+
+ "react-dom": "^17.0.2"
|
|
227
|
+
+ },
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
- 5e8d278f8e: Added an external route binding from the `org` plugin to the catalog index page.
|
|
231
|
+
|
|
232
|
+
This change is needed because `@backstage/plugin-org` now has a required external route that needs to be bound for the app to start.
|
|
233
|
+
|
|
234
|
+
To apply this change to an existing app, make the following change to `packages/app/src/App.tsx`:
|
|
235
|
+
|
|
236
|
+
```diff
|
|
237
|
+
import { ScaffolderPage, scaffolderPlugin } from '@backstage/plugin-scaffolder';
|
|
238
|
+
+import { orgPlugin } from '@backstage/plugin-org';
|
|
239
|
+
import { SearchPage } from '@backstage/plugin-search';
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
And further down within the `createApp` call:
|
|
243
|
+
|
|
244
|
+
```diff
|
|
245
|
+
bind(scaffolderPlugin.externalRoutes, {
|
|
246
|
+
registerComponent: catalogImportPlugin.routes.importPage,
|
|
247
|
+
});
|
|
248
|
+
+ bind(orgPlugin.externalRoutes, {
|
|
249
|
+
+ catalogIndex: catalogPlugin.routes.catalogIndex,
|
|
250
|
+
+ });
|
|
251
|
+
},
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
- fb08e2f285: Updated the configuration of the `app-backend` plugin to enable the static asset store by passing on `database` from the plugin environment to `createRouter`.
|
|
255
|
+
|
|
256
|
+
To apply this change to an existing app, make the following change to `packages/backend/src/plugins/app.ts`:
|
|
257
|
+
|
|
258
|
+
```diff
|
|
259
|
+
export default async function createPlugin({
|
|
260
|
+
logger,
|
|
261
|
+
config,
|
|
262
|
+
+ database,
|
|
263
|
+
}: PluginEnvironment): Promise<Router> {
|
|
264
|
+
return await createRouter({
|
|
265
|
+
logger,
|
|
266
|
+
config,
|
|
267
|
+
+ database,
|
|
268
|
+
appPackageName: 'app',
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
- 7ba416be78: You can now add `SidebarGroup`s to the current `Sidebar`. This will not affect how the current sidebar is displayed, but allows a customization on how the `MobileSidebar` on smaller screens will look like. A `SidebarGroup` will be displayed with the given icon in the `MobileSidebar`.
|
|
274
|
+
|
|
275
|
+
A `SidebarGroup` can either link to an existing page (e.g. `/search` or `/settings`) or wrap components, which will be displayed in a full-screen overlay menu (e.g. `Menu`).
|
|
276
|
+
|
|
277
|
+
```diff
|
|
278
|
+
<Sidebar>
|
|
279
|
+
<SidebarLogo />
|
|
280
|
+
+ <SidebarGroup label="Search" icon={<SearchIcon />} to="/search">
|
|
281
|
+
<SidebarSearchModal />
|
|
282
|
+
+ </SidebarGroup>
|
|
283
|
+
<SidebarDivider />
|
|
284
|
+
+ <SidebarGroup label="Menu" icon={<MenuIcon />}>
|
|
285
|
+
<SidebarItem icon={HomeIcon} to="catalog" text="Home" />
|
|
286
|
+
<SidebarItem icon={CreateComponentIcon} to="create" text="Create..." />
|
|
287
|
+
<SidebarDivider />
|
|
288
|
+
<SidebarScrollWrapper>
|
|
289
|
+
<SidebarItem icon={MapIcon} to="tech-radar" text="Tech Radar" />
|
|
290
|
+
</SidebarScrollWrapper>
|
|
291
|
+
+ </SidebarGroup>
|
|
292
|
+
<SidebarSpace />
|
|
293
|
+
<SidebarDivider />
|
|
294
|
+
+ <SidebarGroup
|
|
295
|
+
+ label="Settings"
|
|
296
|
+
+ icon={<UserSettingsSignInAvatar />}
|
|
297
|
+
+ to="/settings"
|
|
298
|
+
+ >
|
|
299
|
+
<SidebarSettings />
|
|
300
|
+
+ </SidebarGroup>
|
|
301
|
+
</Sidebar>
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Additionally, you can order the groups differently in the `MobileSidebar` than in the usual `Sidebar` simply by giving a group a priority. The groups will be displayed in descending order from left to right.
|
|
305
|
+
|
|
306
|
+
```diff
|
|
307
|
+
<SidebarGroup
|
|
308
|
+
label="Settings"
|
|
309
|
+
icon={<UserSettingsSignInAvatar />}
|
|
310
|
+
to="/settings"
|
|
311
|
+
+ priority={1}
|
|
312
|
+
>
|
|
313
|
+
<SidebarSettings />
|
|
314
|
+
</SidebarGroup>
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
If you decide against adding `SidebarGroup`s to your `Sidebar` the `MobileSidebar` will contain one default menu item, which will open a full-screen overlay menu displaying all the content of the current `Sidebar`.
|
|
318
|
+
|
|
319
|
+
More information on the `SidebarGroup` & the `MobileSidebar` component can be found in the changeset for the `core-components`.
|
|
320
|
+
|
|
321
|
+
- 08fa6a604a: The app template has been updated to add an explicit dependency on `typescript` in the root `package.json`. This is because it was removed as a dependency of `@backstage/cli` in order to decouple the TypeScript versioning in Backstage projects.
|
|
322
|
+
|
|
323
|
+
To apply this change in an existing app, add a `typescript` dependency to your `package.json` in the project root:
|
|
324
|
+
|
|
325
|
+
```json
|
|
326
|
+
"dependencies": {
|
|
327
|
+
...
|
|
328
|
+
"typescript": "~4.5.4",
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
We recommend using a `~` version range since TypeScript releases do not adhere to semver.
|
|
333
|
+
|
|
334
|
+
It may be the case that you end up with errors if you upgrade the TypeScript version. This is because there was a change to TypeScript not long ago that defaulted the type of errors caught in `catch` blocks to `unknown`. You can work around this by adding `"useUnknownInCatchVariables": false` to the `"compilerOptions"` in your `tsconfig.json`:
|
|
335
|
+
|
|
336
|
+
```json
|
|
337
|
+
"compilerOptions": {
|
|
338
|
+
...
|
|
339
|
+
"useUnknownInCatchVariables": false
|
|
340
|
+
}
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Another option is to use the utilities from `@backstage/errors` to assert the type of errors caught in `catch` blocks:
|
|
344
|
+
|
|
345
|
+
```ts
|
|
346
|
+
import { assertError, isError } from '@backstage/errors';
|
|
347
|
+
|
|
348
|
+
try {
|
|
349
|
+
...
|
|
350
|
+
} catch (error) {
|
|
351
|
+
assertError(error);
|
|
352
|
+
...
|
|
353
|
+
// OR
|
|
354
|
+
if (isError(error)) {
|
|
355
|
+
...
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
Yet another issue you might run into when upgrading TypeScript is incompatibilities in the types from `react-use`. The error you would run into looks something like this:
|
|
361
|
+
|
|
362
|
+
```plain
|
|
363
|
+
node_modules/react-use/lib/usePermission.d.ts:1:54 - error TS2304: Cannot find name 'DevicePermissionDescriptor'.
|
|
364
|
+
|
|
365
|
+
1 declare type PermissionDesc = PermissionDescriptor | DevicePermissionDescriptor | MidiPermissionDescriptor | PushPermissionDescriptor;
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
If you encounter this error, the simplest fix is to replace full imports of `react-use` with more specific ones. For example, the following:
|
|
369
|
+
|
|
370
|
+
```ts
|
|
371
|
+
import { useAsync } from 'react-use';
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
Would be converted into this:
|
|
375
|
+
|
|
376
|
+
```ts
|
|
377
|
+
import useAsync from 'react-use/lib/useAsync';
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## 0.4.13
|
|
381
|
+
|
|
382
|
+
### Patch Changes
|
|
383
|
+
|
|
384
|
+
- fb08e2f285: Updated the configuration of the `app-backend` plugin to enable the static asset store by passing on `database` from the plugin environment to `createRouter`.
|
|
385
|
+
|
|
386
|
+
To apply this change to an existing app, make the following change to `packages/backend/src/plugins/app.ts`:
|
|
387
|
+
|
|
388
|
+
```diff
|
|
389
|
+
export default async function createPlugin({
|
|
390
|
+
logger,
|
|
391
|
+
config,
|
|
392
|
+
+ database,
|
|
393
|
+
}: PluginEnvironment): Promise<Router> {
|
|
394
|
+
return await createRouter({
|
|
395
|
+
logger,
|
|
396
|
+
config,
|
|
397
|
+
+ database,
|
|
398
|
+
appPackageName: 'app',
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
- 7ba416be78: You can now add `SidebarGroup`s to the current `Sidebar`. This will not affect how the current sidebar is displayed, but allows a customization on how the `MobileSidebar` on smaller screens will look like. A `SidebarGroup` will be displayed with the given icon in the `MobileSidebar`.
|
|
404
|
+
|
|
405
|
+
A `SidebarGroup` can either link to an existing page (e.g. `/search` or `/settings`) or wrap components, which will be displayed in a full-screen overlay menu (e.g. `Menu`).
|
|
406
|
+
|
|
407
|
+
```diff
|
|
408
|
+
<Sidebar>
|
|
409
|
+
<SidebarLogo />
|
|
410
|
+
+ <SidebarGroup label="Search" icon={<SearchIcon />} to="/search">
|
|
411
|
+
<SidebarSearchModal />
|
|
412
|
+
+ </SidebarGroup>
|
|
413
|
+
<SidebarDivider />
|
|
414
|
+
+ <SidebarGroup label="Menu" icon={<MenuIcon />}>
|
|
415
|
+
<SidebarItem icon={HomeIcon} to="catalog" text="Home" />
|
|
416
|
+
<SidebarItem icon={CreateComponentIcon} to="create" text="Create..." />
|
|
417
|
+
<SidebarDivider />
|
|
418
|
+
<SidebarScrollWrapper>
|
|
419
|
+
<SidebarItem icon={MapIcon} to="tech-radar" text="Tech Radar" />
|
|
420
|
+
</SidebarScrollWrapper>
|
|
421
|
+
+ </SidebarGroup>
|
|
422
|
+
<SidebarSpace />
|
|
423
|
+
<SidebarDivider />
|
|
424
|
+
+ <SidebarGroup
|
|
425
|
+
+ label="Settings"
|
|
426
|
+
+ icon={<UserSettingsSignInAvatar />}
|
|
427
|
+
+ to="/settings"
|
|
428
|
+
+ >
|
|
429
|
+
<SidebarSettings />
|
|
430
|
+
+ </SidebarGroup>
|
|
431
|
+
</Sidebar>
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
Additionally, you can order the groups differently in the `MobileSidebar` than in the usual `Sidebar` simply by giving a group a priority. The groups will be displayed in descending order from left to right.
|
|
435
|
+
|
|
436
|
+
```diff
|
|
437
|
+
<SidebarGroup
|
|
438
|
+
label="Settings"
|
|
439
|
+
icon={<UserSettingsSignInAvatar />}
|
|
440
|
+
to="/settings"
|
|
441
|
+
+ priority={1}
|
|
442
|
+
>
|
|
443
|
+
<SidebarSettings />
|
|
444
|
+
</SidebarGroup>
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
If you decide against adding `SidebarGroup`s to your `Sidebar` the `MobileSidebar` will contain one default menu item, which will open a full-screen overlay menu displaying all the content of the current `Sidebar`.
|
|
448
|
+
|
|
449
|
+
More information on the `SidebarGroup` & the `MobileSidebar` component can be found in the changeset for the `core-components`.
|
|
450
|
+
|
|
451
|
+
- 08fa6a604a: The app template has been updated to add an explicit dependency on `typescript` in the root `package.json`. This is because it was removed as a dependency of `@backstage/cli` in order to decouple the TypeScript versioning in Backstage projects.
|
|
452
|
+
|
|
453
|
+
To apply this change in an existing app, add a `typescript` dependency to your `package.json` in the project root:
|
|
454
|
+
|
|
455
|
+
```json
|
|
456
|
+
"dependencies": {
|
|
457
|
+
...
|
|
458
|
+
"typescript": "~4.5.4",
|
|
459
|
+
}
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
We recommend using a `~` version range since TypeScript releases do not adhere to semver.
|
|
463
|
+
|
|
464
|
+
It may be the case that you end up with errors if you upgrade the TypeScript version. This is because there was a change to TypeScript not long ago that defaulted the type of errors caught in `catch` blocks to `unknown`. You can work around this by adding `"useUnknownInCatchVariables": false` to the `"compilerOptions"` in your `tsconfig.json`:
|
|
465
|
+
|
|
466
|
+
```json
|
|
467
|
+
"compilerOptions": {
|
|
468
|
+
...
|
|
469
|
+
"useUnknownInCatchVariables": false
|
|
470
|
+
}
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
Another option is to use the utilities from `@backstage/errors` to assert the type of errors caught in `catch` blocks:
|
|
474
|
+
|
|
475
|
+
```ts
|
|
476
|
+
import { assertError, isError } from '@backstage/errors';
|
|
477
|
+
|
|
478
|
+
try {
|
|
479
|
+
...
|
|
480
|
+
} catch (error) {
|
|
481
|
+
assertError(error);
|
|
482
|
+
...
|
|
483
|
+
// OR
|
|
484
|
+
if (isError(error)) {
|
|
485
|
+
...
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
- Updated dependencies
|
|
491
|
+
- @backstage/plugin-tech-radar@0.5.3-next.0
|
|
492
|
+
- @backstage/plugin-auth-backend@0.7.0-next.0
|
|
493
|
+
- @backstage/core-components@0.8.5-next.0
|
|
494
|
+
- @backstage/plugin-api-docs@0.6.23-next.0
|
|
495
|
+
- @backstage/plugin-catalog-backend@0.21.0-next.0
|
|
496
|
+
- @backstage/plugin-permission-common@0.4.0-next.0
|
|
497
|
+
- @backstage/cli@0.12.0-next.0
|
|
498
|
+
- @backstage/core-plugin-api@0.6.0-next.0
|
|
499
|
+
- @backstage/plugin-catalog@0.7.9-next.0
|
|
500
|
+
- @backstage/plugin-user-settings@0.3.17-next.0
|
|
501
|
+
- @backstage/backend-common@0.10.4-next.0
|
|
502
|
+
- @backstage/config@0.1.13-next.0
|
|
503
|
+
- @backstage/plugin-app-backend@0.3.22-next.0
|
|
504
|
+
- @backstage/core-app-api@0.5.0-next.0
|
|
505
|
+
- @backstage/plugin-catalog-import@0.7.10-next.0
|
|
506
|
+
- @backstage/plugin-scaffolder@0.11.19-next.0
|
|
507
|
+
- @backstage/plugin-search@0.5.6-next.0
|
|
508
|
+
- @backstage/plugin-techdocs@0.12.15-next.0
|
|
509
|
+
- @backstage/plugin-permission-node@0.4.0-next.0
|
|
510
|
+
- @backstage/catalog-model@0.9.10-next.0
|
|
511
|
+
- @backstage/integration-react@0.1.19-next.0
|
|
512
|
+
- @backstage/plugin-explore@0.3.26-next.0
|
|
513
|
+
- @backstage/plugin-github-actions@0.4.32-next.0
|
|
514
|
+
- @backstage/plugin-lighthouse@0.2.35-next.0
|
|
515
|
+
- @backstage/plugin-scaffolder-backend@0.15.21-next.0
|
|
516
|
+
- @backstage/backend-tasks@0.1.4-next.0
|
|
517
|
+
- @backstage/catalog-client@0.5.5-next.0
|
|
518
|
+
- @backstage/test-utils@0.2.3-next.0
|
|
519
|
+
- @backstage/plugin-proxy-backend@0.2.16-next.0
|
|
520
|
+
- @backstage/plugin-rollbar-backend@0.1.19-next.0
|
|
521
|
+
- @backstage/plugin-search-backend@0.3.1-next.0
|
|
522
|
+
- @backstage/plugin-techdocs-backend@0.12.4-next.0
|
|
523
|
+
|
|
524
|
+
## 0.4.12
|
|
525
|
+
|
|
526
|
+
### Patch Changes
|
|
527
|
+
|
|
528
|
+
- 5333451def: Cleaned up API exports
|
|
529
|
+
- cd529c4094: Add permissions to create-app's PluginEnvironment
|
|
530
|
+
|
|
531
|
+
`CatalogEnvironment` now has a `permissions` field, which means that a permission client must now be provided as part of `PluginEnvironment`. To apply these changes to an existing app, add the following to the `makeCreateEnv` function in `packages/backend/src/index.ts`:
|
|
532
|
+
|
|
533
|
+
```diff
|
|
534
|
+
// packages/backend/src/index.ts
|
|
535
|
+
|
|
536
|
+
+ import { ServerPermissionClient } from '@backstage/plugin-permission-node';
|
|
537
|
+
|
|
538
|
+
function makeCreateEnv(config: Config) {
|
|
539
|
+
...
|
|
540
|
+
+ const permissions = ServerPermissionClient.fromConfig(config, {
|
|
541
|
+
+ discovery,
|
|
542
|
+
+ tokenManager,
|
|
543
|
+
+ });
|
|
544
|
+
|
|
545
|
+
root.info(`Created UrlReader ${reader}`);
|
|
546
|
+
|
|
547
|
+
return (plugin: string): PluginEnvironment => {
|
|
548
|
+
...
|
|
549
|
+
return {
|
|
550
|
+
logger,
|
|
551
|
+
cache,
|
|
552
|
+
database,
|
|
553
|
+
config,
|
|
554
|
+
reader,
|
|
555
|
+
discovery,
|
|
556
|
+
tokenManager,
|
|
557
|
+
scheduler,
|
|
558
|
+
+ permissions,
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
And add a permissions field to the `PluginEnvironment` type in `packages/backend/src/types.ts`:
|
|
565
|
+
|
|
566
|
+
```diff
|
|
567
|
+
// packages/backend/src/types.ts
|
|
568
|
+
|
|
569
|
+
+ import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
|
|
570
|
+
|
|
571
|
+
export type PluginEnvironment = {
|
|
572
|
+
...
|
|
573
|
+
+ permissions: PermissionAuthorizer;
|
|
574
|
+
};
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
[`@backstage/plugin-permission-common`](https://www.npmjs.com/package/@backstage/plugin-permission-common) and [`@backstage/plugin-permission-node`](https://www.npmjs.com/package/@backstage/plugin-permission-node) will need to be installed as dependencies:
|
|
578
|
+
|
|
579
|
+
```diff
|
|
580
|
+
// packages/backend/package.json
|
|
581
|
+
|
|
582
|
+
+ "@backstage/plugin-permission-common": "...",
|
|
583
|
+
+ "@backstage/plugin-permission-node": "...",
|
|
584
|
+
```
|
|
585
|
+
|
|
3
586
|
## 0.4.11
|
|
4
587
|
|
|
5
588
|
## 0.4.10
|