Merge branch 'master' into samiram/fix-banner-pos
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
# Changesets
|
||||
|
||||
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
|
||||
with multi-package repos, or single-package repos to help you version and publish your code. You can
|
||||
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
|
||||
|
||||
We have a quick list of common questions to get you started engaging with this project in
|
||||
[our documentation](https://github.com/changesets/changesets/blob/master/docs/common-questions.md)
|
||||
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"$schema": "https://unpkg.com/@changesets/config@1.3.0/schema.json",
|
||||
"changelog": "@changesets/cli/changelog",
|
||||
"commit": false,
|
||||
"linked": [
|
||||
[
|
||||
"example-app",
|
||||
"@backstage/backend-common",
|
||||
"example-backend",
|
||||
"@backstage/catalog-model",
|
||||
"@backstage/cli-common",
|
||||
"@backstage/cli",
|
||||
"@backstage/config-loader",
|
||||
"@backstage/config",
|
||||
"@backstage/core-api",
|
||||
"@backstage/core",
|
||||
"@backstage/create-app",
|
||||
"@backstage/dev-utils",
|
||||
"docgen",
|
||||
"e2e-test",
|
||||
"storybook",
|
||||
"@techdocs/cli",
|
||||
"@backstage/test-utils-core",
|
||||
"@backstage/test-utils",
|
||||
"@backstage/theme",
|
||||
"@backstage/plugin-api-docs",
|
||||
"@backstage/plugin-app-backend",
|
||||
"@backstage/plugin-auth-backend",
|
||||
"@backstage/plugin-catalog-backend",
|
||||
"@backstage/plugin-catalog",
|
||||
"@backstage/plugin-circleci",
|
||||
"@backstage/plugin-gcp-projects",
|
||||
"@backstage/plugin-github-actions",
|
||||
"@backstage/plugin-gitops-profiles",
|
||||
"@backstage/plugin-graphiql",
|
||||
"@backstage/plugin-graphql-backend",
|
||||
"@backstage/plugin-identity-backend",
|
||||
"@backstage/plugin-jenkins",
|
||||
"@backstage/plugin-lighthouse",
|
||||
"@backstage/plugin-newrelic",
|
||||
"@backstage/plugin-proxy-backend",
|
||||
"@backstage/plugin-register-component",
|
||||
"@backstage/plugin-rollbar-backend",
|
||||
"@backstage/plugin-rollbar",
|
||||
"@backstage/plugin-scaffolder-backend",
|
||||
"@backstage/plugin-scaffolder",
|
||||
"@backstage/plugin-sentry-backend",
|
||||
"@backstage/plugin-sentry",
|
||||
"@backstage/plugin-tech-radar",
|
||||
"@backstage/plugin-techdocs-backend",
|
||||
"@backstage/plugin-techdocs",
|
||||
"@backstage/plugin-welcome"
|
||||
]
|
||||
],
|
||||
"access": "public",
|
||||
"baseBranch": "master",
|
||||
"updateInternalDependencies": "patch",
|
||||
"ignore": []
|
||||
}
|
||||
@@ -6,3 +6,13 @@ coverage:
|
||||
default:
|
||||
threshold: 0% # Ref: https://docs.codecov.io/docs/codecovyml-reference#coveragestatus
|
||||
target: auto
|
||||
|
||||
# Since Backstage is a mono repo, flags here help in getting the code coverage of individual packages.
|
||||
# Documentation: https://docs.codecov.io/docs/flags
|
||||
flags:
|
||||
core:
|
||||
paths:
|
||||
- packages/core/
|
||||
core-api:
|
||||
paths:
|
||||
- packages/core-api/
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
name: Changeset
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
create-release-pr:
|
||||
name: Create Changeset PR
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Install Dependencies
|
||||
run: yarn --frozen-lockfile
|
||||
- name: Create Release Pull Request
|
||||
uses: changesets/action@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -63,6 +63,9 @@ jobs:
|
||||
run: |
|
||||
yarn lerna -- run test -- --coverage
|
||||
bash <(curl -s https://codecov.io/bash)
|
||||
# Upload code coverage for some specific flags. Also see .codecov.yml
|
||||
bash <(curl -s https://codecov.io/bash) -f packages/core/coverage/* -F core
|
||||
bash <(curl -s https://codecov.io/bash) -f packages/core-api/coverage/* -F core-api
|
||||
|
||||
# Publishes current version of packages that are not already present in the registry
|
||||
- name: publish
|
||||
|
||||
@@ -8,6 +8,10 @@ If you encounter issues while upgrading to a newer version, don't hesitate to re
|
||||
|
||||
> Collect changes for the next release below
|
||||
|
||||
### @backstage/core
|
||||
|
||||
- Renamed `SessionStateApi` to `SessionApi` and `logout` to `signOut`. Custom implementations of the `SingInPage` app-component will need to rename their `logout` function. The different auth provider items for the `UserSettingsMenu` have been consolidated into a single `ProviderSettingsItem`, meaning you need to replace existing usages of `OAuthProviderSettings` and `OIDCProviderSettings`. [#2555](https://github.com/spotify/backstage/pull/2555).
|
||||
|
||||
## v0.1.1-alpha.22
|
||||
|
||||
### @backstage/core
|
||||
|
||||
@@ -72,6 +72,21 @@ If you're contributing to the backend or CLI tooling, be mindful of cross-platfo
|
||||
|
||||
Also be sure to skim through our [ADRs](https://github.com/spotify/backstage/tree/master/docs/architecture-decisions) to see if they cover what you're working on. In particular [ADR006: Avoid React.FC and React.SFC](https://github.com/spotify/backstage/blob/master/docs/architecture-decisions/adr006-avoid-react-fc.md) is one to look out for.
|
||||
|
||||
# Creating Changesets
|
||||
|
||||
We use [changesets](https://github.com/atlassian/changesets) to help us prepare releases. It helps us make sure that every package affected by a change gets a proper version number and an entry in its `CHANGELOG.md`. To make the process of generating releases easy. it helps when contributors include changesets with their pull requests.
|
||||
|
||||
## To create a changeset
|
||||
|
||||
1. Run `yarn changeset`
|
||||
2. Select which packages you want to include a changeset for
|
||||
3. Select impact of change that you're introducing (minor, major or patch)
|
||||
4. Add generated changset to Git
|
||||
5. Push the commit with your changeset to the branch associated with your PR
|
||||
6. Accept our gratitude for making the release process easier on the maintainer
|
||||
|
||||
For more information, checkout [adding a changeset](https://github.com/atlassian/changesets/blob/master/docs/adding-a-changeset.md) documentation in changesets repository.
|
||||
|
||||
# Code of Conduct
|
||||
|
||||
This project adheres to the [Spotify FOSS Code of Conduct][code-of-conduct]. By participating, you are expected to honor this code.
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
### Source repo: https://github.com/johnson-jesse/simple-backstage-app-plugin
|
||||
|
||||
ExampleComponent.tsx reference
|
||||
|
||||
```tsx
|
||||
import React, { FC } from 'react';
|
||||
import { Typography, Grid } from '@material-ui/core';
|
||||
import {
|
||||
InfoCard,
|
||||
Header,
|
||||
Page,
|
||||
pageTheme,
|
||||
Content,
|
||||
ContentHeader,
|
||||
HeaderLabel,
|
||||
SupportButton,
|
||||
identityApiRef,
|
||||
} from '@backstage/core';
|
||||
import { useApi } from '@backstage/core-api';
|
||||
import ExampleFetchComponent from '../ExampleFetchComponent';
|
||||
|
||||
const ExampleComponent: FC<{}> = () => {
|
||||
const identityApi = useApi(identityApiRef);
|
||||
const userId = identityApi.getUserId();
|
||||
const profile = identityApi.getProfile();
|
||||
|
||||
return (
|
||||
<Page theme={pageTheme.tool}>
|
||||
<Header
|
||||
title="Welcome to github-playground!"
|
||||
subtitle="Optional subtitle"
|
||||
>
|
||||
<HeaderLabel label="Owner" value="Team X" />
|
||||
<HeaderLabel label="Lifecycle" value="Alpha" />
|
||||
</Header>
|
||||
<Content>
|
||||
<ContentHeader title="Plugin title">
|
||||
<SupportButton>A description of your plugin goes here.</SupportButton>
|
||||
</ContentHeader>
|
||||
<Grid container spacing={3} direction="column">
|
||||
<Grid item>
|
||||
<InfoCard title={userId}>
|
||||
<Typography variant="body1">
|
||||
{`${profile.displayName} | ${profile.email}`}
|
||||
</Typography>
|
||||
</InfoCard>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<ExampleFetchComponent />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Content>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExampleComponent;
|
||||
```
|
||||
@@ -0,0 +1,111 @@
|
||||
### Source repo: https://github.com/johnson-jesse/simple-backstage-app-plugin
|
||||
|
||||
ExampleFetchComponent.tsx reference
|
||||
|
||||
```tsx
|
||||
import React, { FC } from 'react';
|
||||
import { useAsync } from 'react-use';
|
||||
import Alert from '@material-ui/lab/Alert';
|
||||
import {
|
||||
Table,
|
||||
TableColumn,
|
||||
Progress,
|
||||
githubAuthApiRef,
|
||||
} from '@backstage/core';
|
||||
import { useApi } from '@backstage/core-api';
|
||||
import { graphql } from '@octokit/graphql';
|
||||
|
||||
const query = `{
|
||||
viewer {
|
||||
repositories(first: 100) {
|
||||
totalCount
|
||||
nodes {
|
||||
name
|
||||
createdAt
|
||||
description
|
||||
diskUsage
|
||||
isFork
|
||||
}
|
||||
pageInfo {
|
||||
endCursor
|
||||
hasNextPage
|
||||
}
|
||||
}
|
||||
}
|
||||
}`;
|
||||
|
||||
type Node = {
|
||||
name: string;
|
||||
createdAt: string;
|
||||
description: string;
|
||||
diskUsage: number;
|
||||
isFork: boolean;
|
||||
};
|
||||
|
||||
type Viewer = {
|
||||
repositories: {
|
||||
totalCount: number;
|
||||
nodes: Node[];
|
||||
pageInfo: {
|
||||
endCursor: string;
|
||||
hasNextPage: boolean;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
type DenseTableProps = {
|
||||
viewer: Viewer;
|
||||
};
|
||||
|
||||
export const DenseTable: FC<DenseTableProps> = ({ viewer }) => {
|
||||
const columns: TableColumn[] = [
|
||||
{ title: 'Name', field: 'name' },
|
||||
{ title: 'Created', field: 'createdAt' },
|
||||
{ title: 'Description', field: 'description' },
|
||||
{ title: 'Disk Usage', field: 'diskUsage' },
|
||||
{ title: 'Fork', field: 'isFork' },
|
||||
];
|
||||
|
||||
return (
|
||||
<Table
|
||||
title="List Of User's Repositories"
|
||||
options={{ search: false, paging: false }}
|
||||
columns={columns}
|
||||
data={viewer.repositories.nodes}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const ExampleFetchComponent: FC<{}> = () => {
|
||||
const auth = useApi(githubAuthApiRef);
|
||||
|
||||
const { value, loading, error } = useAsync(async (): Promise<any> => {
|
||||
const token = await auth.getAccessToken();
|
||||
|
||||
const gqlEndpoint = graphql.defaults({
|
||||
// Uncomment baseUrl if using enterprise
|
||||
// baseUrl: 'https://github.MY-BIZ.com/api',
|
||||
headers: {
|
||||
authorization: `token ${token}`,
|
||||
},
|
||||
});
|
||||
const { viewer } = await gqlEndpoint(query);
|
||||
return viewer;
|
||||
}, []);
|
||||
|
||||
if (loading) return <Progress />;
|
||||
if (error) return <Alert severity="error">{error.message}</Alert>;
|
||||
if (value && value.repositories) return <DenseTable viewer={value} />;
|
||||
|
||||
return (
|
||||
<Table
|
||||
title="List Of User's Repositories"
|
||||
options={{ search: false, paging: false }}
|
||||
columns={[]}
|
||||
data={[]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExampleFetchComponent;
|
||||
```
|
||||
@@ -35,6 +35,13 @@ full list of providers, see the
|
||||
|
||||
### Identity - WIP
|
||||
|
||||
> NOTE: Identity management and the `SignInPage` in Backstage is NOT a method
|
||||
> for blocking access for unauthorized users, that either requires additional
|
||||
> backend implementation or a separate service like Google's Identity-Aware
|
||||
> Proxy. The identity system only serves to provide a personalized experience
|
||||
> and access to a Backstage Identity Token, which can be passed to backend
|
||||
> plugins.
|
||||
|
||||
Identity management is still work in progress, but there are already a couple of
|
||||
pieces in place that can be used.
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ import {
|
||||
GitlabPublisher,
|
||||
CreateReactAppTemplater,
|
||||
Templaters,
|
||||
RepoVisilityOptions,
|
||||
RepoVisibilityOptions,
|
||||
} from '@backstage/plugin-scaffolder-backend';
|
||||
import { Octokit } from '@octokit/rest';
|
||||
import { Gitlab } from '@gitbeaker/node';
|
||||
@@ -126,7 +126,7 @@ export default async function createPlugin({
|
||||
const githubToken = config.getString('scaffolder.github.token');
|
||||
const repoVisibility = config.getString(
|
||||
'scaffolder.github.visibility',
|
||||
) as RepoVisilityOptions;
|
||||
) as RepoVisibilityOptions;
|
||||
|
||||
const githubClient = new Octokit({ auth: githubToken });
|
||||
const githubPublisher = new GithubPublisher({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# AlertApi
|
||||
|
||||
The AlertApi type is defined at
|
||||
[packages/core-api/src/apis/definitions/AlertApi.ts:29](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/AlertApi.ts#L29).
|
||||
[packages/core-api/src/apis/definitions/AlertApi.ts:29](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/AlertApi.ts#L29).
|
||||
|
||||
The following Utility API implements this type: [alertApiRef](./README.md#alert)
|
||||
|
||||
@@ -38,7 +38,7 @@ export type AlertMessage = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/apis/definitions/AlertApi.ts:19](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/AlertApi.ts#L19).
|
||||
[packages/core-api/src/apis/definitions/AlertApi.ts:19](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/AlertApi.ts#L19).
|
||||
|
||||
Referenced by: [post](#post), [alert\$](#alert).
|
||||
|
||||
@@ -67,7 +67,7 @@ export type Observable<T> = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/types.ts:53](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L53).
|
||||
[packages/core-api/src/types.ts:53](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/types.ts#L53).
|
||||
|
||||
Referenced by: [alert\$](#alert).
|
||||
|
||||
@@ -86,7 +86,7 @@ export type Observer<T> = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/types.ts:24](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L24).
|
||||
[packages/core-api/src/types.ts:24](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/types.ts#L24).
|
||||
|
||||
Referenced by: [Observable](#observable).
|
||||
|
||||
@@ -109,6 +109,6 @@ export type Subscription = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/types.ts:33](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L33).
|
||||
[packages/core-api/src/types.ts:33](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/types.ts#L33).
|
||||
|
||||
Referenced by: [Observable](#observable).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# AppThemeApi
|
||||
|
||||
The AppThemeApi type is defined at
|
||||
[packages/core-api/src/apis/definitions/AppThemeApi.ts:50](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/AppThemeApi.ts#L50).
|
||||
[packages/core-api/src/apis/definitions/AppThemeApi.ts:50](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/AppThemeApi.ts#L50).
|
||||
|
||||
The following Utility API implements this type:
|
||||
[appThemeApiRef](./README.md#apptheme)
|
||||
@@ -76,7 +76,7 @@ export type AppTheme = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/apis/definitions/AppThemeApi.ts:24](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/AppThemeApi.ts#L24).
|
||||
[packages/core-api/src/apis/definitions/AppThemeApi.ts:24](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/AppThemeApi.ts#L24).
|
||||
|
||||
Referenced by: [getInstalledThemes](#getinstalledthemes).
|
||||
|
||||
@@ -87,7 +87,7 @@ export type BackstagePalette = Palette & <a href="#paletteadditions">Palette
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/theme/src/types.ts:70](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/theme/src/types.ts#L70).
|
||||
[packages/theme/src/types.ts:70](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/theme/src/types.ts#L70).
|
||||
|
||||
Referenced by: [BackstageTheme](#backstagetheme).
|
||||
|
||||
@@ -100,7 +100,7 @@ export interface BackstageTheme extends Theme {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/theme/src/types.ts:73](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/theme/src/types.ts#L73).
|
||||
[packages/theme/src/types.ts:73](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/theme/src/types.ts#L73).
|
||||
|
||||
Referenced by: [AppTheme](#apptheme).
|
||||
|
||||
@@ -129,7 +129,7 @@ export type Observable<T> = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/types.ts:53](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L53).
|
||||
[packages/core-api/src/types.ts:53](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/types.ts#L53).
|
||||
|
||||
Referenced by: [activeThemeId\$](#activethemeid).
|
||||
|
||||
@@ -148,7 +148,7 @@ export type Observer<T> = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/types.ts:24](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L24).
|
||||
[packages/core-api/src/types.ts:24](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/types.ts#L24).
|
||||
|
||||
Referenced by: [Observable](#observable).
|
||||
|
||||
@@ -204,7 +204,7 @@ type PaletteAdditions = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/theme/src/types.ts:23](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/theme/src/types.ts#L23).
|
||||
[packages/theme/src/types.ts:23](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/theme/src/types.ts#L23).
|
||||
|
||||
Referenced by: [BackstagePalette](#backstagepalette).
|
||||
|
||||
@@ -227,6 +227,6 @@ export type Subscription = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/types.ts:33](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L33).
|
||||
[packages/core-api/src/types.ts:33](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/types.ts#L33).
|
||||
|
||||
Referenced by: [Observable](#observable).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# BackstageIdentityApi
|
||||
|
||||
The BackstageIdentityApi type is defined at
|
||||
[packages/core-api/src/apis/definitions/auth.ts:144](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L144).
|
||||
[packages/core-api/src/apis/definitions/auth.ts:134](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L134).
|
||||
|
||||
The following Utility APIs implement this type:
|
||||
|
||||
@@ -15,6 +15,8 @@ The following Utility APIs implement this type:
|
||||
|
||||
- [microsoftAuthApiRef](./README.md#microsoftauth)
|
||||
|
||||
- [oauth2ApiRef](./README.md#oauth2)
|
||||
|
||||
- [oktaAuthApiRef](./README.md#oktaauth)
|
||||
|
||||
## Members
|
||||
@@ -66,7 +68,7 @@ export type AuthRequestOptions = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/apis/definitions/auth.ts:40](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L40).
|
||||
[packages/core-api/src/apis/definitions/auth.ts:40](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L40).
|
||||
|
||||
Referenced by: [getBackstageIdentity](#getbackstageidentity).
|
||||
|
||||
@@ -87,6 +89,6 @@ export type BackstageIdentity = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/apis/definitions/auth.ts:157](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L157).
|
||||
[packages/core-api/src/apis/definitions/auth.ts:147](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L147).
|
||||
|
||||
Referenced by: [getBackstageIdentity](#getbackstageidentity).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Config
|
||||
|
||||
The Config type is defined at
|
||||
[packages/config/src/types.ts:32](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/config/src/types.ts#L32).
|
||||
[packages/config/src/types.ts:32](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/config/src/types.ts#L32).
|
||||
|
||||
The following Utility API implements this type:
|
||||
[configApiRef](./README.md#config)
|
||||
@@ -140,7 +140,7 @@ export type Config = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/config/src/types.ts:32](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/config/src/types.ts#L32).
|
||||
[packages/config/src/types.ts:32](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/config/src/types.ts#L32).
|
||||
|
||||
Referenced by: [getConfig](#getconfig), [getOptionalConfig](#getoptionalconfig),
|
||||
[getConfigArray](#getconfigarray),
|
||||
@@ -153,7 +153,7 @@ export type JsonArray = <a href="#jsonvalue">JsonValue</a>[]
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/config/src/types.ts:18](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/config/src/types.ts#L18).
|
||||
[packages/config/src/types.ts:18](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/config/src/types.ts#L18).
|
||||
|
||||
Referenced by: [JsonValue](#jsonvalue).
|
||||
|
||||
@@ -164,7 +164,7 @@ export type JsonObject = { [key in string]?: <a href="#jsonvalue">JsonValue</a>
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/config/src/types.ts:17](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/config/src/types.ts#L17).
|
||||
[packages/config/src/types.ts:17](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/config/src/types.ts#L17).
|
||||
|
||||
Referenced by: [JsonValue](#jsonvalue).
|
||||
|
||||
@@ -181,7 +181,7 @@ export type JsonValue =
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/config/src/types.ts:19](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/config/src/types.ts#L19).
|
||||
[packages/config/src/types.ts:19](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/config/src/types.ts#L19).
|
||||
|
||||
Referenced by: [get](#get), [getOptional](#getoptional),
|
||||
[JsonObject](#jsonobject), [JsonArray](#jsonarray), [Config](#config).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# DiscoveryApi
|
||||
|
||||
The DiscoveryApi type is defined at
|
||||
[packages/core-api/src/apis/definitions/DiscoveryApi.ts:30](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/DiscoveryApi.ts#L30).
|
||||
[packages/core-api/src/apis/definitions/DiscoveryApi.ts:30](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/DiscoveryApi.ts#L30).
|
||||
|
||||
The following Utility API implements this type:
|
||||
[discoveryApiRef](./README.md#discovery)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# ErrorApi
|
||||
|
||||
The ErrorApi type is defined at
|
||||
[packages/core-api/src/apis/definitions/ErrorApi.ts:53](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/ErrorApi.ts#L53).
|
||||
[packages/core-api/src/apis/definitions/ErrorApi.ts:53](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/ErrorApi.ts#L53).
|
||||
|
||||
The following Utility API implements this type: [errorApiRef](./README.md#error)
|
||||
|
||||
@@ -41,7 +41,7 @@ type Error = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/apis/definitions/ErrorApi.ts:24](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/ErrorApi.ts#L24).
|
||||
[packages/core-api/src/apis/definitions/ErrorApi.ts:24](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/ErrorApi.ts#L24).
|
||||
|
||||
Referenced by: [post](#post), [error\$](#error).
|
||||
|
||||
@@ -58,7 +58,7 @@ export type ErrorContext = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/apis/definitions/ErrorApi.ts:33](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/ErrorApi.ts#L33).
|
||||
[packages/core-api/src/apis/definitions/ErrorApi.ts:33](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/ErrorApi.ts#L33).
|
||||
|
||||
Referenced by: [post](#post), [error\$](#error).
|
||||
|
||||
@@ -87,7 +87,7 @@ export type Observable<T> = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/types.ts:53](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L53).
|
||||
[packages/core-api/src/types.ts:53](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/types.ts#L53).
|
||||
|
||||
Referenced by: [error\$](#error).
|
||||
|
||||
@@ -106,7 +106,7 @@ export type Observer<T> = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/types.ts:24](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L24).
|
||||
[packages/core-api/src/types.ts:24](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/types.ts#L24).
|
||||
|
||||
Referenced by: [Observable](#observable).
|
||||
|
||||
@@ -129,6 +129,6 @@ export type Subscription = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/types.ts:33](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L33).
|
||||
[packages/core-api/src/types.ts:33](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/types.ts#L33).
|
||||
|
||||
Referenced by: [Observable](#observable).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# FeatureFlagsApi
|
||||
|
||||
The FeatureFlagsApi type is defined at
|
||||
[packages/core-api/src/apis/definitions/FeatureFlagsApi.ts:41](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/FeatureFlagsApi.ts#L41).
|
||||
[packages/core-api/src/apis/definitions/FeatureFlagsApi.ts:41](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/FeatureFlagsApi.ts#L41).
|
||||
|
||||
The following Utility API implements this type:
|
||||
[featureFlagsApiRef](./README.md#featureflags)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# IdentityApi
|
||||
|
||||
The IdentityApi type is defined at
|
||||
[packages/core-api/src/apis/definitions/IdentityApi.ts:22](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/IdentityApi.ts#L22).
|
||||
[packages/core-api/src/apis/definitions/IdentityApi.ts:22](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/IdentityApi.ts#L22).
|
||||
|
||||
The following Utility API implements this type:
|
||||
[identityApiRef](./README.md#identity)
|
||||
@@ -40,12 +40,12 @@ identity, such as a demo user or mocked user for e2e tests.
|
||||
getIdToken(): Promise<string | undefined>
|
||||
</pre>
|
||||
|
||||
### logout()
|
||||
### signOut()
|
||||
|
||||
Log out the current user
|
||||
Sign out the current user
|
||||
|
||||
<pre>
|
||||
logout(): Promise<void>
|
||||
signOut(): Promise<void>
|
||||
</pre>
|
||||
|
||||
## Supporting types
|
||||
@@ -76,6 +76,6 @@ export type ProfileInfo = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/apis/definitions/auth.ts:172](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L172).
|
||||
[packages/core-api/src/apis/definitions/auth.ts:162](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L162).
|
||||
|
||||
Referenced by: [getProfile](#getprofile).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# OAuthApi
|
||||
|
||||
The OAuthApi type is defined at
|
||||
[packages/core-api/src/apis/definitions/auth.ts:67](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L67).
|
||||
[packages/core-api/src/apis/definitions/auth.ts:67](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L67).
|
||||
|
||||
The following Utility APIs implement this type:
|
||||
|
||||
@@ -50,14 +50,6 @@ getAccessToken(
|
||||
): Promise<string>
|
||||
</pre>
|
||||
|
||||
### logout()
|
||||
|
||||
Log out the user's session. This will reload the page.
|
||||
|
||||
<pre>
|
||||
logout(): Promise<void>
|
||||
</pre>
|
||||
|
||||
## Supporting types
|
||||
|
||||
These types are part of the API declaration, but may not be unique to this API.
|
||||
@@ -90,7 +82,7 @@ export type AuthRequestOptions = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/apis/definitions/auth.ts:40](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L40).
|
||||
[packages/core-api/src/apis/definitions/auth.ts:40](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L40).
|
||||
|
||||
Referenced by: [getAccessToken](#getaccesstoken).
|
||||
|
||||
@@ -116,6 +108,6 @@ export type OAuthScope = string | string[]
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/apis/definitions/auth.ts:38](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L38).
|
||||
[packages/core-api/src/apis/definitions/auth.ts:38](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L38).
|
||||
|
||||
Referenced by: [getAccessToken](#getaccesstoken).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# OAuthRequestApi
|
||||
|
||||
The OAuthRequestApi type is defined at
|
||||
[packages/core-api/src/apis/definitions/OAuthRequestApi.ts:99](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L99).
|
||||
[packages/core-api/src/apis/definitions/OAuthRequestApi.ts:99](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L99).
|
||||
|
||||
The following Utility API implements this type:
|
||||
[oauthRequestApiRef](./README.md#oauthrequest)
|
||||
@@ -72,7 +72,7 @@ export type AuthProvider = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/apis/definitions/OAuthRequestApi.ts:27](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L27).
|
||||
[packages/core-api/src/apis/definitions/OAuthRequestApi.ts:27](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L27).
|
||||
|
||||
Referenced by: [AuthRequesterOptions](#authrequesteroptions),
|
||||
[PendingAuthRequest](#pendingauthrequest).
|
||||
@@ -96,7 +96,7 @@ export type AuthRequester<AuthResponse> = (
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/apis/definitions/OAuthRequestApi.ts:66](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L66).
|
||||
[packages/core-api/src/apis/definitions/OAuthRequestApi.ts:66](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L66).
|
||||
|
||||
Referenced by: [createAuthRequester](#createauthrequester).
|
||||
|
||||
@@ -121,7 +121,7 @@ export type AuthRequesterOptions<AuthResponse> = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/apis/definitions/OAuthRequestApi.ts:43](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L43).
|
||||
[packages/core-api/src/apis/definitions/OAuthRequestApi.ts:43](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L43).
|
||||
|
||||
Referenced by: [createAuthRequester](#createauthrequester).
|
||||
|
||||
@@ -150,7 +150,7 @@ export type Observable<T> = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/types.ts:53](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L53).
|
||||
[packages/core-api/src/types.ts:53](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/types.ts#L53).
|
||||
|
||||
Referenced by: [authRequest\$](#authrequest).
|
||||
|
||||
@@ -169,7 +169,7 @@ export type Observer<T> = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/types.ts:24](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L24).
|
||||
[packages/core-api/src/types.ts:24](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/types.ts#L24).
|
||||
|
||||
Referenced by: [Observable](#observable).
|
||||
|
||||
@@ -204,7 +204,7 @@ export type PendingAuthRequest = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/apis/definitions/OAuthRequestApi.ts:77](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L77).
|
||||
[packages/core-api/src/apis/definitions/OAuthRequestApi.ts:77](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L77).
|
||||
|
||||
Referenced by: [authRequest\$](#authrequest).
|
||||
|
||||
@@ -227,6 +227,6 @@ export type Subscription = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/types.ts:33](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L33).
|
||||
[packages/core-api/src/types.ts:33](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/types.ts#L33).
|
||||
|
||||
Referenced by: [Observable](#observable).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# OpenIdConnectApi
|
||||
|
||||
The OpenIdConnectApi type is defined at
|
||||
[packages/core-api/src/apis/definitions/auth.ts:104](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L104).
|
||||
[packages/core-api/src/apis/definitions/auth.ts:99](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L99).
|
||||
|
||||
The following Utility APIs implement this type:
|
||||
|
||||
@@ -34,14 +34,6 @@ user rejects the login request.
|
||||
getIdToken(options?: <a href="#authrequestoptions">AuthRequestOptions</a>): Promise<string>
|
||||
</pre>
|
||||
|
||||
### logout()
|
||||
|
||||
Log out the user's session. This will reload the page.
|
||||
|
||||
<pre>
|
||||
logout(): Promise<void>
|
||||
</pre>
|
||||
|
||||
## Supporting types
|
||||
|
||||
These types are part of the API declaration, but may not be unique to this API.
|
||||
@@ -74,6 +66,6 @@ export type AuthRequestOptions = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/apis/definitions/auth.ts:40](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L40).
|
||||
[packages/core-api/src/apis/definitions/auth.ts:40](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L40).
|
||||
|
||||
Referenced by: [getIdToken](#getidtoken).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# ProfileInfoApi
|
||||
|
||||
The ProfileInfoApi type is defined at
|
||||
[packages/core-api/src/apis/definitions/auth.ts:127](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L127).
|
||||
[packages/core-api/src/apis/definitions/auth.ts:117](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L117).
|
||||
|
||||
The following Utility APIs implement this type:
|
||||
|
||||
@@ -65,7 +65,7 @@ export type AuthRequestOptions = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/apis/definitions/auth.ts:40](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L40).
|
||||
[packages/core-api/src/apis/definitions/auth.ts:40](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L40).
|
||||
|
||||
Referenced by: [getProfile](#getprofile).
|
||||
|
||||
@@ -93,6 +93,6 @@ export type ProfileInfo = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/apis/definitions/auth.ts:172](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L172).
|
||||
[packages/core-api/src/apis/definitions/auth.ts:162](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L162).
|
||||
|
||||
Referenced by: [getProfile](#getprofile).
|
||||
|
||||
@@ -12,7 +12,7 @@ Used to report alerts and forward them to the app
|
||||
Implemented type: [AlertApi](./AlertApi.md)
|
||||
|
||||
ApiRef:
|
||||
[alertApiRef](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/AlertApi.ts#L41)
|
||||
[alertApiRef](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/AlertApi.ts#L41)
|
||||
|
||||
### appTheme
|
||||
|
||||
@@ -21,7 +21,7 @@ API Used to configure the app theme, and enumerate options
|
||||
Implemented type: [AppThemeApi](./AppThemeApi.md)
|
||||
|
||||
ApiRef:
|
||||
[appThemeApiRef](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/AppThemeApi.ts#L74)
|
||||
[appThemeApiRef](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/AppThemeApi.ts#L74)
|
||||
|
||||
### auth0Auth
|
||||
|
||||
@@ -29,11 +29,10 @@ Provides authentication towards Auth0 APIs
|
||||
|
||||
Implemented types: [OpenIdConnectApi](./OpenIdConnectApi.md),
|
||||
[ProfileInfoApi](./ProfileInfoApi.md),
|
||||
[BackstageIdentityApi](./BackstageIdentityApi.md),
|
||||
[SessionStateApi](./SessionStateApi.md)
|
||||
[BackstageIdentityApi](./BackstageIdentityApi.md), [SessionApi](./SessionApi.md)
|
||||
|
||||
ApiRef:
|
||||
[auth0AuthApiRef](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L273)
|
||||
[auth0AuthApiRef](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L275)
|
||||
|
||||
### config
|
||||
|
||||
@@ -42,7 +41,7 @@ Used to access runtime configuration
|
||||
Implemented type: [Config](./Config.md)
|
||||
|
||||
ApiRef:
|
||||
[configApiRef](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/ConfigApi.ts#L22)
|
||||
[configApiRef](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/ConfigApi.ts#L22)
|
||||
|
||||
### discovery
|
||||
|
||||
@@ -51,7 +50,7 @@ Provides service discovery of backend plugins
|
||||
Implemented type: [DiscoveryApi](./DiscoveryApi.md)
|
||||
|
||||
ApiRef:
|
||||
[discoveryApiRef](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/DiscoveryApi.ts#L44)
|
||||
[discoveryApiRef](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/DiscoveryApi.ts#L44)
|
||||
|
||||
### error
|
||||
|
||||
@@ -60,7 +59,7 @@ Used to report errors and forward them to the app
|
||||
Implemented type: [ErrorApi](./ErrorApi.md)
|
||||
|
||||
ApiRef:
|
||||
[errorApiRef](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/ErrorApi.ts#L65)
|
||||
[errorApiRef](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/ErrorApi.ts#L65)
|
||||
|
||||
### featureFlags
|
||||
|
||||
@@ -69,7 +68,7 @@ Used to toggle functionality in features across Backstage
|
||||
Implemented type: [FeatureFlagsApi](./FeatureFlagsApi.md)
|
||||
|
||||
ApiRef:
|
||||
[featureFlagsApiRef](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/FeatureFlagsApi.ts#L58)
|
||||
[featureFlagsApiRef](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/FeatureFlagsApi.ts#L58)
|
||||
|
||||
### githubAuth
|
||||
|
||||
@@ -77,11 +76,10 @@ Provides authentication towards GitHub APIs
|
||||
|
||||
Implemented types: [OAuthApi](./OAuthApi.md),
|
||||
[ProfileInfoApi](./ProfileInfoApi.md),
|
||||
[BackstageIdentityApi](./BackstageIdentityApi.md),
|
||||
[SessionStateApi](./SessionStateApi.md)
|
||||
[BackstageIdentityApi](./BackstageIdentityApi.md), [SessionApi](./SessionApi.md)
|
||||
|
||||
ApiRef:
|
||||
[githubAuthApiRef](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L230)
|
||||
[githubAuthApiRef](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L232)
|
||||
|
||||
### gitlabAuth
|
||||
|
||||
@@ -89,11 +87,10 @@ Provides authentication towards GitLab APIs
|
||||
|
||||
Implemented types: [OAuthApi](./OAuthApi.md),
|
||||
[ProfileInfoApi](./ProfileInfoApi.md),
|
||||
[BackstageIdentityApi](./BackstageIdentityApi.md),
|
||||
[SessionStateApi](./SessionStateApi.md)
|
||||
[BackstageIdentityApi](./BackstageIdentityApi.md), [SessionApi](./SessionApi.md)
|
||||
|
||||
ApiRef:
|
||||
[gitlabAuthApiRef](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L260)
|
||||
[gitlabAuthApiRef](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L262)
|
||||
|
||||
### googleAuth
|
||||
|
||||
@@ -102,11 +99,10 @@ Provides authentication towards Google APIs and identities
|
||||
Implemented types: [OAuthApi](./OAuthApi.md),
|
||||
[OpenIdConnectApi](./OpenIdConnectApi.md),
|
||||
[ProfileInfoApi](./ProfileInfoApi.md),
|
||||
[BackstageIdentityApi](./BackstageIdentityApi.md),
|
||||
[SessionStateApi](./SessionStateApi.md)
|
||||
[BackstageIdentityApi](./BackstageIdentityApi.md), [SessionApi](./SessionApi.md)
|
||||
|
||||
ApiRef:
|
||||
[googleAuthApiRef](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L213)
|
||||
[googleAuthApiRef](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L215)
|
||||
|
||||
### identity
|
||||
|
||||
@@ -115,7 +111,7 @@ Provides access to the identity of the signed in user
|
||||
Implemented type: [IdentityApi](./IdentityApi.md)
|
||||
|
||||
ApiRef:
|
||||
[identityApiRef](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/IdentityApi.ts#L54)
|
||||
[identityApiRef](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/IdentityApi.ts#L54)
|
||||
|
||||
### microsoftAuth
|
||||
|
||||
@@ -124,11 +120,10 @@ Provides authentication towards Microsoft APIs and identities
|
||||
Implemented types: [OAuthApi](./OAuthApi.md),
|
||||
[OpenIdConnectApi](./OpenIdConnectApi.md),
|
||||
[ProfileInfoApi](./ProfileInfoApi.md),
|
||||
[BackstageIdentityApi](./BackstageIdentityApi.md),
|
||||
[SessionStateApi](./SessionStateApi.md)
|
||||
[BackstageIdentityApi](./BackstageIdentityApi.md), [SessionApi](./SessionApi.md)
|
||||
|
||||
ApiRef:
|
||||
[microsoftAuthApiRef](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L287)
|
||||
[microsoftAuthApiRef](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L289)
|
||||
|
||||
### oauth2
|
||||
|
||||
@@ -136,10 +131,11 @@ Example of how to use oauth2 custom provider
|
||||
|
||||
Implemented types: [OAuthApi](./OAuthApi.md),
|
||||
[OpenIdConnectApi](./OpenIdConnectApi.md),
|
||||
[ProfileInfoApi](./ProfileInfoApi.md), [SessionStateApi](./SessionStateApi.md)
|
||||
[ProfileInfoApi](./ProfileInfoApi.md),
|
||||
[BackstageIdentityApi](./BackstageIdentityApi.md), [SessionApi](./SessionApi.md)
|
||||
|
||||
ApiRef:
|
||||
[oauth2ApiRef](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L301)
|
||||
[oauth2ApiRef](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L303)
|
||||
|
||||
### oauthRequest
|
||||
|
||||
@@ -148,7 +144,7 @@ An API for implementing unified OAuth flows in Backstage
|
||||
Implemented type: [OAuthRequestApi](./OAuthRequestApi.md)
|
||||
|
||||
ApiRef:
|
||||
[oauthRequestApiRef](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L130)
|
||||
[oauthRequestApiRef](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/OAuthRequestApi.ts#L130)
|
||||
|
||||
### oktaAuth
|
||||
|
||||
@@ -157,11 +153,10 @@ Provides authentication towards Okta APIs
|
||||
Implemented types: [OAuthApi](./OAuthApi.md),
|
||||
[OpenIdConnectApi](./OpenIdConnectApi.md),
|
||||
[ProfileInfoApi](./ProfileInfoApi.md),
|
||||
[BackstageIdentityApi](./BackstageIdentityApi.md),
|
||||
[SessionStateApi](./SessionStateApi.md)
|
||||
[BackstageIdentityApi](./BackstageIdentityApi.md), [SessionApi](./SessionApi.md)
|
||||
|
||||
ApiRef:
|
||||
[oktaAuthApiRef](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/auth.ts#L243)
|
||||
[oktaAuthApiRef](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L245)
|
||||
|
||||
### storage
|
||||
|
||||
@@ -170,4 +165,4 @@ Provides the ability to store data which is unique to the user
|
||||
Implemented type: [StorageApi](./StorageApi.md)
|
||||
|
||||
ApiRef:
|
||||
[storageApiRef](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/StorageApi.ts#L68)
|
||||
[storageApiRef](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/StorageApi.ts#L68)
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
# SessionApi
|
||||
|
||||
The SessionApi type is defined at
|
||||
[packages/core-api/src/apis/definitions/auth.ts:190](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L190).
|
||||
|
||||
The following Utility APIs implement this type:
|
||||
|
||||
- [auth0AuthApiRef](./README.md#auth0auth)
|
||||
|
||||
- [githubAuthApiRef](./README.md#githubauth)
|
||||
|
||||
- [gitlabAuthApiRef](./README.md#gitlabauth)
|
||||
|
||||
- [googleAuthApiRef](./README.md#googleauth)
|
||||
|
||||
- [microsoftAuthApiRef](./README.md#microsoftauth)
|
||||
|
||||
- [oauth2ApiRef](./README.md#oauth2)
|
||||
|
||||
- [oktaAuthApiRef](./README.md#oktaauth)
|
||||
|
||||
## Members
|
||||
|
||||
### signIn()
|
||||
|
||||
Sign in with a minimum set of permissions.
|
||||
|
||||
<pre>
|
||||
signIn(): Promise<void>
|
||||
</pre>
|
||||
|
||||
### signOut()
|
||||
|
||||
Sign out from the current session. This will reload the page.
|
||||
|
||||
<pre>
|
||||
signOut(): Promise<void>
|
||||
</pre>
|
||||
|
||||
### sessionState\$()
|
||||
|
||||
Observe the current state of the auth session. Emits the current state on
|
||||
subscription.
|
||||
|
||||
<pre>
|
||||
sessionState$(): <a href="#observable">Observable</a><<a href="#sessionstate">SessionState</a>>
|
||||
</pre>
|
||||
|
||||
## Supporting types
|
||||
|
||||
These types are part of the API declaration, but may not be unique to this API.
|
||||
|
||||
### Observable
|
||||
|
||||
Observable sequence of values and errors, see TC39.
|
||||
|
||||
https://github.com/tc39/proposal-observable
|
||||
|
||||
This is used as a common return type for observable values and can be created
|
||||
using many different observable implementations, such as zen-observable or
|
||||
RxJS 5.
|
||||
|
||||
<pre>
|
||||
export type Observable<T> = {
|
||||
/**
|
||||
* Subscribes to this observable to start receiving new values.
|
||||
*/
|
||||
subscribe(observer: <a href="#observer">Observer</a><T>): <a href="#subscription">Subscription</a>;
|
||||
subscribe(
|
||||
onNext: (value: T) => void,
|
||||
onError?: (error: Error) => void,
|
||||
onComplete?: () => void,
|
||||
): <a href="#subscription">Subscription</a>;
|
||||
}
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/types.ts:53](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/types.ts#L53).
|
||||
|
||||
Referenced by: [sessionState\$](#sessionstate).
|
||||
|
||||
### Observer
|
||||
|
||||
This file contains non-react related core types used throught Backstage.
|
||||
|
||||
Observer interface for consuming an Observer, see TC39.
|
||||
|
||||
<pre>
|
||||
export type Observer<T> = {
|
||||
next?(value: T): void;
|
||||
error?(error: Error): void;
|
||||
complete?(): void;
|
||||
}
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/types.ts:24](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/types.ts#L24).
|
||||
|
||||
Referenced by: [Observable](#observable).
|
||||
|
||||
### SessionState
|
||||
|
||||
Session state values passed to subscribers of the SessionApi.
|
||||
|
||||
<pre>
|
||||
export enum SessionState {
|
||||
SignedIn = 'SignedIn',
|
||||
SignedOut = 'SignedOut',
|
||||
}
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/apis/definitions/auth.ts:182](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/auth.ts#L182).
|
||||
|
||||
Referenced by: [sessionState\$](#sessionstate).
|
||||
|
||||
### Subscription
|
||||
|
||||
Subscription returned when subscribing to an Observable, see TC39.
|
||||
|
||||
<pre>
|
||||
export type Subscription = {
|
||||
/**
|
||||
* Cancels the subscription
|
||||
*/
|
||||
unsubscribe(): void;
|
||||
|
||||
/**
|
||||
* Value indicating whether the subscription is closed.
|
||||
*/
|
||||
readonly closed: Boolean;
|
||||
}
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/types.ts:33](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/types.ts#L33).
|
||||
|
||||
Referenced by: [Observable](#observable).
|
||||
@@ -1,7 +1,7 @@
|
||||
# StorageApi
|
||||
|
||||
The StorageApi type is defined at
|
||||
[packages/core-api/src/apis/definitions/StorageApi.ts:31](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/StorageApi.ts#L31).
|
||||
[packages/core-api/src/apis/definitions/StorageApi.ts:31](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/StorageApi.ts#L31).
|
||||
|
||||
The following Utility API implements this type:
|
||||
[storageApiRef](./README.md#storage)
|
||||
@@ -79,7 +79,7 @@ export type Observable<T> = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/types.ts:53](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L53).
|
||||
[packages/core-api/src/types.ts:53](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/types.ts#L53).
|
||||
|
||||
Referenced by: [observe\$](#observe), [StorageApi](#storageapi).
|
||||
|
||||
@@ -98,7 +98,7 @@ export type Observer<T> = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/types.ts:24](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L24).
|
||||
[packages/core-api/src/types.ts:24](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/types.ts#L24).
|
||||
|
||||
Referenced by: [Observable](#observable).
|
||||
|
||||
@@ -144,7 +144,7 @@ export interface StorageApi {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/apis/definitions/StorageApi.ts:31](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/StorageApi.ts#L31).
|
||||
[packages/core-api/src/apis/definitions/StorageApi.ts:31](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/StorageApi.ts#L31).
|
||||
|
||||
Referenced by: [forBucket](#forbucket).
|
||||
|
||||
@@ -158,7 +158,7 @@ export type StorageValueChange<T = any> = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/apis/definitions/StorageApi.ts:21](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/apis/definitions/StorageApi.ts#L21).
|
||||
[packages/core-api/src/apis/definitions/StorageApi.ts:21](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/apis/definitions/StorageApi.ts#L21).
|
||||
|
||||
Referenced by: [observe\$](#observe), [StorageApi](#storageapi).
|
||||
|
||||
@@ -181,6 +181,6 @@ export type Subscription = {
|
||||
</pre>
|
||||
|
||||
Defined at
|
||||
[packages/core-api/src/types.ts:33](https://github.com/spotify/backstage/blob/82d329555c16af46db9b4e5cd2f44a3cc006a52e/packages/core-api/src/types.ts#L33).
|
||||
[packages/core-api/src/types.ts:33](https://github.com/spotify/backstage/blob/0406ace29aba7332a98ff9ef9feedd65adc75223/packages/core-api/src/types.ts#L33).
|
||||
|
||||
Referenced by: [Observable](#observable).
|
||||
|
||||
@@ -187,10 +187,11 @@ builder.add(
|
||||
);
|
||||
```
|
||||
|
||||
> Start the backend and frontend as before. When the browser loads, you should
|
||||
> be presented with a login page for GitHub. Login as usual with your GitHub
|
||||
> account. If this is your first time, you will be asked to authorize and then
|
||||
> are redirected to the catalog page if all is well.
|
||||
8. Start the backend and frontend as before
|
||||
|
||||
When the browser loads, you should be presented with a login page for GitHub.
|
||||
Login as usual with your GitHub account. If this is your first time, you will be
|
||||
asked to authorize and then are redirected to the catalog page if all is well.
|
||||
|
||||
# Where to go from here
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ title: Adding Custom Plugin to Existing Monorepo App
|
||||
1. When the process finishes, let's start the backend:
|
||||
`yarn --cwd packages/backend start`
|
||||
1. If you see errors starting, refer to
|
||||
[Auth Configuration](https://github.com/johnson-jesse/simple-backstage-app/blob/master/README.md#the-auth-configuration)
|
||||
[Auth Configuration](https://backstage.io/docs/tutorials/quickstart-app-auth#the-auth-configuration)
|
||||
for more information on environment variables.
|
||||
1. And now the frontend, from a new terminal window and the root of your
|
||||
project: `yarn start`
|
||||
@@ -119,67 +119,10 @@ If everything is saved, you should see your name, id, and email on the
|
||||
github-playground page. Our data accessed is synchronous. So we just grab and
|
||||
go.
|
||||
|
||||
https://github.com/spotify/backstage/tree/master/contrib
|
||||
|
||||
6. Here is the entire file for reference
|
||||
<details><summary>Complete ExampleComponent.tsx</summary>
|
||||
<p>
|
||||
|
||||
```tsx
|
||||
import React, { FC } from 'react';
|
||||
import { Typography, Grid } from '@material-ui/core';
|
||||
import {
|
||||
InfoCard,
|
||||
Header,
|
||||
Page,
|
||||
pageTheme,
|
||||
Content,
|
||||
ContentHeader,
|
||||
HeaderLabel,
|
||||
SupportButton,
|
||||
identityApiRef,
|
||||
} from '@backstage/core';
|
||||
import { useApi } from '@backstage/core-api';
|
||||
import ExampleFetchComponent from '../ExampleFetchComponent';
|
||||
|
||||
const ExampleComponent: FC<{}> = () => {
|
||||
const identityApi = useApi(identityApiRef);
|
||||
const userId = identityApi.getUserId();
|
||||
const profile = identityApi.getProfile();
|
||||
|
||||
return (
|
||||
<Page theme={pageTheme.tool}>
|
||||
<Header
|
||||
title="Welcome to github-playground!"
|
||||
subtitle="Optional subtitle"
|
||||
>
|
||||
<HeaderLabel label="Owner" value="Team X" />
|
||||
<HeaderLabel label="Lifecycle" value="Alpha" />
|
||||
</Header>
|
||||
<Content>
|
||||
<ContentHeader title="Plugin title">
|
||||
<SupportButton>A description of your plugin goes here.</SupportButton>
|
||||
</ContentHeader>
|
||||
<Grid container spacing={3} direction="column">
|
||||
<Grid item>
|
||||
<InfoCard title={userId}>
|
||||
<Typography variant="body1">
|
||||
{`${profile.displayName} | ${profile.email}`}
|
||||
</Typography>
|
||||
</InfoCard>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<ExampleFetchComponent />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Content>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExampleComponent;
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
[ExampleComponent.tsx](https://github.com/spotify/backstage/tree/master/contrib/docs/tutorials/quickstart-app-plugin/ExampleComponent.md)
|
||||
|
||||
# The Wipe
|
||||
|
||||
@@ -188,7 +131,7 @@ changes, let's start by wiping this component clean.
|
||||
|
||||
1. Start by opening
|
||||
`root: plugins > github-playground > src > components > ExampleFetchComponent > ExampleFetchComponent.tsx`
|
||||
1. Replace everyting in the file with the following:
|
||||
1. Replace everything in the file with the following:
|
||||
|
||||
```tsx
|
||||
import React, { FC } from 'react';
|
||||
@@ -329,8 +272,8 @@ const { value, loading, error } = useAsync(async (): Promise<any> => {
|
||||
}, []);
|
||||
```
|
||||
|
||||
4. The resolved data is conventiently destructured with value containing our
|
||||
Viewer type. loading as a boolean, self explainatory. And error which is
|
||||
4. The resolved data is conveniently destructured with `value` containing our
|
||||
Viewer type. `loading` as a boolean, self explanatory. And `error` which is
|
||||
present only if necessary. So let's use those as the first 3 of 4 multi
|
||||
return statements.
|
||||
5. Add the _if return_ blocks below our async block
|
||||
@@ -358,123 +301,10 @@ return (
|
||||
8. After saving that, and given we don't have any errors, you should see a table
|
||||
with basic information on your repositories.
|
||||
9. Here is the entire file for reference
|
||||
<details><summary>Complete ExampleFetchComponent.tsx</summary>
|
||||
<p>
|
||||
|
||||
```tsx
|
||||
import React, { FC } from 'react';
|
||||
import { useAsync } from 'react-use';
|
||||
import Alert from '@material-ui/lab/Alert';
|
||||
import {
|
||||
Table,
|
||||
TableColumn,
|
||||
Progress,
|
||||
githubAuthApiRef,
|
||||
} from '@backstage/core';
|
||||
import { useApi } from '@backstage/core-api';
|
||||
import { graphql } from '@octokit/graphql';
|
||||
|
||||
const query = `{
|
||||
viewer {
|
||||
repositories(first: 100) {
|
||||
totalCount
|
||||
nodes {
|
||||
name
|
||||
createdAt
|
||||
description
|
||||
diskUsage
|
||||
isFork
|
||||
}
|
||||
pageInfo {
|
||||
endCursor
|
||||
hasNextPage
|
||||
}
|
||||
}
|
||||
}
|
||||
}`;
|
||||
|
||||
type Node = {
|
||||
name: string;
|
||||
createdAt: string;
|
||||
description: string;
|
||||
diskUsage: number;
|
||||
isFork: boolean;
|
||||
};
|
||||
|
||||
type Viewer = {
|
||||
repositories: {
|
||||
totalCount: number;
|
||||
nodes: Node[];
|
||||
pageInfo: {
|
||||
endCursor: string;
|
||||
hasNextPage: boolean;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
type DenseTableProps = {
|
||||
viewer: Viewer;
|
||||
};
|
||||
|
||||
export const DenseTable: FC<DenseTableProps> = ({ viewer }) => {
|
||||
const columns: TableColumn[] = [
|
||||
{ title: 'Name', field: 'name' },
|
||||
{ title: 'Created', field: 'createdAt' },
|
||||
{ title: 'Description', field: 'description' },
|
||||
{ title: 'Disk Usage', field: 'diskUsage' },
|
||||
{ title: 'Fork', field: 'isFork' },
|
||||
];
|
||||
|
||||
return (
|
||||
<Table
|
||||
title="List Of User's Repositories"
|
||||
options={{ search: false, paging: false }}
|
||||
columns={columns}
|
||||
data={viewer.repositories.nodes}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const ExampleFetchComponent: FC<{}> = () => {
|
||||
const auth = useApi(githubAuthApiRef);
|
||||
|
||||
const { value, loading, error } = useAsync(async (): Promise<any> => {
|
||||
const token = await auth.getAccessToken();
|
||||
|
||||
const gqlEndpoint = graphql.defaults({
|
||||
// Uncomment baseUrl if using enterprise
|
||||
// baseUrl: 'https://github.MY-BIZ.com/api',
|
||||
headers: {
|
||||
authorization: `token ${token}`,
|
||||
},
|
||||
});
|
||||
const { viewer } = await gqlEndpoint(query);
|
||||
return viewer;
|
||||
}, []);
|
||||
|
||||
if (loading) return <Progress />;
|
||||
if (error) return <Alert severity="error">{error.message}</Alert>;
|
||||
if (value && value.repositories) return <DenseTable viewer={value} />;
|
||||
|
||||
return (
|
||||
<Table
|
||||
title="List Of User's Repositories"
|
||||
options={{ search: false, paging: false }}
|
||||
columns={[]}
|
||||
data={[]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExampleFetchComponent;
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
10. We finished! If there are no errors, you should see your own GitHub
|
||||
repoistory information displayed in a basic table. If you run into issues,
|
||||
you can compare the repo that backs this documdnt,
|
||||
[ExampleFetchComponent.tsx](https://github.com/spotify/backstage/tree/master/contrib/docs/tutorials/quickstart-app-plugin/ExampleFetchComponent.md)
|
||||
10. We finished! You should see your own GitHub repository's information
|
||||
displayed in a basic table. If you run into issues, you can compare the repo
|
||||
that backs this document,
|
||||
[simple-backstage-app-plugin](https://github.com/johnson-jesse/simple-backstage-app-plugin)
|
||||
|
||||
# Where to go from here
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
title: Backstage has been accepted into the CNCF Sandbox
|
||||
author: Stefan Ålund
|
||||
authorURL: https://twitter.com/stalund
|
||||
---
|
||||
|
||||
**TL;DR** The Cloud Native Computing Foundation (CNCF) announced that Backstage can begin incubating as an early stage project in the [CNCF Sandbox](https://www.cncf.io/sandbox-projects/). Released open source in March, the platform is built around an advanced service catalog and is designed to streamline software development from end to end.
|
||||
|
||||

|
||||
|
||||
<!--truncate-->
|
||||
|
||||
Backstage garnered quite a bit of interest from developers and organizations when it was first announced, and community interest continues to grow as plugins and new features are added with the open source community. We released the open source version of Backstage ‘early’. That was intentional. Because even though we’ve been using Backstage internally for years, we wanted the open source version to be developed with input and contributions from the community. And that’s exactly the product that’s going into the [CNCF Sandbox](https://www.cncf.io/sandbox-projects/) today.
|
||||
|
||||
Backstage’s ability to simplify tooling and standardize engineering practices has attracted interest from other major tech companies, as well as airlines, auto manufacturers, investment firms, and global retailers. We know that Backstage solves a problem — infrastructure complexity — that’s common to a lot of large and growing companies today. But different companies work differently, use particular toolsets, and have unique use cases. By making Backstage open source, we can build it with people working inside a variety of engineering organizations all over the world. It makes for a better product that serves a wider group of users (beyond that of Spotify’s) and their needs.
|
||||
|
||||
The Backstage community is healthy and growing quickly. Over [130 people](https://github.com/spotify/backstage/graphs/contributors) have contributed to the project, and roughly 40% of pull requests are now coming from external, non-Spotify, contributors. With companies now deciding to [adopt Backstage](https://github.com/spotify/backstage/blob/master/ADOPTERS.md) we are also seeing a shift in the kinds of contributions we are getting from the community. It is truly amazing to see contributions to core parts of the platform as well as significant functionality additions through working [plugins](https://backstage.io/plugins).
|
||||
|
||||
We’re excited to embark on this journey with the CNCF community. There’s so much great tech being built here, and it’s about time we share it to build even greater products, together. Entering into the CNCF Sandbox is just the first step. We are committed to working with the community to bring Backstage through the Incubation step, and finally all the way to becoming a Graduated, top-level project.
|
||||
|
||||
Thanks to everyone for your support so far. We hope you [join us](https://mailchi.mp/spotify/backstage-community) in this next chapter of Backstage's journey. If you have questions or feedback, feel free to [email](mailto:alund@spotify.com) me directly.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 810 KiB |
@@ -471,8 +471,8 @@ class Index extends React.Component {
|
||||
Cloud Native Computing Foundation
|
||||
</a>{' '}
|
||||
sandbox project
|
||||
<div className="cncf-logo" />
|
||||
</Block.SmallTitle>
|
||||
<div className="cncf-logo" />
|
||||
</Block.Container>
|
||||
</Block>
|
||||
</main>
|
||||
|
||||
@@ -1072,6 +1072,7 @@ code {
|
||||
}
|
||||
|
||||
.cncf-block {
|
||||
padding-top: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -1080,4 +1081,5 @@ code {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
margin-bottom: 40px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
+2
-1
@@ -21,7 +21,7 @@
|
||||
"docgen": "lerna run docgen",
|
||||
"docker-build:app": "yarn workspace example-app build && docker build . -t spotify/backstage",
|
||||
"docker-build": "yarn tsc && yarn workspace example-backend build-image",
|
||||
"create-plugin": "backstage-cli create-plugin",
|
||||
"create-plugin": "backstage-cli create-plugin --scope backstage --no-private",
|
||||
"remove-plugin": "backstage-cli remove-plugin",
|
||||
"release": "if [ \"$(git symbolic-ref --short HEAD)\" = master ]; then echo \"don't try to release master\"; exit 1; else lerna version --no-push --force-publish; fi",
|
||||
"prettier:check": "prettier --check .",
|
||||
@@ -37,6 +37,7 @@
|
||||
},
|
||||
"version": "1.0.0",
|
||||
"devDependencies": {
|
||||
"@changesets/cli": "2.10.2",
|
||||
"@spotify/eslint-config-oss": "^1.0.1",
|
||||
"@spotify/prettier-config": "^8.0.0",
|
||||
"concurrently": "^5.2.0",
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
"@backstage/plugin-gitops-profiles": "^0.1.1-alpha.22",
|
||||
"@backstage/plugin-graphiql": "^0.1.1-alpha.22",
|
||||
"@backstage/plugin-jenkins": "^0.1.1-alpha.22",
|
||||
"@backstage/plugin-kubernetes": "^0.1.1-alpha.22",
|
||||
"@backstage/plugin-lighthouse": "^0.1.1-alpha.22",
|
||||
"@backstage/plugin-newrelic": "^0.1.1-alpha.22",
|
||||
"@backstage/plugin-register-component": "^0.1.1-alpha.22",
|
||||
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
import { Router as ApiDocsRouter } from '@backstage/plugin-api-docs';
|
||||
import { Router as SentryRouter } from '@backstage/plugin-sentry';
|
||||
import { EmbeddedDocsRouter as DocsRouter } from '@backstage/plugin-techdocs';
|
||||
import { Router as KubernetesRouter } from '@backstage/plugin-kubernetes';
|
||||
import React from 'react';
|
||||
import {
|
||||
AboutCard,
|
||||
@@ -99,6 +100,11 @@ const ServiceEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
title="Docs"
|
||||
element={<DocsRouter entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/kubernetes/*"
|
||||
title="Kubernetes"
|
||||
element={<KubernetesRouter entity={entity} />}
|
||||
/>
|
||||
</EntityPageLayout>
|
||||
);
|
||||
|
||||
@@ -124,6 +130,11 @@ const WebsiteEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
title="Docs"
|
||||
element={<DocsRouter entity={entity} />}
|
||||
/>
|
||||
<EntityPageLayout.Content
|
||||
path="/kubernetes/*"
|
||||
title="Kubernetes"
|
||||
element={<KubernetesRouter entity={entity} />}
|
||||
/>
|
||||
</EntityPageLayout>
|
||||
);
|
||||
const DefaultEntityPage = ({ entity }: { entity: Entity }) => (
|
||||
|
||||
@@ -33,3 +33,4 @@ export { plugin as Jenkins } from '@backstage/plugin-jenkins';
|
||||
export { plugin as ApiDocs } from '@backstage/plugin-api-docs';
|
||||
export { plugin as GithubPullRequests } from '@roadiehq/backstage-plugin-github-pull-requests';
|
||||
export { plugin as GcpProjects } from '@backstage/plugin-gcp-projects';
|
||||
export { plugin as Kubernetes } from '@backstage/plugin-kubernetes';
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"@backstage/plugin-catalog-backend": "^0.1.1-alpha.22",
|
||||
"@backstage/plugin-graphql-backend": "^0.1.1-alpha.22",
|
||||
"@backstage/plugin-identity-backend": "^0.1.1-alpha.22",
|
||||
"@backstage/plugin-kubernetes-backend": "^0.1.1-alpha.22",
|
||||
"@backstage/plugin-proxy-backend": "^0.1.1-alpha.22",
|
||||
"@backstage/plugin-rollbar-backend": "^0.1.1-alpha.22",
|
||||
"@backstage/plugin-scaffolder-backend": "^0.1.1-alpha.22",
|
||||
|
||||
@@ -34,6 +34,7 @@ import healthcheck from './plugins/healthcheck';
|
||||
import auth from './plugins/auth';
|
||||
import catalog from './plugins/catalog';
|
||||
import identity from './plugins/identity';
|
||||
import kubernetes from './plugins/kubernetes';
|
||||
import rollbar from './plugins/rollbar';
|
||||
import scaffolder from './plugins/scaffolder';
|
||||
import sentry from './plugins/sentry';
|
||||
@@ -73,6 +74,7 @@ async function main() {
|
||||
const rollbarEnv = useHotMemoize(module, () => createEnv('rollbar'));
|
||||
const sentryEnv = useHotMemoize(module, () => createEnv('sentry'));
|
||||
const techdocsEnv = useHotMemoize(module, () => createEnv('techdocs'));
|
||||
const kubernetesEnv = useHotMemoize(module, () => createEnv('kubernetes'));
|
||||
const graphqlEnv = useHotMemoize(module, () => createEnv('graphql'));
|
||||
const appEnv = useHotMemoize(module, () => createEnv('app'));
|
||||
|
||||
@@ -86,6 +88,7 @@ async function main() {
|
||||
.addRouter('/auth', await auth(authEnv))
|
||||
.addRouter('/identity', await identity(identityEnv))
|
||||
.addRouter('/techdocs', await techdocs(techdocsEnv))
|
||||
.addRouter('/kubernetes', await kubernetes(kubernetesEnv))
|
||||
.addRouter('/proxy', await proxy(proxyEnv, '/proxy'))
|
||||
.addRouter('/graphql', await graphql(graphqlEnv))
|
||||
.addRouter('', await app(appEnv));
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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 { createRouter } from '@backstage/plugin-kubernetes-backend';
|
||||
import { PluginEnvironment } from '../types';
|
||||
|
||||
export default async function createPlugin({ logger }: PluginEnvironment) {
|
||||
return await createRouter({ logger });
|
||||
}
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
GitlabPublisher,
|
||||
CreateReactAppTemplater,
|
||||
Templaters,
|
||||
RepoVisilityOptions,
|
||||
RepoVisibilityOptions,
|
||||
} from '@backstage/plugin-scaffolder-backend';
|
||||
import { Octokit } from '@octokit/rest';
|
||||
import { Gitlab } from '@gitbeaker/node';
|
||||
@@ -61,7 +61,7 @@ export default async function createPlugin({
|
||||
try {
|
||||
const repoVisibility = githubConfig.getString(
|
||||
'visibility',
|
||||
) as RepoVisilityOptions;
|
||||
) as RepoVisibilityOptions;
|
||||
|
||||
const githubToken = githubConfig.getString('token');
|
||||
const githubClient = new Octokit({ auth: githubToken });
|
||||
|
||||
@@ -21,6 +21,7 @@ import inquirer, { Answers, Question } from 'inquirer';
|
||||
import { exec as execCb } from 'child_process';
|
||||
import { resolve as resolvePath } from 'path';
|
||||
import os from 'os';
|
||||
import { Command } from 'commander';
|
||||
import {
|
||||
parseOwnerIds,
|
||||
addCodeownersEntry,
|
||||
@@ -32,12 +33,12 @@ import { version as backstageVersion } from '../../lib/version';
|
||||
|
||||
const exec = promisify(execCb);
|
||||
|
||||
async function checkExists(rootDir: string, id: string) {
|
||||
await Task.forItem('checking', id, async () => {
|
||||
const destination = resolvePath(rootDir, 'plugins', id);
|
||||
|
||||
async function checkExists(destination: string) {
|
||||
await Task.forItem('checking', destination, async () => {
|
||||
if (await fs.pathExists(destination)) {
|
||||
const existing = chalk.cyan(destination.replace(`${rootDir}/`, ''));
|
||||
const existing = chalk.cyan(
|
||||
destination.replace(`${paths.targetRoot}/`, ''),
|
||||
);
|
||||
throw new Error(
|
||||
`A plugin with the same name already exists: ${existing}\nPlease try again with a different plugin ID`,
|
||||
);
|
||||
@@ -86,10 +87,9 @@ export const addExportStatement = async (
|
||||
|
||||
export async function addPluginDependencyToApp(
|
||||
rootDir: string,
|
||||
pluginName: string,
|
||||
pluginPackage: string,
|
||||
versionStr: string,
|
||||
) {
|
||||
const pluginPackage = `@backstage/plugin-${pluginName}`;
|
||||
const packageFilePath = 'packages/app/package.json';
|
||||
const packageFile = resolvePath(rootDir, packageFilePath);
|
||||
|
||||
@@ -116,8 +116,11 @@ export async function addPluginDependencyToApp(
|
||||
});
|
||||
}
|
||||
|
||||
export async function addPluginToApp(rootDir: string, pluginName: string) {
|
||||
const pluginPackage = `@backstage/plugin-${pluginName}`;
|
||||
export async function addPluginToApp(
|
||||
rootDir: string,
|
||||
pluginName: string,
|
||||
pluginPackage: string,
|
||||
) {
|
||||
const pluginNameCapitalized = pluginName
|
||||
.split('-')
|
||||
.map(name => capitalize(name))
|
||||
@@ -175,7 +178,7 @@ export async function movePlugin(
|
||||
});
|
||||
}
|
||||
|
||||
export default async () => {
|
||||
export default async (cmd: Command) => {
|
||||
const codeownersPath = await getCodeownersFilePath(paths.targetRoot);
|
||||
|
||||
const questions: Question[] = [
|
||||
@@ -221,20 +224,29 @@ export default async () => {
|
||||
}
|
||||
|
||||
const answers: Answers = await inquirer.prompt(questions);
|
||||
|
||||
const name = cmd.scope
|
||||
? `@${cmd.scope.replace(/^@/, '')}/plugin-${answers.id}`
|
||||
: `plugin-${answers.id}`;
|
||||
const npmRegistry = cmd.npmRegistry && cmd.scope ? cmd.npmRegistry : '';
|
||||
const privatePackage = cmd.private === false ? false : true;
|
||||
const isMonoRepo = await fs.pathExists(paths.resolveTargetRoot('lerna.json'));
|
||||
const appPackage = paths.resolveTargetRoot('packages/app');
|
||||
const templateDir = paths.resolveOwn('templates/default-plugin');
|
||||
const tempDir = resolvePath(os.tmpdir(), answers.id);
|
||||
const pluginDir = paths.resolveTargetRoot('plugins', answers.id);
|
||||
const pluginDir = isMonoRepo
|
||||
? paths.resolveTargetRoot('plugins', answers.id)
|
||||
: paths.resolveTargetRoot(answers.id);
|
||||
const ownerIds = parseOwnerIds(answers.owner);
|
||||
const { version } = await fs.readJson(paths.resolveTargetRoot('lerna.json'));
|
||||
const { version } = isMonoRepo
|
||||
? await fs.readJson(paths.resolveTargetRoot('lerna.json'))
|
||||
: { version: '0.1.0' };
|
||||
|
||||
Task.log();
|
||||
Task.log('Creating the plugin...');
|
||||
|
||||
try {
|
||||
Task.section('Checking if the plugin ID is available');
|
||||
await checkExists(paths.targetRoot, answers.id);
|
||||
await checkExists(pluginDir);
|
||||
|
||||
Task.section('Creating a temporary plugin directory');
|
||||
await createTemporaryPluginFolder(tempDir);
|
||||
@@ -244,6 +256,9 @@ export default async () => {
|
||||
...answers,
|
||||
version,
|
||||
backstageVersion,
|
||||
name,
|
||||
privatePackage,
|
||||
npmRegistry,
|
||||
});
|
||||
|
||||
Task.section('Moving to final location');
|
||||
@@ -254,10 +269,10 @@ export default async () => {
|
||||
|
||||
if (await fs.pathExists(appPackage)) {
|
||||
Task.section('Adding plugin as dependency in app');
|
||||
await addPluginDependencyToApp(paths.targetRoot, answers.id, version);
|
||||
await addPluginDependencyToApp(paths.targetRoot, name, version);
|
||||
|
||||
Task.section('Import plugin in app');
|
||||
await addPluginToApp(paths.targetRoot, answers.id);
|
||||
await addPluginToApp(paths.targetRoot, answers.id, name);
|
||||
}
|
||||
|
||||
if (ownerIds && ownerIds.length) {
|
||||
@@ -269,11 +284,7 @@ export default async () => {
|
||||
}
|
||||
|
||||
Task.log();
|
||||
Task.log(
|
||||
`🥇 Successfully created ${chalk.cyan(
|
||||
`@backstage/plugin-${answers.id}`,
|
||||
)}`,
|
||||
);
|
||||
Task.log(`🥇 Successfully created ${chalk.cyan(`${name}`)}`);
|
||||
Task.log();
|
||||
Task.exit();
|
||||
} catch (error) {
|
||||
|
||||
@@ -62,6 +62,9 @@ export function registerCommands(program: CommanderStatic) {
|
||||
program
|
||||
.command('create-plugin')
|
||||
.description('Creates a new plugin in the current repository')
|
||||
.option('--scope <scope>', 'NPM scope')
|
||||
.option('--npm-registry <URL>', 'NPM registry URL')
|
||||
.option('--no-private', 'Public NPM Package')
|
||||
.action(
|
||||
lazy(() => import('./create-plugin/createPlugin').then(m => m.default)),
|
||||
);
|
||||
|
||||
@@ -30,6 +30,9 @@ import { version as backstageVersion } from '../../lib/version';
|
||||
export type PluginData = {
|
||||
id: string;
|
||||
name: string;
|
||||
privatePackage: string;
|
||||
version: string;
|
||||
npmRegistry: string;
|
||||
};
|
||||
|
||||
const fileHandlers = [
|
||||
@@ -62,11 +65,8 @@ export default async (cmd: Command) => {
|
||||
promptFunc = yesPromptFunc;
|
||||
}
|
||||
|
||||
const { version } = await fs.readJson(paths.resolveTargetRoot('lerna.json'));
|
||||
|
||||
const data = await readPluginData();
|
||||
const templateFiles = await diffTemplateFiles('default-plugin', {
|
||||
version,
|
||||
backstageVersion,
|
||||
...data,
|
||||
});
|
||||
@@ -77,9 +77,19 @@ export default async (cmd: Command) => {
|
||||
// Reads templating data from the existing plugin
|
||||
async function readPluginData(): Promise<PluginData> {
|
||||
let name: string;
|
||||
let privatePackage: string;
|
||||
let version: string;
|
||||
let npmRegistry: string;
|
||||
try {
|
||||
const pkg = require(paths.resolveTarget('package.json'));
|
||||
name = pkg.name;
|
||||
privatePackage = pkg.private;
|
||||
version = pkg.version;
|
||||
const scope = name.split('/')[0];
|
||||
if (`${scope}:registry` in pkg.publishConfig) {
|
||||
const registryURL = pkg.publishConfig[`${scope}:registry`];
|
||||
npmRegistry = `"${scope}:registry" : "${registryURL}"`;
|
||||
} else npmRegistry = '';
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to read target package, ${error}`);
|
||||
}
|
||||
@@ -96,5 +106,5 @@ async function readPluginData(): Promise<PluginData> {
|
||||
|
||||
const id = pluginIdMatch[1];
|
||||
|
||||
return { id, name };
|
||||
return { id, name, privatePackage, version, npmRegistry };
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
{
|
||||
"name": "@backstage/plugin-{{id}}",
|
||||
"name": "{{name}}",
|
||||
"version": "{{version}}",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
"private": true,
|
||||
{{#if privatePackage}} "private": {{privatePackage}},
|
||||
{{/if}}
|
||||
"publishConfig": {
|
||||
{{#if npmRegistry}} "registry": "{{npmRegistry}}",
|
||||
{{/if}}
|
||||
"access": "public",
|
||||
"main": "dist/index.esm.js",
|
||||
"types": "dist/index.d.ts"
|
||||
|
||||
@@ -46,9 +46,9 @@ export type IdentityApi = {
|
||||
// TODO: getProfile(): Promise<Profile> - We want this to be async when added, but needs more work.
|
||||
|
||||
/**
|
||||
* Log out the current user
|
||||
* Sign out the current user
|
||||
*/
|
||||
logout(): Promise<void>;
|
||||
signOut(): Promise<void>;
|
||||
};
|
||||
|
||||
export const identityApiRef = createApiRef<IdentityApi>({
|
||||
|
||||
@@ -90,11 +90,6 @@ export type OAuthApi = {
|
||||
scope?: OAuthScope,
|
||||
options?: AuthRequestOptions,
|
||||
): Promise<string>;
|
||||
|
||||
/**
|
||||
* Log out the user's session. This will reload the page.
|
||||
*/
|
||||
logout(): Promise<void>;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -114,11 +109,6 @@ export type OpenIdConnectApi = {
|
||||
* The returned promise can be rejected, but only if the user rejects the login request.
|
||||
*/
|
||||
getIdToken(options?: AuthRequestOptions): Promise<string>;
|
||||
|
||||
/**
|
||||
* Log out the user's session. This will reload the page.
|
||||
*/
|
||||
logout(): Promise<void>;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -187,7 +177,7 @@ export type ProfileInfo = {
|
||||
};
|
||||
|
||||
/**
|
||||
* Session state values passed to subscribers of the SessionStateApi.
|
||||
* Session state values passed to subscribers of the SessionApi.
|
||||
*/
|
||||
export enum SessionState {
|
||||
SignedIn = 'SignedIn',
|
||||
@@ -195,10 +185,22 @@ export enum SessionState {
|
||||
}
|
||||
|
||||
/**
|
||||
* This API provides access to an sessionState$ observable which provides an update when the
|
||||
* user performs a sign in or sign out from an auth provider.
|
||||
* The SessionApi provides basic controls for any auth provider that is tied to a persistent session.
|
||||
*/
|
||||
export type SessionStateApi = {
|
||||
export type SessionApi = {
|
||||
/**
|
||||
* Sign in with a minimum set of permissions.
|
||||
*/
|
||||
signIn(): Promise<void>;
|
||||
|
||||
/**
|
||||
* Sign out from the current session. This will reload the page.
|
||||
*/
|
||||
signOut(): Promise<void>;
|
||||
|
||||
/**
|
||||
* Observe the current state of the auth session. Emits the current state on subscription.
|
||||
*/
|
||||
sessionState$(): Observable<SessionState>;
|
||||
};
|
||||
|
||||
@@ -215,7 +217,7 @@ export const googleAuthApiRef = createApiRef<
|
||||
OpenIdConnectApi &
|
||||
ProfileInfoApi &
|
||||
BackstageIdentityApi &
|
||||
SessionStateApi
|
||||
SessionApi
|
||||
>({
|
||||
id: 'core.auth.google',
|
||||
description: 'Provides authentication towards Google APIs and identities',
|
||||
@@ -228,7 +230,7 @@ export const googleAuthApiRef = createApiRef<
|
||||
* for a full list of supported scopes.
|
||||
*/
|
||||
export const githubAuthApiRef = createApiRef<
|
||||
OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionStateApi
|
||||
OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi
|
||||
>({
|
||||
id: 'core.auth.github',
|
||||
description: 'Provides authentication towards GitHub APIs',
|
||||
@@ -245,7 +247,7 @@ export const oktaAuthApiRef = createApiRef<
|
||||
OpenIdConnectApi &
|
||||
ProfileInfoApi &
|
||||
BackstageIdentityApi &
|
||||
SessionStateApi
|
||||
SessionApi
|
||||
>({
|
||||
id: 'core.auth.okta',
|
||||
description: 'Provides authentication towards Okta APIs',
|
||||
@@ -258,7 +260,7 @@ export const oktaAuthApiRef = createApiRef<
|
||||
* for a full list of supported scopes.
|
||||
*/
|
||||
export const gitlabAuthApiRef = createApiRef<
|
||||
OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionStateApi
|
||||
OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi
|
||||
>({
|
||||
id: 'core.auth.gitlab',
|
||||
description: 'Provides authentication towards GitLab APIs',
|
||||
@@ -271,7 +273,7 @@ export const gitlabAuthApiRef = createApiRef<
|
||||
* for a full list of supported scopes.
|
||||
*/
|
||||
export const auth0AuthApiRef = createApiRef<
|
||||
OpenIdConnectApi & ProfileInfoApi & BackstageIdentityApi & SessionStateApi
|
||||
OpenIdConnectApi & ProfileInfoApi & BackstageIdentityApi & SessionApi
|
||||
>({
|
||||
id: 'core.auth.auth0',
|
||||
description: 'Provides authentication towards Auth0 APIs',
|
||||
@@ -289,7 +291,7 @@ export const microsoftAuthApiRef = createApiRef<
|
||||
OpenIdConnectApi &
|
||||
ProfileInfoApi &
|
||||
BackstageIdentityApi &
|
||||
SessionStateApi
|
||||
SessionApi
|
||||
>({
|
||||
id: 'core.auth.microsoft',
|
||||
description: 'Provides authentication towards Microsoft APIs and identities',
|
||||
@@ -302,8 +304,8 @@ export const oauth2ApiRef = createApiRef<
|
||||
OAuthApi &
|
||||
OpenIdConnectApi &
|
||||
ProfileInfoApi &
|
||||
SessionStateApi &
|
||||
BackstageIdentityApi
|
||||
BackstageIdentityApi &
|
||||
SessionApi
|
||||
>({
|
||||
id: 'core.auth.oauth2',
|
||||
description: 'Example of how to use oauth2 custom provider',
|
||||
|
||||
@@ -19,7 +19,7 @@ import { DefaultAuthConnector } from '../../../../lib/AuthConnector';
|
||||
import { GithubSession } from './types';
|
||||
import {
|
||||
OAuthApi,
|
||||
SessionStateApi,
|
||||
SessionApi,
|
||||
SessionState,
|
||||
ProfileInfo,
|
||||
BackstageIdentity,
|
||||
@@ -61,7 +61,7 @@ const DEFAULT_PROVIDER = {
|
||||
icon: GithubIcon,
|
||||
};
|
||||
|
||||
class GithubAuth implements OAuthApi, SessionStateApi {
|
||||
class GithubAuth implements OAuthApi, SessionApi {
|
||||
static create({
|
||||
discoveryApi,
|
||||
environment = 'development',
|
||||
@@ -102,12 +102,20 @@ class GithubAuth implements OAuthApi, SessionStateApi {
|
||||
return new GithubAuth(authSessionStore);
|
||||
}
|
||||
|
||||
constructor(private readonly sessionManager: SessionManager<GithubSession>) {}
|
||||
|
||||
async signIn() {
|
||||
await this.getAccessToken();
|
||||
}
|
||||
|
||||
async signOut() {
|
||||
await this.sessionManager.removeSession();
|
||||
}
|
||||
|
||||
sessionState$(): Observable<SessionState> {
|
||||
return this.sessionManager.sessionState$();
|
||||
}
|
||||
|
||||
constructor(private readonly sessionManager: SessionManager<GithubSession>) {}
|
||||
|
||||
async getAccessToken(scope?: string, options?: AuthRequestOptions) {
|
||||
const session = await this.sessionManager.getSession({
|
||||
...options,
|
||||
@@ -128,10 +136,6 @@ class GithubAuth implements OAuthApi, SessionStateApi {
|
||||
return session?.profile;
|
||||
}
|
||||
|
||||
async logout() {
|
||||
await this.sessionManager.removeSession();
|
||||
}
|
||||
|
||||
static normalizeScope(scope?: string): Set<string> {
|
||||
if (!scope) {
|
||||
return new Set();
|
||||
|
||||
@@ -32,7 +32,7 @@ import {
|
||||
ProfileInfo,
|
||||
ProfileInfoApi,
|
||||
SessionState,
|
||||
SessionStateApi,
|
||||
SessionApi,
|
||||
BackstageIdentityApi,
|
||||
} from '../../../definitions/auth';
|
||||
import { OAuth2Session } from './types';
|
||||
@@ -75,7 +75,7 @@ class OAuth2
|
||||
OpenIdConnectApi,
|
||||
ProfileInfoApi,
|
||||
BackstageIdentityApi,
|
||||
SessionStateApi {
|
||||
SessionApi {
|
||||
static create({
|
||||
discoveryApi,
|
||||
environment = 'development',
|
||||
@@ -129,6 +129,14 @@ class OAuth2
|
||||
this.scopeTransform = options.scopeTransform;
|
||||
}
|
||||
|
||||
async signIn() {
|
||||
await this.getAccessToken();
|
||||
}
|
||||
|
||||
async signOut() {
|
||||
await this.sessionManager.removeSession();
|
||||
}
|
||||
|
||||
sessionState$(): Observable<SessionState> {
|
||||
return this.sessionManager.sessionState$();
|
||||
}
|
||||
@@ -150,10 +158,6 @@ class OAuth2
|
||||
return session?.providerInfo.idToken ?? '';
|
||||
}
|
||||
|
||||
async logout() {
|
||||
await this.sessionManager.removeSession();
|
||||
}
|
||||
|
||||
async getBackstageIdentity(
|
||||
options: AuthRequestOptions = {},
|
||||
): Promise<BackstageIdentity | undefined> {
|
||||
|
||||
@@ -26,7 +26,7 @@ export class AppIdentity implements IdentityApi {
|
||||
private userId?: string;
|
||||
private profile?: ProfileInfo;
|
||||
private idTokenFunc?: () => Promise<string>;
|
||||
private logoutFunc?: () => Promise<void>;
|
||||
private signOutFunc?: () => Promise<void>;
|
||||
|
||||
getUserId(): string {
|
||||
if (!this.hasIdentity) {
|
||||
@@ -55,13 +55,13 @@ export class AppIdentity implements IdentityApi {
|
||||
return this.idTokenFunc?.();
|
||||
}
|
||||
|
||||
async logout(): Promise<void> {
|
||||
async signOut(): Promise<void> {
|
||||
if (!this.hasIdentity) {
|
||||
throw new Error(
|
||||
'Tried to access IdentityApi logoutFunc before app was loaded',
|
||||
'Tried to access IdentityApi signOutFunc before app was loaded',
|
||||
);
|
||||
}
|
||||
await this.logoutFunc?.();
|
||||
await this.signOutFunc?.();
|
||||
location.reload();
|
||||
}
|
||||
|
||||
@@ -80,6 +80,6 @@ export class AppIdentity implements IdentityApi {
|
||||
this.userId = result.userId;
|
||||
this.profile = result.profile;
|
||||
this.idTokenFunc = result.getIdToken;
|
||||
this.logoutFunc = result.logout;
|
||||
this.signOutFunc = result.signOut;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,10 +38,11 @@ export type SignInResult = {
|
||||
* Function used to retrieve an ID token for the signed in user.
|
||||
*/
|
||||
getIdToken?: () => Promise<string>;
|
||||
|
||||
/**
|
||||
* Logout handler that will be called if the user requests a logout.
|
||||
* Sign out handler that will be called if the user requests to sign out.
|
||||
*/
|
||||
logout?: () => Promise<void>;
|
||||
signOut?: () => Promise<void>;
|
||||
};
|
||||
|
||||
export type SignInPageProps = {
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/config": "^0.1.1-alpha.22",
|
||||
"@backstage/core-api": "^0.1.1-alpha.22",
|
||||
"@backstage/core-api": "0.1.1-alpha.22",
|
||||
"@backstage/theme": "^0.1.1-alpha.22",
|
||||
"@material-ui/core": "^4.11.0",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
|
||||
@@ -37,6 +37,7 @@ const useStyles = makeStyles(theme => ({
|
||||
},
|
||||
},
|
||||
header: {
|
||||
display: 'inline-block',
|
||||
padding: theme.spacing(2, 2, 2, 2.5),
|
||||
},
|
||||
headerTitle: {
|
||||
@@ -202,7 +203,7 @@ export const InfoCard = ({
|
||||
}}
|
||||
title={title}
|
||||
subheader={subheader}
|
||||
style={{ display: 'inline-block', ...headerStyle }}
|
||||
style={{ ...headerStyle }}
|
||||
{...headerProps}
|
||||
/>
|
||||
<Divider />
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
} from '@backstage/core-api';
|
||||
import Star from '@material-ui/icons/Star';
|
||||
import React from 'react';
|
||||
import { OAuthProviderSettings, OIDCProviderSettings } from './Settings';
|
||||
import { ProviderSettingsItem } from './Settings';
|
||||
|
||||
export const DefaultProviderSettings = () => {
|
||||
const configApi = useApi(configApiRef);
|
||||
@@ -35,42 +35,42 @@ export const DefaultProviderSettings = () => {
|
||||
return (
|
||||
<>
|
||||
{providers.includes('google') && (
|
||||
<OIDCProviderSettings
|
||||
<ProviderSettingsItem
|
||||
title="Google"
|
||||
apiRef={googleAuthApiRef}
|
||||
icon={Star}
|
||||
/>
|
||||
)}
|
||||
{providers.includes('microsoft') && (
|
||||
<OIDCProviderSettings
|
||||
<ProviderSettingsItem
|
||||
title="Microsoft"
|
||||
apiRef={microsoftAuthApiRef}
|
||||
icon={Star}
|
||||
/>
|
||||
)}
|
||||
{providers.includes('github') && (
|
||||
<OAuthProviderSettings
|
||||
<ProviderSettingsItem
|
||||
title="Github"
|
||||
apiRef={githubAuthApiRef}
|
||||
icon={Star}
|
||||
/>
|
||||
)}
|
||||
{providers.includes('gitlab') && (
|
||||
<OAuthProviderSettings
|
||||
<ProviderSettingsItem
|
||||
title="Gitlab"
|
||||
apiRef={gitlabAuthApiRef}
|
||||
icon={Star}
|
||||
/>
|
||||
)}
|
||||
{providers.includes('okta') && (
|
||||
<OIDCProviderSettings
|
||||
<ProviderSettingsItem
|
||||
title="Okta"
|
||||
apiRef={oktaAuthApiRef}
|
||||
icon={Star}
|
||||
/>
|
||||
)}
|
||||
{providers.includes('oauth2') && (
|
||||
<OIDCProviderSettings
|
||||
<ProviderSettingsItem
|
||||
title="YourOrg"
|
||||
apiRef={oauth2ApiRef}
|
||||
icon={Star}
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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,
|
||||
OAuthApi,
|
||||
SessionStateApi,
|
||||
useApi,
|
||||
Subscription,
|
||||
IconComponent,
|
||||
SessionState,
|
||||
} from '@backstage/core-api';
|
||||
import React, { FC, useState, useEffect } from 'react';
|
||||
import { ProviderSettingsItem } from './ProviderSettingsItem';
|
||||
|
||||
type OAuthProviderSidebarProps = {
|
||||
title: string;
|
||||
icon: IconComponent;
|
||||
apiRef: ApiRef<OAuthApi & SessionStateApi>;
|
||||
};
|
||||
|
||||
export const OAuthProviderSettings: FC<OAuthProviderSidebarProps> = ({
|
||||
title,
|
||||
icon,
|
||||
apiRef,
|
||||
}) => {
|
||||
const api = useApi(apiRef);
|
||||
const [signedIn, setSignedIn] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
let didCancel = false;
|
||||
|
||||
const checkSession = async () => {
|
||||
const session = await api.getAccessToken('', { optional: true });
|
||||
if (!didCancel) {
|
||||
setSignedIn(!!session);
|
||||
}
|
||||
};
|
||||
let subscription: Subscription;
|
||||
const observeSession = () => {
|
||||
subscription = api
|
||||
.sessionState$()
|
||||
.subscribe((sessionState: SessionState) => {
|
||||
if (!didCancel) {
|
||||
setSignedIn(sessionState === SessionState.SignedIn);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
checkSession();
|
||||
observeSession();
|
||||
return () => {
|
||||
didCancel = true;
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
}, [api]);
|
||||
|
||||
return (
|
||||
<ProviderSettingsItem
|
||||
title={title}
|
||||
icon={icon}
|
||||
signedIn={signedIn}
|
||||
api={api}
|
||||
signInHandler={() => api.getAccessToken()}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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,
|
||||
OpenIdConnectApi,
|
||||
SessionStateApi,
|
||||
useApi,
|
||||
Subscription,
|
||||
IconComponent,
|
||||
SessionState,
|
||||
} from '@backstage/core-api';
|
||||
import React, { FC, useState, useEffect } from 'react';
|
||||
import { ProviderSettingsItem } from './ProviderSettingsItem';
|
||||
|
||||
export type OIDCProviderSidebarProps = {
|
||||
title: string;
|
||||
icon: IconComponent;
|
||||
apiRef: ApiRef<OpenIdConnectApi & SessionStateApi>;
|
||||
};
|
||||
|
||||
export const OIDCProviderSettings: FC<OIDCProviderSidebarProps> = ({
|
||||
title,
|
||||
icon,
|
||||
apiRef,
|
||||
}) => {
|
||||
const api = useApi(apiRef);
|
||||
const [signedIn, setSignedIn] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
let didCancel = false;
|
||||
|
||||
const checkSession = async () => {
|
||||
const session = await api.getIdToken({ optional: true });
|
||||
if (!didCancel) {
|
||||
setSignedIn(!!session);
|
||||
}
|
||||
};
|
||||
|
||||
let subscription: Subscription;
|
||||
const observeSession = () => {
|
||||
subscription = api
|
||||
.sessionState$()
|
||||
.subscribe((sessionState: SessionState) => {
|
||||
if (!didCancel) {
|
||||
setSignedIn(sessionState === SessionState.SignedIn);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
checkSession();
|
||||
observeSession();
|
||||
return () => {
|
||||
didCancel = true;
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
}, [api]);
|
||||
|
||||
return (
|
||||
<ProviderSettingsItem
|
||||
title={title}
|
||||
icon={icon}
|
||||
signedIn={signedIn}
|
||||
api={api}
|
||||
signInHandler={() => api.getIdToken()}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -14,8 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { IconComponent, OAuthApi, OpenIdConnectApi } from '@backstage/core-api';
|
||||
import React, { FC, useState, useEffect } from 'react';
|
||||
import {
|
||||
ListItem,
|
||||
ListItemIcon,
|
||||
@@ -25,42 +24,67 @@ import {
|
||||
} from '@material-ui/core';
|
||||
import PowerButton from '@material-ui/icons/PowerSettingsNew';
|
||||
import { ToggleButton } from '@material-ui/lab';
|
||||
import {
|
||||
ApiRef,
|
||||
SessionApi,
|
||||
useApi,
|
||||
IconComponent,
|
||||
SessionState,
|
||||
} from '@backstage/core-api';
|
||||
|
||||
type Props = {
|
||||
type OAuthProviderSidebarProps = {
|
||||
title: string;
|
||||
icon: IconComponent;
|
||||
signedIn: boolean;
|
||||
api: OAuthApi | OpenIdConnectApi;
|
||||
signInHandler: Function;
|
||||
apiRef: ApiRef<SessionApi>;
|
||||
};
|
||||
|
||||
export const ProviderSettingsItem = ({
|
||||
export const ProviderSettingsItem: FC<OAuthProviderSidebarProps> = ({
|
||||
title,
|
||||
icon: Icon,
|
||||
signedIn,
|
||||
api,
|
||||
signInHandler,
|
||||
}: Props) => (
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<Icon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={title} />
|
||||
<ListItemSecondaryAction>
|
||||
<ToggleButton
|
||||
size="small"
|
||||
value={title}
|
||||
selected={signedIn}
|
||||
onChange={() => (signedIn ? api.logout() : signInHandler())}
|
||||
>
|
||||
<Tooltip
|
||||
placement="top"
|
||||
arrow
|
||||
title={signedIn ? `Sign out from ${title}` : `Sign in to ${title}`}
|
||||
apiRef,
|
||||
}) => {
|
||||
const api = useApi(apiRef);
|
||||
const [signedIn, setSignedIn] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
let didCancel = false;
|
||||
|
||||
const subscription = api
|
||||
.sessionState$()
|
||||
.subscribe((sessionState: SessionState) => {
|
||||
if (!didCancel) {
|
||||
setSignedIn(sessionState === SessionState.SignedIn);
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
didCancel = true;
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
}, [api]);
|
||||
|
||||
return (
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<Icon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={title} />
|
||||
<ListItemSecondaryAction>
|
||||
<ToggleButton
|
||||
size="small"
|
||||
value={title}
|
||||
selected={signedIn}
|
||||
onChange={() => (signedIn ? api.signOut() : api.signIn())}
|
||||
>
|
||||
<PowerButton />
|
||||
</Tooltip>
|
||||
</ToggleButton>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItem>
|
||||
);
|
||||
<Tooltip
|
||||
placement="top"
|
||||
arrow
|
||||
title={signedIn ? `Sign out from ${title}` : `Sign in to ${title}`}
|
||||
>
|
||||
<PowerButton />
|
||||
</Tooltip>
|
||||
</ToggleButton>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItem>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -43,7 +43,7 @@ export const UserSettingsMenu = () => {
|
||||
<MoreVertIcon />
|
||||
</IconButton>
|
||||
<Menu anchorEl={anchorEl} open={open} onClose={handleClose}>
|
||||
<MenuItem onClick={() => identityApi.logout()}>
|
||||
<MenuItem onClick={() => identityApi.signOut()}>
|
||||
<ListItemIcon>
|
||||
<SignOutIcon />
|
||||
</ListItemIcon>
|
||||
|
||||
@@ -15,6 +15,4 @@
|
||||
*/
|
||||
|
||||
export { ProviderSettingsItem } from './ProviderSettingsItem';
|
||||
export { OAuthProviderSettings } from './OAuthProviderSettings';
|
||||
export { OIDCProviderSettings } from './OIDCProviderSettings';
|
||||
export { SidebarUserSettings } from './UserSettings';
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
SidebarSearchField,
|
||||
SidebarSpace,
|
||||
SidebarUserSettings,
|
||||
OAuthProviderSettings,
|
||||
ProviderSettingsItem,
|
||||
} from '.';
|
||||
import HomeOutlinedIcon from '@material-ui/icons/HomeOutlined';
|
||||
import AddCircleOutlineIcon from '@material-ui/icons/AddCircleOutline';
|
||||
@@ -60,7 +60,7 @@ export const SampleSidebar = () => (
|
||||
<SidebarDivider />
|
||||
<SidebarUserSettings
|
||||
providerSettings={
|
||||
<OAuthProviderSettings
|
||||
<ProviderSettingsItem
|
||||
title="Github"
|
||||
apiRef={githubAuthApiRef}
|
||||
icon={Star}
|
||||
|
||||
@@ -37,8 +37,8 @@ const Component: ProviderComponent = ({ onResult }) => {
|
||||
profile: profile!,
|
||||
getIdToken: () =>
|
||||
auth0AuthApi.getBackstageIdentity().then(i => i!.idToken),
|
||||
logout: async () => {
|
||||
await auth0AuthApi.logout();
|
||||
signOut: async () => {
|
||||
await auth0AuthApi.signOut();
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
@@ -79,8 +79,8 @@ const loader: ProviderLoader = async apis => {
|
||||
userId: identity.id,
|
||||
profile: profile!,
|
||||
getIdToken: () => auth0AuthApi.getBackstageIdentity().then(i => i!.idToken),
|
||||
logout: async () => {
|
||||
await auth0AuthApi.logout();
|
||||
signOut: async () => {
|
||||
await auth0AuthApi.signOut();
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -44,8 +44,8 @@ const Component: ProviderComponent = ({ config, onResult }) => {
|
||||
getIdToken: () => {
|
||||
return authApi.getBackstageIdentity().then(i => i!.idToken);
|
||||
},
|
||||
logout: async () => {
|
||||
await authApi.logout();
|
||||
signOut: async () => {
|
||||
await authApi.signOut();
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
@@ -87,8 +87,8 @@ const loader: ProviderLoader = async (apis, apiRef) => {
|
||||
userId: identity.id,
|
||||
profile: profile!,
|
||||
getIdToken: () => authApi.getBackstageIdentity().then(i => i!.idToken),
|
||||
logout: async () => {
|
||||
await authApi.logout();
|
||||
signOut: async () => {
|
||||
await authApi.signOut();
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -83,14 +83,14 @@ export const useSignInProviders = (
|
||||
const apiHolder = useApiHolder();
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
// This decorates the result with logout logic from this hook
|
||||
// This decorates the result with sign out logic from this hook
|
||||
const handleWrappedResult = useCallback(
|
||||
(result: SignInResult) => {
|
||||
onResult({
|
||||
...result,
|
||||
logout: async () => {
|
||||
signOut: async () => {
|
||||
localStorage.removeItem(PROVIDER_STORAGE_KEY);
|
||||
await result.logout?.();
|
||||
await result.signOut?.();
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
@@ -20,19 +20,16 @@ import {
|
||||
SignInResult,
|
||||
ApiHolder,
|
||||
ApiRef,
|
||||
OAuthApi,
|
||||
ProfileInfoApi,
|
||||
BackstageIdentityApi,
|
||||
SessionStateApi,
|
||||
SessionApi,
|
||||
} from '@backstage/core-api';
|
||||
|
||||
export type SignInConfig = {
|
||||
id: string;
|
||||
title: string;
|
||||
message: string;
|
||||
apiRef: ApiRef<
|
||||
OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionStateApi
|
||||
>;
|
||||
apiRef: ApiRef<ProfileInfoApi & BackstageIdentityApi & SessionApi>;
|
||||
};
|
||||
|
||||
export type IdentityProviders = ('guest' | 'custom' | SignInConfig)[];
|
||||
@@ -43,9 +40,7 @@ export type ProviderComponent = ComponentType<
|
||||
|
||||
export type ProviderLoader = (
|
||||
apis: ApiHolder,
|
||||
apiRef: ApiRef<
|
||||
OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionStateApi
|
||||
>,
|
||||
apiRef: ApiRef<ProfileInfoApi & BackstageIdentityApi & SessionApi>,
|
||||
) => Promise<SignInResult | undefined>;
|
||||
|
||||
export type SignInProvider = {
|
||||
|
||||
+1
-2
@@ -1,4 +1,3 @@
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
@@ -31,4 +30,4 @@ dist-types
|
||||
site
|
||||
|
||||
# Local configuration files
|
||||
*.local.yaml
|
||||
*.local.yaml
|
||||
@@ -16,7 +16,7 @@
|
||||
"test:all": "lerna run test -- --coverage",
|
||||
"lint": "lerna run lint --since origin/master --",
|
||||
"lint:all": "lerna run lint --",
|
||||
"create-plugin": "backstage-cli create-plugin",
|
||||
"create-plugin": "backstage-cli create-plugin --scope backstage --no-private",
|
||||
"remove-plugin": "backstage-cli remove-plugin"
|
||||
},
|
||||
"workspaces": {
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ import {
|
||||
GitlabPublisher,
|
||||
CreateReactAppTemplater,
|
||||
Templaters,
|
||||
RepoVisilityOptions,
|
||||
RepoVisibilityOptions,
|
||||
} from '@backstage/plugin-scaffolder-backend';
|
||||
import { Octokit } from '@octokit/rest';
|
||||
import { Gitlab } from '@gitbeaker/node';
|
||||
@@ -42,7 +42,7 @@ export default async function createPlugin({
|
||||
const githubToken = config.getString('scaffolder.github.token');
|
||||
const repoVisibility = config.getString(
|
||||
'scaffolder.github.visibility',
|
||||
) as RepoVisilityOptions;
|
||||
) as RepoVisibilityOptions;
|
||||
|
||||
const githubClient = new Octokit({ auth: githubToken });
|
||||
const githubPublisher = new GithubPublisher({
|
||||
|
||||
@@ -81,7 +81,11 @@ async function buildDistWorkspace(workspaceName: string, rootDir: string) {
|
||||
const path = paths.resolveOwnRoot(pkgJsonPath);
|
||||
const pkgTemplate = await fs.readFile(path, 'utf8');
|
||||
const { dependencies = {}, devDependencies = {} } = JSON.parse(
|
||||
handlebars.compile(pkgTemplate)({ version: '0.0.0' }),
|
||||
handlebars.compile(pkgTemplate)({
|
||||
version: '0.0.0',
|
||||
privatePackage: true,
|
||||
scopeName: '@backstage',
|
||||
}),
|
||||
);
|
||||
|
||||
Array<string>()
|
||||
|
||||
@@ -36,7 +36,7 @@ builder.add(identityApiRef, {
|
||||
getUserId: () => 'guest',
|
||||
getProfile: () => ({ email: 'guest@example.com' }),
|
||||
getIdToken: () => undefined,
|
||||
logout: async () => {},
|
||||
signOut: async () => {},
|
||||
});
|
||||
|
||||
const oauthRequestApi = builder.add(
|
||||
|
||||
@@ -18,7 +18,7 @@ FROM python:3.8-alpine
|
||||
RUN apk update && apk --no-cache add gcc musl-dev openjdk11-jdk curl graphviz ttf-dejavu fontconfig
|
||||
|
||||
RUN curl -L http://sourceforge.net/projects/plantuml/files/plantuml.1.2020.16.jar/download > /opt/plantuml.jar
|
||||
RUN pip install --upgrade pip && pip install mkdocs-techdocs-core==0.0.7
|
||||
RUN pip install --upgrade pip && pip install mkdocs-techdocs-core==0.0.8
|
||||
|
||||
# Create script to call plantuml.jar from a location in path
|
||||
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
!!! test
|
||||
Testing somethin
|
||||
|
||||
Abbreviations:
|
||||
Some text about MOCDOC
|
||||
|
||||
\*[MOCDOC]: Mock Documentation
|
||||
|
||||
This is a paragraph.
|
||||
{: #test_id .test_class }
|
||||
|
||||
@@ -61,3 +60,40 @@ digraph G {
|
||||
```
|
||||
|
||||
:bulb:
|
||||
|
||||
=== "JavaScript"
|
||||
|
||||
```javascript
|
||||
import { test } from 'something';
|
||||
|
||||
const addThingToThing = (a, b) a + b;
|
||||
```
|
||||
|
||||
=== "Java"
|
||||
|
||||
```java
|
||||
public void function() {
|
||||
test();
|
||||
}
|
||||
```
|
||||
|
||||
```java tab="java"
|
||||
public void function() {
|
||||
test();
|
||||
}
|
||||
```
|
||||
|
||||
```java tab="java 2"
|
||||
public void function() {
|
||||
test();
|
||||
}
|
||||
```
|
||||
|
||||
```javascript
|
||||
import { test } from 'something';
|
||||
|
||||
const addThingToThing = (a, b) a + b;
|
||||
```
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
*[MOCDOC]: Mock Documentation
|
||||
|
||||
@@ -48,8 +48,72 @@ python -m black src/
|
||||
|
||||
**Note:** This will write to all Python files in `src/` with the formatted code. If you would like to only check to see if it passes, simply append the `--check` flag.
|
||||
|
||||
## MkDocs plugins and extensions
|
||||
|
||||
The TechDocs Core MkDocs plugin comes with a set of extensions and plugins that mkdocs supports. Below you can find a list of all extensions and plugins that are included in the
|
||||
TechDocs Core plugin:
|
||||
|
||||
Plugins:
|
||||
|
||||
- [search](https://www.mkdocs.org/user-guide/configuration/#search)
|
||||
- [mkdocs-monorepo-plugin](https://github.com/spotify/mkdocs-monorepo-plugin)
|
||||
|
||||
Extensions:
|
||||
|
||||
- [admonition](https://squidfunk.github.io/mkdocs-material/reference/admonitions/#admonitions)
|
||||
- [toc](https://python-markdown.github.io/extensions/toc/)
|
||||
- [pymdown](https://facelessuser.github.io/pymdown-extensions/)
|
||||
- caret
|
||||
- critic
|
||||
- details
|
||||
- emoji
|
||||
- superfences
|
||||
- inlinehilite
|
||||
- magiclink
|
||||
- mark
|
||||
- smartsymobls
|
||||
- highlight
|
||||
- extra
|
||||
- tabbed
|
||||
- tasklist
|
||||
- tilde
|
||||
- [markdown_inline_graphviz](https://pypi.org/project/markdown-inline-graphviz/)
|
||||
- [plantuml_markdown](https://pypi.org/project/plantuml-markdown/)
|
||||
|
||||
## Changelog
|
||||
|
||||
### 0.0.8
|
||||
|
||||
- Superfences and Codehilite doesn't work very well together (squidfunk/mkdocs-material#1604) so therefore the codehilite extension is replaced by pymdownx.highlight
|
||||
|
||||
* Uses pymdownx extensions v.7.1 instead of 8.0.0 to allow legacy_tab_classes config. This makes the techdocs core plugin compatible with the usage of tabs for grouping markdown with the following syntax:
|
||||
|
||||
````
|
||||
```java tab="java 2"
|
||||
public void function() {
|
||||
....
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
as well as the new
|
||||
|
||||
````
|
||||
=== "Java"
|
||||
|
||||
```java
|
||||
public void function() {
|
||||
....
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
The pymdownx extension will be bumped too 8.0.0 in the near future.
|
||||
|
||||
- pymdownx.tabbed is added to support tabs to group markdown content, such as codeblocks.
|
||||
|
||||
- "PyMdown Extensions includes three extensions that are meant to replace their counterpart in the default Python Markdown extensions." Therefore some extensions has been taken away in this version that comes by default from pymdownx.extra which is added now (https://facelessuser.github.io/pymdown-extensions/usage_notes/#incompatible-extensions)
|
||||
|
||||
### 0.0.7
|
||||
|
||||
- Fix an issue with configuration of emoji support
|
||||
|
||||
@@ -7,7 +7,7 @@ mkdocs-monorepo-plugin==0.4.5
|
||||
plantuml-markdown==3.1.2
|
||||
markdown_inline_graphviz_extension==1.1
|
||||
pygments==2.6.1
|
||||
pymdown-extensions==8.0.0
|
||||
pymdown-extensions==7.1
|
||||
|
||||
# The linter using for Python
|
||||
# Note: This requires Python 3.6+ to run, but can format Python 2 code too.
|
||||
|
||||
@@ -17,38 +17,34 @@ from setuptools import setup, find_packages
|
||||
|
||||
|
||||
setup(
|
||||
name='mkdocs-techdocs-core',
|
||||
version='0.0.7',
|
||||
description='A Mkdocs package that contains TechDocs defaults',
|
||||
long_description='',
|
||||
keywords='mkdocs',
|
||||
url='https://github.com/spotify/backstage',
|
||||
author='TechDocs Core',
|
||||
author_email='pulp-fiction@spotify.com',
|
||||
license='Apache-2.0',
|
||||
python_requires='>=3.7',
|
||||
name="mkdocs-techdocs-core",
|
||||
version="0.0.8",
|
||||
description="A Mkdocs package that contains TechDocs defaults",
|
||||
long_description="",
|
||||
keywords="mkdocs",
|
||||
url="https://github.com/spotify/backstage",
|
||||
author="TechDocs Core",
|
||||
author_email="pulp-fiction@spotify.com",
|
||||
license="Apache-2.0",
|
||||
python_requires=">=3.7",
|
||||
install_requires=[
|
||||
'mkdocs>=1.1.2',
|
||||
'mkdocs-material==5.3.2',
|
||||
'mkdocs-monorepo-plugin==0.4.5',
|
||||
'plantuml-markdown==3.1.2',
|
||||
'markdown_inline_graphviz_extension==1.1',
|
||||
'pygments==2.6.1',
|
||||
'pymdown-extensions==8.0.0'
|
||||
"mkdocs>=1.1.2",
|
||||
"mkdocs-material==5.3.2",
|
||||
"mkdocs-monorepo-plugin==0.4.5",
|
||||
"plantuml-markdown==3.1.2",
|
||||
"markdown_inline_graphviz_extension==1.1",
|
||||
"pygments==2.6.1",
|
||||
"pymdown-extensions==7.1",
|
||||
],
|
||||
classifiers=[
|
||||
'Development Status :: 1 - Planning',
|
||||
'Intended Audience :: Developers',
|
||||
'Intended Audience :: Information Technology',
|
||||
'License :: OSI Approved :: Apache Software License',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 3 :: Only',
|
||||
'Programming Language :: Python :: 3.7'
|
||||
"Development Status :: 1 - Planning",
|
||||
"Intended Audience :: Developers",
|
||||
"Intended Audience :: Information Technology",
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
],
|
||||
packages=find_packages(),
|
||||
entry_points={
|
||||
'mkdocs.plugins': [
|
||||
'techdocs-core = src.core:TechDocsCore'
|
||||
]
|
||||
}
|
||||
entry_points={"mkdocs.plugins": ["techdocs-core = src.core:TechDocsCore"]},
|
||||
)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
"""
|
||||
|
||||
from mkdocs.plugins import BasePlugin, PluginCollection
|
||||
from mkdocs.plugins import BasePlugin
|
||||
from mkdocs.theme import Theme
|
||||
from mkdocs.contrib.search import SearchPlugin
|
||||
from mkdocs_monorepo_plugin.plugin import MonorepoPlugin
|
||||
@@ -54,25 +54,11 @@ class TechDocsCore(BasePlugin):
|
||||
|
||||
# Markdown Extensions
|
||||
config["markdown_extensions"].append("admonition")
|
||||
config["markdown_extensions"].append("abbr")
|
||||
config["markdown_extensions"].append("attr_list")
|
||||
config["markdown_extensions"].append("def_list")
|
||||
config["markdown_extensions"].append("codehilite")
|
||||
config["mdx_configs"]["codehilite"] = {
|
||||
"linenums": True,
|
||||
"guess_lang": False,
|
||||
"pygments_style": "friendly",
|
||||
}
|
||||
config["markdown_extensions"].append("toc")
|
||||
config["mdx_configs"]["toc"] = {
|
||||
"permalink": True,
|
||||
}
|
||||
config["markdown_extensions"].append("footnotes")
|
||||
config["markdown_extensions"].append("markdown.extensions.tables")
|
||||
config["markdown_extensions"].append("pymdownx.betterem")
|
||||
config["mdx_configs"]["pymdownx.betterem"] = {
|
||||
"smart_enable": "all",
|
||||
}
|
||||
|
||||
config["markdown_extensions"].append("pymdownx.caret")
|
||||
config["markdown_extensions"].append("pymdownx.critic")
|
||||
config["markdown_extensions"].append("pymdownx.details")
|
||||
@@ -83,6 +69,18 @@ class TechDocsCore(BasePlugin):
|
||||
config["markdown_extensions"].append("pymdownx.mark")
|
||||
config["markdown_extensions"].append("pymdownx.smartsymbols")
|
||||
config["markdown_extensions"].append("pymdownx.superfences")
|
||||
config["mdx_configs"]["pymdownx.superfences"] = {
|
||||
"legacy_tab_classes": True,
|
||||
}
|
||||
config["markdown_extensions"].append("pymdownx.highlight")
|
||||
config["mdx_configs"]["pymdownx.highlight"] = {
|
||||
"linenums": True,
|
||||
}
|
||||
config["markdown_extensions"].append("pymdownx.extra")
|
||||
config["mdx_configs"]["pymdownx.betterem"] = {
|
||||
"smart_enable": "all",
|
||||
}
|
||||
config["markdown_extensions"].append("pymdownx.tabbed")
|
||||
config["markdown_extensions"].append("pymdownx.tasklist")
|
||||
config["mdx_configs"]["pymdownx.tasklist"] = {
|
||||
"custom_checkbox": True,
|
||||
|
||||
@@ -58,7 +58,7 @@ describe('Catalog Filter', () => {
|
||||
] as Entity[]),
|
||||
};
|
||||
|
||||
const indentityApi: Partial<IdentityApi> = {
|
||||
const identityApi: Partial<IdentityApi> = {
|
||||
getUserId: () => 'tools@example.com',
|
||||
};
|
||||
|
||||
@@ -68,7 +68,7 @@ describe('Catalog Filter', () => {
|
||||
<ApiProvider
|
||||
apis={ApiRegistry.from([
|
||||
[catalogApiRef, catalogApi],
|
||||
[identityApiRef, indentityApi],
|
||||
[identityApiRef, identityApi],
|
||||
[storageApiRef, MockStorageApi.create()],
|
||||
])}
|
||||
>
|
||||
|
||||
@@ -46,6 +46,9 @@ const useStyles = makeStyles(theme => ({
|
||||
gridTemplateColumns: '250px 1fr',
|
||||
gridColumnGap: theme.spacing(2),
|
||||
},
|
||||
buttonSpacing: {
|
||||
marginLeft: theme.spacing(2),
|
||||
},
|
||||
}));
|
||||
|
||||
const CatalogPageContents = () => {
|
||||
@@ -56,6 +59,7 @@ const CatalogPageContents = () => {
|
||||
reload,
|
||||
matchingEntities,
|
||||
availableTags,
|
||||
isCatalogEmpty,
|
||||
} = useFilteredEntities();
|
||||
const configApi = useApi(configApiRef);
|
||||
const catalogApi = useApi(catalogApiRef);
|
||||
@@ -141,6 +145,9 @@ const CatalogPageContents = () => {
|
||||
[isStarredEntity, userId, orgName],
|
||||
);
|
||||
|
||||
const showAddExampleEntities =
|
||||
configApi.has('catalog.exampleEntityLocations') && isCatalogEmpty;
|
||||
|
||||
return (
|
||||
<CatalogLayout>
|
||||
<CatalogTabs
|
||||
@@ -158,6 +165,16 @@ const CatalogPageContents = () => {
|
||||
>
|
||||
Create Component
|
||||
</Button>
|
||||
{showAddExampleEntities && (
|
||||
<Button
|
||||
className={styles.buttonSpacing}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={addMockData}
|
||||
>
|
||||
Add example components
|
||||
</Button>
|
||||
)}
|
||||
<SupportButton>All your software catalog entities</SupportButton>
|
||||
</ContentHeader>
|
||||
<div className={styles.contentWrapper}>
|
||||
@@ -174,7 +191,6 @@ const CatalogPageContents = () => {
|
||||
entities={matchingEntities}
|
||||
loading={loading}
|
||||
error={error}
|
||||
onAddMockData={addMockData}
|
||||
/>
|
||||
</div>
|
||||
</Content>
|
||||
|
||||
@@ -46,7 +46,6 @@ describe('CatalogTable component', () => {
|
||||
entities={[]}
|
||||
loading={false}
|
||||
error={{ code: 'error' }}
|
||||
onAddMockData={() => {}}
|
||||
/>,
|
||||
),
|
||||
);
|
||||
@@ -63,7 +62,6 @@ describe('CatalogTable component', () => {
|
||||
titlePreamble="Owned"
|
||||
entities={entities}
|
||||
loading={false}
|
||||
onAddMockData={() => {}}
|
||||
/>,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -16,11 +16,10 @@
|
||||
import { Entity, LocationSpec } from '@backstage/catalog-model';
|
||||
import { Table, TableColumn, TableProps } from '@backstage/core';
|
||||
import { Chip, Link } from '@material-ui/core';
|
||||
import Add from '@material-ui/icons/Add';
|
||||
import Edit from '@material-ui/icons/Edit';
|
||||
import GitHub from '@material-ui/icons/GitHub';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
import React, { Dispatch } from 'react';
|
||||
import React from 'react';
|
||||
import { generatePath, Link as RouterLink } from 'react-router-dom';
|
||||
import { findLocationForEntityMeta } from '../../data/utils';
|
||||
import { useStarredEntities } from '../../hooks/useStarredEntites';
|
||||
@@ -87,7 +86,6 @@ type CatalogTableProps = {
|
||||
titlePreamble: string;
|
||||
loading: boolean;
|
||||
error?: any;
|
||||
onAddMockData: Dispatch<void>;
|
||||
};
|
||||
|
||||
export const CatalogTable = ({
|
||||
@@ -95,7 +93,6 @@ export const CatalogTable = ({
|
||||
loading,
|
||||
error,
|
||||
titlePreamble,
|
||||
onAddMockData,
|
||||
}: CatalogTableProps) => {
|
||||
const { isStarredEntity, toggleStarredEntity } = useStarredEntities();
|
||||
|
||||
@@ -151,13 +148,6 @@ export const CatalogTable = ({
|
||||
onClick: () => toggleStarredEntity(rowData),
|
||||
};
|
||||
},
|
||||
{
|
||||
icon: () => <Add />,
|
||||
tooltip: 'Add example components',
|
||||
isFreeAction: true,
|
||||
onClick: onAddMockData,
|
||||
hidden: !(entities && entities.length === 0),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
|
||||
@@ -47,7 +47,7 @@ export const EntityFilterGroupsProvider = ({
|
||||
function useProvideEntityFilters(): FilterGroupsContext {
|
||||
const catalogApi = useApi(catalogApiRef);
|
||||
const [{ value: entities, error }, doReload] = useAsyncFn(() =>
|
||||
catalogApi.getEntities(),
|
||||
catalogApi.getEntities({ kind: 'Component' }),
|
||||
);
|
||||
|
||||
const filterGroups = useRef<{
|
||||
@@ -62,6 +62,7 @@ function useProvideEntityFilters(): FilterGroupsContext {
|
||||
}>({});
|
||||
const [matchingEntities, setMatchingEntities] = useState<Entity[]>([]);
|
||||
const [availableTags, setAvailableTags] = useState<string[]>([]);
|
||||
const [isCatalogEmpty, setCatalogEmpty] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
doReload();
|
||||
@@ -86,6 +87,7 @@ function useProvideEntityFilters(): FilterGroupsContext {
|
||||
),
|
||||
);
|
||||
setAvailableTags(collectTags(entities));
|
||||
setCatalogEmpty(entities !== undefined && entities.length === 0);
|
||||
}, [entities, error]);
|
||||
|
||||
const register = useCallback(
|
||||
@@ -143,6 +145,7 @@ function useProvideEntityFilters(): FilterGroupsContext {
|
||||
filterGroupStates,
|
||||
matchingEntities,
|
||||
availableTags,
|
||||
isCatalogEmpty,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ export type FilterGroupsContext = {
|
||||
filterGroupStates: { [filterGroupId: string]: FilterGroupStates };
|
||||
matchingEntities: Entity[];
|
||||
availableTags: string[];
|
||||
isCatalogEmpty: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,6 +31,7 @@ export function useFilteredEntities() {
|
||||
error: context.error,
|
||||
matchingEntities: context.matchingEntities,
|
||||
availableTags: context.availableTags,
|
||||
isCatalogEmpty: context.isCatalogEmpty,
|
||||
reload: context.reload,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -24,8 +24,7 @@ import { Entity } from '@backstage/catalog-model';
|
||||
import { WarningPanel } from '@backstage/core';
|
||||
|
||||
export const isPluginApplicableToEntity = (entity: Entity) =>
|
||||
Boolean(entity.metadata.annotations?.[CIRCLECI_ANNOTATION]) &&
|
||||
entity.metadata.annotations?.[CIRCLECI_ANNOTATION] !== '';
|
||||
Boolean(entity.metadata.annotations?.[CIRCLECI_ANNOTATION]);
|
||||
|
||||
export const Router = ({ entity }: { entity: Entity }) =>
|
||||
!isPluginApplicableToEntity(entity) ? (
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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 { GCPApi } from './GCPApi';
|
||||
import { Project, Operation, Status } from './types';
|
||||
|
||||
const BaseURL =
|
||||
'https://content-cloudresourcemanager.googleapis.com/v1/projects';
|
||||
|
||||
export class GCPClient implements GCPApi {
|
||||
async listProjects({ token }: { token: string }): Promise<Project[]> {
|
||||
const response = await fetch(BaseURL, {
|
||||
headers: new Headers({
|
||||
Accept: '*/*',
|
||||
Authorization: `Bearer ${token}`,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
return [
|
||||
{
|
||||
name: 'Error',
|
||||
projectNumber: 'Response status is not OK',
|
||||
projectId: 'Error',
|
||||
lifecycleState: 'error',
|
||||
createTime: 'Error',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
return data.projects;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async getProject(
|
||||
projectId: string,
|
||||
token: Promise<string>,
|
||||
): Promise<Project> {
|
||||
const url = `${BaseURL}/${projectId}`;
|
||||
const response = await fetch(url, {
|
||||
headers: new Headers({
|
||||
Authorization: `Bearer ${await token}`,
|
||||
}),
|
||||
});
|
||||
|
||||
const dataBlank: Project = {
|
||||
name: 'Error',
|
||||
projectNumber: `Response status is ${response.status}`,
|
||||
projectId: 'Error',
|
||||
lifecycleState: 'error',
|
||||
createTime: 'Error',
|
||||
};
|
||||
|
||||
if (!response.ok) {
|
||||
return dataBlank;
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
const newData: Project = data;
|
||||
|
||||
return newData;
|
||||
}
|
||||
|
||||
async createProject(
|
||||
projectName: string,
|
||||
projectId: string,
|
||||
token: string,
|
||||
): Promise<Operation> {
|
||||
const status: Status = {
|
||||
code: 0,
|
||||
message: '',
|
||||
details: [],
|
||||
};
|
||||
|
||||
const op: Operation = {
|
||||
name: '',
|
||||
metadata: '',
|
||||
done: true,
|
||||
error: status,
|
||||
response: '',
|
||||
};
|
||||
|
||||
const newProject: Project = {
|
||||
name: projectName,
|
||||
projectId: projectId,
|
||||
};
|
||||
|
||||
const body = JSON.stringify(newProject);
|
||||
|
||||
const response = await fetch(BaseURL, {
|
||||
headers: new Headers({
|
||||
Accept: '*/*',
|
||||
Authorization: `Bearer ${token}`,
|
||||
}),
|
||||
body: body,
|
||||
method: 'POST',
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
status.code = response.status;
|
||||
return op;
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -17,18 +17,16 @@
|
||||
import { createApiRef } from '@backstage/core';
|
||||
import { Project, Operation } from './types';
|
||||
|
||||
export const GCPApiRef = createApiRef<GCPApi>({
|
||||
export const gcpApiRef = createApiRef<GcpApi>({
|
||||
id: 'plugin.gcpprojects.service',
|
||||
description: 'Used by the GCP Projects plugin to make requests',
|
||||
});
|
||||
|
||||
export type GCPApi = {
|
||||
listProjects: ({ token }: { token: string }) => Promise<Project[]>;
|
||||
getProject: (projectId: string, token: Promise<string>) => Promise<Project>;
|
||||
createProject: (
|
||||
projectName: string,
|
||||
projectId: string,
|
||||
owner: string,
|
||||
token: string,
|
||||
) => Promise<Operation>;
|
||||
export type GcpApi = {
|
||||
listProjects(): Promise<Project[]>;
|
||||
getProject(projectId: string): Promise<Project>;
|
||||
createProject(options: {
|
||||
projectId: string;
|
||||
projectName: string;
|
||||
}): Promise<Operation>;
|
||||
};
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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 { OAuthApi } from '@backstage/core';
|
||||
import { GcpApi } from './GcpApi';
|
||||
import { Operation, Project } from './types';
|
||||
|
||||
const BASE_URL =
|
||||
'https://content-cloudresourcemanager.googleapis.com/v1/projects';
|
||||
|
||||
export class GcpClient implements GcpApi {
|
||||
constructor(private readonly googleAuthApi: OAuthApi) {}
|
||||
|
||||
async listProjects(): Promise<Project[]> {
|
||||
const response = await fetch(BASE_URL, {
|
||||
headers: {
|
||||
Accept: '*/*',
|
||||
Authorization: `Bearer ${await this.getToken()}`,
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`List request failed to ${BASE_URL} with ${response.status} ${response.statusText}`,
|
||||
);
|
||||
}
|
||||
|
||||
const { projects } = await response.json();
|
||||
return projects;
|
||||
}
|
||||
|
||||
async getProject(projectId: string): Promise<Project> {
|
||||
const url = `${BASE_URL}/${projectId}`;
|
||||
const response = await fetch(url, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${await this.getToken()}`,
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Get request failed to ${url} with ${response.status} ${response.statusText}`,
|
||||
);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
async createProject(options: {
|
||||
projectId: string;
|
||||
projectName: string;
|
||||
}): Promise<Operation> {
|
||||
const newProject: Project = {
|
||||
name: options.projectName,
|
||||
projectId: options.projectId,
|
||||
};
|
||||
|
||||
const response = await fetch(BASE_URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Accept: '*/*',
|
||||
Authorization: `Bearer ${await this.getToken()}`,
|
||||
},
|
||||
body: JSON.stringify(newProject),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Create request failed to ${BASE_URL} with ${response.status} ${response.statusText}`,
|
||||
);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
async getToken(): Promise<string> {
|
||||
// NOTE(freben): There's a .read-only variant of this scope that we could
|
||||
// use for readonly operations, but that means we would ask the user for a
|
||||
// second auth during creation and I decided to keep the wider scope for
|
||||
// all ops for now
|
||||
return this.googleAuthApi.getAccessToken(
|
||||
'https://www.googleapis.com/auth/cloud-platform',
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export * from './GCPApi';
|
||||
export * from './GCPClient';
|
||||
export * from './GcpApi';
|
||||
export * from './GcpClient';
|
||||
export * from './types';
|
||||
|
||||
@@ -14,24 +14,23 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { FC, useState } from 'react';
|
||||
import { Grid, Button, TextField } from '@material-ui/core';
|
||||
|
||||
import {
|
||||
InfoCard,
|
||||
Content,
|
||||
ContentHeader,
|
||||
Header,
|
||||
HeaderLabel,
|
||||
InfoCard,
|
||||
Page,
|
||||
pageTheme,
|
||||
SimpleStepper,
|
||||
SimpleStepperStep,
|
||||
StructuredMetadataTable,
|
||||
HeaderLabel,
|
||||
Page,
|
||||
Header,
|
||||
pageTheme,
|
||||
SupportButton,
|
||||
} from '@backstage/core';
|
||||
import { Button, Grid, TextField } from '@material-ui/core';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
export const Project: FC<{}> = () => {
|
||||
export const Project = () => {
|
||||
const [projectName, setProjectName] = useState('');
|
||||
const [projectId, setProjectId] = useState('');
|
||||
const [disabled, setDisabled] = useState(true);
|
||||
|
||||
@@ -14,6 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
Content,
|
||||
ContentHeader,
|
||||
Header,
|
||||
HeaderLabel,
|
||||
Page,
|
||||
pageTheme,
|
||||
SupportButton,
|
||||
useApi,
|
||||
WarningPanel,
|
||||
} from '@backstage/core';
|
||||
import {
|
||||
Button,
|
||||
ButtonGroup,
|
||||
@@ -27,20 +38,9 @@ import {
|
||||
Theme,
|
||||
Typography,
|
||||
} from '@material-ui/core';
|
||||
import {
|
||||
useApi,
|
||||
googleAuthApiRef,
|
||||
HeaderLabel,
|
||||
Page,
|
||||
Header,
|
||||
pageTheme,
|
||||
SupportButton,
|
||||
Content,
|
||||
ContentHeader,
|
||||
} from '@backstage/core';
|
||||
import React from 'react';
|
||||
import { useAsync } from 'react-use';
|
||||
import { GCPApiRef } from '../../api';
|
||||
import { gcpApiRef } from '../../api';
|
||||
|
||||
const useStyles = makeStyles<Theme>(theme => ({
|
||||
root: {
|
||||
@@ -56,34 +56,27 @@ const useStyles = makeStyles<Theme>(theme => ({
|
||||
}));
|
||||
|
||||
const DetailsPage = () => {
|
||||
const api = useApi(GCPApiRef);
|
||||
const googleApi = useApi(googleAuthApiRef);
|
||||
const token = googleApi.getAccessToken(
|
||||
'https://www.googleapis.com/auth/cloud-platform.read-only',
|
||||
);
|
||||
|
||||
const api = useApi(gcpApiRef);
|
||||
const classes = useStyles();
|
||||
const status = useAsync(
|
||||
() =>
|
||||
|
||||
const { loading, error, value: details } = useAsync(
|
||||
async () =>
|
||||
api.getProject(
|
||||
decodeURIComponent(location.search.split('projectId=')[1]),
|
||||
token,
|
||||
),
|
||||
[location.search],
|
||||
);
|
||||
|
||||
if (status.loading) {
|
||||
if (loading) {
|
||||
return <LinearProgress />;
|
||||
} else if (status.error) {
|
||||
} else if (error) {
|
||||
return (
|
||||
<Typography variant="h6" color="error">
|
||||
Failed to load build, {status.error.message}
|
||||
</Typography>
|
||||
<WarningPanel title="Failed to load project">
|
||||
{error.toString()}
|
||||
</WarningPanel>
|
||||
);
|
||||
}
|
||||
|
||||
const details = status.value;
|
||||
|
||||
return (
|
||||
<Table component={Paper} className={classes.table}>
|
||||
<Table>
|
||||
|
||||
@@ -17,18 +17,19 @@
|
||||
// NEEDS WORK
|
||||
|
||||
import {
|
||||
Link,
|
||||
useApi,
|
||||
googleAuthApiRef,
|
||||
HeaderLabel,
|
||||
Page,
|
||||
Header,
|
||||
pageTheme,
|
||||
SupportButton,
|
||||
Content,
|
||||
ContentHeader,
|
||||
Header,
|
||||
HeaderLabel,
|
||||
Link,
|
||||
Page,
|
||||
pageTheme,
|
||||
SupportButton,
|
||||
useApi,
|
||||
WarningPanel,
|
||||
} from '@backstage/core';
|
||||
import {
|
||||
Button,
|
||||
LinearProgress,
|
||||
Paper,
|
||||
Table,
|
||||
@@ -38,11 +39,10 @@ import {
|
||||
TableRow,
|
||||
Tooltip,
|
||||
Typography,
|
||||
Button,
|
||||
} from '@material-ui/core';
|
||||
import React from 'react';
|
||||
import { useAsync } from 'react-use';
|
||||
import { GCPApiRef, Project } from '../../api';
|
||||
import { gcpApiRef, Project } from '../../api';
|
||||
|
||||
const LongText = ({ text, max }: { text: string; max: number }) => {
|
||||
if (text.length < max) {
|
||||
@@ -63,27 +63,17 @@ const labels = (
|
||||
);
|
||||
|
||||
const PageContents = () => {
|
||||
const api = useApi(GCPApiRef);
|
||||
const googleApi = useApi(googleAuthApiRef);
|
||||
const api = useApi(gcpApiRef);
|
||||
|
||||
const { loading, error, value } = useAsync(async () => {
|
||||
const token = await googleApi.getAccessToken(
|
||||
'https://www.googleapis.com/auth/cloud-platform.read-only',
|
||||
);
|
||||
|
||||
const projects = api.listProjects({ token });
|
||||
return projects;
|
||||
});
|
||||
const { loading, error, value } = useAsync(() => api.listProjects());
|
||||
|
||||
if (loading) {
|
||||
return <LinearProgress />;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
} else if (error) {
|
||||
return (
|
||||
<Typography variant="h2" color="error">
|
||||
{error.message}{' '}
|
||||
</Typography>
|
||||
<WarningPanel title="Failed to load projects">
|
||||
{error.toString()}
|
||||
</WarningPanel>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,34 +15,43 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
createApiFactory,
|
||||
createPlugin,
|
||||
createRouteRef,
|
||||
createApiFactory,
|
||||
googleAuthApiRef,
|
||||
} from '@backstage/core';
|
||||
import { ProjectListPage } from './components/ProjectListPage';
|
||||
import { ProjectDetailsPage } from './components/ProjectDetailsPage';
|
||||
import { gcpApiRef, GcpClient } from './api';
|
||||
import { NewProjectPage } from './components/NewProjectPage';
|
||||
import { GCPApiRef, GCPClient } from './api';
|
||||
import { ProjectDetailsPage } from './components/ProjectDetailsPage';
|
||||
import { ProjectListPage } from './components/ProjectListPage';
|
||||
|
||||
export const rootRouteRef = createRouteRef({
|
||||
path: '/gcp-projects',
|
||||
title: 'GCP Projects',
|
||||
});
|
||||
export const ProjectRouteRef = createRouteRef({
|
||||
export const projectRouteRef = createRouteRef({
|
||||
path: '/gcp-projects/project',
|
||||
title: 'GCP Project Page',
|
||||
});
|
||||
export const NewProjectRouteRef = createRouteRef({
|
||||
export const newProjectRouteRef = createRouteRef({
|
||||
path: '/gcp-projects/new',
|
||||
title: 'GCP Project Page',
|
||||
});
|
||||
|
||||
export const plugin = createPlugin({
|
||||
id: 'gcp-projects',
|
||||
apis: [createApiFactory(GCPApiRef, new GCPClient())],
|
||||
apis: [
|
||||
createApiFactory({
|
||||
api: gcpApiRef,
|
||||
deps: { googleAuthApi: googleAuthApiRef },
|
||||
factory({ googleAuthApi }) {
|
||||
return new GcpClient(googleAuthApi);
|
||||
},
|
||||
}),
|
||||
],
|
||||
register({ router }) {
|
||||
router.addRoute(rootRouteRef, ProjectListPage);
|
||||
router.addRoute(ProjectRouteRef, ProjectDetailsPage);
|
||||
router.addRoute(NewProjectRouteRef, NewProjectPage);
|
||||
router.addRoute(projectRouteRef, ProjectDetailsPage);
|
||||
router.addRoute(newProjectRouteRef, NewProjectPage);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -23,13 +23,12 @@ import { GITHUB_ACTIONS_ANNOTATION } from './useProjectName';
|
||||
import { WarningPanel } from '@backstage/core';
|
||||
|
||||
export const isPluginApplicableToEntity = (entity: Entity) =>
|
||||
Boolean(entity.metadata.annotations?.[GITHUB_ACTIONS_ANNOTATION]) &&
|
||||
entity.metadata.annotations?.[GITHUB_ACTIONS_ANNOTATION] !== '';
|
||||
Boolean(entity.metadata.annotations?.[GITHUB_ACTIONS_ANNOTATION]);
|
||||
|
||||
export const Router = ({ entity }: { entity: Entity }) =>
|
||||
// TODO(shmidt-i): move warning to a separate standardized component
|
||||
!isPluginApplicableToEntity(entity) ? (
|
||||
<WarningPanel title=" GitHubActions plugin:">
|
||||
<WarningPanel title="GitHubActions plugin:">
|
||||
<pre>{GITHUB_ACTIONS_ANNOTATION}</pre> annotation is missing on the
|
||||
entity.
|
||||
</WarningPanel>
|
||||
|
||||
@@ -23,8 +23,7 @@ import { WarningPanel } from '@backstage/core';
|
||||
import { CITable } from './BuildsPage/lib/CITable';
|
||||
|
||||
export const isPluginApplicableToEntity = (entity: Entity) =>
|
||||
Boolean(entity.metadata.annotations?.[JENKINS_ANNOTATION]) &&
|
||||
entity.metadata.annotations?.[JENKINS_ANNOTATION] !== '';
|
||||
Boolean(entity.metadata.annotations?.[JENKINS_ANNOTATION]);
|
||||
|
||||
export const Router = ({ entity }: { entity: Entity }) => {
|
||||
return !isPluginApplicableToEntity(entity) ? (
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
extends: [require.resolve('@backstage/cli/config/eslint.backend')],
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
# Kubernetes Backend
|
||||
|
||||
WORK IN PROGRESS
|
||||
|
||||
This is the backend part of the Kubernetes plugin.
|
||||
|
||||
It responds to Kubernetes requests from the frontend.
|
||||
|
||||
## Links
|
||||
|
||||
- [The Backstage homepage](https://backstage.io)
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "@backstage/plugin-kubernetes-backend",
|
||||
"version": "0.1.1-alpha.22",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"main": "dist/index.cjs.js",
|
||||
"types": "dist/index.d.ts"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "backstage-cli backend:dev",
|
||||
"build": "backstage-cli backend:build",
|
||||
"lint": "backstage-cli lint",
|
||||
"test": "backstage-cli test",
|
||||
"prepack": "backstage-cli prepack",
|
||||
"postpack": "backstage-cli postpack",
|
||||
"clean": "backstage-cli clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/backend-common": "^0.1.1-alpha.22",
|
||||
"@types/express": "^4.17.6",
|
||||
"compression": "^1.7.4",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.17.1",
|
||||
"express-promise-router": "^3.0.3",
|
||||
"fs-extra": "^9.0.0",
|
||||
"helmet": "^4.0.0",
|
||||
"morgan": "^1.10.0",
|
||||
"winston": "^3.2.1",
|
||||
"yn": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.1.1-alpha.22",
|
||||
"jest-fetch-mock": "^3.0.3"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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 '@backstage/backend-common';
|
||||
|
||||
describe('test', () => {
|
||||
it('unbreaks the test runner', () => {
|
||||
expect(true).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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 * from './service/router';
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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 yn from 'yn';
|
||||
import { getRootLogger } from '@backstage/backend-common';
|
||||
import { startStandaloneServer } from './service/standaloneServer';
|
||||
|
||||
const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 3004;
|
||||
const enableCors = yn(process.env.PLUGIN_CORS, { default: false });
|
||||
const logger = getRootLogger();
|
||||
|
||||
startStandaloneServer({ port, enableCors, logger }).catch(err => {
|
||||
logger.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
logger.info('CTRL+C pressed; exiting.');
|
||||
process.exit(0);
|
||||
});
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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 express from 'express';
|
||||
import Router from 'express-promise-router';
|
||||
import { Logger } from 'winston';
|
||||
|
||||
export interface RouterOptions {
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
const makeRouter = (logger: Logger): express.Router => {
|
||||
const router = Router();
|
||||
router.use(express.json());
|
||||
|
||||
router.get('/services/:serviceId', async (req, res) => {
|
||||
const serviceId = req.params.serviceId;
|
||||
logger.info(`HERE ${serviceId}`);
|
||||
res.send({ serviceId });
|
||||
});
|
||||
|
||||
return router;
|
||||
};
|
||||
|
||||
export async function createRouter(
|
||||
options: RouterOptions,
|
||||
): Promise<express.Router> {
|
||||
const logger = options.logger;
|
||||
|
||||
logger.info('Initializing Kubernetes backend');
|
||||
return makeRouter(logger);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* 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 {
|
||||
errorHandler,
|
||||
notFoundHandler,
|
||||
requestLoggingHandler,
|
||||
} from '@backstage/backend-common';
|
||||
import compression from 'compression';
|
||||
import cors from 'cors';
|
||||
import express from 'express';
|
||||
import helmet from 'helmet';
|
||||
import { Logger } from 'winston';
|
||||
import { createRouter } from './router';
|
||||
|
||||
export interface ApplicationOptions {
|
||||
enableCors: boolean;
|
||||
logger: Logger;
|
||||
}
|
||||
|
||||
export async function createStandaloneApplication(
|
||||
options: ApplicationOptions,
|
||||
): Promise<express.Application> {
|
||||
const { enableCors, logger } = options;
|
||||
const app = express();
|
||||
|
||||
app.use(helmet());
|
||||
if (enableCors) {
|
||||
app.use(cors());
|
||||
}
|
||||
app.use(compression());
|
||||
app.use(express.json());
|
||||
app.use(requestLoggingHandler());
|
||||
app.use('/', await createRouter({ logger }));
|
||||
app.use(notFoundHandler());
|
||||
app.use(errorHandler());
|
||||
|
||||
return app;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user