Merge branch 'backstage:master' into master

This commit is contained in:
Hasan Ozdemir
2021-12-16 14:22:04 +01:00
committed by GitHub
165 changed files with 1968 additions and 598 deletions
@@ -1,6 +0,0 @@
---
'@backstage/plugin-search-backend-module-elasticsearch': patch
---
Add `newClient()` method to re-use the configuration of the elastic search
engine with custom clients
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-github-actions': patch
---
Show empty state only when workflow API call has completed
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/core-app-api': patch
---
Deprecated `Auth0Auth`, pointing to using `OAuth2` directly instead.
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/app-defaults': patch
'@backstage/core-app-api': patch
'@backstage/core-plugin-api': patch
---
Add `FetchApi` and related `fetchApiRef` which implement fetch, with an added Backstage token header when available.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-kubernetes': patch
---
Fixed styling bug for the CronJobsAccordions and updated Completed pods to display a green dot.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/core-components': patch
---
Items in `<SidebarSubmenu>` are now only active when their full path is active (including search parameters).
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-react': patch
---
added useOwnedEntities hook to get the list of entities of the logged-in user
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-catalog-backend': patch
---
Fixed the handling of optional locations so that the catalog no longer logs `NotFoundError`s for missing optional locations.
+25
View File
@@ -0,0 +1,25 @@
---
'@backstage/plugin-catalog': patch
---
Deprecated the `CatalogClientWrapper` class.
The default implementation of `catalogApiRef` that this plugin exposes, is now powered by the new `fetchApiRef`. The default implementation of _that_ API, in turn, has the ability to inject the user's Backstage token in requests in a similar manner to what the deprecated `CatalogClientWrapper` used to do. The latter has therefore been taken out of the default catalog API implementation.
If you use a custom `fetchApiRef` implementation that does NOT issue tokens, or use a custom `catalogApiRef` implementation which does NOT use the default `fetchApiRef`, you can still for some time wrap your catalog API in this class to get back the old behavior:
```ts
// Add this to your packages/app/src/plugins.ts if you want to get back the old
// catalog client behavior:
createApiFactory({
api: catalogApiRef,
deps: { discoveryApi: discoveryApiRef, identityApi: identityApiRef },
factory: ({ discoveryApi, identityApi }) =>
new CatalogClientWrapper({
client: new CatalogClient({ discoveryApi }),
identityApi,
}),
}),
```
But do consider migrating to making use of the `fetchApiRef` as soon as convenient, since the wrapper class will be removed in a future release.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/catalog-client': patch
---
Add the ability to supply a custom `fetchApi`. In the default frontend app setup, this will use the `fetchApiRef` implementation.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-scaffolder-backend': patch
---
Makes cookiecutter a default, but optional action based on if a containerRunner argument is passed in to createRouter or createBuiltinActions
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-scaffolder-backend': patch
---
Adding changes to create GitLab Merge Request using custom action
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/core-plugin-api': patch
---
Deprecated `auth0AuthApiRef`, `oauth2ApiRef`, `oidcAuthApiRef`, `samlAuthApiRef`, and marked the rest of the auth `ApiRef`s as experimental. For more information on how to address the deprecations, see https://backstage.io/docs/api/deprecations#generic-auth-api-refs.
@@ -1,5 +0,0 @@
---
'@backstage/plugin-org': patch
---
Added `entityFilterKind` property for `EntityOwnershipCard`
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder': patch
---
Added OwnedEntityPicker field which displays Owned Entities in options
-6
View File
@@ -1,6 +0,0 @@
---
'@backstage/backend-common': patch
---
Each plugin now saves to a separate sqlite database file when `connection.filename` is provided in the sqlite config.
Any existing sqlite database files will be ignored.
-6
View File
@@ -1,6 +0,0 @@
---
'@backstage/core-app-api': patch
'@backstage/core-components': patch
---
Switched out usage of deprecated `OAuthRequestApi` types from `@backstage/core-plugin-api`.
-58
View File
@@ -1,58 +0,0 @@
---
'@backstage/plugin-azure-devops': patch
'@backstage/plugin-azure-devops-backend': patch
'@backstage/plugin-azure-devops-common': patch
---
Created some initial filters that can be used to create pull request columns:
- All
- AssignedToUser
- AssignedToCurrentUser
- AssignedToTeam
- AssignedToTeams
- AssignedToCurrentUsersTeams
- CreatedByUser
- CreatedByCurrentUser
- CreatedByTeam
- CreatedByTeams
- CreatedByCurrentUsersTeams
Example custom column creation:
```tsx
const COLUMN_CONFIGS: PullRequestColumnConfig[] = [
{
title: 'Created by me',
filters: [{ type: FilterType.CreatedByCurrentUser }],
},
{
title: 'Created by Backstage Core',
filters: [
{
type: FilterType.CreatedByTeam,
teamName: 'Backstage Core',
},
],
},
{
title: 'Assigned to my teams',
filters: [{ type: FilterType.AssignedToCurrentUsersTeams }],
},
{
title: 'Other PRs',
filters: [{ type: FilterType.All }],
simplified: true,
},
];
<Route
path="/azure-pull-requests"
element={
<AzurePullRequestsPage
projectName="{PROJECT_NAME}"
defaultColumnConfigs={COLUMN_CONFIGS}
/>
}
/>;
```
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/catalog-client': patch
---
Add support for passing paging parameters to the getEntities call of the catalog client
-13
View File
@@ -1,13 +0,0 @@
---
'@backstage/create-app': patch
---
Updated the root `package.json` to include files with `.cjs` and `.mjs` extensions in the `"lint-staged"` configuration.
To make this change to an existing app, apply the following changes to the `package.json` file:
```diff
"lint-staged": {
- "*.{js,jsx,ts,tsx}": [
+ "*.{js,jsx,ts,tsx,mjs,cjs}": [
```
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/cli': patch
---
Add support for `.cjs` and `.mjs` extensions in local and dependency modules.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-auth-backend': patch
---
export minimal typescript types for OIDC provider
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/core-components': patch
---
Add Missing Override Components Type for SidebarSpace, SidebarSpacer, and SidebarDivider Components.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/catalog-model': patch
---
Added an optional `presence` field to Location spec, which describes whether the target of a location is required to exist or not. It defaults to `'required'`, which is the current behaviour of the catalog.
@@ -1,5 +0,0 @@
---
'@backstage/plugin-techdocs': patch
---
Fix issue where assets weren't being fetched from the correct URL path for doc URLs without trailing slashes
+9
View File
@@ -0,0 +1,9 @@
---
'@backstage/core-components': patch
'@backstage/plugin-scaffolder': patch
---
In @backstage/plugin-scaffolder - When user will have one option available in hostUrl or owner - autoselect and select component should be readonly.
in @backstage/core-components - Select component has extended API with few more props: native : boolean, disabled: boolean. native - if set to true - Select component will use native browser select picker (not rendered by Material UI lib ).
disabled - if set to true - action on component will not be possible.
-5
View File
@@ -1,5 +0,0 @@
---
'@backstage/plugin-catalog-react': patch
---
`useEntityTypeFilter`: Skip updating selected types if a kind filter change did not change them.
-14
View File
@@ -1,14 +0,0 @@
---
'@backstage/plugin-apache-airflow': minor
---
Introduces a new plugin for the Apache Airflow workflow management platform.
This implementation has been tested with the Apache Airflow v2 API,
authenticating with basic authentication through the Backstage proxy plugin.
Supported functionality includes:
- Information card of version information of the Airflow instance
- Information card of instance health for the meta-database and scheduler
- Table of DAGs with meta information and status, along with a link to view
details in the Airflow UI
-11
View File
@@ -1,11 +0,0 @@
---
'@backstage/core-plugin-api': patch
---
Renamed `AuthProvider` to `AuthProviderInfo` and add a required 'id' property to match the majority of usage. The `AuthProvider` type without the `id` property still exists but is deprecated, and all usage of it without an `id` is deprecated as well. For example, calling `createAuthRequest` without a `provider.id` is deprecated and it will be required in the future.
The following types have been renamed. The old names are still exported but deprecated, and are scheduled for removal in a future release.
- Renamed `AuthRequesterOptions` to `OAuthRequesterOptions`
- Renamed `AuthRequester` to `OAuthRequester`
- Renamed `PendingAuthRequest` to `PendingOAuthRequest`
+11
View File
@@ -0,0 +1,11 @@
catalog:
- plugins/catalog/**/*
- plugins/catalog-*/**/*
- packages/catalog-*/**/*
scaffolder:
- plugins/scaffolder/**/*
- plugins/scaffolder-*/**/*
search:
- plugins/search/**/*
- plugins/search-*/**/*
- packages/search-*/**/*
+2
View File
@@ -12,6 +12,7 @@ Atlassian
automations
autoscaling
Autoscaling
autoselect
Avro
backrub
Bigtable
@@ -53,6 +54,7 @@ configs
const
cookiecutter
cron
cronjobs
css
Datadog
dataflow
+12
View File
@@ -0,0 +1,12 @@
name: 'Pull Request Labeler'
on:
- pull_request_target
jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v3
with:
repo-token: '${{ secrets.GITHUB_TOKEN }}'
sync-labels: true
@@ -264,6 +264,12 @@ following objects:
- horizontalpodautoscalers
- ingresses
The following RBAC permissions are required on the batch API group for the
following objects:
- jobs
- cronjobs
## Surfacing your Kubernetes components as part of an entity
There are two ways to surface your Kubernetes components as part of an entity.
@@ -34,6 +34,8 @@ import {
OneLoginAuth,
UnhandledErrorForwarder,
AtlassianAuth,
createFetchApi,
FetchMiddlewares,
} from '@backstage/core-app-api';
import {
@@ -42,6 +44,8 @@ import {
analyticsApiRef,
errorApiRef,
discoveryApiRef,
fetchApiRef,
identityApiRef,
oauthRequestApiRef,
googleAuthApiRef,
githubAuthApiRef,
@@ -92,6 +96,27 @@ export const apis = [
deps: { errorApi: errorApiRef },
factory: ({ errorApi }) => WebStorage.create({ errorApi }),
}),
createApiFactory({
api: fetchApiRef,
deps: {
configApi: configApiRef,
identityApi: identityApiRef,
discoveryApi: discoveryApiRef,
},
factory: ({ configApi, identityApi, discoveryApi }) => {
return createFetchApi({
middleware: [
FetchMiddlewares.resolvePluginProtocol({
discoveryApi,
}),
FetchMiddlewares.injectIdentityAuth({
identityApi,
config: configApi,
}),
],
});
},
}),
createApiFactory({
api: oauthRequestApiRef,
deps: {},
+18
View File
@@ -1,5 +1,23 @@
# example-app
## 0.2.57
### Patch Changes
- Updated dependencies
- @backstage/plugin-github-actions@0.4.27
- @backstage/core-app-api@0.2.1
- @backstage/plugin-kubernetes@0.5.1
- @backstage/core-plugin-api@0.3.1
- @backstage/core-components@0.8.1
- @backstage/plugin-org@0.3.31
- @backstage/plugin-azure-devops@0.1.7
- @backstage/cli@0.10.2
- @backstage/catalog-model@0.9.8
- @backstage/plugin-techdocs@0.12.10
- @backstage/plugin-catalog-react@0.6.7
- @backstage/plugin-apache-airflow@0.1.0
## 0.2.56
### Patch Changes
+13 -13
View File
@@ -1,39 +1,39 @@
{
"name": "example-app",
"version": "0.2.56",
"version": "0.2.57",
"private": true,
"bundled": true,
"dependencies": {
"@backstage/app-defaults": "^0.1.2",
"@backstage/catalog-model": "^0.9.7",
"@backstage/cli": "^0.10.1",
"@backstage/core-app-api": "^0.2.0",
"@backstage/core-components": "^0.8.0",
"@backstage/core-plugin-api": "^0.3.0",
"@backstage/catalog-model": "^0.9.8",
"@backstage/cli": "^0.10.2",
"@backstage/core-app-api": "^0.2.1",
"@backstage/core-components": "^0.8.1",
"@backstage/core-plugin-api": "^0.3.1",
"@backstage/integration-react": "^0.1.15",
"@backstage/plugin-api-docs": "^0.6.18",
"@backstage/plugin-azure-devops": "^0.1.6",
"@backstage/plugin-apache-airflow": "^0.0.0",
"@backstage/plugin-azure-devops": "^0.1.7",
"@backstage/plugin-apache-airflow": "^0.1.0",
"@backstage/plugin-badges": "^0.2.16",
"@backstage/plugin-catalog": "^0.7.4",
"@backstage/plugin-catalog-graph": "^0.2.3",
"@backstage/plugin-catalog-import": "^0.7.5",
"@backstage/plugin-catalog-react": "^0.6.5",
"@backstage/plugin-catalog-react": "^0.6.7",
"@backstage/plugin-circleci": "^0.2.31",
"@backstage/plugin-cloudbuild": "^0.2.29",
"@backstage/plugin-code-coverage": "^0.1.19",
"@backstage/plugin-cost-insights": "^0.11.13",
"@backstage/plugin-explore": "^0.3.22",
"@backstage/plugin-gcp-projects": "^0.3.10",
"@backstage/plugin-github-actions": "^0.4.26",
"@backstage/plugin-github-actions": "^0.4.27",
"@backstage/plugin-graphiql": "^0.2.24",
"@backstage/plugin-home": "^0.4.7",
"@backstage/plugin-jenkins": "^0.5.14",
"@backstage/plugin-kafka": "^0.2.22",
"@backstage/plugin-kubernetes": "^0.5.0",
"@backstage/plugin-kubernetes": "^0.5.1",
"@backstage/plugin-lighthouse": "^0.2.31",
"@backstage/plugin-newrelic": "^0.3.10",
"@backstage/plugin-org": "^0.3.30",
"@backstage/plugin-org": "^0.3.31",
"@backstage/plugin-pagerduty": "0.3.19",
"@backstage/plugin-rollbar": "^0.3.20",
"@backstage/plugin-scaffolder": "^0.11.14",
@@ -41,7 +41,7 @@
"@backstage/plugin-sentry": "^0.3.30",
"@backstage/plugin-shortcuts": "^0.1.15",
"@backstage/plugin-tech-radar": "^0.4.13",
"@backstage/plugin-techdocs": "^0.12.9",
"@backstage/plugin-techdocs": "^0.12.10",
"@backstage/plugin-todo": "^0.1.16",
"@backstage/plugin-user-settings": "^0.3.13",
"@backstage/search-common": "^0.2.0",
+7
View File
@@ -1,5 +1,12 @@
# @backstage/backend-common
## 0.9.14
### Patch Changes
- fe24bc9a32: Each plugin now saves to a separate sqlite database file when `connection.filename` is provided in the sqlite config.
Any existing sqlite database files will be ignored.
## 0.9.13
### Patch Changes
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/backend-common",
"description": "Common functionality library for Backstage backends",
"version": "0.9.13",
"version": "0.9.14",
"main": "src/index.ts",
"types": "src/index.ts",
"private": false,
@@ -81,7 +81,7 @@
}
},
"devDependencies": {
"@backstage/cli": "^0.10.1",
"@backstage/cli": "^0.10.2",
"@backstage/test-utils": "^0.1.24",
"@types/archiver": "^5.1.0",
"@types/compression": "^1.7.0",
+14
View File
@@ -1,5 +1,19 @@
# example-backend
## 0.2.57
### Patch Changes
- Updated dependencies
- @backstage/plugin-search-backend-module-elasticsearch@0.0.7
- @backstage/plugin-catalog-backend@0.19.2
- @backstage/plugin-scaffolder-backend@0.15.17
- @backstage/backend-common@0.9.14
- @backstage/plugin-azure-devops-backend@0.2.5
- @backstage/plugin-auth-backend@0.5.1
- @backstage/catalog-model@0.9.8
- example-app@0.2.57
## 0.2.56
### Patch Changes
+10 -10
View File
@@ -1,6 +1,6 @@
{
"name": "example-backend",
"version": "0.2.56",
"version": "0.2.57",
"main": "dist/index.cjs.js",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -24,16 +24,16 @@
"migrate:create": "knex migrate:make -x ts"
},
"dependencies": {
"@backstage/backend-common": "^0.9.13",
"@backstage/backend-common": "^0.9.14",
"@backstage/catalog-client": "^0.5.2",
"@backstage/catalog-model": "^0.9.7",
"@backstage/catalog-model": "^0.9.8",
"@backstage/config": "^0.1.10",
"@backstage/integration": "^0.6.10",
"@backstage/plugin-app-backend": "^0.3.19",
"@backstage/plugin-auth-backend": "^0.5.0",
"@backstage/plugin-azure-devops-backend": "^0.2.4",
"@backstage/plugin-auth-backend": "^0.5.1",
"@backstage/plugin-azure-devops-backend": "^0.2.5",
"@backstage/plugin-badges-backend": "^0.1.13",
"@backstage/plugin-catalog-backend": "^0.19.1",
"@backstage/plugin-catalog-backend": "^0.19.2",
"@backstage/plugin-code-coverage-backend": "^0.1.16",
"@backstage/plugin-graphql-backend": "^0.1.9",
"@backstage/plugin-jenkins-backend": "^0.1.9",
@@ -41,11 +41,11 @@
"@backstage/plugin-kafka-backend": "^0.2.12",
"@backstage/plugin-proxy-backend": "^0.2.14",
"@backstage/plugin-rollbar-backend": "^0.1.16",
"@backstage/plugin-scaffolder-backend": "^0.15.16",
"@backstage/plugin-scaffolder-backend": "^0.15.17",
"@backstage/plugin-scaffolder-backend-module-rails": "^0.2.0",
"@backstage/plugin-search-backend": "^0.2.8",
"@backstage/plugin-search-backend-node": "^0.4.2",
"@backstage/plugin-search-backend-module-elasticsearch": "^0.0.6",
"@backstage/plugin-search-backend-module-elasticsearch": "^0.0.7",
"@backstage/plugin-search-backend-module-pg": "^0.2.2",
"@backstage/plugin-techdocs-backend": "^0.12.0",
"@backstage/plugin-tech-insights-backend": "^0.1.3",
@@ -56,7 +56,7 @@
"@octokit/rest": "^18.5.3",
"azure-devops-node-api": "^11.0.1",
"dockerode": "^3.3.1",
"example-app": "^0.2.56",
"example-app": "^0.2.57",
"express": "^4.17.1",
"express-promise-router": "^4.1.0",
"express-prom-bundle": "^6.3.6",
@@ -68,7 +68,7 @@
"winston": "^3.2.1"
},
"devDependencies": {
"@backstage/cli": "^0.10.1",
"@backstage/cli": "^0.10.2",
"@types/dockerode": "^3.3.0",
"@types/express": "^4.17.6",
"@types/express-serve-static-core": "^4.17.5"
+9 -1
View File
@@ -71,7 +71,7 @@ export interface CatalogApi {
// @public
export class CatalogClient implements CatalogApi {
constructor(options: { discoveryApi: DiscoveryApi });
constructor(options: { discoveryApi: DiscoveryApi; fetchApi?: FetchApi });
addLocation(
{ type, target, dryRun, presence }: AddLocationRequest,
options?: CatalogRequestOptions,
@@ -121,6 +121,9 @@ export type CatalogEntitiesRequest = {
| Record<string, string | symbol | (string | symbol)[]>
| undefined;
fields?: string[] | undefined;
offset?: number;
limit?: number;
after?: string;
};
// @public
@@ -155,4 +158,9 @@ export type DiscoveryApi = {
// @public
export const ENTITY_STATUS_CATALOG_PROCESSING_TYPE =
'backstage.io/catalog-processing';
// @public
export type FetchApi = {
fetch: typeof fetch;
};
```
@@ -175,6 +175,24 @@ describe('CatalogClient', () => {
{ apiVersion: '2' },
]);
});
it('builds paging parameters properly', async () => {
expect.assertions(2);
server.use(
rest.get(`${mockBaseUrl}/entities`, (req, res, ctx) => {
expect(req.url.search).toBe('?offset=1&limit=2&after=%3D');
return res(ctx.json([]));
}),
);
const response = await client.getEntities(
{ offset: 1, limit: 2, after: '=' },
{ token },
);
expect(response.items).toEqual([]);
});
});
describe('getLocationById', () => {
+21 -8
View File
@@ -25,7 +25,7 @@ import {
stringifyLocationReference,
} from '@backstage/catalog-model';
import { ResponseError } from '@backstage/errors';
import fetch from 'cross-fetch';
import crossFetch from 'cross-fetch';
import {
CATALOG_FILTER_EXISTS,
AddLocationRequest,
@@ -38,6 +38,7 @@ import {
CatalogEntityAncestorsResponse,
} from './types/api';
import { DiscoveryApi } from './types/discovery';
import { FetchApi } from './types/fetch';
/**
* A frontend and backend compatible client for communicating with the Backstage Catalog.
@@ -46,9 +47,11 @@ import { DiscoveryApi } from './types/discovery';
* */
export class CatalogClient implements CatalogApi {
private readonly discoveryApi: DiscoveryApi;
private readonly fetchApi: FetchApi;
constructor(options: { discoveryApi: DiscoveryApi }) {
constructor(options: { discoveryApi: DiscoveryApi; fetchApi?: FetchApi }) {
this.discoveryApi = options.discoveryApi;
this.fetchApi = options.fetchApi || { fetch: crossFetch };
}
/**
@@ -110,7 +113,7 @@ export class CatalogClient implements CatalogApi {
request?: CatalogEntitiesRequest,
options?: CatalogRequestOptions,
): Promise<CatalogListResponse<Entity>> {
const { filter = [], fields = [] } = request ?? {};
const { filter = [], fields = [], offset, limit, after } = request ?? {};
const filterItems = [filter].flat();
const params: string[] = [];
@@ -141,6 +144,16 @@ export class CatalogClient implements CatalogApi {
params.push(`fields=${fields.map(encodeURIComponent).join(',')}`);
}
if (offset !== undefined) {
params.push(`offset=${offset}`);
}
if (limit !== undefined) {
params.push(`limit=${limit}`);
}
if (after !== undefined) {
params.push(`after=${encodeURIComponent(after)}`);
}
const query = params.length ? `?${params.join('&')}` : '';
const entities: Entity[] = await this.requestRequired(
'GET',
@@ -206,7 +219,7 @@ export class CatalogClient implements CatalogApi {
* @public
*/
async refreshEntity(entityRef: string, options?: CatalogRequestOptions) {
const response = await fetch(
const response = await this.fetchApi.fetch(
`${await this.discoveryApi.getBaseUrl('catalog')}/refresh`,
{
headers: {
@@ -237,7 +250,7 @@ export class CatalogClient implements CatalogApi {
{ type = 'url', target, dryRun, presence }: AddLocationRequest,
options?: CatalogRequestOptions,
): Promise<AddLocationResponse> {
const response = await fetch(
const response = await this.fetchApi.fetch(
`${await this.discoveryApi.getBaseUrl('catalog')}/locations${
dryRun ? '?dryRun=true' : ''
}`,
@@ -376,7 +389,7 @@ export class CatalogClient implements CatalogApi {
const headers: Record<string, string> = options?.token
? { Authorization: `Bearer ${options.token}` }
: {};
const response = await fetch(url, { method, headers });
const response = await this.fetchApi.fetch(url, { method, headers });
if (!response.ok) {
throw await ResponseError.fromResponse(response);
@@ -392,7 +405,7 @@ export class CatalogClient implements CatalogApi {
const headers: Record<string, string> = options?.token
? { Authorization: `Bearer ${options.token}` }
: {};
const response = await fetch(url, { method, headers });
const response = await this.fetchApi.fetch(url, { method, headers });
if (!response.ok) {
throw await ResponseError.fromResponse(response);
@@ -410,7 +423,7 @@ export class CatalogClient implements CatalogApi {
const headers: Record<string, string> = options?.token
? { Authorization: `Bearer ${options.token}` }
: {};
const response = await fetch(url, { method, headers });
const response = await this.fetchApi.fetch(url, { method, headers });
if (!response.ok) {
if (response.status === 404) {
+70
View File
@@ -29,11 +29,81 @@ export const CATALOG_FILTER_EXISTS = Symbol('CATALOG_FILTER_EXISTS');
* @public
*/
export type CatalogEntitiesRequest = {
/**
* If given, return only entities that match the given patterns.
*
* @remarks
*
* If multiple filter sets are given as an array, then there is effectively an
* OR between each filter set.
*
* Within one filter set, there is effectively an AND between the various
* keys.
*
* Within one key, if there are more than one value, then there is effectively
* an OR between them.
*
* Example: For an input of
*
* ```
* [
* { kind: ['API', 'Component'] },
* { 'metadata.name': 'a', 'metadata.namespace': 'b' }
* ]
* ```
*
* This effectively means
*
* ```
* (kind = EITHER 'API' OR 'Component')
* OR
* (metadata.name = 'a' AND metadata.namespace = 'b' )
* ```
*
* Each key is a dot separated path in each object.
*
* As a value you can also pass in the symbol `CATALOG_FILTER_EXISTS`
* (exported from this package), which means that you assert on the existence
* of that key, no matter what its value is.
*/
filter?:
| Record<string, string | symbol | (string | symbol)[]>[]
| Record<string, string | symbol | (string | symbol)[]>
| undefined;
/**
* If given, return only the parts of each entity that match those dot
* separated paths in each object.
*
* @remarks
*
* Example: For an input of `['kind', 'metadata.annotations']`, then response
* objects will be shaped like
*
* ```
* {
* "kind": "Component",
* "metadata": {
* "annotations": {
* "foo": "bar"
* }
* }
* }
* ```
*/
fields?: string[] | undefined;
/**
* If given, skips over the first N items in the result set.
*/
offset?: number;
/**
* If given, returns at most N items from the result set.
*/
limit?: number;
/**
* If given, skips over all items before that cursor as returned by a previous
* request.
*/
after?: string;
};
/**
@@ -15,7 +15,7 @@
*/
/**
* This is a copy of the core DiscoveryApi, to avoid importing core.
* This is a copy of the DiscoveryApi, to avoid importing core-plugin-api.
*
* @public
*/
@@ -0,0 +1,24 @@
/*
* Copyright 2021 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.
*/
/**
* This is a copy of FetchApi, to avoid importing core-plugin-api.
*
* @public
*/
export type FetchApi = {
fetch: typeof fetch;
};
@@ -25,5 +25,6 @@ export type {
CatalogEntityAncestorsResponse,
} from './api';
export type { DiscoveryApi } from './discovery';
export type { FetchApi } from './fetch';
export { CATALOG_FILTER_EXISTS } from './api';
export { ENTITY_STATUS_CATALOG_PROCESSING_TYPE } from './status';
+6
View File
@@ -1,5 +1,11 @@
# @backstage/catalog-model
## 0.9.8
### Patch Changes
- ad7338bb48: Added an optional `presence` field to Location spec, which describes whether the target of a location is required to exist or not. It defaults to `'required'`, which is the current behaviour of the catalog.
## 0.9.7
### Patch Changes
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/catalog-model",
"description": "Types and validators that help describe the model of a Backstage Catalog",
"version": "0.9.7",
"version": "0.9.8",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -42,7 +42,7 @@
"yup": "^0.32.9"
},
"devDependencies": {
"@backstage/cli": "^0.10.0",
"@backstage/cli": "^0.10.2",
"@types/jest": "^26.0.7",
"@types/lodash": "^4.14.151",
"yaml": "^1.9.2"
+6
View File
@@ -1,5 +1,11 @@
# @backstage/cli
## 0.10.2
### Patch Changes
- 25dfc2d483: Add support for `.cjs` and `.mjs` extensions in local and dependency modules.
## 0.10.1
### Patch Changes
+5 -5
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/cli",
"description": "CLI for developing Backstage plugins and apps",
"version": "0.10.1",
"version": "0.10.2",
"private": false,
"publishConfig": {
"access": "public"
@@ -116,11 +116,11 @@
"yn": "^4.0.0"
},
"devDependencies": {
"@backstage/backend-common": "^0.9.13",
"@backstage/backend-common": "^0.9.14",
"@backstage/config": "^0.1.11",
"@backstage/core-components": "^0.8.0",
"@backstage/core-plugin-api": "^0.3.0",
"@backstage/core-app-api": "^0.2.0",
"@backstage/core-components": "^0.8.1",
"@backstage/core-plugin-api": "^0.3.1",
"@backstage/core-app-api": "^0.2.1",
"@backstage/dev-utils": "^0.2.14",
"@backstage/test-utils": "^0.1.24",
"@backstage/theme": "^0.2.14",
+9
View File
@@ -1,5 +1,14 @@
# @backstage/codemods
## 0.1.26
### Patch Changes
- Updated dependencies
- @backstage/core-app-api@0.2.1
- @backstage/core-plugin-api@0.3.1
- @backstage/core-components@0.8.1
## 0.1.25
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/codemods",
"description": "A collection of codemods for Backstage projects",
"version": "0.1.25",
"version": "0.1.26",
"private": false,
"publishConfig": {
"access": "public",
+10
View File
@@ -1,5 +1,15 @@
# @backstage/core-app-api
## 0.2.1
### Patch Changes
- c11ce4f552: Deprecated `Auth0Auth`, pointing to using `OAuth2` directly instead.
- 9d6503e86c: Switched out usage of deprecated `OAuthRequestApi` types from `@backstage/core-plugin-api`.
- Updated dependencies
- @backstage/core-plugin-api@0.3.1
- @backstage/core-components@0.8.1
## 0.2.0
### Minor Changes
+29
View File
@@ -24,6 +24,7 @@ import { BackstageIdentityApi } from '@backstage/core-plugin-api';
import { BackstagePlugin } from '@backstage/core-plugin-api';
import { bitbucketAuthApiRef } from '@backstage/core-plugin-api';
import { ComponentType } from 'react';
import { Config } from '@backstage/config';
import { ConfigReader } from '@backstage/config';
import { createApp as createApp_2 } from '@backstage/app-defaults';
import { DiscoveryApi } from '@backstage/core-plugin-api';
@@ -34,6 +35,7 @@ import { ExternalRouteRef } from '@backstage/core-plugin-api';
import { FeatureFlag } from '@backstage/core-plugin-api';
import { FeatureFlagsApi } from '@backstage/core-plugin-api';
import { FeatureFlagsSaveOptions } from '@backstage/core-plugin-api';
import { FetchApi } from '@backstage/core-plugin-api';
import { gitlabAuthApiRef } from '@backstage/core-plugin-api';
import { googleAuthApiRef } from '@backstage/core-plugin-api';
import { IconComponent } from '@backstage/core-plugin-api';
@@ -318,6 +320,12 @@ export function createApp(
options?: Parameters<typeof createApp_2>[0],
): BackstageApp & AppContext;
// @public
export function createFetchApi(options: {
baseImplementation?: typeof fetch | undefined;
middleware?: FetchMiddleware | FetchMiddleware[] | undefined;
}): FetchApi;
// @public
export function createSpecializedApp(options: AppOptions): BackstageApp;
@@ -369,6 +377,27 @@ export type FeatureFlaggedProps = {
}
);
// @public
export interface FetchMiddleware {
apply(next: typeof fetch): typeof fetch;
}
// @public
export class FetchMiddlewares {
static injectIdentityAuth(options: {
identityApi: IdentityApi;
config?: Config;
urlPrefixAllowlist?: string[];
header?: {
name: string;
value: (backstageToken: string) => string;
};
}): FetchMiddleware;
static resolvePluginProtocol(options: {
discoveryApi: DiscoveryApi;
}): FetchMiddleware;
}
// @public
export const FlatRoutes: (props: FlatRoutesProps) => JSX.Element | null;
+4 -4
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/core-app-api",
"description": "Core app API used by Backstage apps",
"version": "0.2.0",
"version": "0.2.1",
"private": false,
"publishConfig": {
"access": "public",
@@ -30,9 +30,9 @@
},
"dependencies": {
"@backstage/app-defaults": "^0.1.2",
"@backstage/core-components": "^0.8.0",
"@backstage/core-components": "^0.8.1",
"@backstage/config": "^0.1.11",
"@backstage/core-plugin-api": "^0.3.0",
"@backstage/core-plugin-api": "^0.3.1",
"@backstage/theme": "^0.2.14",
"@backstage/types": "^0.1.1",
"@backstage/version-bridge": "^0.1.1",
@@ -49,7 +49,7 @@
"react": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.10.1",
"@backstage/cli": "^0.10.2",
"@backstage/test-utils": "^0.1.24",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
@@ -0,0 +1,76 @@
/*
* Copyright 2021 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 { Config } from '@backstage/config';
import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api';
import { IdentityAuthInjectorFetchMiddleware } from './IdentityAuthInjectorFetchMiddleware';
import { PluginProtocolResolverFetchMiddleware } from './PluginProtocolResolverFetchMiddleware';
import { FetchMiddleware } from './types';
/**
* A collection of common middlewares for the FetchApi.
*
* @public
*/
export class FetchMiddlewares {
/**
* Handles translation from `plugin://` URLs to concrete http(s) URLs based on
* the discovery API.
*
* @remarks
*
* If the request is for `plugin://catalog/entities?filter=x=y`, the discovery
* API will be queried for `'catalog'`. If it returned
* `https://backstage.example.net/api/catalog`, the resulting query would be
* `https://backstage.example.net/api/catalog/entities?filter=x=y`.
*
* If the incoming URL protocol was not `plugin`, the request is just passed
* through verbatim to the underlying implementation.
*/
static resolvePluginProtocol(options: {
discoveryApi: DiscoveryApi;
}): FetchMiddleware {
return new PluginProtocolResolverFetchMiddleware(options.discoveryApi);
}
/**
* Injects a Backstage token header when the user is signed in.
*
* @remarks
*
* Per default, an `Authorization: Bearer <token>` is generated. This can be
* customized using the `header` option.
*
* The header injection only happens on allowlisted URLs. Per default, if the
* `config` option is passed in, the `backend.baseUrl` is allowlisted, unless
* the `urlPrefixAllowlist` option is passed in, in which case it takes
* precedence. If you pass in neither config nor an allowlist, the middleware
* will have no effect.
*/
static injectIdentityAuth(options: {
identityApi: IdentityApi;
config?: Config;
urlPrefixAllowlist?: string[];
header?: {
name: string;
value: (backstageToken: string) => string;
};
}): FetchMiddleware {
return IdentityAuthInjectorFetchMiddleware.create(options);
}
private constructor() {}
}
@@ -0,0 +1,153 @@
/*
* Copyright 2021 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 { ConfigReader } from '@backstage/config';
import { IdentityApi } from '@backstage/core-plugin-api';
import { IdentityAuthInjectorFetchMiddleware } from './IdentityAuthInjectorFetchMiddleware';
describe('IdentityAuthInjectorFetchMiddleware', () => {
it('creates using defaults', async () => {
const middleware = IdentityAuthInjectorFetchMiddleware.create({
identityApi: undefined as any,
});
expect(middleware.urlPrefixAllowlist).toEqual([]);
expect(middleware.headerName).toEqual('authorization');
expect(middleware.headerValue('t')).toEqual('Bearer t');
});
it('creates using config', async () => {
const middleware = IdentityAuthInjectorFetchMiddleware.create({
identityApi: undefined as any,
config: new ConfigReader({
backend: { baseUrl: 'https://example.com/api' },
}),
header: { name: 'auth', value: t => `${t}!` },
});
expect(middleware.urlPrefixAllowlist).toEqual(['https://example.com/api']);
expect(middleware.headerName).toEqual('auth');
expect(middleware.headerValue('t')).toEqual('t!');
});
it('creates using explicit allowlist', async () => {
const middleware = IdentityAuthInjectorFetchMiddleware.create({
identityApi: undefined as any,
config: new ConfigReader({
backend: { baseUrl: 'https://example.com/api' },
}),
urlPrefixAllowlist: ['https://a.com', 'http://b.com:8080/'],
});
expect(middleware.urlPrefixAllowlist).toEqual([
'https://a.com',
'http://b.com:8080',
]);
});
it('injects the header only when a token is available', async () => {
const tokenFunction = jest.fn();
const identityApi = {
getCredentials: tokenFunction,
} as unknown as IdentityApi;
const middleware = new IdentityAuthInjectorFetchMiddleware(
identityApi,
['https://example.com'],
'Authorization',
token => `Bearer ${token}`,
);
const inner = jest.fn();
const outer = middleware.apply(inner);
// No token available
tokenFunction.mockResolvedValueOnce({ token: undefined });
await outer(new Request('https://example.com'));
expect([...inner.mock.calls[0][0].headers.entries()]).toEqual([]);
// Supply a token, header gets added
tokenFunction.mockResolvedValueOnce({ token: 'token' });
await outer(new Request('https://example.com'));
expect([...inner.mock.calls[1][0].headers.entries()]).toEqual([
['authorization', 'Bearer token'],
]);
// Token no longer available
tokenFunction.mockResolvedValueOnce({ token: undefined });
await outer(new Request('https://example.com'));
expect([...inner.mock.calls[2][0].headers.entries()]).toEqual([]);
});
it('does not overwrite an existing header with the same name', async () => {
const identityApi = {
getCredentials: () => ({ token: 'token' }),
} as unknown as IdentityApi;
const middleware = new IdentityAuthInjectorFetchMiddleware(
identityApi,
['https://example.com'],
'Authorization',
token => `Bearer ${token}`,
);
const inner = jest.fn();
const outer = middleware.apply(inner);
// No token available
await outer(new Request('https://example.com'));
expect([...inner.mock.calls[0][0].headers.entries()]).toEqual([
['authorization', 'Bearer token'],
]);
// Supply a token, header gets added
await outer(
new Request('https://example.com', {
headers: { authorization: 'do-not-clobber' },
}),
);
expect([...inner.mock.calls[1][0].headers.entries()]).toEqual([
['authorization', 'do-not-clobber'],
]);
});
it('does not affect requests outside the allowlist', async () => {
const identityApi = {
getCredentials: () => ({ token: 'token' }),
} as unknown as IdentityApi;
const middleware = new IdentityAuthInjectorFetchMiddleware(
identityApi,
['https://example.com:8080/root'],
'Authorization',
token => `Bearer ${token}`,
);
const inner = jest.fn();
const outer = middleware.apply(inner);
await outer(new Request('https://example.com:8080/root'));
await outer(new Request('https://example.com:8080/root/sub'));
await outer(new Request('https://example.com:8080/root2'));
await outer(new Request('https://example.com/root'));
await outer(new Request('http://example.com:8080/root'));
await outer(new Request('https://example.com/root'));
const no: string[][] = [];
const yes: string[][] = [['authorization', 'Bearer token']];
expect([...inner.mock.calls[0][0].headers.entries()]).toEqual(yes);
expect([...inner.mock.calls[1][0].headers.entries()]).toEqual(yes);
expect([...inner.mock.calls[2][0].headers.entries()]).toEqual(no);
expect([...inner.mock.calls[3][0].headers.entries()]).toEqual(no);
expect([...inner.mock.calls[4][0].headers.entries()]).toEqual(no);
expect([...inner.mock.calls[5][0].headers.entries()]).toEqual(no);
});
});
@@ -0,0 +1,82 @@
/*
* Copyright 2021 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 { Config } from '@backstage/config';
import { IdentityApi } from '@backstage/core-plugin-api';
import { FetchMiddleware } from './types';
/**
* A fetch middleware, which injects a Backstage token header when the user is
* signed in.
*/
export class IdentityAuthInjectorFetchMiddleware implements FetchMiddleware {
static create(options: {
identityApi: IdentityApi;
config?: Config;
urlPrefixAllowlist?: string[];
header?: {
name: string;
value: (backstageToken: string) => string;
};
}): IdentityAuthInjectorFetchMiddleware {
const allowlist: string[] = [];
if (options.urlPrefixAllowlist) {
allowlist.push(...options.urlPrefixAllowlist);
} else if (options.config) {
allowlist.push(options.config.getString('backend.baseUrl'));
}
const headerName = options.header?.name || 'authorization';
const headerValue = options.header?.value || (token => `Bearer ${token}`);
return new IdentityAuthInjectorFetchMiddleware(
options.identityApi,
allowlist.map(prefix => prefix.replace(/\/$/, '')),
headerName,
headerValue,
);
}
constructor(
public readonly identityApi: IdentityApi,
public readonly urlPrefixAllowlist: string[],
public readonly headerName: string,
public readonly headerValue: (pluginId: string) => string,
) {}
apply(next: typeof fetch): typeof fetch {
return async (input, init) => {
// Skip this middleware if the header already exists, or if the URL
// doesn't match any of the allowlist items, or if there was no token
const request = new Request(input, init);
const { token } = await this.identityApi.getCredentials();
if (
request.headers.get(this.headerName) ||
!this.urlPrefixAllowlist.some(
prefix =>
request.url === prefix || request.url.startsWith(`${prefix}/`),
) ||
typeof token !== 'string' ||
!token
) {
return next(input, init);
}
request.headers.set(this.headerName, this.headerValue(token));
return next(request);
};
}
}
@@ -0,0 +1,93 @@
/*
* Copyright 2021 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 { DiscoveryApi } from '@backstage/core-plugin-api';
import { PluginProtocolResolverFetchMiddleware } from './PluginProtocolResolverFetchMiddleware';
describe('PluginProtocolResolverFetchMiddleware', () => {
it.each([['https://passthrough.com/a']])(
'passes through regular URLs, %p',
async url => {
const resolve = jest.fn();
const discoveryApi = { getBaseUrl: resolve } as unknown as DiscoveryApi;
const middleware = new PluginProtocolResolverFetchMiddleware(
discoveryApi,
);
const inner = jest.fn();
const outer = middleware.apply(inner);
await outer(url);
expect(inner.mock.calls[0][0]).toBe(url);
expect(resolve).not.toBeCalled();
},
);
it.each([
[
'plugin://my-plugin/sub/path',
'my-plugin',
'https://real.com/base',
'https://real.com/base/sub/path',
],
[
'plugin://my-plugin/sub/path/',
'my-plugin',
'https://real.com/base/',
'https://real.com/base/sub/path/',
],
['plugin://x', 'x', 'http://real.com:8080', 'http://real.com:8080'],
[
'plugin://x/a/b?c=d&e=f#g',
'x',
'https://real.com/base',
'https://real.com/base/a/b?c=d&e=f#g',
],
[
'plugin://x?c=d&e=f#g',
'x',
'https://real.com:8080/base',
'https://real.com:8080/base?c=d&e=f#g',
],
[
'plugin://username:password@x?c=d&e=f#g',
'x',
'https://real.com:8080/base',
'https://username:password@real.com:8080/base?c=d&e=f#g',
],
[
'plugin://x?c=d&e=f#g',
'x',
'https://username:password@real.com:8080/base',
'https://username:password@real.com:8080/base?c=d&e=f#g',
],
])(
'resolves backstage URLs, %p',
async (original, host, resolved, result) => {
const resolve = jest.fn();
const discoveryApi = { getBaseUrl: resolve } as unknown as DiscoveryApi;
const middleware = new PluginProtocolResolverFetchMiddleware(
discoveryApi,
);
const inner = jest.fn();
const outer = middleware.apply(inner);
resolve.mockResolvedValueOnce(resolved);
await outer(original);
expect(inner.mock.calls[0][0]).toBe(result);
expect(resolve).toHaveBeenLastCalledWith(host);
},
);
});
@@ -0,0 +1,61 @@
/*
* Copyright 2021 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 { DiscoveryApi } from '@backstage/core-plugin-api';
import { FetchMiddleware } from './types';
function join(left: string, right: string): string {
if (!right || right === '/') {
return left;
}
return `${left.replace(/\/$/, '')}/${right.replace(/^\//, '')}`;
}
/**
* Handles translation from plugin://some-plugin-id/<path> to concrete http(s)
* URLs.
*/
export class PluginProtocolResolverFetchMiddleware implements FetchMiddleware {
constructor(private readonly discoveryApi: DiscoveryApi) {}
apply(next: typeof fetch): typeof fetch {
return async (input, init) => {
const request = new Request(input, init);
const prefix = 'plugin://';
if (!request.url.startsWith(prefix)) {
return next(input, init);
}
// Switch to a known protocol, since browser URL parsing misbehaves wildly
// on foreign protocols
const { hostname, pathname, search, hash, username, password } = new URL(
`http://${request.url.substring(prefix.length)}`,
);
let base = await this.discoveryApi.getBaseUrl(hostname);
if (username || password) {
const baseUrl = new URL(base);
const authority = `${username}${password ? `:${password}` : ''}@`;
base = `${baseUrl.protocol}//${authority}${baseUrl.host}${baseUrl.pathname}`;
}
const target = `${join(base, pathname)}${search}${hash}`;
return next(target, request);
};
}
}
@@ -0,0 +1,46 @@
/*
* Copyright 2021 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 { FetchApi } from '@backstage/core-plugin-api';
import { FetchMiddleware } from './types';
/**
* Builds a fetch API, based on the builtin fetch wrapped by a set of optional
* middleware implementations that add behaviors.
*
* @remarks
*
* The middleware are applied in reverse order, i.e. the last one will be
* "closest" to the base implementation. Passing in `[M1, M2, M3]` effectively
* leads to `M1(M2(M3(baseImplementation)))`.
*
* @public
*/
export function createFetchApi(options: {
baseImplementation?: typeof fetch | undefined;
middleware?: FetchMiddleware | FetchMiddleware[] | undefined;
}): FetchApi {
let result = options.baseImplementation || global.fetch;
const middleware = [options.middleware ?? []].flat().reverse();
for (const m of middleware) {
result = m.apply(result);
}
return {
fetch: result,
};
}
@@ -0,0 +1,19 @@
/*
* Copyright 2021 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.
*/
export { createFetchApi } from './createFetchApi';
export { FetchMiddlewares } from './FetchMiddlewares';
export type { FetchMiddleware } from './types';
@@ -0,0 +1,30 @@
/*
* Copyright 2021 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.
*/
/**
* A middleware that modifies the behavior of an ongoing fetch.
*
* @public
*/
export interface FetchMiddleware {
/**
* Applies this middleware to an inner implementation.
*
* @param next - The next, inner, implementation, that this middleware shall
* call out to as part of the request cycle.
*/
apply(next: typeof fetch): typeof fetch;
}
@@ -27,5 +27,6 @@ export * from './ConfigApi';
export * from './DiscoveryApi';
export * from './ErrorApi';
export * from './FeatureFlagsApi';
export * from './FetchApi';
export * from './OAuthRequestApi';
export * from './StorageApi';
+10
View File
@@ -1,5 +1,15 @@
# @backstage/core-components
## 0.8.1
### Patch Changes
- 2c17e5b073: Items in `<SidebarSubmenu>` are now only active when their full path is active (including search parameters).
- 9d6503e86c: Switched out usage of deprecated `OAuthRequestApi` types from `@backstage/core-plugin-api`.
- 1680a1c5ac: Add Missing Override Components Type for SidebarSpace, SidebarSpacer, and SidebarDivider Components.
- Updated dependencies
- @backstage/core-plugin-api@0.3.1
## 0.8.0
### Minor Changes
+9 -5
View File
@@ -814,13 +814,10 @@ export type ResponseErrorPanelClassKey = 'text' | 'divider';
export function RoutedTabs(props: { routes: SubRoute_2[] }): JSX.Element;
// Warning: (ae-forgotten-export) The symbol "SelectProps" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "SelectComponent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function Select(props: SelectProps): JSX.Element;
// Warning: (ae-missing-release-tag) "SelectClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SelectClassKey =
| 'formControl'
@@ -830,11 +827,18 @@ export type SelectClassKey =
| 'checkbox'
| 'root';
// Warning: (ae-missing-release-tag) "SelectInputBaseClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SelectedItems = string | string[] | number | number[];
// @public (undocumented)
export type SelectInputBaseClassKey = 'root' | 'input';
// @public (undocumented)
export type SelectItem = {
label: string;
value: string | number;
};
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "Sidebar" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
+4 -4
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/core-components",
"description": "Core components used by Backstage plugins and apps",
"version": "0.8.0",
"version": "0.8.1",
"private": false,
"publishConfig": {
"access": "public",
@@ -30,7 +30,7 @@
},
"dependencies": {
"@backstage/config": "^0.1.11",
"@backstage/core-plugin-api": "^0.3.0",
"@backstage/core-plugin-api": "^0.3.1",
"@backstage/errors": "^0.1.5",
"@backstage/theme": "^0.2.14",
"@material-table/core": "^3.1.0",
@@ -72,8 +72,8 @@
"react-dom": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
"@backstage/core-app-api": "^0.2.0",
"@backstage/cli": "^0.10.1",
"@backstage/core-app-api": "^0.2.1",
"@backstage/cli": "^0.10.2",
"@backstage/test-utils": "^0.1.24",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
@@ -21,17 +21,18 @@ import FormControl from '@material-ui/core/FormControl';
import InputBase from '@material-ui/core/InputBase';
import MenuItem from '@material-ui/core/MenuItem';
import Select from '@material-ui/core/Select';
import Typography from '@material-ui/core/Typography';
import {
createStyles,
makeStyles,
Theme,
withStyles,
} from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import React, { useEffect, useState } from 'react';
import ClosedDropdown from './static/ClosedDropdown';
import OpenedDropdown from './static/OpenedDropdown';
/** @public */
export type SelectInputBaseClassKey = 'root' | 'input';
const BootstrapInput = withStyles(
@@ -60,6 +61,7 @@ const BootstrapInput = withStyles(
{ name: 'BackstageSelectInputBase' },
)(InputBase);
/** @public */
export type SelectClassKey =
| 'formControl'
| 'label'
@@ -93,6 +95,7 @@ const useStyles = makeStyles(
margin: 2,
},
checkbox: {},
root: {
display: 'flex',
flexDirection: 'column',
@@ -101,23 +104,28 @@ const useStyles = makeStyles(
{ name: 'BackstageSelect' },
);
type Item = {
/** @public */
export type SelectItem = {
label: string;
value: string | number;
};
type Selection = string | string[] | number | number[];
/** @public */
export type SelectedItems = string | string[] | number | number[];
export type SelectProps = {
multiple?: boolean;
items: Item[];
items: SelectItem[];
label: string;
placeholder?: string;
selected?: Selection;
onChange: (arg: Selection) => void;
selected?: SelectedItems;
onChange: (arg: SelectedItems) => void;
triggerReset?: boolean;
native?: boolean;
disabled?: boolean;
};
/** @public */
export function SelectComponent(props: SelectProps) {
const {
multiple,
@@ -127,9 +135,11 @@ export function SelectComponent(props: SelectProps) {
selected,
onChange,
triggerReset,
native = false,
disabled = false,
} = props;
const classes = useStyles();
const [value, setValue] = useState<Selection>(
const [value, setValue] = useState<SelectedItems>(
selected || (multiple ? [] : ''),
);
const [isOpen, setOpen] = useState(false);
@@ -145,11 +155,15 @@ export function SelectComponent(props: SelectProps) {
}, [selected]);
const handleChange = (event: React.ChangeEvent<{ value: unknown }>) => {
setValue(event.target.value as Selection);
onChange(event.target.value as Selection);
setValue(event.target.value as SelectedItems);
onChange(event.target.value as SelectedItems);
};
const handleClick = (event: React.ChangeEvent<any>) => {
if (disabled) {
event.preventDefault();
return;
}
setOpen(previous => {
if (multiple && !(event.target instanceof HTMLElement)) {
return true;
@@ -175,6 +189,8 @@ export function SelectComponent(props: SelectProps) {
<FormControl className={classes.formControl}>
<Select
value={value}
native={native}
disabled={disabled}
data-testid="select"
displayEmpty
multiple={multiple}
@@ -223,19 +239,26 @@ export function SelectComponent(props: SelectProps) {
{placeholder && !multiple && (
<MenuItem value={[]}>{placeholder}</MenuItem>
)}
{items &&
items.map(item => (
<MenuItem key={item.value} value={item.value}>
{multiple && (
<Checkbox
color="primary"
checked={(value as any[]).includes(item.value) || false}
className={classes.checkbox}
/>
)}
{item.label}
</MenuItem>
))}
{native
? items &&
items.map(item => (
<option value={item.value} key={item.value}>
{item.label}
</option>
))
: items &&
items.map(item => (
<MenuItem key={item.value} value={item.value}>
{multiple && (
<Checkbox
color="primary"
checked={(value as any[]).includes(item.value) || false}
className={classes.checkbox}
/>
)}
{item.label}
</MenuItem>
))}
</Select>
</FormControl>
</ClickAwayListener>
@@ -15,6 +15,11 @@
*/
export { SelectComponent as Select } from './Select';
export type { SelectClassKey, SelectInputBaseClassKey } from './Select';
export type {
SelectClassKey,
SelectedItems,
SelectInputBaseClassKey,
SelectItem,
} from './Select';
export type { ClosedDropdownClassKey } from './static/ClosedDropdown';
export type { OpenedDropdownClassKey } from './static/OpenedDropdown';
+14
View File
@@ -1,5 +1,19 @@
# @backstage/core-plugin-api
## 0.3.1
### Patch Changes
- 18d4f500af: Deprecated the `AnyAnalyticsContext` type and mark the `AnalyticsApi` experimental.
- 8a7372cfd5: Deprecated `auth0AuthApiRef`, `oauth2ApiRef`, `oidcAuthApiRef`, `samlAuthApiRef`, and marked the rest of the auth `ApiRef`s as experimental. For more information on how to address the deprecations, see https://backstage.io/docs/api/deprecations#generic-auth-api-refs.
- 760791a642: Renamed `AuthProvider` to `AuthProviderInfo` and add a required 'id' property to match the majority of usage. The `AuthProvider` type without the `id` property still exists but is deprecated, and all usage of it without an `id` is deprecated as well. For example, calling `createAuthRequest` without a `provider.id` is deprecated and it will be required in the future.
The following types have been renamed. The old names are still exported but deprecated, and are scheduled for removal in a future release.
- Renamed `AuthRequesterOptions` to `OAuthRequesterOptions`
- Renamed `AuthRequester` to `OAuthRequester`
- Renamed `PendingAuthRequest` to `PendingOAuthRequest`
## 0.3.0
### Minor Changes
+21 -12
View File
@@ -35,25 +35,26 @@ export type AlertMessage = {
severity?: 'success' | 'info' | 'warning' | 'error';
};
// @public
// @alpha
export type AnalyticsApi = {
captureEvent(event: AnalyticsEvent): void;
};
// @public
// @alpha
export const analyticsApiRef: ApiRef<AnalyticsApi>;
// @public
// @alpha
export const AnalyticsContext: (options: {
attributes: Partial<AnalyticsContextValue>;
children: ReactNode;
}) => JSX.Element;
// @public
export type AnalyticsContextValue = CommonAnalyticsContext &
AnyAnalyticsContext;
// @alpha
export type AnalyticsContextValue = CommonAnalyticsContext & {
[param in string]: string | boolean | number | undefined;
};
// @public
// @alpha
export type AnalyticsEvent = {
action: string;
subject: string;
@@ -62,12 +63,12 @@ export type AnalyticsEvent = {
context: AnalyticsContextValue;
};
// @public
// @alpha
export type AnalyticsEventAttributes = {
[attribute in string]: string | boolean | number;
};
// @public
// @alpha
export type AnalyticsTracker = {
captureEvent: (
action: string,
@@ -79,7 +80,7 @@ export type AnalyticsTracker = {
) => void;
};
// @public
// @public @deprecated
export type AnyAnalyticsContext = {
[param in string]: string | boolean | number | undefined;
};
@@ -282,7 +283,7 @@ export type BootErrorPageProps = {
error: Error;
};
// @public
// @alpha
export type CommonAnalyticsContext = {
pluginId: string;
routeRef: string;
@@ -505,6 +506,14 @@ export enum FeatureFlagState {
None = 0,
}
// @public
export type FetchApi = {
fetch: typeof fetch;
};
// @public
export const fetchApiRef: ApiRef<FetchApi>;
// @public
export function getComponentData<T>(
node: ReactNode,
@@ -820,7 +829,7 @@ export type TypesToApiRefs<T> = {
[key in keyof T]: ApiRef<T[key]>;
};
// @public
// @alpha
export function useAnalytics(): AnalyticsTracker;
// @public
+3 -3
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/core-plugin-api",
"description": "Core API used by Backstage plugins",
"version": "0.3.0",
"version": "0.3.1",
"private": false,
"publishConfig": {
"access": "public",
@@ -45,8 +45,8 @@
"react": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.10.1",
"@backstage/core-app-api": "^0.2.0",
"@backstage/cli": "^0.10.2",
"@backstage/core-app-api": "^0.2.1",
"@backstage/test-utils": "^0.1.24",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
@@ -60,7 +60,7 @@ export const useAnalyticsContext = (): AnalyticsContextValue => {
* Analytics contexts are additive, meaning the context ultimately emitted with
* an event is the combination of all contexts in the parent tree.
*
* @public
* @alpha
*/
export const AnalyticsContext = (options: {
attributes: Partial<AnalyticsContextValue>;
@@ -17,7 +17,7 @@
/**
* Common analytics context attributes.
*
* @public
* @alpha
*/
export type CommonAnalyticsContext = {
/**
@@ -40,6 +40,7 @@ export type CommonAnalyticsContext = {
* Allows arbitrary scalar values as context attributes too.
*
* @public
* @deprecated Will be removed, use `AnalyticsContextValue` instead
*/
export type AnyAnalyticsContext = {
[param in string]: string | boolean | number | undefined;
@@ -48,7 +49,8 @@ export type AnyAnalyticsContext = {
/**
* Analytics context envelope.
*
* @public
* @alpha
*/
export type AnalyticsContextValue = CommonAnalyticsContext &
AnyAnalyticsContext;
export type AnalyticsContextValue = CommonAnalyticsContext & {
[param in string]: string | boolean | number | undefined;
};
@@ -35,7 +35,7 @@ function useAnalyticsApi(): AnalyticsApi {
/**
* Gets a pre-configured analytics tracker.
*
* @public
* @alpha
*/
export function useAnalytics(): AnalyticsTracker {
const trackerRef = useRef<Tracker | null>(null);
@@ -21,7 +21,7 @@ import { AnalyticsContextValue } from '../../analytics/types';
* Represents an event worth tracking in an analytics system that could inform
* how users of a Backstage instance are using its features.
*
* @public
* @alpha
*/
export type AnalyticsEvent = {
/**
@@ -79,7 +79,7 @@ export type AnalyticsEvent = {
* A structure allowing other arbitrary metadata to be provided by analytics
* event emitters.
*
* @public
* @alpha
*/
export type AnalyticsEventAttributes = {
[attribute in string]: string | boolean | number;
@@ -89,7 +89,7 @@ export type AnalyticsEventAttributes = {
* Represents a tracker with methods that can be called to track events in a
* configured analytics service.
*
* @public
* @alpha
*/
export type AnalyticsTracker = {
captureEvent: (
@@ -103,6 +103,8 @@ export type AnalyticsTracker = {
};
/**
* **EXPERIMENTAL**
*
* The Analytics API is used to track user behavior in a Backstage instance.
*
* @remarks
@@ -111,7 +113,7 @@ export type AnalyticsTracker = {
* useAnalytics() hook. This will return a pre-configured AnalyticsTracker
* with relevant methods for instrumentation.
*
* @public
* @alpha
*/
export type AnalyticsApi = {
/**
@@ -122,9 +124,11 @@ export type AnalyticsApi = {
};
/**
* **EXPERIMENTAL**
*
* The {@link ApiRef} of {@link AnalyticsApi}.
*
* @public
* @alpha
*/
export const analyticsApiRef: ApiRef<AnalyticsApi> = createApiRef({
id: 'core.analytics',
@@ -0,0 +1,37 @@
/*
* Copyright 2021 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 { ApiRef, createApiRef } from '../system';
/**
* A wrapper for the fetch API, that has additional behaviors such as the
* ability to automatically inject auth information where necessary.
*
* @public
*/
export type FetchApi = {
fetch: typeof fetch;
};
/**
* A wrapper for the fetch API, that has additional behaviors such as the
* ability to automatically inject auth information where necessary.
*
* @public
*/
export const fetchApiRef: ApiRef<FetchApi> = createApiRef({
id: 'core.fetch',
});
@@ -29,6 +29,7 @@ export * from './ConfigApi';
export * from './DiscoveryApi';
export * from './ErrorApi';
export * from './FeatureFlagsApi';
export * from './FetchApi';
export * from './IdentityApi';
export * from './OAuthRequestApi';
export * from './StorageApi';
+14
View File
@@ -1,5 +1,19 @@
# @backstage/create-app
## 0.4.8
### Patch Changes
- 25dfc2d483: Updated the root `package.json` to include files with `.cjs` and `.mjs` extensions in the `"lint-staged"` configuration.
To make this change to an existing app, apply the following changes to the `package.json` file:
```diff
"lint-staged": {
- "*.{js,jsx,ts,tsx}": [
+ "*.{js,jsx,ts,tsx,mjs,cjs}": [
```
## 0.4.7
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/create-app",
"description": "A CLI that helps you create your own Backstage app",
"version": "0.4.7",
"version": "0.4.8",
"private": false,
"publishConfig": {
"access": "public"
+4 -4
View File
@@ -23,8 +23,8 @@
},
"dependencies": {
"@backstage/catalog-model": "^0.9.7",
"@backstage/core-components": "^0.8.0",
"@backstage/core-plugin-api": "^0.3.0",
"@backstage/core-components": "^0.8.1",
"@backstage/core-plugin-api": "^0.3.1",
"@backstage/plugin-catalog-react": "^0.6.5",
"@backstage/theme": "^0.2.14",
"@material-ui/core": "^4.12.2",
@@ -37,8 +37,8 @@
"react": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.10.1",
"@backstage/core-app-api": "^0.2.0",
"@backstage/cli": "^0.10.2",
"@backstage/core-app-api": "^0.2.1",
"@backstage/dev-utils": "^0.2.14",
"@backstage/test-utils": "^0.1.24",
"@testing-library/jest-dom": "^5.10.1",
+4 -4
View File
@@ -22,8 +22,8 @@
},
"dependencies": {
"@backstage/config": "^0.1.5",
"@backstage/core-components": "^0.8.0",
"@backstage/core-plugin-api": "^0.3.0",
"@backstage/core-components": "^0.8.1",
"@backstage/core-plugin-api": "^0.3.1",
"@backstage/theme": "^0.2.14",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
@@ -35,8 +35,8 @@
"react": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.10.1",
"@backstage/core-app-api": "^0.2.0",
"@backstage/cli": "^0.10.2",
"@backstage/core-app-api": "^0.2.1",
"@backstage/dev-utils": "^0.2.14",
"@backstage/test-utils": "^0.1.24",
"@testing-library/jest-dom": "^5.10.1",
+22
View File
@@ -0,0 +1,22 @@
# @backstage/plugin-apache-airflow
## 0.1.0
### Minor Changes
- 9aea335911: Introduces a new plugin for the Apache Airflow workflow management platform.
This implementation has been tested with the Apache Airflow v2 API,
authenticating with basic authentication through the Backstage proxy plugin.
Supported functionality includes:
- Information card of version information of the Airflow instance
- Information card of instance health for the meta-database and scheduler
- Table of DAGs with meta information and status, along with a link to view
details in the Airflow UI
### Patch Changes
- Updated dependencies
- @backstage/core-plugin-api@0.3.1
- @backstage/core-components@0.8.1
+3
View File
@@ -2,6 +2,9 @@
Welcome to the apache-airflow plugin!
This plugin serves as frontend to the REST API exposed by Apache Airflow.
Note only [Airflow v2 (and later)](https://airflow.apache.org/docs/apache-airflow/stable/deprecated-rest-api-ref.html) integrate with the plugin.
## Feature Requests & Ideas
- [ ] Add support for running multiple instances of Airflow for monitoring
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-apache-airflow",
"version": "0.0.0",
"version": "0.1.0",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -20,8 +20,8 @@
"clean": "backstage-cli clean"
},
"dependencies": {
"@backstage/core-components": "^0.8.0",
"@backstage/core-plugin-api": "^0.3.0",
"@backstage/core-components": "^0.8.1",
"@backstage/core-plugin-api": "^0.3.1",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.57",
@@ -33,8 +33,8 @@
"react": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.10.1",
"@backstage/core-app-api": "^0.2.0",
"@backstage/cli": "^0.10.2",
"@backstage/core-app-api": "^0.2.1",
"@backstage/dev-utils": "^0.2.14",
"@backstage/test-utils": "^0.1.24",
"@testing-library/jest-dom": "^5.10.1",
+4 -4
View File
@@ -32,8 +32,8 @@
"dependencies": {
"@asyncapi/react-component": "^1.0.0-next.25",
"@backstage/catalog-model": "^0.9.7",
"@backstage/core-components": "^0.8.0",
"@backstage/core-plugin-api": "^0.3.0",
"@backstage/core-components": "^0.8.1",
"@backstage/core-plugin-api": "^0.3.1",
"@backstage/plugin-catalog": "^0.7.4",
"@backstage/plugin-catalog-react": "^0.6.5",
"@backstage/theme": "^0.2.14",
@@ -54,8 +54,8 @@
"react": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.10.1",
"@backstage/core-app-api": "^0.2.0",
"@backstage/cli": "^0.10.2",
"@backstage/core-app-api": "^0.2.1",
"@backstage/dev-utils": "^0.2.14",
"@backstage/test-utils": "^0.1.24",
"@testing-library/jest-dom": "^5.10.1",
+9
View File
@@ -1,5 +1,14 @@
# @backstage/plugin-auth-backend
## 0.5.1
### Patch Changes
- 699c2e9ddc: export minimal typescript types for OIDC provider
- Updated dependencies
- @backstage/backend-common@0.9.14
- @backstage/catalog-model@0.9.8
## 0.5.0
### Minor Changes
+4 -4
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/plugin-auth-backend",
"description": "A Backstage backend plugin that handles authentication",
"version": "0.5.0",
"version": "0.5.1",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -30,9 +30,9 @@
"clean": "backstage-cli clean"
},
"dependencies": {
"@backstage/backend-common": "^0.9.13",
"@backstage/backend-common": "^0.9.14",
"@backstage/catalog-client": "^0.5.2",
"@backstage/catalog-model": "^0.9.7",
"@backstage/catalog-model": "^0.9.8",
"@backstage/config": "^0.1.11",
"@backstage/errors": "^0.1.5",
"@backstage/test-utils": "^0.1.24",
@@ -73,7 +73,7 @@
"yn": "^4.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.10.1",
"@backstage/cli": "^0.10.2",
"@types/body-parser": "^1.19.0",
"@types/cookie-parser": "^1.4.2",
"@types/express-session": "^1.17.2",
+61
View File
@@ -1,5 +1,66 @@
# @backstage/plugin-azure-devops-backend
## 0.2.5
### Patch Changes
- daf32e2c9b: Created some initial filters that can be used to create pull request columns:
- All
- AssignedToUser
- AssignedToCurrentUser
- AssignedToTeam
- AssignedToTeams
- AssignedToCurrentUsersTeams
- CreatedByUser
- CreatedByCurrentUser
- CreatedByTeam
- CreatedByTeams
- CreatedByCurrentUsersTeams
Example custom column creation:
```tsx
const COLUMN_CONFIGS: PullRequestColumnConfig[] = [
{
title: 'Created by me',
filters: [{ type: FilterType.CreatedByCurrentUser }],
},
{
title: 'Created by Backstage Core',
filters: [
{
type: FilterType.CreatedByTeam,
teamName: 'Backstage Core',
},
],
},
{
title: 'Assigned to my teams',
filters: [{ type: FilterType.AssignedToCurrentUsersTeams }],
},
{
title: 'Other PRs',
filters: [{ type: FilterType.All }],
simplified: true,
},
];
<Route
path="/azure-pull-requests"
element={
<AzurePullRequestsPage
projectName="{PROJECT_NAME}"
defaultColumnConfigs={COLUMN_CONFIGS}
/>
}
/>;
```
- Updated dependencies
- @backstage/backend-common@0.9.14
- @backstage/plugin-azure-devops-common@0.1.3
## 0.2.4
### Patch Changes
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-azure-devops-backend",
"version": "0.2.4",
"version": "0.2.5",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -20,9 +20,9 @@
"clean": "backstage-cli clean"
},
"dependencies": {
"@backstage/backend-common": "^0.9.13",
"@backstage/backend-common": "^0.9.14",
"@backstage/config": "^0.1.11",
"@backstage/plugin-azure-devops-common": "^0.1.2",
"@backstage/plugin-azure-devops-common": "^0.1.3",
"@types/express": "^4.17.6",
"azure-devops-node-api": "^11.0.1",
"express": "^4.17.1",
@@ -31,7 +31,7 @@
"yn": "^4.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.10.1",
"@backstage/cli": "^0.10.2",
"@types/supertest": "^2.0.8",
"supertest": "^4.0.2",
"msw": "^0.35.0"
+57
View File
@@ -1,5 +1,62 @@
# @backstage/plugin-azure-devops-common
## 0.1.3
### Patch Changes
- daf32e2c9b: Created some initial filters that can be used to create pull request columns:
- All
- AssignedToUser
- AssignedToCurrentUser
- AssignedToTeam
- AssignedToTeams
- AssignedToCurrentUsersTeams
- CreatedByUser
- CreatedByCurrentUser
- CreatedByTeam
- CreatedByTeams
- CreatedByCurrentUsersTeams
Example custom column creation:
```tsx
const COLUMN_CONFIGS: PullRequestColumnConfig[] = [
{
title: 'Created by me',
filters: [{ type: FilterType.CreatedByCurrentUser }],
},
{
title: 'Created by Backstage Core',
filters: [
{
type: FilterType.CreatedByTeam,
teamName: 'Backstage Core',
},
],
},
{
title: 'Assigned to my teams',
filters: [{ type: FilterType.AssignedToCurrentUsersTeams }],
},
{
title: 'Other PRs',
filters: [{ type: FilterType.All }],
simplified: true,
},
];
<Route
path="/azure-pull-requests"
element={
<AzurePullRequestsPage
projectName="{PROJECT_NAME}"
defaultColumnConfigs={COLUMN_CONFIGS}
/>
}
/>;
```
## 0.1.2
### Patch Changes
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-azure-devops-common",
"version": "0.1.2",
"version": "0.1.3",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -29,7 +29,7 @@
"clean": "backstage-cli clean"
},
"devDependencies": {
"@backstage/cli": "^0.10.1"
"@backstage/cli": "^0.10.2"
},
"files": [
"dist"
+64
View File
@@ -1,5 +1,69 @@
# @backstage/plugin-azure-devops
## 0.1.7
### Patch Changes
- daf32e2c9b: Created some initial filters that can be used to create pull request columns:
- All
- AssignedToUser
- AssignedToCurrentUser
- AssignedToTeam
- AssignedToTeams
- AssignedToCurrentUsersTeams
- CreatedByUser
- CreatedByCurrentUser
- CreatedByTeam
- CreatedByTeams
- CreatedByCurrentUsersTeams
Example custom column creation:
```tsx
const COLUMN_CONFIGS: PullRequestColumnConfig[] = [
{
title: 'Created by me',
filters: [{ type: FilterType.CreatedByCurrentUser }],
},
{
title: 'Created by Backstage Core',
filters: [
{
type: FilterType.CreatedByTeam,
teamName: 'Backstage Core',
},
],
},
{
title: 'Assigned to my teams',
filters: [{ type: FilterType.AssignedToCurrentUsersTeams }],
},
{
title: 'Other PRs',
filters: [{ type: FilterType.All }],
simplified: true,
},
];
<Route
path="/azure-pull-requests"
element={
<AzurePullRequestsPage
projectName="{PROJECT_NAME}"
defaultColumnConfigs={COLUMN_CONFIGS}
/>
}
/>;
```
- Updated dependencies
- @backstage/core-plugin-api@0.3.1
- @backstage/core-components@0.8.1
- @backstage/plugin-azure-devops-common@0.1.3
- @backstage/catalog-model@0.9.8
- @backstage/plugin-catalog-react@0.6.7
## 0.1.6
### Patch Changes
+8 -8
View File
@@ -1,6 +1,6 @@
{
"name": "@backstage/plugin-azure-devops",
"version": "0.1.6",
"version": "0.1.7",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -27,12 +27,12 @@
"clean": "backstage-cli clean"
},
"dependencies": {
"@backstage/catalog-model": "^0.9.7",
"@backstage/core-components": "^0.8.0",
"@backstage/core-plugin-api": "^0.3.0",
"@backstage/catalog-model": "^0.9.8",
"@backstage/core-components": "^0.8.1",
"@backstage/core-plugin-api": "^0.3.1",
"@backstage/errors": "^0.1.4",
"@backstage/plugin-azure-devops-common": "^0.1.2",
"@backstage/plugin-catalog-react": "^0.6.5",
"@backstage/plugin-azure-devops-common": "^0.1.3",
"@backstage/plugin-catalog-react": "^0.6.7",
"@backstage/theme": "^0.2.14",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
@@ -46,8 +46,8 @@
"react": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.10.1",
"@backstage/core-app-api": "^0.2.0",
"@backstage/cli": "^0.10.2",
"@backstage/core-app-api": "^0.2.1",
"@backstage/dev-utils": "^0.2.14",
"@backstage/test-utils": "^0.1.24",
"@testing-library/jest-dom": "^5.10.1",
+4 -4
View File
@@ -28,8 +28,8 @@
},
"dependencies": {
"@backstage/catalog-model": "^0.9.7",
"@backstage/core-components": "^0.8.0",
"@backstage/core-plugin-api": "^0.3.0",
"@backstage/core-components": "^0.8.1",
"@backstage/core-plugin-api": "^0.3.1",
"@backstage/errors": "^0.1.5",
"@backstage/plugin-catalog-react": "^0.6.5",
"@backstage/theme": "^0.2.14",
@@ -43,8 +43,8 @@
"react": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.10.1",
"@backstage/core-app-api": "^0.2.0",
"@backstage/cli": "^0.10.2",
"@backstage/core-app-api": "^0.2.1",
"@backstage/dev-utils": "^0.2.14",
"@backstage/test-utils": "^0.1.24",
"@testing-library/jest-dom": "^5.10.1",
+3 -3
View File
@@ -23,8 +23,8 @@
"dependencies": {
"@backstage/catalog-model": "^0.9.7",
"@backstage/cli": "^0.10.1",
"@backstage/core-components": "^0.8.0",
"@backstage/core-plugin-api": "^0.3.0",
"@backstage/core-components": "^0.8.1",
"@backstage/core-plugin-api": "^0.3.1",
"@backstage/plugin-catalog": "^0.7.4",
"@backstage/plugin-catalog-react": "^0.6.5",
"@date-io/luxon": "1.x",
@@ -42,7 +42,7 @@
"react": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.10.1",
"@backstage/cli": "^0.10.2",
"@backstage/dev-utils": "^0.2.14",
"@testing-library/jest-dom": "^5.10.1",
"cross-fetch": "^3.0.6"
+4 -4
View File
@@ -22,8 +22,8 @@
},
"dependencies": {
"@backstage/catalog-model": "^0.9.7",
"@backstage/core-components": "^0.8.0",
"@backstage/core-plugin-api": "^0.3.0",
"@backstage/core-components": "^0.8.1",
"@backstage/core-plugin-api": "^0.3.1",
"@backstage/plugin-catalog-react": "^0.6.5",
"@backstage/theme": "^0.2.14",
"@material-ui/core": "^4.12.2",
@@ -40,8 +40,8 @@
"react": "^16.13.1 || ^17.0.0"
},
"devDependencies": {
"@backstage/cli": "^0.10.1",
"@backstage/core-app-api": "^0.2.0",
"@backstage/cli": "^0.10.2",
"@backstage/core-app-api": "^0.2.1",
"@backstage/dev-utils": "^0.2.14",
"@backstage/test-utils": "^0.1.24",
"@testing-library/jest-dom": "^5.10.1",
+9
View File
@@ -1,5 +1,14 @@
# @backstage/plugin-catalog-backend
## 0.19.2
### Patch Changes
- 3368f27aef: Fixed the handling of optional locations so that the catalog no longer logs `NotFoundError`s for missing optional locations.
- Updated dependencies
- @backstage/backend-common@0.9.14
- @backstage/catalog-model@0.9.8
## 0.19.1
### Patch Changes
+4 -4
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/plugin-catalog-backend",
"description": "The Backstage backend plugin that provides the Backstage catalog",
"version": "0.19.1",
"version": "0.19.2",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
@@ -30,9 +30,9 @@
"clean": "backstage-cli clean"
},
"dependencies": {
"@backstage/backend-common": "^0.9.13",
"@backstage/backend-common": "^0.9.14",
"@backstage/catalog-client": "^0.5.2",
"@backstage/catalog-model": "^0.9.7",
"@backstage/catalog-model": "^0.9.8",
"@backstage/config": "^0.1.11",
"@backstage/errors": "^0.1.5",
"@backstage/integration": "^0.6.10",
@@ -63,7 +63,7 @@
},
"devDependencies": {
"@backstage/backend-test-utils": "^0.1.10",
"@backstage/cli": "^0.10.1",
"@backstage/cli": "^0.10.2",
"@backstage/test-utils": "^0.1.24",
"@types/core-js": "^2.5.4",
"@types/git-url-parse": "^9.0.0",

Some files were not shown because too many files have changed in this diff Show More