From 78fa27c542ef305c17fc15150f0b51837a337485 Mon Sep 17 00:00:00 2001 From: Ryan Vazquez Date: Wed, 2 Sep 2020 11:37:33 -0400 Subject: [PATCH 01/34] forward classes prop to cardheader --- .../core/src/layout/InfoCard/InfoCard.tsx | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/packages/core/src/layout/InfoCard/InfoCard.tsx b/packages/core/src/layout/InfoCard/InfoCard.tsx index 86e9c79ced..983356dd4a 100644 --- a/packages/core/src/layout/InfoCard/InfoCard.tsx +++ b/packages/core/src/layout/InfoCard/InfoCard.tsx @@ -20,8 +20,10 @@ import { CardActions, CardContent, CardHeader, + CardHeaderProps, Divider, withStyles, + createStyles, makeStyles, } from '@material-ui/core'; import classNames from 'classnames'; @@ -40,10 +42,25 @@ const useStyles = makeStyles(theme => ({ }, })); -const BoldHeader = withStyles(theme => ({ - title: { fontWeight: 700 }, - subheader: { paddingTop: theme.spacing(1) }, -}))(CardHeader); +const useBoldHeaderStyles = makeStyles(theme => + createStyles({ + title: { + fontWeight: 700, + }, + subheader: { + paddingTop: theme.spacing(1), + }, + root: {}, + avatar: {}, + action: {}, + content: {}, + }), +); + +const BoldHeader = ({ classes, ...props }: CardHeaderProps) => { + const styles = useBoldHeaderStyles({ classes }); + return ; +}; const CardActionsTopRight = withStyles(theme => ({ root: { @@ -120,8 +137,6 @@ const VARIANT_STYLES = { * ... */ type Props = { - title?: ReactNode; - subheader?: ReactNode; divider?: boolean; deepLink?: BottomLinkProps; slackChannel?: string; @@ -130,14 +145,14 @@ type Props = { cardStyle?: object; children?: ReactNode; headerStyle?: object; - headerProps?: object; + headerProps?: CardHeaderProps; actionsClassName?: string; actions?: ReactNode; cardClassName?: string; actionsTopRight?: ReactNode; className?: string; noPadding?: boolean; -}; +} & Pick; export const InfoCard: FC = ({ title, From 66a2a870bccab753ff80f9d093f3519850bb36d2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 7 Sep 2020 20:04:23 +0200 Subject: [PATCH 02/34] plugins/tech-radar: migrate to new plugin pattern and avoid using api for config --- packages/app/src/App.tsx | 5 + packages/app/src/apis.ts | 10 -- .../default-app/packages/app/src/App.tsx | 5 + .../default-app/packages/app/src/apis.ts | 10 -- plugins/tech-radar/README.md | 108 ++++------------- plugins/tech-radar/dev/index.tsx | 12 +- plugins/tech-radar/package.json | 2 +- plugins/tech-radar/src/api.ts | 35 ------ .../src/components/RadarComponent.test.tsx | 2 +- .../src/components/RadarPage.test.tsx | 110 ++++-------------- .../tech-radar/src/components/RadarPage.tsx | 66 ++++++----- plugins/tech-radar/src/index.ts | 2 + plugins/tech-radar/src/plugin.ts | 4 - 13 files changed, 102 insertions(+), 269 deletions(-) diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 8ddf53783d..8482bc9a8a 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -28,6 +28,7 @@ import { hot } from 'react-hot-loader/root'; import { providers } from './identityProviders'; import { Router as CatalogRouter } from '@backstage/plugin-catalog'; import { Router as DocsRouter } from '@backstage/plugin-techdocs'; +import { Router as TechRadarRouter } from '@backstage/plugin-tech-radar'; import { Route, Routes, Navigate } from 'react-router'; import { EntityPage } from './components/catalog/EntityPage'; @@ -60,6 +61,10 @@ const AppRoutes = () => ( element={} /> } /> + } + /> {...deprecatedAppRoutes} diff --git a/packages/app/src/apis.ts b/packages/app/src/apis.ts index b391e95d62..b79a6850bd 100644 --- a/packages/app/src/apis.ts +++ b/packages/app/src/apis.ts @@ -51,8 +51,6 @@ import { LighthouseRestApi, } from '@backstage/plugin-lighthouse'; -import { techRadarApiRef, TechRadar } from '@backstage/plugin-tech-radar'; - import { CircleCIApi, circleCIApiRef } from '@backstage/plugin-circleci'; import { catalogApiRef, CatalogClient } from '@backstage/plugin-catalog'; @@ -182,14 +180,6 @@ export const apis = (config: ConfigApi) => { }), ); - builder.add( - techRadarApiRef, - new TechRadar({ - width: 1500, - height: 800, - }), - ); - builder.add(catalogApiRef, new CatalogClient({ discoveryApi })); builder.add(scaffolderApiRef, new ScaffolderApi({ discoveryApi })); diff --git a/packages/create-app/templates/default-app/packages/app/src/App.tsx b/packages/create-app/templates/default-app/packages/app/src/App.tsx index 3e6a0ef00e..06ef257931 100644 --- a/packages/create-app/templates/default-app/packages/app/src/App.tsx +++ b/packages/create-app/templates/default-app/packages/app/src/App.tsx @@ -11,6 +11,7 @@ import { AppSidebar } from './sidebar'; import { Route, Routes, Navigate } from 'react-router'; import { Router as CatalogRouter } from '@backstage/plugin-catalog'; import { Router as DocsRouter } from '@backstage/plugin-techdocs'; +import { Router as TechRadarRouter } from '@backstage/plugin-tech-radar'; import { EntityPage } from './components/catalog/EntityPage'; const app = createApp({ @@ -35,6 +36,10 @@ const App: FC<{}> = () => ( element={} /> } /> + } + /> {deprecatedAppRoutes} diff --git a/packages/create-app/templates/default-app/packages/app/src/apis.ts b/packages/create-app/templates/default-app/packages/app/src/apis.ts index 14351eaba7..ba4343801f 100644 --- a/packages/create-app/templates/default-app/packages/app/src/apis.ts +++ b/packages/create-app/templates/default-app/packages/app/src/apis.ts @@ -29,8 +29,6 @@ import { TechDocsStorageApi, } from '@backstage/plugin-techdocs'; -import { techRadarApiRef, TechRadar } from '@backstage/plugin-tech-radar'; - import { catalogApiRef, CatalogClient } from '@backstage/plugin-catalog'; import { CircleCIApi, circleCIApiRef } from '@backstage/plugin-circleci'; @@ -72,14 +70,6 @@ export const apis = (config: ConfigApi) => { builder.add(scaffolderApiRef, new ScaffolderApi({ discoveryApi })); - builder.add( - techRadarApiRef, - new TechRadar({ - width: 1500, - height: 800, - }), - ); - builder.add( techdocsStorageApiRef, new TechDocsStorageApi({ apiOrigin: techdocsStorageUrl }), diff --git a/plugins/tech-radar/README.md b/plugins/tech-radar/README.md index fb9d220b8c..cbe4dd22eb 100644 --- a/plugins/tech-radar/README.md +++ b/plugins/tech-radar/README.md @@ -29,71 +29,34 @@ For either simple or advanced installations, you'll need to add the dependency u yarn add @backstage/plugin-tech-radar ``` -### Simple Configuration +### Configuration -In your `apis.ts` set up the simple "out of the box" implementation for Tech Radar: - -```ts -import { ApiHolder, ApiRegistry } from '@backstage/core'; -import { - techRadarApiRef, - TechRadar, -} from '@backstage/plugin-tech-radar'; - -const builder = ApiRegistry.builder(); - -builder.add(techRadarApiRef, new TechRadar({ - width: 1400, - height: 800 -)); - -export default builder.build() as ApiHolder; -``` - -Congrats, you're done! We'll just load it with [example data](src/sampleData.ts) to get you started. Just go to to see it live in action. - -And if you'd like to configure it more, such as providing it with your own data, see the `TechRadarApi` TypeScript interface below for the options: - -```ts -export interface TechRadarComponentProps { - width: number; - height: number; - getData?: () => Promise; - svgProps?: object; -} - -export interface TechRadarApi extends TechRadarComponentProps { - title?: string; - subtitle?: string; -} -``` - -You can see the API directly over at [src/api.ts](./src/api.ts). - -### Advanced Configuration - -This way won't expose an `/tech-radar` path. Instead, you'll need to create your own Backstage plugin and use the Tech Radar as any other React UI component. - -In your Backstage app, run the following command: - -```sh -yarn create-plugin -``` - -In your plugin, in any React component you'd like to import the Tech Radar, do the following: +Modify your app routes to include the Router component exported from the tech radar, for example: ```tsx -import { TechRadarComponent } from '@backstage/plugin-tech-radar'; +import { Router as TechRadarRouter } from '@backstage/plugin-tech-radar'; -function MyCustomRadar() { - return ; -} +// Inside App component + + {/* other routes ... */} + } + /> + {/* other routes ... */} +; ``` -If you'd like to configure it more, see the `TechRadarComponentProps` TypeScript interface for options: +If you'd like to configure it more, see the `TechRadarPageProps` and `TechRadarComponentProps` types for options: ```ts -export interface TechRadarComponentProps { +export type TechRadarPageProps = TechRadarComponentProps & { + title?: string; + subtitle?: string; + pageTitle?: string; +}; + +export interface TechRadarPageProps { width: number; height: number; getData?: () => Promise; @@ -101,8 +64,6 @@ export interface TechRadarComponentProps { } ``` -You can see the API directly over at [src/api.ts](./src/api.ts). - ## Frequently Asked Questions ### Who created the Tech Radar? @@ -111,7 +72,7 @@ You can see the API directly over at [src/api.ts](./src/api.ts). ### How do I load in my own data? -It's simple. In both the Simple (Backstage plugin) and Advanced (React component) configurations, you can pass through a `getData` prop which expects a `Promise` signature. See more in [src/api.ts](./src/api.ts). +It's simple, you can pass through a `getData` prop which expects a `Promise` signature. Here's an example: @@ -133,42 +94,21 @@ const getHardCodedData = () => ], }); -// Simple -builder.add(techRadarApiRef, new TechRadar({ - width: 1400, - height: 800, - getData: getHardCodedData -)); - -// Advanced - +; ``` ### How do I write tests? You can use the `svgProps` option to pass custom React props to the `` element we create for the Tech Radar. This complements well with the `data-testid` attribute and the `@testing-library/react` library we use in Backstage. -```ts -// Simple -builder.add( - techRadarApiRef, - new TechRadar({ - width: 1400, - height: 800, - svgProps: { - 'data-testid': 'tech-radar-svg', - }, - }), -); - -// Advanced +```tsx ; +/> // Then, in your tests... // const { getByTestId } = render(...); diff --git a/plugins/tech-radar/dev/index.tsx b/plugins/tech-radar/dev/index.tsx index ac19b63a90..92eb6da567 100644 --- a/plugins/tech-radar/dev/index.tsx +++ b/plugins/tech-radar/dev/index.tsx @@ -15,14 +15,6 @@ */ import { createDevApp } from '@backstage/dev-utils'; -import { plugin } from '../src/plugin'; -import { techRadarApiRef, TechRadar } from '../src'; +import { plugin } from '../src'; -createDevApp() - .registerPlugin(plugin) - .registerApiFactory({ - implements: techRadarApiRef, - deps: {}, - factory: () => new TechRadar({ width: 1500, height: 800 }), - }) - .render(); +createDevApp().registerPlugin(plugin).render(); diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index 4039f40878..f5639c7581 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -22,7 +22,7 @@ }, "dependencies": { "@backstage/core": "^0.1.1-alpha.21", - "@backstage/test-utils-core": "^0.1.1-alpha.21", + "@backstage/test-utils": "^0.1.1-alpha.21", "@backstage/theme": "^0.1.1-alpha.21", "@material-ui/core": "^4.9.1", "@material-ui/icons": "^4.9.1", diff --git a/plugins/tech-radar/src/api.ts b/plugins/tech-radar/src/api.ts index 856cf4ff3c..7a6e790136 100644 --- a/plugins/tech-radar/src/api.ts +++ b/plugins/tech-radar/src/api.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import { createApiRef } from '@backstage/core'; import { MovedState } from './utils/types'; /** @@ -72,37 +71,3 @@ export interface TechRadarApi extends TechRadarComponentProps { subtitle?: string; pageTitle?: string; } - -export const techRadarApiRef = createApiRef({ - id: 'plugin.techradar', - description: 'Used by the Tech Radar to render the visualization', -}); - -export class TechRadar implements TechRadarApi { - // Default columns - public width: TechRadarApi['width']; - public height: TechRadarApi['height']; - public getData: TechRadarApi['getData']; - public svgProps: TechRadarApi['svgProps']; - public title: TechRadarApi['title']; - public subtitle: TechRadarApi['subtitle']; - public pageTitle: TechRadarApi['pageTitle']; - - constructor(overrideOptions: TechRadarApi) { - const defaultOptions: Partial = { - title: 'Tech Radar', - subtitle: 'Pick the recommended technologies for your projects', - pageTitle: 'Company Radar', - }; - - const options = { ...defaultOptions, ...overrideOptions }; - - this.width = options.width; - this.height = options.height; - this.getData = options.getData; - this.svgProps = options.svgProps; - this.title = options.title; - this.subtitle = options.subtitle; - this.pageTitle = options.pageTitle; - } -} diff --git a/plugins/tech-radar/src/components/RadarComponent.test.tsx b/plugins/tech-radar/src/components/RadarComponent.test.tsx index 2f3fcff198..5591d74b82 100644 --- a/plugins/tech-radar/src/components/RadarComponent.test.tsx +++ b/plugins/tech-radar/src/components/RadarComponent.test.tsx @@ -19,7 +19,7 @@ import { render, waitForElement } from '@testing-library/react'; import { ThemeProvider } from '@material-ui/core'; import { lightTheme } from '@backstage/theme'; import { ApiRegistry, ApiProvider, errorApiRef } from '@backstage/core'; -import { withLogCollector } from '@backstage/test-utils-core'; +import { withLogCollector } from '@backstage/test-utils'; import GetBBoxPolyfill from '../utils/polyfills/getBBox'; import RadarComponent from './RadarComponent'; diff --git a/plugins/tech-radar/src/components/RadarPage.test.tsx b/plugins/tech-radar/src/components/RadarPage.test.tsx index c318985acd..97fae16380 100644 --- a/plugins/tech-radar/src/components/RadarPage.test.tsx +++ b/plugins/tech-radar/src/components/RadarPage.test.tsx @@ -19,11 +19,10 @@ import { render, waitForElement } from '@testing-library/react'; import { ThemeProvider } from '@material-ui/core'; import { lightTheme } from '@backstage/theme'; import { ApiRegistry, ApiProvider, errorApiRef } from '@backstage/core'; -import { withLogCollector } from '@backstage/test-utils-core'; import GetBBoxPolyfill from '../utils/polyfills/getBBox'; -import { techRadarApiRef, TechRadar } from '../index'; -import RadarPage from './RadarPage'; +import { RadarPage } from './RadarPage'; +import { MockErrorApi, wrapInTestApp } from '@backstage/test-utils'; describe('RadarPage', () => { beforeAll(() => { @@ -35,24 +34,18 @@ describe('RadarPage', () => { }); it('should render a progress bar', async () => { - const errorApi = { post: () => {} }; - const techRadarApi = new TechRadar({ + const techRadarProps = { width: 1200, height: 800, svgProps: { 'data-testid': 'tech-radar-svg' }, - }); + }; const { getByTestId, queryByTestId } = render( - - - - - , + wrapInTestApp( + + + , + ), ); expect(getByTestId('progress')).toBeInTheDocument(); @@ -61,24 +54,18 @@ describe('RadarPage', () => { }); it('should render a header with a svg', async () => { - const errorApi = { post: () => {} }; - const techRadarApi = new TechRadar({ + const techRadarProps = { width: 1200, height: 800, svgProps: { 'data-testid': 'tech-radar-svg' }, - }); + }; const { getByText, getByTestId } = render( - - - - - , + wrapInTestApp( + + + , + ), ); await waitForElement(() => getByTestId('tech-radar-svg')); @@ -90,78 +77,29 @@ describe('RadarPage', () => { }); it('should call the errorApi if load fails', async () => { - const errorApi = { post: jest.fn() }; + const errorApi = new MockErrorApi({ collect: true }); const techRadarLoadFail = () => Promise.reject(new Error('404 Page Not Found')); - const techRadarApi = new TechRadar({ + const techRadarProps = { width: 1200, height: 800, getData: techRadarLoadFail, svgProps: { 'data-testid': 'tech-radar-svg' }, - }); + }; const { queryByTestId } = render( - - + + , ); await waitForElement(() => !queryByTestId('progress')); - expect(errorApi.post).toHaveBeenCalledTimes(1); - expect(errorApi.post).toHaveBeenCalledWith(new Error('404 Page Not Found')); + expect(errorApi.getErrors()).toEqual([ + { error: new Error('404 Page Not Found'), context: undefined }, + ]); expect(queryByTestId('tech-radar-svg')).not.toBeInTheDocument(); }); - - it('should not render without errorApiRef', () => { - const techRadarApi = new TechRadar({ - width: 1200, - height: 800, - }); - - expect( - withLogCollector(['error'], () => { - expect(() => { - render( - - - - - , - ); - }).toThrow(); - }).error[0], - ).toMatch( - /^Error: Uncaught \[Error: No implementation available for apiRef{core.error}\]/, - ); - }); - - it('should not render without techRadarApiRef', () => { - const errorApi = { post: () => {} }; - - expect( - withLogCollector(['error'], () => { - expect(() => { - render( - - - - - , - ); - }).toThrow(); - }).error[0], - ).toMatch( - /^Error: Uncaught \[Error: No implementation available for apiRef{plugin.techradar}\]/, - ); - }); }); diff --git a/plugins/tech-radar/src/components/RadarPage.tsx b/plugins/tech-radar/src/components/RadarPage.tsx index 1aefb72eca..519c9afeee 100644 --- a/plugins/tech-radar/src/components/RadarPage.tsx +++ b/plugins/tech-radar/src/components/RadarPage.tsx @@ -24,36 +24,46 @@ import { HeaderLabel, SupportButton, pageTheme, - useApi, } from '@backstage/core'; import RadarComponent from '../components/RadarComponent'; -import { techRadarApiRef, TechRadarApi } from '../api'; +import { TechRadarComponentProps } from '../api'; -const RadarPage = (): JSX.Element => { - const techRadarApi = useApi(techRadarApiRef); - - return ( - -
- - -
- - - - This is used for visualizing the official guidelines of different - areas of software development such as languages, frameworks, - infrastructure and processes. - - - - - - - - -
- ); +export type TechRadarPageProps = TechRadarComponentProps & { + title?: string; + subtitle?: string; + pageTitle?: string; }; -export default RadarPage; +export const RadarPage = ({ + title, + subtitle, + pageTitle, + ...props +}: TechRadarPageProps): JSX.Element => ( + +
+ + +
+ + + + This is used for visualizing the official guidelines of different + areas of software development such as languages, frameworks, + infrastructure and processes. + + + + + + + + +
+); + +RadarPage.defaultProps = { + title: 'Tech Radar', + subtitle: 'Pick the recommended technologies for your projects', + pageTitle: 'Company Radar', +}; diff --git a/plugins/tech-radar/src/index.ts b/plugins/tech-radar/src/index.ts index df22e57558..d7b4921e9a 100644 --- a/plugins/tech-radar/src/index.ts +++ b/plugins/tech-radar/src/index.ts @@ -16,6 +16,8 @@ export { plugin } from './plugin'; +export { RadarPage as Router } from './components/RadarPage'; + /** * The TypeScript API for configuring Tech Radar. */ diff --git a/plugins/tech-radar/src/plugin.ts b/plugins/tech-radar/src/plugin.ts index 3497a66f5d..d8dc41af2e 100644 --- a/plugins/tech-radar/src/plugin.ts +++ b/plugins/tech-radar/src/plugin.ts @@ -15,11 +15,7 @@ */ import { createPlugin } from '@backstage/core'; -import RadarPage from './components/RadarPage'; export const plugin = createPlugin({ id: 'tech-radar', - register({ router }) { - router.registerRoute('/tech-radar', RadarPage); - }, }); From 0ffed8b711aa0b62c5b59ff8e60cec95f6fad5c6 Mon Sep 17 00:00:00 2001 From: Ivan Shmidt Date: Mon, 7 Sep 2020 22:54:23 +0200 Subject: [PATCH 03/34] fix: 404 page --- packages/core-api/src/app/App.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core-api/src/app/App.tsx b/packages/core-api/src/app/App.tsx index bfa26b7547..ccdfc4fc7f 100644 --- a/packages/core-api/src/app/App.tsx +++ b/packages/core-api/src/app/App.tsx @@ -191,7 +191,7 @@ export class PrivateAppImpl implements BackstageApp { FeatureFlags.registeredFeatureFlags = registeredFeatureFlags; } - routes.push(} />); + routes.push(} />); return routes; } From 298851b31240fabcc1ba20bb126fb9f4e806c291 Mon Sep 17 00:00:00 2001 From: Ivan Shmidt Date: Mon, 7 Sep 2020 23:03:33 +0200 Subject: [PATCH 04/34] feat(plugin-explore): migrate to new routing api --- packages/app/src/App.tsx | 4 +++- .../templates/default-app/packages/app/src/App.tsx | 5 ++++- plugins/explore/package.json | 3 ++- plugins/explore/src/components/ExplorePluginPage.tsx | 6 ++---- plugins/explore/src/components/Router.tsx | 10 ++++++++++ plugins/explore/src/index.ts | 1 + plugins/explore/src/plugin.ts | 7 ++----- 7 files changed, 24 insertions(+), 12 deletions(-) create mode 100644 plugins/explore/src/components/Router.tsx diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 8ddf53783d..759901c11e 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -28,6 +28,7 @@ import { hot } from 'react-hot-loader/root'; import { providers } from './identityProviders'; import { Router as CatalogRouter } from '@backstage/plugin-catalog'; import { Router as DocsRouter } from '@backstage/plugin-techdocs'; +import { Router as ExploreRouter } from '@backstage/plugin-explore'; import { Route, Routes, Navigate } from 'react-router'; import { EntityPage } from './components/catalog/EntityPage'; @@ -55,12 +56,13 @@ const deprecatedAppRoutes = app.getRoutes(); const AppRoutes = () => ( + } /> } /> - + } /> {...deprecatedAppRoutes} ); diff --git a/packages/create-app/templates/default-app/packages/app/src/App.tsx b/packages/create-app/templates/default-app/packages/app/src/App.tsx index 3e6a0ef00e..cd03e20f06 100644 --- a/packages/create-app/templates/default-app/packages/app/src/App.tsx +++ b/packages/create-app/templates/default-app/packages/app/src/App.tsx @@ -11,6 +11,8 @@ import { AppSidebar } from './sidebar'; import { Route, Routes, Navigate } from 'react-router'; import { Router as CatalogRouter } from '@backstage/plugin-catalog'; import { Router as DocsRouter } from '@backstage/plugin-techdocs'; +import { Router as ExploreRouter } from '@backstage/plugin-explore'; + import { EntityPage } from './components/catalog/EntityPage'; const app = createApp({ @@ -30,12 +32,13 @@ const App: FC<{}> = () => ( + } /> } /> - + } /> {deprecatedAppRoutes} diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 42176c45cf..1a4a44b9cd 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -29,7 +29,8 @@ "classnames": "^2.2.6", "react": "^16.13.1", "react-dom": "^16.13.1", - "react-use": "^15.3.3" + "react-use": "^15.3.3", + "react-router": "6.0.0-beta.0" }, "devDependencies": { "@backstage/cli": "^0.1.1-alpha.21", diff --git a/plugins/explore/src/components/ExplorePluginPage.tsx b/plugins/explore/src/components/ExplorePluginPage.tsx index 3e073ad322..4365157f62 100644 --- a/plugins/explore/src/components/ExplorePluginPage.tsx +++ b/plugins/explore/src/components/ExplorePluginPage.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React, { FC } from 'react'; +import React from 'react'; import { makeStyles, Typography } from '@material-ui/core'; import { Content, @@ -107,7 +107,7 @@ const toolsCards = [ }, ]; -const ExplorePluginPage: FC<{}> = () => { +export const ExplorePluginPage = () => { const classes = useStyles(); return ( @@ -130,5 +130,3 @@ const ExplorePluginPage: FC<{}> = () => { ); }; - -export default ExplorePluginPage; diff --git a/plugins/explore/src/components/Router.tsx b/plugins/explore/src/components/Router.tsx new file mode 100644 index 0000000000..f2556b75ed --- /dev/null +++ b/plugins/explore/src/components/Router.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { Route, Routes } from 'react-router'; +import { ExplorePluginPage } from './ExplorePluginPage'; +import { rootRouteRef } from '../plugin'; + +export const Router = () => ( + + } /> + +); diff --git a/plugins/explore/src/index.ts b/plugins/explore/src/index.ts index 3a0a0fe2d3..ff7857cacd 100644 --- a/plugins/explore/src/index.ts +++ b/plugins/explore/src/index.ts @@ -15,3 +15,4 @@ */ export { plugin } from './plugin'; +export { Router } from './components/Router'; diff --git a/plugins/explore/src/plugin.ts b/plugins/explore/src/plugin.ts index 66e48a9b15..75ea892242 100644 --- a/plugins/explore/src/plugin.ts +++ b/plugins/explore/src/plugin.ts @@ -14,12 +14,9 @@ * limitations under the License. */ -import { createPlugin } from '@backstage/core'; -import ExplorePluginPage from './components/ExplorePluginPage'; +import { createPlugin, createRouteRef } from '@backstage/core'; +export const rootRouteRef = createRouteRef({ path: '', title: 'Explore' }); export const plugin = createPlugin({ id: 'explore', - register({ router }) { - router.registerRoute('/explore', ExplorePluginPage); - }, }); From 1486990b9100a03a7210052c6ee31d6339c7d80b Mon Sep 17 00:00:00 2001 From: Ivan Shmidt Date: Mon, 7 Sep 2020 23:28:00 +0200 Subject: [PATCH 05/34] fix: missing header --- plugins/explore/src/components/Router.tsx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/plugins/explore/src/components/Router.tsx b/plugins/explore/src/components/Router.tsx index f2556b75ed..becb2522d0 100644 --- a/plugins/explore/src/components/Router.tsx +++ b/plugins/explore/src/components/Router.tsx @@ -1,3 +1,19 @@ +/* + * 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 React from 'react'; import { Route, Routes } from 'react-router'; import { ExplorePluginPage } from './ExplorePluginPage'; From 2371529edda0e84d6fe50a21245166e7a04120f5 Mon Sep 17 00:00:00 2001 From: Ivan Shmidt Date: Tue, 8 Sep 2020 09:53:34 +0200 Subject: [PATCH 06/34] feat: remove explore plugin from app --- packages/app/src/App.tsx | 2 -- .../create-app/templates/default-app/packages/app/src/App.tsx | 2 -- 2 files changed, 4 deletions(-) diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 759901c11e..187ee27e3e 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -28,7 +28,6 @@ import { hot } from 'react-hot-loader/root'; import { providers } from './identityProviders'; import { Router as CatalogRouter } from '@backstage/plugin-catalog'; import { Router as DocsRouter } from '@backstage/plugin-techdocs'; -import { Router as ExploreRouter } from '@backstage/plugin-explore'; import { Route, Routes, Navigate } from 'react-router'; import { EntityPage } from './components/catalog/EntityPage'; @@ -62,7 +61,6 @@ const AppRoutes = () => ( element={} /> } /> - } /> {...deprecatedAppRoutes} ); diff --git a/packages/create-app/templates/default-app/packages/app/src/App.tsx b/packages/create-app/templates/default-app/packages/app/src/App.tsx index cd03e20f06..ba43c351b2 100644 --- a/packages/create-app/templates/default-app/packages/app/src/App.tsx +++ b/packages/create-app/templates/default-app/packages/app/src/App.tsx @@ -11,7 +11,6 @@ import { AppSidebar } from './sidebar'; import { Route, Routes, Navigate } from 'react-router'; import { Router as CatalogRouter } from '@backstage/plugin-catalog'; import { Router as DocsRouter } from '@backstage/plugin-techdocs'; -import { Router as ExploreRouter } from '@backstage/plugin-explore'; import { EntityPage } from './components/catalog/EntityPage'; @@ -38,7 +37,6 @@ const App: FC<{}> = () => ( element={} /> } /> - } /> {deprecatedAppRoutes} From 493e8052b8c8d6802fb44408931ed50d6ed43204 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 8 Sep 2020 10:28:17 +0200 Subject: [PATCH 07/34] graphiql: move to new plugin pattern --- packages/app/src/App.tsx | 2 ++ .../graphiql/src/components/GraphiQLPage/GraphiQLPage.tsx | 4 ++-- plugins/graphiql/src/index.ts | 1 + plugins/graphiql/src/plugin.ts | 5 ----- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index aa6727c859..3d4f297e8e 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -28,6 +28,7 @@ import { hot } from 'react-hot-loader/root'; import { providers } from './identityProviders'; import { Router as CatalogRouter } from '@backstage/plugin-catalog'; import { Router as DocsRouter } from '@backstage/plugin-techdocs'; +import { Router as GraphiQLRouter } from '@backstage/plugin-graphiql'; import { Router as TechRadarRouter } from '@backstage/plugin-tech-radar'; import { Route, Routes, Navigate } from 'react-router'; @@ -66,6 +67,7 @@ const AppRoutes = () => ( path="/tech-radar" element={} /> + } /> {...deprecatedAppRoutes} ); diff --git a/plugins/graphiql/src/components/GraphiQLPage/GraphiQLPage.tsx b/plugins/graphiql/src/components/GraphiQLPage/GraphiQLPage.tsx index a16fdf3ee6..7eb91b59d8 100644 --- a/plugins/graphiql/src/components/GraphiQLPage/GraphiQLPage.tsx +++ b/plugins/graphiql/src/components/GraphiQLPage/GraphiQLPage.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React, { FC } from 'react'; +import React from 'react'; import { Content, Header, @@ -30,7 +30,7 @@ import { graphQlBrowseApiRef } from '../../lib/api'; import { GraphiQLBrowser } from '../GraphiQLBrowser'; import { Typography } from '@material-ui/core'; -export const GraphiQLPage: FC<{}> = () => { +export const GraphiQLPage = () => { const graphQlBrowseApi = useApi(graphQlBrowseApiRef); const endpoints = useAsync(() => graphQlBrowseApi.getEndpoints()); diff --git a/plugins/graphiql/src/index.ts b/plugins/graphiql/src/index.ts index e7614aba81..50698cdb4c 100644 --- a/plugins/graphiql/src/index.ts +++ b/plugins/graphiql/src/index.ts @@ -15,5 +15,6 @@ */ export { plugin } from './plugin'; +export { GraphiQLPage as Router } from './components'; export * from './lib/api'; export * from './route-refs'; diff --git a/plugins/graphiql/src/plugin.ts b/plugins/graphiql/src/plugin.ts index f118faf871..7763284d81 100644 --- a/plugins/graphiql/src/plugin.ts +++ b/plugins/graphiql/src/plugin.ts @@ -15,12 +15,7 @@ */ import { createPlugin } from '@backstage/core'; -import { GraphiQLPage } from './components'; -import { graphiQLRouteRef } from './route-refs'; export const plugin = createPlugin({ id: 'graphiql', - register({ router }) { - router.addRoute(graphiQLRouteRef, GraphiQLPage); - }, }); From d4505128cb470931b4654e3cb32c924d97c390f2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 3 Sep 2020 17:18:01 +0200 Subject: [PATCH 08/34] core-api: remove save functionality from ApiTestRegistry + any type --- .../core-api/src/apis/ApiTestRegistry.test.ts | 36 ------------------- packages/core-api/src/apis/ApiTestRegistry.ts | 27 +++++--------- packages/core-api/src/apis/helpers.ts | 4 +-- packages/core-api/src/apis/types.ts | 6 ++-- 4 files changed, 14 insertions(+), 59 deletions(-) diff --git a/packages/core-api/src/apis/ApiTestRegistry.test.ts b/packages/core-api/src/apis/ApiTestRegistry.test.ts index fa42e64707..a4fbf1b144 100644 --- a/packages/core-api/src/apis/ApiTestRegistry.test.ts +++ b/packages/core-api/src/apis/ApiTestRegistry.test.ts @@ -37,26 +37,6 @@ describe('ApiTestRegistry', () => { expect(registry.get(cRef)).toBe(undefined); }); - it('should remove factories when resetting', () => { - const registry = new ApiTestRegistry(); - registry.register({ implements: aRef, deps: {}, factory: () => 3 }); - expect(registry.get(aRef)).toBe(3); - registry.reset(); - expect(registry.get(aRef)).toBe(undefined); - }); - - it('should keep saved factories when resetting', () => { - const registry = new ApiTestRegistry(); - registry.register({ implements: aRef, deps: {}, factory: () => 3 }); - registry.save(); - registry.register({ implements: bRef, deps: {}, factory: () => 'x' }); - expect(registry.get(aRef)).toBe(3); - expect(registry.get(bRef)).toBe('x'); - registry.reset(); - expect(registry.get(aRef)).toBe(3); - expect(registry.get(bRef)).toBe(undefined); - }); - it('should register factories with dependencies', () => { // 100% coverage + happy typescript = hasOwnProperty + this atrocity const cDeps = Object.create( @@ -135,20 +115,4 @@ describe('ApiTestRegistry', () => { expect(registry.get(aRef)).toBe(2); expect(factory).toHaveBeenCalledTimes(1); }); - - it('should call factory again after reset', () => { - const registry = new ApiTestRegistry(); - const factory = jest.fn().mockReturnValue(2); - registry.register({ implements: aRef, deps: {}, factory }); - registry.save(); - - expect(factory).toHaveBeenCalledTimes(0); - expect(registry.get(aRef)).toBe(2); - expect(factory).toHaveBeenCalledTimes(1); - expect(registry.get(aRef)).toBe(2); - expect(factory).toHaveBeenCalledTimes(1); - registry.reset(); - expect(registry.get(aRef)).toBe(2); - expect(factory).toHaveBeenCalledTimes(2); - }); }); diff --git a/packages/core-api/src/apis/ApiTestRegistry.ts b/packages/core-api/src/apis/ApiTestRegistry.ts index 7aed3c7917..6c85db056c 100644 --- a/packages/core-api/src/apis/ApiTestRegistry.ts +++ b/packages/core-api/src/apis/ApiTestRegistry.ts @@ -15,18 +15,17 @@ */ import { ApiRef } from './ApiRef'; -import { TypesToApiRefs, AnyApiRef, ApiHolder, ApiFactory } from './types'; +import { + TypesToApiRefs, + AnyApiRef, + ApiHolder, + ApiFactory, + AnyApiFactory, +} from './types'; export class ApiTestRegistry implements ApiHolder { private readonly apis = new Map(); - private factories = new Map< - AnyApiRef, - ApiFactory - >(); - private savedFactories = new Map< - AnyApiRef, - ApiFactory - >(); + private factories = new Map(); get(ref: ApiRef): T | undefined { return this.load(ref); @@ -37,16 +36,6 @@ export class ApiTestRegistry implements ApiHolder { return this; } - reset() { - this.factories = this.savedFactories; - this.apis.clear(); - } - - save(): ApiTestRegistry { - this.savedFactories = new Map(this.factories); - return this; - } - private load(ref: ApiRef, loading: AnyApiRef[] = []): T | undefined { const impl = this.apis.get(ref); if (impl) { diff --git a/packages/core-api/src/apis/helpers.ts b/packages/core-api/src/apis/helpers.ts index d8f8e8ac11..e2274a20f1 100644 --- a/packages/core-api/src/apis/helpers.ts +++ b/packages/core-api/src/apis/helpers.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { ApiFactory } from './types'; +import { AnyApiFactory, ApiFactory } from './types'; /** * Used to infer types for a standalone ApiFactory that isn't immediately passed @@ -23,6 +23,6 @@ import { ApiFactory } from './types'; */ export function createApiFactory( factory: ApiFactory, -): ApiFactory { +): AnyApiFactory { return factory; } diff --git a/packages/core-api/src/apis/types.ts b/packages/core-api/src/apis/types.ts index 4ee9b39ca9..52355f5396 100644 --- a/packages/core-api/src/apis/types.ts +++ b/packages/core-api/src/apis/types.ts @@ -16,13 +16,13 @@ import { ApiRef } from './ApiRef'; -export type AnyApiRef = ApiRef; +export type AnyApiRef = ApiRef; export type ApiRefType = T extends ApiRef ? U : never; export type TypesToApiRefs = { [key in keyof T]: ApiRef }; -export type ApiRefsToTypes }> = { +export type ApiRefsToTypes }> = { [key in keyof T]: ApiRefType; }; @@ -35,3 +35,5 @@ export type ApiFactory = { deps: TypesToApiRefs; factory(deps: Deps): Impl extends Api ? Impl : never; }; + +export type AnyApiFactory = ApiFactory; From 98b626fefb39f8322de0d3ece536c23fd0834eae Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 4 Sep 2020 10:14:24 +0200 Subject: [PATCH 09/34] core-api: added ApiFactoryRegistry --- .../src/apis/ApiFactoryRegistry.test.ts | 66 +++++++++++++++++ .../core-api/src/apis/ApiFactoryRegistry.ts | 71 +++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 packages/core-api/src/apis/ApiFactoryRegistry.test.ts create mode 100644 packages/core-api/src/apis/ApiFactoryRegistry.ts diff --git a/packages/core-api/src/apis/ApiFactoryRegistry.test.ts b/packages/core-api/src/apis/ApiFactoryRegistry.test.ts new file mode 100644 index 0000000000..43370f41a7 --- /dev/null +++ b/packages/core-api/src/apis/ApiFactoryRegistry.test.ts @@ -0,0 +1,66 @@ +/* + * 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 { ApiFactoryRegistry } from './ApiFactoryRegistry'; +import { createApiRef } from './ApiRef'; + +const aRef = createApiRef({ id: 'a', description: '' }); +const aFactory1 = { implements: aRef, deps: {}, factory: () => 1 }; +const aFactory2 = { implements: aRef, deps: {}, factory: () => 2 }; +const bRef = createApiRef({ id: 'b', description: '' }); +const bFactory = { implements: bRef, deps: {}, factory: () => 'x' }; +const cRef = createApiRef({ id: 'c', description: '' }); +const cFactory = { implements: cRef, deps: {}, factory: () => 'y' }; + +describe('ApiFactoryRegistry', () => { + it('should be empty when created', () => { + const registry = new ApiFactoryRegistry(); + expect(registry.getAllApis()).toEqual(new Set()); + }); + + it('should register a factory', () => { + const registry = new ApiFactoryRegistry(); + expect(registry.register('default', aFactory1)).toBe(true); + expect(registry.get(aRef)).toBe(aFactory1); + expect(registry.getAllApis()).toEqual(new Set([aRef])); + }); + + it('should prioritize factories based on scope', () => { + const registry = new ApiFactoryRegistry(); + expect(registry.register('default', aFactory1)).toBe(true); + expect(registry.get(aRef)).toBe(aFactory1); + expect(registry.register('app', aFactory2)).toBe(true); + expect(registry.get(aRef)).toBe(aFactory2); + expect(registry.register('default', aFactory1)).toBe(false); + expect(registry.get(aRef)).toBe(aFactory2); + expect(registry.register('static', aFactory1)).toBe(true); + expect(registry.get(aRef)).toBe(aFactory1); + expect(registry.register('app', aFactory2)).toBe(false); + expect(registry.get(aRef)).toBe(aFactory1); + expect(registry.getAllApis()).toEqual(new Set([aRef])); + }); + + it('should register multiple factories without conflict', () => { + const registry = new ApiFactoryRegistry(); + expect(registry.register('static', aFactory1)).toBe(true); + expect(registry.register('default', bFactory)).toBe(true); + expect(registry.register('app', cFactory)).toBe(true); + expect(registry.get(aRef)).toBe(aFactory1); + expect(registry.get(bRef)).toBe(bFactory); + expect(registry.get(cRef)).toBe(cFactory); + expect(registry.getAllApis()).toEqual(new Set([aRef, bRef, cRef])); + }); +}); diff --git a/packages/core-api/src/apis/ApiFactoryRegistry.ts b/packages/core-api/src/apis/ApiFactoryRegistry.ts new file mode 100644 index 0000000000..b81b560220 --- /dev/null +++ b/packages/core-api/src/apis/ApiFactoryRegistry.ts @@ -0,0 +1,71 @@ +/* + * 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 { + ApiFactoryHolder, + ApiFactory, + AnyApiRef, + AnyApiFactory, +} from './types'; +import { ApiRef } from './ApiRef'; + +type ApiFactoryScope = + | 'default' // Default factories registered by core and plugins + | 'app' // Factories registered in the app, overriding default ones + | 'static'; // APIs that can't be overridden, e.g. config + +enum ScopeLevels { + default = 10, + app = 50, + static = 100, +} + +type FactoryTuple = { + level: number; + factory: AnyApiFactory; +}; + +export class ApiFactoryRegistry implements ApiFactoryHolder { + private readonly factories = new Map(); + + register( + scope: ApiFactoryScope, + factory: ApiFactory, + ) { + const level = ScopeLevels[scope]; + const existing = this.factories.get(factory.implements); + if (existing && existing.level > level) { + return false; + } + + this.factories.set(factory.implements, { level, factory }); + return true; + } + + get( + api: ApiRef, + ): ApiFactory | undefined { + const tuple = this.factories.get(api); + if (!tuple) { + return undefined; + } + return tuple.factory as ApiFactory; + } + + getAllApis(): Set { + return new Set(this.factories.keys()); + } +} From d0567352a53d4c6a487176dba881a04b4d212b64 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 4 Sep 2020 10:28:21 +0200 Subject: [PATCH 10/34] core-api: refine api types and add ApiFactoryHolder --- packages/core-api/src/apis/types.ts | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/packages/core-api/src/apis/types.ts b/packages/core-api/src/apis/types.ts index 52355f5396..bb09fbecae 100644 --- a/packages/core-api/src/apis/types.ts +++ b/packages/core-api/src/apis/types.ts @@ -22,7 +22,7 @@ export type ApiRefType = T extends ApiRef ? U : never; export type TypesToApiRefs = { [key in keyof T]: ApiRef }; -export type ApiRefsToTypes }> = { +export type ApiRefsToTypes }> = { [key in keyof T]: ApiRefType; }; @@ -30,10 +30,24 @@ export type ApiHolder = { get(api: ApiRef): T | undefined; }; -export type ApiFactory = { +export type ApiFactory< + Api, + Impl, + Deps extends { [name in string]: unknown } +> = { implements: ApiRef; deps: TypesToApiRefs; factory(deps: Deps): Impl extends Api ? Impl : never; }; -export type AnyApiFactory = ApiFactory; +export type AnyApiFactory = ApiFactory< + unknown, + unknown, + { [key in string]: unknown } +>; + +export type ApiFactoryHolder = { + get( + api: ApiRef, + ): ApiFactory | undefined; +}; From b9e838c8b7f94154c430d2ed21b5fd7f8186dbba Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 4 Sep 2020 15:42:53 +0200 Subject: [PATCH 11/34] core-api: added ApiResolver --- .../core-api/src/apis/ApiResolver.test.ts | 177 ++++++++++++++++++ packages/core-api/src/apis/ApiResolver.ts | 115 ++++++++++++ 2 files changed, 292 insertions(+) create mode 100644 packages/core-api/src/apis/ApiResolver.test.ts create mode 100644 packages/core-api/src/apis/ApiResolver.ts diff --git a/packages/core-api/src/apis/ApiResolver.test.ts b/packages/core-api/src/apis/ApiResolver.test.ts new file mode 100644 index 0000000000..ab4a571cd5 --- /dev/null +++ b/packages/core-api/src/apis/ApiResolver.test.ts @@ -0,0 +1,177 @@ +/* + * 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 { ApiResolver } from './ApiResolver'; +import { createApiRef } from './ApiRef'; +import { ApiFactoryRegistry } from './ApiFactoryRegistry'; + +const aRef = createApiRef({ id: 'a', description: '' }); +const bRef = createApiRef({ id: 'b', description: '' }); +const cRef = createApiRef<{ x: string }>({ id: 'c', description: '' }); + +function createRegistry() { + const registry = new ApiFactoryRegistry(); + registry.register('default', { + implements: aRef, + deps: {}, + factory: () => 1, + }); + registry.register('default', { + implements: bRef, + deps: {}, + factory: () => 'b', + }); + registry.register('default', { + implements: cRef, + deps: { b: bRef }, + factory: ({ b }) => ({ x: 'x', b }), + }); + return registry; +} + +function createLongCyclicRegistry() { + const registry = new ApiFactoryRegistry(); + registry.register('default', { + implements: aRef, + deps: { b: bRef }, + factory: () => 1, + }); + registry.register('default', { + implements: bRef, + deps: { c: cRef }, + factory: () => 'b', + }); + registry.register('default', { + implements: cRef, + deps: { a: aRef }, + factory: () => ({ x: 'x' }), + }); + return registry; +} + +function createShortCyclicRegistry() { + const registry = new ApiFactoryRegistry(); + registry.register('default', { + implements: aRef, + deps: { a: aRef }, + factory: () => 1, + }); + registry.register('default', { + implements: bRef, + deps: { c: cRef }, + factory: () => 'b', + }); + registry.register('default', { + implements: cRef, + deps: { b: bRef }, + factory: () => ({ x: 'x' }), + }); + return registry; +} + +describe('ApiResolver', () => { + it('should be created empty', () => { + const resolver = new ApiResolver(new ApiFactoryRegistry()); + expect(resolver.get(aRef)).toBe(undefined); + expect(resolver.get(bRef)).toBe(undefined); + expect(resolver.get(cRef)).toBe(undefined); + }); + + it('should instantiate APIs', () => { + const resolver = new ApiResolver(createRegistry()); + expect(resolver.get(aRef)).toBe(1); + expect(resolver.get(bRef)).toBe('b'); + expect(resolver.get(cRef)).toEqual({ x: 'x', b: 'b' }); + expect(resolver.get(cRef)).toBe(resolver.get(cRef)); + }); + + it('should detect long dependency cycles', () => { + const resolver = new ApiResolver(createLongCyclicRegistry()); + expect(() => resolver.get(aRef)).toThrow( + 'Circular dependency of api factory for apiRef{a}', + ); + // Second call for same ref should still throw + expect(() => resolver.get(aRef)).toThrow( + 'Circular dependency of api factory for apiRef{a}', + ); + expect(() => resolver.get(bRef)).toThrow( + 'Circular dependency of api factory for apiRef{b}', + ); + expect(() => resolver.get(cRef)).toThrow( + 'Circular dependency of api factory for apiRef{c}', + ); + }); + + it('should detect short dependency cycles', () => { + const resolver = new ApiResolver(createShortCyclicRegistry()); + expect(() => resolver.get(aRef)).toThrow( + 'Circular dependency of api factory for apiRef{a}', + ); + expect(() => resolver.get(bRef)).toThrow( + 'Circular dependency of api factory for apiRef{b}', + ); + expect(() => resolver.get(cRef)).toThrow( + 'Circular dependency of api factory for apiRef{c}', + ); + }); + + it('should validate a factory holder', () => { + expect(() => { + ApiResolver.validateFactories(createRegistry(), [aRef, bRef, cRef]); + }).not.toThrow(); + }); + + it('should find dependency cycles with validation', () => { + const short = createShortCyclicRegistry(); + expect(() => + ApiResolver.validateFactories(short, short.getAllApis()), + ).toThrow('Circular dependency of api factory for apiRef{a}'); + expect(() => ApiResolver.validateFactories(short, [bRef])).toThrow( + 'Circular dependency of api factory for apiRef{b}', + ); + expect(() => ApiResolver.validateFactories(short, [cRef])).toThrow( + 'Circular dependency of api factory for apiRef{c}', + ); + + const long = createLongCyclicRegistry(); + expect(() => + ApiResolver.validateFactories(long, long.getAllApis()), + ).toThrow('Circular dependency of api factory for apiRef{a}'); + expect(() => ApiResolver.validateFactories(long, [bRef])).toThrow( + 'Circular dependency of api factory for apiRef{b}', + ); + expect(() => ApiResolver.validateFactories(long, [cRef])).toThrow( + 'Circular dependency of api factory for apiRef{c}', + ); + }); + + it('should only call factory func once', () => { + const registry = new ApiFactoryRegistry(); + const factory = jest.fn().mockReturnValue(2); + registry.register('default', { + implements: aRef, + deps: {}, + factory, + }); + + const resolver = new ApiResolver(registry); + expect(factory).toHaveBeenCalledTimes(0); + expect(resolver.get(aRef)).toBe(2); + expect(factory).toHaveBeenCalledTimes(1); + expect(resolver.get(aRef)).toBe(2); + expect(factory).toHaveBeenCalledTimes(1); + }); +}); diff --git a/packages/core-api/src/apis/ApiResolver.ts b/packages/core-api/src/apis/ApiResolver.ts new file mode 100644 index 0000000000..9f48a75783 --- /dev/null +++ b/packages/core-api/src/apis/ApiResolver.ts @@ -0,0 +1,115 @@ +/* + * 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 } from './ApiRef'; +import { + ApiHolder, + ApiFactoryHolder, + AnyApiRef, + TypesToApiRefs, +} from './types'; + +export class ApiResolver implements ApiHolder { + private readonly apis = new Map(); + + /** + * Validate factories by making sure that each of the apis can be created + * without hitting any circular dependencies. + */ + static validateFactories( + factories: ApiFactoryHolder, + apis: Iterable, + ) { + for (const api of apis) { + const heap = [api]; + const allDeps = new Set(); + + while (heap.length) { + const apiRef = heap.shift()!; + const factory = factories.get(apiRef); + if (!factory) { + continue; + } + + for (const dep of Object.values(factory.deps)) { + if (dep === api) { + throw new Error(`Circular dependency of api factory for ${api}`); + } + if (!allDeps.has(dep)) { + allDeps.add(dep); + heap.push(dep); + } + } + } + } + } + + constructor(private readonly factories: ApiFactoryHolder) {} + + get(ref: ApiRef): T | undefined { + return this.load(ref); + } + + private load(ref: ApiRef, loading: AnyApiRef[] = []): T | undefined { + const impl = this.apis.get(ref); + if (impl) { + return impl as T; + } + + const factory = this.factories.get(ref); + if (!factory) { + return undefined; + } + + if (loading.includes(factory.implements)) { + throw new Error( + `Circular dependency of api factory for ${factory.implements}`, + ); + } + + const deps = this.loadDeps(ref, factory.deps, [ + ...loading, + factory.implements, + ]); + const api = factory.factory(deps); + this.apis.set(ref, api); + return api as T; + } + + private loadDeps( + dependent: ApiRef, + apis: TypesToApiRefs, + loading: AnyApiRef[], + ): T { + const impls = {} as T; + + for (const key in apis) { + if (apis.hasOwnProperty(key)) { + const ref = apis[key]; + + const api = this.load(ref, loading); + if (!api) { + throw new Error( + `No API factory available for dependency ${ref} of dependent ${dependent}`, + ); + } + impls[key] = api; + } + } + + return impls; + } +} From d1eeb01b016efa5485353aa6936000b4fbb4a580 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 4 Sep 2020 15:44:18 +0200 Subject: [PATCH 12/34] core-api: overload createApiFactory with a singleton helper --- packages/core-api/src/apis/helpers.ts | 30 +++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/packages/core-api/src/apis/helpers.ts b/packages/core-api/src/apis/helpers.ts index e2274a20f1..95be80e541 100644 --- a/packages/core-api/src/apis/helpers.ts +++ b/packages/core-api/src/apis/helpers.ts @@ -14,15 +14,37 @@ * limitations under the License. */ -import { AnyApiFactory, ApiFactory } from './types'; +import { ApiFactory } from './types'; +import { ApiRef } from './ApiRef'; /** * Used to infer types for a standalone ApiFactory that isn't immediately passed * to another function. * This function doesn't actually do anything, it's only used to infer types. */ -export function createApiFactory( - factory: ApiFactory, -): AnyApiFactory { +export function createApiFactory< + Api, + Impl extends Api, + Deps extends { [name in string]: unknown } +>(factory: ApiFactory): ApiFactory; +export function createApiFactory( + api: ApiRef, + instance: Impl, +): ApiFactory; +export function createApiFactory< + Api, + Impl extends Api, + Deps extends { [name in string]: unknown } +>( + factory: ApiFactory | ApiRef, + instance?: Impl, +): ApiFactory { + if ('id' in factory) { + return ({ + implements: factory, + deps: {}, + factory: () => instance!, + } as unknown) as ApiFactory; + } return factory; } From 4e390d6e9df89623477d0a1d058b4b9a381fd4f5 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 4 Sep 2020 15:54:32 +0200 Subject: [PATCH 13/34] core-api: simplify ApiFactory type --- .../core-api/src/apis/ApiFactoryRegistry.ts | 10 ++++---- packages/core-api/src/apis/ApiTestRegistry.ts | 4 +++- packages/core-api/src/apis/helpers.ts | 23 +++++++++---------- packages/core-api/src/apis/types.ts | 16 ++++--------- 4 files changed, 22 insertions(+), 31 deletions(-) diff --git a/packages/core-api/src/apis/ApiFactoryRegistry.ts b/packages/core-api/src/apis/ApiFactoryRegistry.ts index b81b560220..9d75944d8b 100644 --- a/packages/core-api/src/apis/ApiFactoryRegistry.ts +++ b/packages/core-api/src/apis/ApiFactoryRegistry.ts @@ -41,9 +41,9 @@ type FactoryTuple = { export class ApiFactoryRegistry implements ApiFactoryHolder { private readonly factories = new Map(); - register( + register( scope: ApiFactoryScope, - factory: ApiFactory, + factory: ApiFactory, ) { const level = ScopeLevels[scope]; const existing = this.factories.get(factory.implements); @@ -55,14 +55,12 @@ export class ApiFactoryRegistry implements ApiFactoryHolder { return true; } - get( - api: ApiRef, - ): ApiFactory | undefined { + get(api: ApiRef): ApiFactory | undefined { const tuple = this.factories.get(api); if (!tuple) { return undefined; } - return tuple.factory as ApiFactory; + return tuple.factory as ApiFactory; } getAllApis(): Set { diff --git a/packages/core-api/src/apis/ApiTestRegistry.ts b/packages/core-api/src/apis/ApiTestRegistry.ts index 6c85db056c..d41d959e99 100644 --- a/packages/core-api/src/apis/ApiTestRegistry.ts +++ b/packages/core-api/src/apis/ApiTestRegistry.ts @@ -31,7 +31,9 @@ export class ApiTestRegistry implements ApiHolder { return this.load(ref); } - register(factory: ApiFactory): ApiTestRegistry { + register( + factory: ApiFactory, + ): ApiTestRegistry { this.factories.set(factory.implements, factory); return this; } diff --git a/packages/core-api/src/apis/helpers.ts b/packages/core-api/src/apis/helpers.ts index 95be80e541..dda6c57fb0 100644 --- a/packages/core-api/src/apis/helpers.ts +++ b/packages/core-api/src/apis/helpers.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { ApiFactory } from './types'; +import { ApiFactory, TypesToApiRefs } from './types'; import { ApiRef } from './ApiRef'; /** @@ -26,25 +26,24 @@ export function createApiFactory< Api, Impl extends Api, Deps extends { [name in string]: unknown } ->(factory: ApiFactory): ApiFactory; -export function createApiFactory( +>(factory: ApiFactory): ApiFactory; +export function createApiFactory( api: ApiRef, - instance: Impl, -): ApiFactory; + instance: Api, +): ApiFactory; export function createApiFactory< Api, - Impl extends Api, Deps extends { [name in string]: unknown } >( - factory: ApiFactory | ApiRef, - instance?: Impl, -): ApiFactory { + factory: ApiFactory | ApiRef, + instance?: Api, +): ApiFactory { if ('id' in factory) { - return ({ + return { implements: factory, - deps: {}, + deps: {} as TypesToApiRefs, factory: () => instance!, - } as unknown) as ApiFactory; + }; } return factory; } diff --git a/packages/core-api/src/apis/types.ts b/packages/core-api/src/apis/types.ts index bb09fbecae..5b2956cfa1 100644 --- a/packages/core-api/src/apis/types.ts +++ b/packages/core-api/src/apis/types.ts @@ -30,24 +30,16 @@ export type ApiHolder = { get(api: ApiRef): T | undefined; }; -export type ApiFactory< - Api, - Impl, - Deps extends { [name in string]: unknown } -> = { +export type ApiFactory = { implements: ApiRef; deps: TypesToApiRefs; - factory(deps: Deps): Impl extends Api ? Impl : never; + factory(deps: Deps): Api; }; -export type AnyApiFactory = ApiFactory< - unknown, - unknown, - { [key in string]: unknown } ->; +export type AnyApiFactory = ApiFactory; export type ApiFactoryHolder = { get( api: ApiRef, - ): ApiFactory | undefined; + ): ApiFactory | undefined; }; From c8faa6a73da331148adfe215ea52f8853730f9a7 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 4 Sep 2020 16:08:04 +0200 Subject: [PATCH 14/34] core-api,app: switch to auto DI with ApiResolver and ApiFactories --- packages/app/src/apis.ts | 293 ++++++++++--------- packages/core-api/src/app/App.tsx | 103 ++++--- packages/core-api/src/app/types.ts | 19 +- packages/core/src/api-wrappers/createApp.tsx | 4 +- 4 files changed, 235 insertions(+), 184 deletions(-) diff --git a/packages/app/src/apis.ts b/packages/app/src/apis.ts index b79a6850bd..77252ac458 100644 --- a/packages/app/src/apis.ts +++ b/packages/app/src/apis.ts @@ -15,11 +15,9 @@ */ import { - ApiRegistry, alertApiRef, errorApiRef, AlertApiForwarder, - ConfigApi, ErrorApiForwarder, ErrorAlerter, featureFlagsApiRef, @@ -44,6 +42,8 @@ import { microsoftAuthApiRef, storageApiRef, WebStorage, + createApiFactory, + configApiRef, } from '@backstage/core'; import { @@ -82,135 +82,162 @@ import { githubPullRequestsApiRef, } from '@roadiehq/backstage-plugin-github-pull-requests'; -export const apis = (config: ConfigApi) => { - // eslint-disable-next-line no-console - console.log(`Creating APIs for ${config.getString('app.title')}`); - - const backendUrl = config.getString('backend.baseUrl'); - const techdocsUrl = config.getString('techdocs.storageUrl'); - - const builder = ApiRegistry.builder(); - - const discoveryApi = builder.add( - discoveryApiRef, - UrlPatternDiscovery.compile(`${backendUrl}/{{ pluginId }}`), - ); - const alertApi = builder.add(alertApiRef, new AlertApiForwarder()); - const errorApi = builder.add( - errorApiRef, - new ErrorAlerter(alertApi, new ErrorApiForwarder()), - ); - - builder.add(storageApiRef, WebStorage.create({ errorApi })); - builder.add(GCPApiRef, new GCPClient()); - builder.add( - circleCIApiRef, - new CircleCIApi(`${backendUrl}/proxy/circleci/api`), - ); - - builder.add(jenkinsApiRef, new JenkinsApi(`${backendUrl}/proxy/jenkins/api`)); - - builder.add(githubActionsApiRef, new GithubActionsClient()); - - builder.add(featureFlagsApiRef, new FeatureFlags()); - - builder.add(lighthouseApiRef, LighthouseRestApi.fromConfig(config)); - - builder.add(travisCIApiRef, new TravisCIApi()); - builder.add(githubPullRequestsApiRef, new GithubPullRequestsClient()); - - const oauthRequestApi = builder.add( - oauthRequestApiRef, - new OAuthRequestManager(), - ); - - builder.add( - googleAuthApiRef, - GoogleAuth.create({ - discoveryApi, - oauthRequestApi, - }), - ); - - builder.add( - microsoftAuthApiRef, - MicrosoftAuth.create({ - discoveryApi, - oauthRequestApi, - }), - ); - - const githubAuthApi = builder.add( - githubAuthApiRef, - GithubAuth.create({ - discoveryApi, - oauthRequestApi, - }), - ); - - builder.add( - oktaAuthApiRef, - OktaAuth.create({ - discoveryApi, - oauthRequestApi, - }), - ); - - builder.add( - gitlabAuthApiRef, - GitlabAuth.create({ - discoveryApi, - oauthRequestApi, - }), - ); - - builder.add( - auth0AuthApiRef, - Auth0Auth.create({ - discoveryApi, - oauthRequestApi, - }), - ); - - builder.add( - oauth2ApiRef, - OAuth2.create({ - discoveryApi, - oauthRequestApi, - }), - ); - - builder.add(catalogApiRef, new CatalogClient({ discoveryApi })); - - builder.add(scaffolderApiRef, new ScaffolderApi({ discoveryApi })); - - builder.add(gitOpsApiRef, new GitOpsRestApi('http://localhost:3008')); - - builder.add( - graphQlBrowseApiRef, - GraphQLEndpoints.from([ - GraphQLEndpoints.create({ - id: 'gitlab', - title: 'GitLab', - url: 'https://gitlab.com/api/graphql', +export const apis = [ + createApiFactory(alertApiRef, new AlertApiForwarder()), + createApiFactory({ + implements: errorApiRef, + deps: { alertApi: alertApiRef }, + factory: ({ alertApi }) => + new ErrorAlerter(alertApi, new ErrorApiForwarder()), + }), + createApiFactory({ + implements: storageApiRef, + deps: { errorApi: errorApiRef }, + factory: ({ errorApi }) => WebStorage.create({ errorApi }), + }), + createApiFactory({ + implements: discoveryApiRef, + deps: { configApi: configApiRef }, + factory: ({ configApi }) => + UrlPatternDiscovery.compile( + `${configApi.getString('backend.baseUrl')}/{{ pluginId }}`, + ), + }), + createApiFactory(GCPApiRef, new GCPClient()), + createApiFactory({ + implements: circleCIApiRef, + deps: { configApi: configApiRef }, + factory: ({ configApi }) => + new CircleCIApi( + `${configApi.getString('backend.baseUrl')}/proxy/circleci/api`, + ), + }), + createApiFactory({ + implements: jenkinsApiRef, + deps: { configApi: configApiRef }, + factory: ({ configApi }) => + new JenkinsApi( + `${configApi.getString('backend.baseUrl')}/proxy/jenkins/api`, + ), + }), + createApiFactory(githubActionsApiRef, new GithubActionsClient()), + createApiFactory(featureFlagsApiRef, new FeatureFlags()), + createApiFactory({ + implements: lighthouseApiRef, + deps: { configApi: configApiRef }, + factory: ({ configApi }) => LighthouseRestApi.fromConfig(configApi), + }), + createApiFactory(travisCIApiRef, new TravisCIApi()), + createApiFactory(githubPullRequestsApiRef, new GithubPullRequestsClient()), + createApiFactory(oauthRequestApiRef, new OAuthRequestManager()), + createApiFactory({ + implements: techRadarApiRef, + deps: {}, + factory: () => new TechRadar({ width: 1500, height: 800 }), + }), + createApiFactory({ + implements: googleAuthApiRef, + deps: { + discoveryApi: discoveryApiRef, + oauthRequestApi: oauthRequestApiRef, + }, + factory: ({ discoveryApi, oauthRequestApi }) => + GoogleAuth.create({ discoveryApi, oauthRequestApi }), + }), + createApiFactory({ + implements: microsoftAuthApiRef, + deps: { + discoveryApi: discoveryApiRef, + oauthRequestApi: oauthRequestApiRef, + }, + factory: ({ discoveryApi, oauthRequestApi }) => + MicrosoftAuth.create({ discoveryApi, oauthRequestApi }), + }), + createApiFactory({ + implements: githubAuthApiRef, + deps: { + discoveryApi: discoveryApiRef, + oauthRequestApi: oauthRequestApiRef, + }, + factory: ({ discoveryApi, oauthRequestApi }) => + GithubAuth.create({ discoveryApi, oauthRequestApi }), + }), + createApiFactory({ + implements: oktaAuthApiRef, + deps: { + discoveryApi: discoveryApiRef, + oauthRequestApi: oauthRequestApiRef, + }, + factory: ({ discoveryApi, oauthRequestApi }) => + OktaAuth.create({ discoveryApi, oauthRequestApi }), + }), + createApiFactory({ + implements: gitlabAuthApiRef, + deps: { + discoveryApi: discoveryApiRef, + oauthRequestApi: oauthRequestApiRef, + }, + factory: ({ discoveryApi, oauthRequestApi }) => + GitlabAuth.create({ discoveryApi, oauthRequestApi }), + }), + createApiFactory({ + implements: auth0AuthApiRef, + deps: { + discoveryApi: discoveryApiRef, + oauthRequestApi: oauthRequestApiRef, + }, + factory: ({ discoveryApi, oauthRequestApi }) => + Auth0Auth.create({ discoveryApi, oauthRequestApi }), + }), + createApiFactory({ + implements: oauth2ApiRef, + deps: { + discoveryApi: discoveryApiRef, + oauthRequestApi: oauthRequestApiRef, + }, + factory: ({ discoveryApi, oauthRequestApi }) => + OAuth2.create({ discoveryApi, oauthRequestApi }), + }), + createApiFactory({ + implements: catalogApiRef, + deps: { discoveryApi: discoveryApiRef }, + factory: ({ discoveryApi }) => new CatalogClient({ discoveryApi }), + }), + createApiFactory({ + implements: scaffolderApiRef, + deps: { discoveryApi: discoveryApiRef }, + factory: ({ discoveryApi }) => new ScaffolderApi({ discoveryApi }), + }), + createApiFactory(gitOpsApiRef, new GitOpsRestApi('http://localhost:3008')), + createApiFactory({ + implements: graphQlBrowseApiRef, + deps: { errorApi: errorApiRef, githubAuthApi: githubAuthApiRef }, + factory: ({ errorApi, githubAuthApi }) => + GraphQLEndpoints.from([ + GraphQLEndpoints.create({ + id: 'gitlab', + title: 'GitLab', + url: 'https://gitlab.com/api/graphql', + }), + GraphQLEndpoints.github({ + id: 'github', + title: 'GitHub', + errorApi, + githubAuthApi, + }), + ]), + }), + createApiFactory({ + implements: rollbarApiRef, + deps: { discoveryApi: discoveryApiRef }, + factory: ({ discoveryApi }) => new RollbarClient({ discoveryApi }), + }), + createApiFactory({ + implements: techdocsStorageApiRef, + deps: { configApi: configApiRef }, + factory: ({ configApi }) => + new TechDocsStorageApi({ + apiOrigin: configApi.getString('techdocs.storageUrl'), }), - GraphQLEndpoints.github({ - id: 'github', - title: 'GitHub', - errorApi, - githubAuthApi, - }), - ]), - ); - - builder.add(rollbarApiRef, new RollbarClient({ discoveryApi })); - - builder.add( - techdocsStorageApiRef, - new TechDocsStorageApi({ - apiOrigin: techdocsUrl, - }), - ); - - return builder.build(); -}; + }), +]; diff --git a/packages/core-api/src/app/App.tsx b/packages/core-api/src/app/App.tsx index ccdfc4fc7f..ca8ab28e8c 100644 --- a/packages/core-api/src/app/App.tsx +++ b/packages/core-api/src/app/App.tsx @@ -26,7 +26,6 @@ import { BackstageApp, AppComponents, AppConfigLoader, - Apis, SignInResult, SignInPageProps, } from './types'; @@ -42,7 +41,6 @@ import { AppThemeProvider } from './AppThemeProvider'; import { IconComponent, SystemIcons, SystemIconKey } from '../icons'; import { - ApiHolder, ApiProvider, ApiRegistry, AppTheme, @@ -51,18 +49,22 @@ import { configApiRef, ConfigReader, useApi, + AnyApiFactory, + ApiHolder, } from '../apis'; -import { ApiAggregator } from '../apis/ApiAggregator'; import { useAsync } from 'react-use'; import { AppIdentity } from './AppIdentity'; +import { ApiFactoryRegistry } from '../apis/ApiFactoryRegistry'; +import { ApiResolver } from '../apis/ApiResolver'; type FullAppOptions = { - apis: Apis; + apis: Iterable; icons: SystemIcons; plugins: BackstagePlugin[]; components: AppComponents; themes: AppTheme[]; configLoader?: AppConfigLoader; + defaultApiFactories: Iterable; }; function useConfigLoader( @@ -101,31 +103,27 @@ function useConfigLoader( } export class PrivateAppImpl implements BackstageApp { - private apis?: ApiHolder = undefined; + private apiHolder?: ApiHolder; + private configApi?: ConfigApi; + + private readonly apis: Iterable; private readonly icons: SystemIcons; private readonly plugins: BackstagePlugin[]; private readonly components: AppComponents; private readonly themes: AppTheme[]; private readonly configLoader?: AppConfigLoader; + private readonly defaultApiFactories: Iterable; private readonly identityApi = new AppIdentity(); - private apisOrFactory: Apis; - constructor(options: FullAppOptions) { - this.apisOrFactory = options.apis; + this.apis = options.apis; this.icons = options.icons; this.plugins = options.plugins; this.components = options.components; this.themes = options.themes; this.configLoader = options.configLoader; - } - - getApis(): ApiHolder { - if (!this.apis) { - throw new Error('Tried to access APIs before app was loaded'); - } - return this.apis; + this.defaultApiFactories = options.defaultApiFactories; } getPlugins(): BackstagePlugin[] { @@ -186,9 +184,9 @@ export class PrivateAppImpl implements BackstageApp { } } - const FeatureFlags = this.apis && this.apis.get(featureFlagsApiRef); - if (FeatureFlags) { - FeatureFlags.registeredFeatureFlags = registeredFeatureFlags; + const featureFlags = this.getApiHolder().get(featureFlagsApiRef); + if (featureFlags) { + featureFlags.registeredFeatureFlags = registeredFeatureFlags; } routes.push(} />); @@ -210,28 +208,14 @@ export class PrivateAppImpl implements BackstageApp { ); if ('node' in loadedConfig) { + // Loading or error return loadedConfig.node; } - const configApi = loadedConfig.api; - const appApis = ApiRegistry.from([ - [appThemeApiRef, appThemeApi], - [configApiRef, configApi], - [identityApiRef, this.identityApi], - ]); - - if (!this.apis) { - if ('get' in this.apisOrFactory) { - this.apis = this.apisOrFactory; - } else { - this.apis = this.apisOrFactory(configApi); - } - } - - const apis = new ApiAggregator(this.apis, appApis); + this.configApi = loadedConfig.api; return ( - + {children} @@ -306,6 +290,55 @@ export class PrivateAppImpl implements BackstageApp { return AppRouter; } + private getApiHolder(): ApiHolder { + if (this.apiHolder) { + return this.apiHolder; + } + + const registry = new ApiFactoryRegistry(); + + registry.register('static', { + implements: appThemeApiRef, + deps: {}, + factory: () => AppThemeSelector.createWithStorage(this.themes), + }); + registry.register('static', { + implements: configApiRef, + deps: {}, + factory: () => { + if (!this.configApi) { + throw new Error( + 'Tried to access config API before config was loaded', + ); + } + return this.configApi; + }, + }); + registry.register('static', { + implements: identityApiRef, + deps: {}, + factory: () => this.identityApi, + }); + + for (const factory of this.defaultApiFactories) { + registry.register('default', factory); + } + + for (const factory of this.apis) { + if (!registry.register('app', factory)) { + throw new Error( + `Duplicate or forbidden API factory for ${factory.implements} in app`, + ); + } + } + + ApiResolver.validateFactories(registry, registry.getAllApis()); + + this.apiHolder = new ApiResolver(registry); + + return this.apiHolder; + } + verify() { const pluginIds = new Set(); diff --git a/packages/core-api/src/app/types.ts b/packages/core-api/src/app/types.ts index db7a0897b1..565e073aed 100644 --- a/packages/core-api/src/app/types.ts +++ b/packages/core-api/src/app/types.ts @@ -17,8 +17,8 @@ import { ComponentType } from 'react'; import { IconComponent, SystemIconKey, SystemIcons } from '../icons'; import { BackstagePlugin } from '../plugin'; -import { ApiHolder } from '../apis'; -import { AppTheme, ConfigApi, ProfileInfo } from '../apis/definitions'; +import { AnyApiFactory } from '../apis'; +import { AppTheme, ProfileInfo } from '../apis/definitions'; import { AppConfig } from '@backstage/config'; export type BootErrorPageProps = { @@ -77,16 +77,12 @@ export type AppComponents = { */ export type AppConfigLoader = () => Promise; -// TODO(Rugvip): Temporary workaround for accessing config when instantiating APIs, we might want to do this differently -export type Apis = ApiHolder | ((config: ConfigApi) => ApiHolder); - export type AppOptions = { /** - * A holder of all APIs available in the app. - * - * Use for example ApiRegistry or ApiTestRegistry. + * A collection of ApiFactories to register in the application to either + * add add new ones, or override factories provided by default or by plugins. */ - apis?: Apis; + apis?: Iterable; /** * Supply icons to override the default ones. @@ -138,11 +134,6 @@ export type AppOptions = { }; export type BackstageApp = { - /** - * Get the holder for all APIs available in the app. - */ - getApis(): ApiHolder; - /** * Returns all plugins registered for the app. */ diff --git a/packages/core/src/api-wrappers/createApp.tsx b/packages/core/src/api-wrappers/createApp.tsx index 9d2096cfff..6073b3cef6 100644 --- a/packages/core/src/api-wrappers/createApp.tsx +++ b/packages/core/src/api-wrappers/createApp.tsx @@ -17,7 +17,6 @@ import React, { FC } from 'react'; import privateExports, { AppOptions, - ApiRegistry, defaultSystemIcons, BootErrorPageProps, AppConfigLoader, @@ -94,7 +93,7 @@ export function createApp(options?: AppOptions) { ); }; - const apis = options?.apis ?? ApiRegistry.from([]); + const apis = options?.apis ?? []; const icons = { ...defaultSystemIcons, ...options?.icons }; const plugins = options?.plugins ?? []; const components = { @@ -127,6 +126,7 @@ export function createApp(options?: AppOptions) { components, themes, configLoader, + defaultApiFactories: [], }); app.verify(); From 1067ae85e726859d8b73c630b5f3033ec84b5054 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 4 Sep 2020 16:10:47 +0200 Subject: [PATCH 15/34] core-api: make it possible for plugins to include ApiFactories --- packages/core-api/src/app/App.tsx | 12 ++++++++++++ packages/core-api/src/plugin/Plugin.tsx | 6 ++++++ packages/core-api/src/plugin/types.ts | 2 ++ 3 files changed, 20 insertions(+) diff --git a/packages/core-api/src/app/App.tsx b/packages/core-api/src/app/App.tsx index ca8ab28e8c..b5434522fe 100644 --- a/packages/core-api/src/app/App.tsx +++ b/packages/core-api/src/app/App.tsx @@ -324,6 +324,18 @@ export class PrivateAppImpl implements BackstageApp { registry.register('default', factory); } + for (const plugin of this.plugins) { + for (const factory of plugin.getApis()) { + if (!registry.register('default', factory)) { + throw new Error( + `Plugin ${plugin.getId()} tried to register duplicate or forbidden API factory for ${ + factory.implements + }`, + ); + } + } + } + for (const factory of this.apis) { if (!registry.register('app', factory)) { throw new Error( diff --git a/packages/core-api/src/plugin/Plugin.tsx b/packages/core-api/src/plugin/Plugin.tsx index bf98919c2b..1835ec03ad 100644 --- a/packages/core-api/src/plugin/Plugin.tsx +++ b/packages/core-api/src/plugin/Plugin.tsx @@ -24,9 +24,11 @@ import { } from './types'; import { validateBrowserCompat, validateFlagName } from '../app/FeatureFlags'; import { RouteRef } from '../routing'; +import { AnyApiFactory } from '../apis'; export type PluginConfig = { id: string; + apis?: Iterable; register?(hooks: PluginHooks): void; }; @@ -65,6 +67,10 @@ export class PluginImpl { return this.config.id; } + getApis(): Iterable { + return this.config.apis ?? []; + } + output(): PluginOutput[] { if (this.storedOutput) { return this.storedOutput; diff --git a/packages/core-api/src/plugin/types.ts b/packages/core-api/src/plugin/types.ts index fabe97434e..12992f3620 100644 --- a/packages/core-api/src/plugin/types.ts +++ b/packages/core-api/src/plugin/types.ts @@ -16,6 +16,7 @@ import { ComponentType } from 'react'; import { RouteRef } from '../routing'; +import { AnyApiFactory } from '../apis'; export type RouteOptions = { // Whether the route path must match exactly, defaults to true. @@ -70,4 +71,5 @@ export type PluginOutput = export type BackstagePlugin = { getId(): string; output(): PluginOutput[]; + getApis(): Iterable; }; From db291ab3235c0e5e1caa6e13fa470a253b110aaa Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 4 Sep 2020 16:59:01 +0200 Subject: [PATCH 16/34] app: move a bunch of APIs to defaultApis in core --- packages/app/src/apis.ts | 100 -------------- packages/core-api/src/app/App.tsx | 8 +- packages/core/src/api-wrappers/createApp.tsx | 3 +- packages/core/src/api-wrappers/defaultApis.ts | 125 ++++++++++++++++++ 4 files changed, 131 insertions(+), 105 deletions(-) create mode 100644 packages/core/src/api-wrappers/defaultApis.ts diff --git a/packages/app/src/apis.ts b/packages/app/src/apis.ts index 77252ac458..a9a1d4cff7 100644 --- a/packages/app/src/apis.ts +++ b/packages/app/src/apis.ts @@ -15,33 +15,10 @@ */ import { - alertApiRef, errorApiRef, - AlertApiForwarder, - ErrorApiForwarder, - ErrorAlerter, - featureFlagsApiRef, - FeatureFlags, discoveryApiRef, UrlPatternDiscovery, - GoogleAuth, - GithubAuth, - OAuth2, - OktaAuth, - GitlabAuth, - Auth0Auth, - MicrosoftAuth, - oauthRequestApiRef, - OAuthRequestManager, - googleAuthApiRef, githubAuthApiRef, - oauth2ApiRef, - oktaAuthApiRef, - gitlabAuthApiRef, - auth0AuthApiRef, - microsoftAuthApiRef, - storageApiRef, - WebStorage, createApiFactory, configApiRef, } from '@backstage/core'; @@ -83,18 +60,6 @@ import { } from '@roadiehq/backstage-plugin-github-pull-requests'; export const apis = [ - createApiFactory(alertApiRef, new AlertApiForwarder()), - createApiFactory({ - implements: errorApiRef, - deps: { alertApi: alertApiRef }, - factory: ({ alertApi }) => - new ErrorAlerter(alertApi, new ErrorApiForwarder()), - }), - createApiFactory({ - implements: storageApiRef, - deps: { errorApi: errorApiRef }, - factory: ({ errorApi }) => WebStorage.create({ errorApi }), - }), createApiFactory({ implements: discoveryApiRef, deps: { configApi: configApiRef }, @@ -121,7 +86,6 @@ export const apis = [ ), }), createApiFactory(githubActionsApiRef, new GithubActionsClient()), - createApiFactory(featureFlagsApiRef, new FeatureFlags()), createApiFactory({ implements: lighthouseApiRef, deps: { configApi: configApiRef }, @@ -129,75 +93,11 @@ export const apis = [ }), createApiFactory(travisCIApiRef, new TravisCIApi()), createApiFactory(githubPullRequestsApiRef, new GithubPullRequestsClient()), - createApiFactory(oauthRequestApiRef, new OAuthRequestManager()), createApiFactory({ implements: techRadarApiRef, deps: {}, factory: () => new TechRadar({ width: 1500, height: 800 }), }), - createApiFactory({ - implements: googleAuthApiRef, - deps: { - discoveryApi: discoveryApiRef, - oauthRequestApi: oauthRequestApiRef, - }, - factory: ({ discoveryApi, oauthRequestApi }) => - GoogleAuth.create({ discoveryApi, oauthRequestApi }), - }), - createApiFactory({ - implements: microsoftAuthApiRef, - deps: { - discoveryApi: discoveryApiRef, - oauthRequestApi: oauthRequestApiRef, - }, - factory: ({ discoveryApi, oauthRequestApi }) => - MicrosoftAuth.create({ discoveryApi, oauthRequestApi }), - }), - createApiFactory({ - implements: githubAuthApiRef, - deps: { - discoveryApi: discoveryApiRef, - oauthRequestApi: oauthRequestApiRef, - }, - factory: ({ discoveryApi, oauthRequestApi }) => - GithubAuth.create({ discoveryApi, oauthRequestApi }), - }), - createApiFactory({ - implements: oktaAuthApiRef, - deps: { - discoveryApi: discoveryApiRef, - oauthRequestApi: oauthRequestApiRef, - }, - factory: ({ discoveryApi, oauthRequestApi }) => - OktaAuth.create({ discoveryApi, oauthRequestApi }), - }), - createApiFactory({ - implements: gitlabAuthApiRef, - deps: { - discoveryApi: discoveryApiRef, - oauthRequestApi: oauthRequestApiRef, - }, - factory: ({ discoveryApi, oauthRequestApi }) => - GitlabAuth.create({ discoveryApi, oauthRequestApi }), - }), - createApiFactory({ - implements: auth0AuthApiRef, - deps: { - discoveryApi: discoveryApiRef, - oauthRequestApi: oauthRequestApiRef, - }, - factory: ({ discoveryApi, oauthRequestApi }) => - Auth0Auth.create({ discoveryApi, oauthRequestApi }), - }), - createApiFactory({ - implements: oauth2ApiRef, - deps: { - discoveryApi: discoveryApiRef, - oauthRequestApi: oauthRequestApiRef, - }, - factory: ({ discoveryApi, oauthRequestApi }) => - OAuth2.create({ discoveryApi, oauthRequestApi }), - }), createApiFactory({ implements: catalogApiRef, deps: { discoveryApi: discoveryApiRef }, diff --git a/packages/core-api/src/app/App.tsx b/packages/core-api/src/app/App.tsx index b5434522fe..1897a12d16 100644 --- a/packages/core-api/src/app/App.tsx +++ b/packages/core-api/src/app/App.tsx @@ -64,7 +64,7 @@ type FullAppOptions = { components: AppComponents; themes: AppTheme[]; configLoader?: AppConfigLoader; - defaultApiFactories: Iterable; + defaultApis: Iterable; }; function useConfigLoader( @@ -112,7 +112,7 @@ export class PrivateAppImpl implements BackstageApp { private readonly components: AppComponents; private readonly themes: AppTheme[]; private readonly configLoader?: AppConfigLoader; - private readonly defaultApiFactories: Iterable; + private readonly defaultApis: Iterable; private readonly identityApi = new AppIdentity(); @@ -123,7 +123,7 @@ export class PrivateAppImpl implements BackstageApp { this.components = options.components; this.themes = options.themes; this.configLoader = options.configLoader; - this.defaultApiFactories = options.defaultApiFactories; + this.defaultApis = options.defaultApis; } getPlugins(): BackstagePlugin[] { @@ -320,7 +320,7 @@ export class PrivateAppImpl implements BackstageApp { factory: () => this.identityApi, }); - for (const factory of this.defaultApiFactories) { + for (const factory of this.defaultApis) { registry.register('default', factory); } diff --git a/packages/core/src/api-wrappers/createApp.tsx b/packages/core/src/api-wrappers/createApp.tsx index 6073b3cef6..7fe77423e2 100644 --- a/packages/core/src/api-wrappers/createApp.tsx +++ b/packages/core/src/api-wrappers/createApp.tsx @@ -25,6 +25,7 @@ import { BrowserRouter, MemoryRouter } from 'react-router-dom'; import { ErrorPage } from '../layout/ErrorPage'; import { Progress } from '../components/Progress'; +import { defaultApis } from './defaultApis'; import { lightTheme, darkTheme } from '@backstage/theme'; import { AppConfig, JsonObject } from '@backstage/config'; @@ -126,7 +127,7 @@ export function createApp(options?: AppOptions) { components, themes, configLoader, - defaultApiFactories: [], + defaultApis, }); app.verify(); diff --git a/packages/core/src/api-wrappers/defaultApis.ts b/packages/core/src/api-wrappers/defaultApis.ts new file mode 100644 index 0000000000..7c471ce25e --- /dev/null +++ b/packages/core/src/api-wrappers/defaultApis.ts @@ -0,0 +1,125 @@ +/* + * 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 { + alertApiRef, + errorApiRef, + AlertApiForwarder, + ErrorApiForwarder, + ErrorAlerter, + featureFlagsApiRef, + FeatureFlags, + discoveryApiRef, + GoogleAuth, + GithubAuth, + OAuth2, + OktaAuth, + GitlabAuth, + Auth0Auth, + MicrosoftAuth, + oauthRequestApiRef, + OAuthRequestManager, + googleAuthApiRef, + githubAuthApiRef, + oauth2ApiRef, + oktaAuthApiRef, + gitlabAuthApiRef, + auth0AuthApiRef, + microsoftAuthApiRef, + storageApiRef, + WebStorage, + createApiFactory, +} from '@backstage/core-api'; + +export const defaultApis = [ + createApiFactory(alertApiRef, new AlertApiForwarder()), + createApiFactory({ + implements: errorApiRef, + deps: { alertApi: alertApiRef }, + factory: ({ alertApi }) => + new ErrorAlerter(alertApi, new ErrorApiForwarder()), + }), + createApiFactory({ + implements: storageApiRef, + deps: { errorApi: errorApiRef }, + factory: ({ errorApi }) => WebStorage.create({ errorApi }), + }), + createApiFactory(featureFlagsApiRef, new FeatureFlags()), + createApiFactory(oauthRequestApiRef, new OAuthRequestManager()), + createApiFactory({ + implements: googleAuthApiRef, + deps: { + discoveryApi: discoveryApiRef, + oauthRequestApi: oauthRequestApiRef, + }, + factory: ({ discoveryApi, oauthRequestApi }) => + GoogleAuth.create({ discoveryApi, oauthRequestApi }), + }), + createApiFactory({ + implements: microsoftAuthApiRef, + deps: { + discoveryApi: discoveryApiRef, + oauthRequestApi: oauthRequestApiRef, + }, + factory: ({ discoveryApi, oauthRequestApi }) => + MicrosoftAuth.create({ discoveryApi, oauthRequestApi }), + }), + createApiFactory({ + implements: githubAuthApiRef, + deps: { + discoveryApi: discoveryApiRef, + oauthRequestApi: oauthRequestApiRef, + }, + factory: ({ discoveryApi, oauthRequestApi }) => + GithubAuth.create({ discoveryApi, oauthRequestApi }), + }), + createApiFactory({ + implements: oktaAuthApiRef, + deps: { + discoveryApi: discoveryApiRef, + oauthRequestApi: oauthRequestApiRef, + }, + factory: ({ discoveryApi, oauthRequestApi }) => + OktaAuth.create({ discoveryApi, oauthRequestApi }), + }), + createApiFactory({ + implements: gitlabAuthApiRef, + deps: { + discoveryApi: discoveryApiRef, + oauthRequestApi: oauthRequestApiRef, + }, + factory: ({ discoveryApi, oauthRequestApi }) => + GitlabAuth.create({ discoveryApi, oauthRequestApi }), + }), + createApiFactory({ + implements: auth0AuthApiRef, + deps: { + discoveryApi: discoveryApiRef, + oauthRequestApi: oauthRequestApiRef, + }, + factory: ({ discoveryApi, oauthRequestApi }) => + Auth0Auth.create({ discoveryApi, oauthRequestApi }), + }), + createApiFactory({ + implements: oauth2ApiRef, + deps: { + discoveryApi: discoveryApiRef, + oauthRequestApi: oauthRequestApiRef, + }, + factory: ({ discoveryApi, oauthRequestApi }) => + OAuth2.create({ discoveryApi, oauthRequestApi }), + }), +]; From aa235dd154d9ca067286e862cf745918af5f4014 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 4 Sep 2020 17:09:41 +0200 Subject: [PATCH 17/34] app: move api factories out to plugins --- packages/app/src/apis.ts | 80 ++------------------------- plugins/catalog/src/plugin.ts | 15 ++++- plugins/circleci/src/plugin.ts | 13 ++++- plugins/gcp-projects/src/plugin.ts | 8 ++- plugins/github-actions/src/plugin.ts | 8 ++- plugins/gitops-profiles/src/plugin.ts | 6 +- plugins/graphiql/src/plugin.ts | 16 +++++- plugins/jenkins/src/plugin.ts | 18 +++++- plugins/lighthouse/src/plugin.ts | 10 +++- plugins/rollbar/src/plugin.ts | 15 ++++- plugins/scaffolder/src/plugin.ts | 14 ++++- plugins/techdocs/src/plugin.ts | 18 +++++- 12 files changed, 134 insertions(+), 87 deletions(-) diff --git a/packages/app/src/apis.ts b/packages/app/src/apis.ts index a9a1d4cff7..a21ecebb9d 100644 --- a/packages/app/src/apis.ts +++ b/packages/app/src/apis.ts @@ -23,32 +23,10 @@ import { configApiRef, } from '@backstage/core'; -import { - lighthouseApiRef, - LighthouseRestApi, -} from '@backstage/plugin-lighthouse'; - -import { CircleCIApi, circleCIApiRef } from '@backstage/plugin-circleci'; -import { catalogApiRef, CatalogClient } from '@backstage/plugin-catalog'; - -import { gitOpsApiRef, GitOpsRestApi } from '@backstage/plugin-gitops-profiles'; import { graphQlBrowseApiRef, GraphQLEndpoints, } from '@backstage/plugin-graphiql'; -import { scaffolderApiRef, ScaffolderApi } from '@backstage/plugin-scaffolder'; -import { - techdocsStorageApiRef, - TechDocsStorageApi, -} from '@backstage/plugin-techdocs'; - -import { rollbarApiRef, RollbarClient } from '@backstage/plugin-rollbar'; -import { GCPClient, GCPApiRef } from '@backstage/plugin-gcp-projects'; -import { - GithubActionsClient, - githubActionsApiRef, -} from '@backstage/plugin-github-actions'; -import { jenkinsApiRef, JenkinsApi } from '@backstage/plugin-jenkins'; import { TravisCIApi, @@ -68,47 +46,6 @@ export const apis = [ `${configApi.getString('backend.baseUrl')}/{{ pluginId }}`, ), }), - createApiFactory(GCPApiRef, new GCPClient()), - createApiFactory({ - implements: circleCIApiRef, - deps: { configApi: configApiRef }, - factory: ({ configApi }) => - new CircleCIApi( - `${configApi.getString('backend.baseUrl')}/proxy/circleci/api`, - ), - }), - createApiFactory({ - implements: jenkinsApiRef, - deps: { configApi: configApiRef }, - factory: ({ configApi }) => - new JenkinsApi( - `${configApi.getString('backend.baseUrl')}/proxy/jenkins/api`, - ), - }), - createApiFactory(githubActionsApiRef, new GithubActionsClient()), - createApiFactory({ - implements: lighthouseApiRef, - deps: { configApi: configApiRef }, - factory: ({ configApi }) => LighthouseRestApi.fromConfig(configApi), - }), - createApiFactory(travisCIApiRef, new TravisCIApi()), - createApiFactory(githubPullRequestsApiRef, new GithubPullRequestsClient()), - createApiFactory({ - implements: techRadarApiRef, - deps: {}, - factory: () => new TechRadar({ width: 1500, height: 800 }), - }), - createApiFactory({ - implements: catalogApiRef, - deps: { discoveryApi: discoveryApiRef }, - factory: ({ discoveryApi }) => new CatalogClient({ discoveryApi }), - }), - createApiFactory({ - implements: scaffolderApiRef, - deps: { discoveryApi: discoveryApiRef }, - factory: ({ discoveryApi }) => new ScaffolderApi({ discoveryApi }), - }), - createApiFactory(gitOpsApiRef, new GitOpsRestApi('http://localhost:3008')), createApiFactory({ implements: graphQlBrowseApiRef, deps: { errorApi: errorApiRef, githubAuthApi: githubAuthApiRef }, @@ -127,17 +64,8 @@ export const apis = [ }), ]), }), - createApiFactory({ - implements: rollbarApiRef, - deps: { discoveryApi: discoveryApiRef }, - factory: ({ discoveryApi }) => new RollbarClient({ discoveryApi }), - }), - createApiFactory({ - implements: techdocsStorageApiRef, - deps: { configApi: configApiRef }, - factory: ({ configApi }) => - new TechDocsStorageApi({ - apiOrigin: configApi.getString('techdocs.storageUrl'), - }), - }), + + // TODO: move to plugins + createApiFactory(travisCIApiRef, new TravisCIApi()), + createApiFactory(githubPullRequestsApiRef, new GithubPullRequestsClient()), ]; diff --git a/plugins/catalog/src/plugin.ts b/plugins/catalog/src/plugin.ts index 4bfbf2453b..61cdf5c95a 100644 --- a/plugins/catalog/src/plugin.ts +++ b/plugins/catalog/src/plugin.ts @@ -14,8 +14,21 @@ * limitations under the License. */ -import { createPlugin } from '@backstage/core'; +import { + createPlugin, + createApiFactory, + discoveryApiRef, +} from '@backstage/core'; +import { catalogApiRef } from './api/types'; +import { CatalogClient } from './api/CatalogClient'; export const plugin = createPlugin({ id: 'catalog', + apis: [ + createApiFactory({ + implements: catalogApiRef, + deps: { discoveryApi: discoveryApiRef }, + factory: ({ discoveryApi }) => new CatalogClient({ discoveryApi }), + }), + ], }); diff --git a/plugins/circleci/src/plugin.ts b/plugins/circleci/src/plugin.ts index 47ecccef4f..06c6381c37 100644 --- a/plugins/circleci/src/plugin.ts +++ b/plugins/circleci/src/plugin.ts @@ -13,13 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createPlugin } from '@backstage/core'; +import { createPlugin, createApiFactory, configApiRef } from '@backstage/core'; import { circleCIRouteRef, circleCIBuildRouteRef } from './route-refs'; import BuildsPage from './pages/BuildsPage/BuildsPage'; import BuildWithStepsPage from './pages/BuildWithStepsPage/BuildWithStepsPage'; +import { circleCIApiRef, CircleCIApi } from './api'; export const plugin = createPlugin({ id: 'circleci', + apis: [ + createApiFactory({ + implements: circleCIApiRef, + deps: { configApi: configApiRef }, + factory: ({ configApi }) => + new CircleCIApi( + `${configApi.getString('backend.baseUrl')}/proxy/circleci/api`, + ), + }), + ], register({ router }) { router.addRoute(circleCIRouteRef, BuildsPage); router.addRoute(circleCIBuildRouteRef, BuildWithStepsPage); diff --git a/plugins/gcp-projects/src/plugin.ts b/plugins/gcp-projects/src/plugin.ts index 29c7d74434..41aacde597 100644 --- a/plugins/gcp-projects/src/plugin.ts +++ b/plugins/gcp-projects/src/plugin.ts @@ -14,10 +14,15 @@ * limitations under the License. */ -import { createPlugin, createRouteRef } from '@backstage/core'; +import { + createPlugin, + createRouteRef, + createApiFactory, +} from '@backstage/core'; import { ProjectListPage } from './components/ProjectListPage'; import { ProjectDetailsPage } from './components/ProjectDetailsPage'; import { NewProjectPage } from './components/NewProjectPage'; +import { GCPApiRef, GCPClient } from './api'; export const rootRouteRef = createRouteRef({ path: '/gcp-projects', @@ -34,6 +39,7 @@ export const NewProjectRouteRef = createRouteRef({ export const plugin = createPlugin({ id: 'gcp-projects', + apis: [createApiFactory(GCPApiRef, new GCPClient())], register({ router }) { router.addRoute(rootRouteRef, ProjectListPage); router.addRoute(ProjectRouteRef, ProjectDetailsPage); diff --git a/plugins/github-actions/src/plugin.ts b/plugins/github-actions/src/plugin.ts index 7e08229d6d..9e3c965d46 100644 --- a/plugins/github-actions/src/plugin.ts +++ b/plugins/github-actions/src/plugin.ts @@ -14,7 +14,12 @@ * limitations under the License. */ -import { createPlugin, createRouteRef } from '@backstage/core'; +import { + createPlugin, + createRouteRef, + createApiFactory, +} from '@backstage/core'; +import { githubActionsApiRef, GithubActionsClient } from './api'; // TODO(freben): This is just a demo route for now export const rootRouteRef = createRouteRef({ @@ -29,4 +34,5 @@ export const buildRouteRef = createRouteRef({ export const plugin = createPlugin({ id: 'github-actions', + apis: [createApiFactory(githubActionsApiRef, new GithubActionsClient())], }); diff --git a/plugins/gitops-profiles/src/plugin.ts b/plugins/gitops-profiles/src/plugin.ts index af180aff20..45820644f7 100644 --- a/plugins/gitops-profiles/src/plugin.ts +++ b/plugins/gitops-profiles/src/plugin.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { createPlugin } from '@backstage/core'; +import { createPlugin, createApiFactory } from '@backstage/core'; import ProfileCatalog from './components/ProfileCatalog'; import ClusterPage from './components/ClusterPage'; import ClusterList from './components/ClusterList'; @@ -23,9 +23,13 @@ import { gitOpsClusterDetailsRoute, gitOpsClusterCreateRoute, } from './routes'; +import { gitOpsApiRef, GitOpsRestApi } from './api'; export const plugin = createPlugin({ id: 'gitops-profiles', + apis: [ + createApiFactory(gitOpsApiRef, new GitOpsRestApi('http://localhost:3008')), + ], register({ router }) { router.addRoute(gitOpsClusterListRoute, ClusterList); router.addRoute(gitOpsClusterDetailsRoute, ClusterPage); diff --git a/plugins/graphiql/src/plugin.ts b/plugins/graphiql/src/plugin.ts index 7763284d81..28d27802d0 100644 --- a/plugins/graphiql/src/plugin.ts +++ b/plugins/graphiql/src/plugin.ts @@ -14,8 +14,22 @@ * limitations under the License. */ -import { createPlugin } from '@backstage/core'; +import { createPlugin, createApiFactory } from '@backstage/core'; +import { graphQlBrowseApiRef, GraphQLEndpoints } from './lib/api'; export const plugin = createPlugin({ id: 'graphiql', + apis: [ + // GitLab is used as an example endpoint, but most plug + createApiFactory( + graphQlBrowseApiRef, + GraphQLEndpoints.from([ + GraphQLEndpoints.create({ + id: 'gitlab', + title: 'GitLab', + url: 'https://gitlab.com/api/graphql', + }), + ]), + ), + ], }); diff --git a/plugins/jenkins/src/plugin.ts b/plugins/jenkins/src/plugin.ts index 979b0a31cf..fe24e1b63d 100644 --- a/plugins/jenkins/src/plugin.ts +++ b/plugins/jenkins/src/plugin.ts @@ -14,8 +14,14 @@ * limitations under the License. */ -import { createPlugin, createRouteRef } from '@backstage/core'; +import { + createPlugin, + createRouteRef, + createApiFactory, + configApiRef, +} from '@backstage/core'; import { DetailedViewPage } from './pages/BuildWithStepsPage'; +import { jenkinsApiRef, JenkinsApi } from './api'; export const buildRouteRef = createRouteRef({ path: '/jenkins/job', @@ -24,6 +30,16 @@ export const buildRouteRef = createRouteRef({ export const plugin = createPlugin({ id: 'jenkins', + apis: [ + createApiFactory({ + implements: jenkinsApiRef, + deps: { configApi: configApiRef }, + factory: ({ configApi }) => + new JenkinsApi( + `${configApi.getString('backend.baseUrl')}/proxy/jenkins/api`, + ), + }), + ], register({ router }) { router.addRoute(buildRouteRef, DetailedViewPage); }, diff --git a/plugins/lighthouse/src/plugin.ts b/plugins/lighthouse/src/plugin.ts index f8da8d84ed..5700a9991f 100644 --- a/plugins/lighthouse/src/plugin.ts +++ b/plugins/lighthouse/src/plugin.ts @@ -14,13 +14,21 @@ * limitations under the License. */ -import { createPlugin } from '@backstage/core'; +import { createPlugin, createApiFactory, configApiRef } from '@backstage/core'; import AuditList from './components/AuditList'; import AuditView from './components/AuditView'; import CreateAudit from './components/CreateAudit'; +import { lighthouseApiRef, LighthouseRestApi } from './api'; export const plugin = createPlugin({ id: 'lighthouse', + apis: [ + createApiFactory({ + implements: lighthouseApiRef, + deps: { configApi: configApiRef }, + factory: ({ configApi }) => LighthouseRestApi.fromConfig(configApi), + }), + ], register({ router }) { router.registerRoute('/lighthouse', AuditList); router.registerRoute('/lighthouse/audit/:id', AuditView); diff --git a/plugins/rollbar/src/plugin.ts b/plugins/rollbar/src/plugin.ts index 2cf464a8f6..21432572e1 100644 --- a/plugins/rollbar/src/plugin.ts +++ b/plugins/rollbar/src/plugin.ts @@ -14,13 +14,26 @@ * limitations under the License. */ -import { createPlugin } from '@backstage/core'; +import { + createPlugin, + createApiFactory, + discoveryApiRef, +} from '@backstage/core'; import { rootRouteRef, entityRouteRef } from './routes'; import { RollbarHome } from './components/RollbarHome/RollbarHome'; import { RollbarProjectPage } from './components/RollbarProjectPage/RollbarProjectPage'; +import { rollbarApiRef } from './api/RollbarApi'; +import { RollbarClient } from './api/RollbarClient'; export const plugin = createPlugin({ id: 'rollbar', + apis: [ + createApiFactory({ + implements: rollbarApiRef, + deps: { discoveryApi: discoveryApiRef }, + factory: ({ discoveryApi }) => new RollbarClient({ discoveryApi }), + }), + ], register({ router }) { router.addRoute(rootRouteRef, RollbarHome); router.addRoute(entityRouteRef, RollbarProjectPage); diff --git a/plugins/scaffolder/src/plugin.ts b/plugins/scaffolder/src/plugin.ts index 8c4ed5badd..15ec749f2f 100644 --- a/plugins/scaffolder/src/plugin.ts +++ b/plugins/scaffolder/src/plugin.ts @@ -14,13 +14,25 @@ * limitations under the License. */ -import { createPlugin } from '@backstage/core'; +import { + createPlugin, + createApiFactory, + discoveryApiRef, +} from '@backstage/core'; import { ScaffolderPage } from './components/ScaffolderPage'; import { TemplatePage } from './components/TemplatePage'; import { rootRoute, templateRoute } from './routes'; +import { scaffolderApiRef, ScaffolderApi } from './api'; export const plugin = createPlugin({ id: 'scaffolder', + apis: [ + createApiFactory({ + implements: scaffolderApiRef, + deps: { discoveryApi: discoveryApiRef }, + factory: ({ discoveryApi }) => new ScaffolderApi({ discoveryApi }), + }), + ], register({ router }) { router.addRoute(rootRoute, ScaffolderPage); router.addRoute(templateRoute, TemplatePage); diff --git a/plugins/techdocs/src/plugin.ts b/plugins/techdocs/src/plugin.ts index e75d488595..673089be75 100644 --- a/plugins/techdocs/src/plugin.ts +++ b/plugins/techdocs/src/plugin.ts @@ -29,7 +29,13 @@ * limitations under the License. */ -import { createPlugin, createRouteRef } from '@backstage/core'; +import { + createPlugin, + createRouteRef, + createApiFactory, + configApiRef, +} from '@backstage/core'; +import { techdocsStorageApiRef, TechDocsStorageApi } from './api'; export const rootRouteRef = createRouteRef({ path: '', @@ -48,4 +54,14 @@ export const rootCatalogDocsRouteRef = createRouteRef({ export const plugin = createPlugin({ id: 'techdocs', + apis: [ + createApiFactory({ + implements: techdocsStorageApiRef, + deps: { configApi: configApiRef }, + factory: ({ configApi }) => + new TechDocsStorageApi({ + apiOrigin: configApi.getString('techdocs.storageUrl'), + }), + }), + ], }); From bcaa18886020144d0e67a61b5d3dbe90eaa469ec Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 4 Sep 2020 17:18:18 +0200 Subject: [PATCH 18/34] core: add default DiscoveryApi factory that uses /api --- packages/app/src/apis.ts | 1 + packages/core/src/api-wrappers/defaultApis.ts | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/packages/app/src/apis.ts b/packages/app/src/apis.ts index a21ecebb9d..12d3594921 100644 --- a/packages/app/src/apis.ts +++ b/packages/app/src/apis.ts @@ -38,6 +38,7 @@ import { } from '@roadiehq/backstage-plugin-github-pull-requests'; export const apis = [ + // TODO(Rugvip): migrate to use /api createApiFactory({ implements: discoveryApiRef, deps: { configApi: configApiRef }, diff --git a/packages/core/src/api-wrappers/defaultApis.ts b/packages/core/src/api-wrappers/defaultApis.ts index 7c471ce25e..82b60d31e6 100644 --- a/packages/core/src/api-wrappers/defaultApis.ts +++ b/packages/core/src/api-wrappers/defaultApis.ts @@ -42,9 +42,19 @@ import { storageApiRef, WebStorage, createApiFactory, + configApiRef, + UrlPatternDiscovery, } from '@backstage/core-api'; export const defaultApis = [ + createApiFactory({ + implements: discoveryApiRef, + deps: { configApi: configApiRef }, + factory: ({ configApi }) => + UrlPatternDiscovery.compile( + `${configApi.getString('backend.baseUrl')}/api/{{ pluginId }}`, + ), + }), createApiFactory(alertApiRef, new AlertApiForwarder()), createApiFactory({ implements: errorApiRef, From e7c04aedab92ed932ca132f09adf94a85a338fa4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 4 Sep 2020 17:23:12 +0200 Subject: [PATCH 19/34] dev-utils: remove separate ApiTestRegistry setup --- .../dev-utils/src/devApp/apiFactories.test.ts | 36 ------ packages/dev-utils/src/devApp/apiFactories.ts | 108 ------------------ packages/dev-utils/src/devApp/render.tsx | 38 +----- plugins/graphiql/dev/index.tsx | 2 +- plugins/lighthouse/dev/index.tsx | 2 +- plugins/techdocs/dev/index.tsx | 2 +- 6 files changed, 9 insertions(+), 179 deletions(-) delete mode 100644 packages/dev-utils/src/devApp/apiFactories.test.ts delete mode 100644 packages/dev-utils/src/devApp/apiFactories.ts diff --git a/packages/dev-utils/src/devApp/apiFactories.test.ts b/packages/dev-utils/src/devApp/apiFactories.test.ts deleted file mode 100644 index be3ae2cdbe..0000000000 --- a/packages/dev-utils/src/devApp/apiFactories.test.ts +++ /dev/null @@ -1,36 +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 * as apiFactories from './apiFactories'; -import { ApiTestRegistry, ApiFactory } from '@backstage/core'; - -describe('apiFactories', () => { - it('should be possible to get an instance of each API', () => { - const registry = new ApiTestRegistry(); - const factories: ApiFactory[] = Object.values( - apiFactories, - ); - - for (const factory of factories) { - registry.register(factory); - } - - for (const factory of factories) { - const api = registry.get(factory.implements); - expect(api).toBeDefined(); - } - }); -}); diff --git a/packages/dev-utils/src/devApp/apiFactories.ts b/packages/dev-utils/src/devApp/apiFactories.ts deleted file mode 100644 index 4cf208f5d2..0000000000 --- a/packages/dev-utils/src/devApp/apiFactories.ts +++ /dev/null @@ -1,108 +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 { - alertApiRef, - errorApiRef, - ErrorApiForwarder, - AlertApi, - createApiFactory, - ErrorAlerter, - AlertApiForwarder, - oauthRequestApiRef, - OAuthRequestManager, - UrlPatternDiscovery, - discoveryApiRef, - GoogleAuth, - googleAuthApiRef, - GithubAuth, - githubAuthApiRef, - GitlabAuth, - gitlabAuthApiRef, - Auth0Auth, - auth0AuthApiRef, -} from '@backstage/core'; - -// TODO(rugvip): We should likely figure out how to reuse all of these between apps -// and plugin serve with minimal boilerplate. For example we might move everything -// to DI, and provide factories for the default implementations, so this just becomes -// a list of things like `[ErrorApiForwarder.factory, AlertApiDialog.factory]`. - -export const alertApiFactory = createApiFactory({ - implements: alertApiRef, - deps: {}, - factory: (): AlertApi => new AlertApiForwarder(), -}); - -export const errorApiFactory = createApiFactory({ - implements: errorApiRef, - deps: { alertApi: alertApiRef }, - factory: ({ alertApi }) => - new ErrorAlerter(alertApi, new ErrorApiForwarder()), -}); - -export const oauthRequestApiFactory = createApiFactory({ - implements: oauthRequestApiRef, - deps: {}, - factory: () => new OAuthRequestManager(), -}); - -export const discoveryApiFactory = createApiFactory({ - implements: discoveryApiRef, - deps: {}, - factory: () => - UrlPatternDiscovery.compile(`http://localhost:7000/{{ pluginId }}`), -}); - -export const googleAuthApiFactory = createApiFactory({ - implements: googleAuthApiRef, - deps: { discoveryApi: discoveryApiRef, oauthRequestApi: oauthRequestApiRef }, - factory: ({ discoveryApi, oauthRequestApi }) => - GoogleAuth.create({ - discoveryApi, - oauthRequestApi, - }), -}); - -export const githubAuthApiFactory = createApiFactory({ - implements: githubAuthApiRef, - deps: { discoveryApi: discoveryApiRef, oauthRequestApi: oauthRequestApiRef }, - factory: ({ discoveryApi, oauthRequestApi }) => - GithubAuth.create({ - discoveryApi, - oauthRequestApi, - }), -}); - -export const gitlabAuthApiFactory = createApiFactory({ - implements: gitlabAuthApiRef, - deps: { discoveryApi: discoveryApiRef, oauthRequestApi: oauthRequestApiRef }, - factory: ({ discoveryApi, oauthRequestApi }) => - GitlabAuth.create({ - discoveryApi, - oauthRequestApi, - }), -}); - -export const auth0AuthApiFactory = createApiFactory({ - implements: auth0AuthApiRef, - deps: { discoveryApi: discoveryApiRef, oauthRequestApi: oauthRequestApiRef }, - factory: ({ discoveryApi, oauthRequestApi }) => - Auth0Auth.create({ - discoveryApi, - oauthRequestApi, - }), -}); diff --git a/packages/dev-utils/src/devApp/render.tsx b/packages/dev-utils/src/devApp/render.tsx index cde39fdd05..f223fcd4e7 100644 --- a/packages/dev-utils/src/devApp/render.tsx +++ b/packages/dev-utils/src/devApp/render.tsx @@ -26,12 +26,10 @@ import { SidebarSpacer, ApiFactory, createPlugin, - ApiTestRegistry, - ApiHolder, AlertDisplay, OAuthRequestDialog, + AnyApiFactory, } from '@backstage/core'; -import * as defaultApiFactories from './apiFactories'; import SentimentDissatisfiedIcon from '@material-ui/icons/SentimentDissatisfied'; // TODO(rugvip): export proper plugin type from core that isn't the plugin class @@ -43,7 +41,7 @@ type BackstagePlugin = ReturnType; */ class DevAppBuilder { private readonly plugins = new Array(); - private readonly factories = new Array>(); + private readonly apis = new Array(); private readonly rootChildren = new Array(); /** @@ -57,10 +55,10 @@ class DevAppBuilder { /** * Register an API factory to add to the app */ - registerApiFactory( - factory: ApiFactory, + registerApi( + factory: ApiFactory, ): DevAppBuilder { - this.factories.push(factory); + this.apis.push(factory); return this; } @@ -79,7 +77,7 @@ class DevAppBuilder { */ build(): ComponentType<{}> { const app = createApp({ - apis: this.setupApiRegistry(this.factories), + apis: this.apis, plugins: this.plugins, }); @@ -170,30 +168,6 @@ class DevAppBuilder { ); } - // Set up an API registry that merges together default implementations with ones provided through config. - private setupApiRegistry( - providedFactories: ApiFactory[], - ): ApiHolder { - const providedApis = new Set( - providedFactories.map(factory => factory.implements), - ); - - // Exlude any default API factory that we receive a factory for in the config - const defaultFactories = Object.values(defaultApiFactories).filter( - factory => !providedApis.has(factory.implements), - ); - const allFactories = [...defaultFactories, ...providedFactories]; - - // Use a test registry with dependency injection so that the consumer - // can override APIs but still depend on the default implementations. - const registry = new ApiTestRegistry(); - for (const factory of allFactories) { - registry.register(factory); - } - - return registry; - } - private findPluginPaths(plugins: BackstagePlugin[]) { const paths = new Array(); diff --git a/plugins/graphiql/dev/index.tsx b/plugins/graphiql/dev/index.tsx index efcf19a89d..93b7b35334 100644 --- a/plugins/graphiql/dev/index.tsx +++ b/plugins/graphiql/dev/index.tsx @@ -20,7 +20,7 @@ import { plugin, GraphQLEndpoints, graphQlBrowseApiRef } from '../src'; createDevApp() .registerPlugin(plugin) - .registerApiFactory({ + .registerApi({ implements: graphQlBrowseApiRef, deps: { errorApi: errorApiRef, diff --git a/plugins/lighthouse/dev/index.tsx b/plugins/lighthouse/dev/index.tsx index 6496fb658a..6fa39577f2 100644 --- a/plugins/lighthouse/dev/index.tsx +++ b/plugins/lighthouse/dev/index.tsx @@ -20,7 +20,7 @@ import { lighthouseApiRef, LighthouseRestApi } from '../src'; createDevApp() .registerPlugin(plugin) - .registerApiFactory({ + .registerApi({ implements: lighthouseApiRef, deps: {}, factory: () => new LighthouseRestApi('http://localhost:3003'), diff --git a/plugins/techdocs/dev/index.tsx b/plugins/techdocs/dev/index.tsx index b415256fde..9902cf6526 100644 --- a/plugins/techdocs/dev/index.tsx +++ b/plugins/techdocs/dev/index.tsx @@ -20,7 +20,7 @@ import { TechDocsDevStorageApi } from './api'; import { techdocsStorageApiRef } from '../src'; createDevApp() - .registerApiFactory({ + .registerApi({ deps: {}, factory: () => new TechDocsDevStorageApi({ From a5741ff0aa4242ad7d3e9a5916ec82f4a85a825f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 4 Sep 2020 17:33:55 +0200 Subject: [PATCH 20/34] test-utils: switch to new auto DI api --- .../testUtils/apis/ErrorApi/MockErrorApi.ts | 13 +------------ .../apis/StorageApi/MockStorageApi.ts | 7 ------- .../src/testUtils/appWrappers.test.tsx | 3 --- .../test-utils/src/testUtils/appWrappers.tsx | 6 +++--- .../{mockApiRegistry.ts => mockApis.ts} | 18 +++++++++--------- 5 files changed, 13 insertions(+), 34 deletions(-) rename packages/test-utils/src/testUtils/{mockApiRegistry.ts => mockApis.ts} (70%) diff --git a/packages/test-utils/src/testUtils/apis/ErrorApi/MockErrorApi.ts b/packages/test-utils/src/testUtils/apis/ErrorApi/MockErrorApi.ts index 9b22a352e8..7bf50314d0 100644 --- a/packages/test-utils/src/testUtils/apis/ErrorApi/MockErrorApi.ts +++ b/packages/test-utils/src/testUtils/apis/ErrorApi/MockErrorApi.ts @@ -14,12 +14,7 @@ * limitations under the License. */ -import { - ErrorApi, - ErrorContext, - errorApiRef, - Observable, -} from '@backstage/core-api'; +import { ErrorApi, ErrorContext, Observable } from '@backstage/core-api'; type Options = { collect?: boolean; @@ -40,12 +35,6 @@ const nullObservable = { }; export class MockErrorApi implements ErrorApi { - static factory = { - implements: errorApiRef, - deps: {}, - factory: () => new MockErrorApi(), - }; - private readonly errors = new Array(); private readonly waiters = new Set(); diff --git a/packages/test-utils/src/testUtils/apis/StorageApi/MockStorageApi.ts b/packages/test-utils/src/testUtils/apis/StorageApi/MockStorageApi.ts index a3a4ef16d6..006b44a49c 100644 --- a/packages/test-utils/src/testUtils/apis/StorageApi/MockStorageApi.ts +++ b/packages/test-utils/src/testUtils/apis/StorageApi/MockStorageApi.ts @@ -17,7 +17,6 @@ import { Observable, StorageApi, - storageApiRef, StorageValueChange, } from '@backstage/core-api'; import ObservableImpl from 'zen-observable'; @@ -25,12 +24,6 @@ import ObservableImpl from 'zen-observable'; export type MockStorageBucket = { [key: string]: any }; export class MockStorageApi implements StorageApi { - static factory = { - implements: storageApiRef, - deps: {}, - factory: () => MockStorageApi.create(), - }; - private readonly namespace: string; private readonly data: MockStorageBucket; diff --git a/packages/test-utils/src/testUtils/appWrappers.test.tsx b/packages/test-utils/src/testUtils/appWrappers.test.tsx index 19c02c2158..464c547ecc 100644 --- a/packages/test-utils/src/testUtils/appWrappers.test.tsx +++ b/packages/test-utils/src/testUtils/appWrappers.test.tsx @@ -49,9 +49,6 @@ describe('wrapInTestApp', () => { expect.stringMatching( /^Warning: An update to %s inside a test was not wrapped in act\(...\)/, ), - expect.stringMatching( - /^Warning: An update to %s inside a test was not wrapped in act\(...\)/, - ), ]); }); diff --git a/packages/test-utils/src/testUtils/appWrappers.tsx b/packages/test-utils/src/testUtils/appWrappers.tsx index 2e3a73e346..182de1ef63 100644 --- a/packages/test-utils/src/testUtils/appWrappers.tsx +++ b/packages/test-utils/src/testUtils/appWrappers.tsx @@ -24,7 +24,7 @@ import privateExports, { } from '@backstage/core-api'; import { RenderResult } from '@testing-library/react'; import { renderWithEffects } from '@backstage/test-utils-core'; -import { createMockApiRegistry } from './mockApiRegistry'; +import { mockApis } from './mockApis'; const { PrivateAppImpl } = privateExports; @@ -58,10 +58,9 @@ export function wrapInTestApp( options: TestAppOptions = {}, ): ReactElement { const { routeEntries = ['/'] } = options; - const apis = createMockApiRegistry(); const app = new PrivateAppImpl({ - apis, + apis: [], components: { NotFoundErrorPage, BootErrorPage, @@ -80,6 +79,7 @@ export function wrapInTestApp( variant: 'light', }, ], + defaultApis: mockApis, }); let Wrapper: ComponentType; diff --git a/packages/test-utils/src/testUtils/mockApiRegistry.ts b/packages/test-utils/src/testUtils/mockApis.ts similarity index 70% rename from packages/test-utils/src/testUtils/mockApiRegistry.ts rename to packages/test-utils/src/testUtils/mockApis.ts index 15733ead88..e05a8e6cac 100644 --- a/packages/test-utils/src/testUtils/mockApiRegistry.ts +++ b/packages/test-utils/src/testUtils/mockApis.ts @@ -14,14 +14,14 @@ * limitations under the License. */ -import { ApiTestRegistry } from '@backstage/core-api'; +import { + storageApiRef, + errorApiRef, + createApiFactory, +} from '@backstage/core-api'; import { MockErrorApi, MockStorageApi } from './apis'; -export function createMockApiRegistry(): ApiTestRegistry { - const registry = new ApiTestRegistry(); - - registry.register(MockErrorApi.factory); - registry.register(MockStorageApi.factory); - - return registry; -} +export const mockApis = [ + createApiFactory(errorApiRef, new MockErrorApi()), + createApiFactory(storageApiRef, MockStorageApi.create()), +]; From c4f794aacbb64de10ead8951bb08e6cc73959640 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 4 Sep 2020 17:34:25 +0200 Subject: [PATCH 21/34] core-api: remove ApiTestRegistry --- .../core-api/src/apis/ApiTestRegistry.test.ts | 118 ------------------ packages/core-api/src/apis/ApiTestRegistry.ts | 90 ------------- packages/core-api/src/apis/index.ts | 1 - 3 files changed, 209 deletions(-) delete mode 100644 packages/core-api/src/apis/ApiTestRegistry.test.ts delete mode 100644 packages/core-api/src/apis/ApiTestRegistry.ts diff --git a/packages/core-api/src/apis/ApiTestRegistry.test.ts b/packages/core-api/src/apis/ApiTestRegistry.test.ts deleted file mode 100644 index a4fbf1b144..0000000000 --- a/packages/core-api/src/apis/ApiTestRegistry.test.ts +++ /dev/null @@ -1,118 +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 { ApiTestRegistry } from './ApiTestRegistry'; -import { createApiRef } from './ApiRef'; - -describe('ApiTestRegistry', () => { - const aRef = createApiRef({ id: 'a', description: '' }); - const bRef = createApiRef({ id: 'b', description: '' }); - const cRef = createApiRef({ id: 'c', description: '' }); - - it('should be created', () => { - const registry = new ApiTestRegistry(); - expect(registry.get(aRef)).toBe(undefined); - expect(registry.get(bRef)).toBe(undefined); - expect(registry.get(cRef)).toBe(undefined); - }); - - it('should register a factory', () => { - const registry = new ApiTestRegistry(); - registry.register({ implements: aRef, deps: {}, factory: () => 3 }); - expect(registry.get(aRef)).toBe(3); - expect(registry.get(bRef)).toBe(undefined); - expect(registry.get(cRef)).toBe(undefined); - }); - - it('should register factories with dependencies', () => { - // 100% coverage + happy typescript = hasOwnProperty + this atrocity - const cDeps = Object.create( - { c: cRef }, - { a: { enumerable: true, value: aRef } }, - ); - cDeps.b = bRef; - - const registry = new ApiTestRegistry(); - registry.register({ implements: aRef, deps: {}, factory: () => 3 }); - registry.register({ - implements: bRef, - deps: { dep: aRef }, - factory: ({ dep }) => `hello ${dep}`, - }); - registry.register({ - implements: cRef, - deps: cDeps, - factory: ({ a, b }) => b.repeat(a), - }); - expect(registry.get(aRef)).toBe(3); - expect(registry.get(bRef)).toBe('hello 3'); - expect(registry.get(cRef)).toBe('hello 3hello 3hello 3'); - }); - - it('should not allow cyclic dependencies', () => { - const registry = new ApiTestRegistry(); - registry.register({ - implements: aRef, - deps: { b: bRef }, - factory: () => 1, - }); - registry.register({ - implements: bRef, - deps: { c: cRef }, - factory: () => 'b', - }); - registry.register({ - implements: cRef, - deps: { a: aRef }, - factory: () => 'c', - }); - expect(() => registry.get(aRef)).toThrow( - 'Circular dependency of api factory for apiRef{a}', - ); - expect(() => registry.get(bRef)).toThrow( - 'Circular dependency of api factory for apiRef{b}', - ); - expect(() => registry.get(cRef)).toThrow( - 'Circular dependency of api factory for apiRef{c}', - ); - }); - - it('should throw error if dependency is not available', () => { - const registry = new ApiTestRegistry(); - registry.register({ - implements: aRef, - deps: { b: bRef }, - factory: () => 1, - }); - expect(() => registry.get(aRef)).toThrow( - 'No API factory available for dependency apiRef{b} of dependent apiRef{a}', - ); - expect(registry.get(bRef)).toBe(undefined); - expect(registry.get(cRef)).toBe(undefined); - }); - - it('should only call factory func once', () => { - const registry = new ApiTestRegistry(); - const factory = jest.fn().mockReturnValue(2); - registry.register({ implements: aRef, deps: {}, factory }); - - expect(factory).toHaveBeenCalledTimes(0); - expect(registry.get(aRef)).toBe(2); - expect(factory).toHaveBeenCalledTimes(1); - expect(registry.get(aRef)).toBe(2); - expect(factory).toHaveBeenCalledTimes(1); - }); -}); diff --git a/packages/core-api/src/apis/ApiTestRegistry.ts b/packages/core-api/src/apis/ApiTestRegistry.ts deleted file mode 100644 index d41d959e99..0000000000 --- a/packages/core-api/src/apis/ApiTestRegistry.ts +++ /dev/null @@ -1,90 +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 } from './ApiRef'; -import { - TypesToApiRefs, - AnyApiRef, - ApiHolder, - ApiFactory, - AnyApiFactory, -} from './types'; - -export class ApiTestRegistry implements ApiHolder { - private readonly apis = new Map(); - private factories = new Map(); - - get(ref: ApiRef): T | undefined { - return this.load(ref); - } - - register( - factory: ApiFactory, - ): ApiTestRegistry { - this.factories.set(factory.implements, factory); - return this; - } - - private load(ref: ApiRef, loading: AnyApiRef[] = []): T | undefined { - const impl = this.apis.get(ref); - if (impl) { - return impl as T; - } - - const factory = this.factories.get(ref); - if (!factory) { - return undefined; - } - - if (loading.includes(factory.implements)) { - throw new Error( - `Circular dependency of api factory for ${factory.implements}`, - ); - } - - const deps = this.loadDeps(ref, factory.deps, [ - ...loading, - factory.implements, - ]); - const api = factory.factory(deps); - this.apis.set(ref, api); - return api as T; - } - - private loadDeps( - dependent: ApiRef, - apis: TypesToApiRefs, - loading: AnyApiRef[], - ): T { - const impls = {} as T; - - for (const key in apis) { - if (apis.hasOwnProperty(key)) { - const ref = apis[key]; - - const api = this.load(ref, loading); - if (!api) { - throw new Error( - `No API factory available for dependency ${ref} of dependent ${dependent}`, - ); - } - impls[key] = api; - } - } - - return impls; - } -} diff --git a/packages/core-api/src/apis/index.ts b/packages/core-api/src/apis/index.ts index c3689b6703..c856a13668 100644 --- a/packages/core-api/src/apis/index.ts +++ b/packages/core-api/src/apis/index.ts @@ -16,7 +16,6 @@ export { ApiProvider, useApi, useApiHolder } from './ApiProvider'; export { ApiRegistry } from './ApiRegistry'; -export { ApiTestRegistry } from './ApiTestRegistry'; export * from './ApiRef'; export * from './types'; export * from './helpers'; From beb9269841b49152588a2604414216738ea56e88 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 4 Sep 2020 17:40:57 +0200 Subject: [PATCH 22/34] core-api: docs for ApiFactoryRegistry and do not override same scope --- .../src/apis/ApiFactoryRegistry.test.ts | 4 ++++ .../core-api/src/apis/ApiFactoryRegistry.ts | 22 +++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/packages/core-api/src/apis/ApiFactoryRegistry.test.ts b/packages/core-api/src/apis/ApiFactoryRegistry.test.ts index 43370f41a7..8b4818ac53 100644 --- a/packages/core-api/src/apis/ApiFactoryRegistry.test.ts +++ b/packages/core-api/src/apis/ApiFactoryRegistry.test.ts @@ -42,12 +42,16 @@ describe('ApiFactoryRegistry', () => { const registry = new ApiFactoryRegistry(); expect(registry.register('default', aFactory1)).toBe(true); expect(registry.get(aRef)).toBe(aFactory1); + expect(registry.register('default', aFactory2)).toBe(false); + expect(registry.get(aRef)).toBe(aFactory1); expect(registry.register('app', aFactory2)).toBe(true); expect(registry.get(aRef)).toBe(aFactory2); expect(registry.register('default', aFactory1)).toBe(false); expect(registry.get(aRef)).toBe(aFactory2); expect(registry.register('static', aFactory1)).toBe(true); expect(registry.get(aRef)).toBe(aFactory1); + expect(registry.register('static', aFactory2)).toBe(false); + expect(registry.get(aRef)).toBe(aFactory2); expect(registry.register('app', aFactory2)).toBe(false); expect(registry.get(aRef)).toBe(aFactory1); expect(registry.getAllApis()).toEqual(new Set([aRef])); diff --git a/packages/core-api/src/apis/ApiFactoryRegistry.ts b/packages/core-api/src/apis/ApiFactoryRegistry.ts index 9d75944d8b..fa52249e25 100644 --- a/packages/core-api/src/apis/ApiFactoryRegistry.ts +++ b/packages/core-api/src/apis/ApiFactoryRegistry.ts @@ -34,24 +34,38 @@ enum ScopeLevels { } type FactoryTuple = { - level: number; + priority: number; factory: AnyApiFactory; }; +/** + * ApiFactoryRegistry is an ApiFactoryHolder implementation that enables + * registration of API Factories with different scope. + * + * Each scope has an assigned priority, where factories registered with + * higher priority scopes override ones with lower priority. + */ export class ApiFactoryRegistry implements ApiFactoryHolder { private readonly factories = new Map(); + /** + * Register a new API factory. Returns true if the factory was added + * to the registry. + * + * A factory will not be added to the registry if there is already + * an existing factory with the same or higher priority. + */ register( scope: ApiFactoryScope, factory: ApiFactory, ) { - const level = ScopeLevels[scope]; + const priority = ScopeLevels[scope]; const existing = this.factories.get(factory.implements); - if (existing && existing.level > level) { + if (existing && existing.priority > priority) { return false; } - this.factories.set(factory.implements, { level, factory }); + this.factories.set(factory.implements, { priority, factory }); return true; } From 38b67031023d2e718f960379ae3ae25426803196 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 4 Sep 2020 17:45:38 +0200 Subject: [PATCH 23/34] core-api: change ApiFactory.implements to .api --- packages/app/src/apis.ts | 4 ++-- .../src/apis/ApiFactoryRegistry.test.ts | 10 +++++----- .../core-api/src/apis/ApiFactoryRegistry.ts | 10 +++++----- .../core-api/src/apis/ApiResolver.test.ts | 20 +++++++++---------- packages/core-api/src/apis/ApiResolver.ts | 11 +++------- packages/core-api/src/apis/helpers.ts | 2 +- packages/core-api/src/apis/types.ts | 2 +- packages/core-api/src/app/App.tsx | 10 +++++----- packages/core/src/api-wrappers/defaultApis.ts | 20 +++++++++---------- plugins/catalog/src/plugin.ts | 2 +- plugins/circleci/dev/index.tsx | 4 ++-- plugins/circleci/src/plugin.ts | 2 +- plugins/graphiql/dev/index.tsx | 2 +- plugins/jenkins/src/plugin.ts | 2 +- plugins/lighthouse/dev/index.tsx | 2 +- plugins/lighthouse/src/plugin.ts | 2 +- plugins/rollbar/src/plugin.ts | 2 +- plugins/scaffolder/src/plugin.ts | 2 +- plugins/techdocs/dev/index.tsx | 2 +- plugins/techdocs/src/plugin.ts | 2 +- 20 files changed, 54 insertions(+), 59 deletions(-) diff --git a/packages/app/src/apis.ts b/packages/app/src/apis.ts index 12d3594921..7f57f6f970 100644 --- a/packages/app/src/apis.ts +++ b/packages/app/src/apis.ts @@ -40,7 +40,7 @@ import { export const apis = [ // TODO(Rugvip): migrate to use /api createApiFactory({ - implements: discoveryApiRef, + api: discoveryApiRef, deps: { configApi: configApiRef }, factory: ({ configApi }) => UrlPatternDiscovery.compile( @@ -48,7 +48,7 @@ export const apis = [ ), }), createApiFactory({ - implements: graphQlBrowseApiRef, + api: graphQlBrowseApiRef, deps: { errorApi: errorApiRef, githubAuthApi: githubAuthApiRef }, factory: ({ errorApi, githubAuthApi }) => GraphQLEndpoints.from([ diff --git a/packages/core-api/src/apis/ApiFactoryRegistry.test.ts b/packages/core-api/src/apis/ApiFactoryRegistry.test.ts index 8b4818ac53..9f44adaef3 100644 --- a/packages/core-api/src/apis/ApiFactoryRegistry.test.ts +++ b/packages/core-api/src/apis/ApiFactoryRegistry.test.ts @@ -18,12 +18,12 @@ import { ApiFactoryRegistry } from './ApiFactoryRegistry'; import { createApiRef } from './ApiRef'; const aRef = createApiRef({ id: 'a', description: '' }); -const aFactory1 = { implements: aRef, deps: {}, factory: () => 1 }; -const aFactory2 = { implements: aRef, deps: {}, factory: () => 2 }; +const aFactory1 = { api: aRef, deps: {}, factory: () => 1 }; +const aFactory2 = { api: aRef, deps: {}, factory: () => 2 }; const bRef = createApiRef({ id: 'b', description: '' }); -const bFactory = { implements: bRef, deps: {}, factory: () => 'x' }; +const bFactory = { api: bRef, deps: {}, factory: () => 'x' }; const cRef = createApiRef({ id: 'c', description: '' }); -const cFactory = { implements: cRef, deps: {}, factory: () => 'y' }; +const cFactory = { api: cRef, deps: {}, factory: () => 'y' }; describe('ApiFactoryRegistry', () => { it('should be empty when created', () => { @@ -51,7 +51,7 @@ describe('ApiFactoryRegistry', () => { expect(registry.register('static', aFactory1)).toBe(true); expect(registry.get(aRef)).toBe(aFactory1); expect(registry.register('static', aFactory2)).toBe(false); - expect(registry.get(aRef)).toBe(aFactory2); + expect(registry.get(aRef)).toBe(aFactory1); expect(registry.register('app', aFactory2)).toBe(false); expect(registry.get(aRef)).toBe(aFactory1); expect(registry.getAllApis()).toEqual(new Set([aRef])); diff --git a/packages/core-api/src/apis/ApiFactoryRegistry.ts b/packages/core-api/src/apis/ApiFactoryRegistry.ts index fa52249e25..0d36e6c550 100644 --- a/packages/core-api/src/apis/ApiFactoryRegistry.ts +++ b/packages/core-api/src/apis/ApiFactoryRegistry.ts @@ -27,7 +27,7 @@ type ApiFactoryScope = | 'app' // Factories registered in the app, overriding default ones | 'static'; // APIs that can't be overridden, e.g. config -enum ScopeLevels { +enum ScopePriority { default = 10, app = 50, static = 100, @@ -59,13 +59,13 @@ export class ApiFactoryRegistry implements ApiFactoryHolder { scope: ApiFactoryScope, factory: ApiFactory, ) { - const priority = ScopeLevels[scope]; - const existing = this.factories.get(factory.implements); - if (existing && existing.priority > priority) { + const priority = ScopePriority[scope]; + const existing = this.factories.get(factory.api); + if (existing && existing.priority >= priority) { return false; } - this.factories.set(factory.implements, { priority, factory }); + this.factories.set(factory.api, { priority, factory }); return true; } diff --git a/packages/core-api/src/apis/ApiResolver.test.ts b/packages/core-api/src/apis/ApiResolver.test.ts index ab4a571cd5..3cd40f289e 100644 --- a/packages/core-api/src/apis/ApiResolver.test.ts +++ b/packages/core-api/src/apis/ApiResolver.test.ts @@ -25,17 +25,17 @@ const cRef = createApiRef<{ x: string }>({ id: 'c', description: '' }); function createRegistry() { const registry = new ApiFactoryRegistry(); registry.register('default', { - implements: aRef, + api: aRef, deps: {}, factory: () => 1, }); registry.register('default', { - implements: bRef, + api: bRef, deps: {}, factory: () => 'b', }); registry.register('default', { - implements: cRef, + api: cRef, deps: { b: bRef }, factory: ({ b }) => ({ x: 'x', b }), }); @@ -45,17 +45,17 @@ function createRegistry() { function createLongCyclicRegistry() { const registry = new ApiFactoryRegistry(); registry.register('default', { - implements: aRef, + api: aRef, deps: { b: bRef }, factory: () => 1, }); registry.register('default', { - implements: bRef, + api: bRef, deps: { c: cRef }, factory: () => 'b', }); registry.register('default', { - implements: cRef, + api: cRef, deps: { a: aRef }, factory: () => ({ x: 'x' }), }); @@ -65,17 +65,17 @@ function createLongCyclicRegistry() { function createShortCyclicRegistry() { const registry = new ApiFactoryRegistry(); registry.register('default', { - implements: aRef, + api: aRef, deps: { a: aRef }, factory: () => 1, }); registry.register('default', { - implements: bRef, + api: bRef, deps: { c: cRef }, factory: () => 'b', }); registry.register('default', { - implements: cRef, + api: cRef, deps: { b: bRef }, factory: () => ({ x: 'x' }), }); @@ -162,7 +162,7 @@ describe('ApiResolver', () => { const registry = new ApiFactoryRegistry(); const factory = jest.fn().mockReturnValue(2); registry.register('default', { - implements: aRef, + api: aRef, deps: {}, factory, }); diff --git a/packages/core-api/src/apis/ApiResolver.ts b/packages/core-api/src/apis/ApiResolver.ts index 9f48a75783..cb65186a37 100644 --- a/packages/core-api/src/apis/ApiResolver.ts +++ b/packages/core-api/src/apis/ApiResolver.ts @@ -74,16 +74,11 @@ export class ApiResolver implements ApiHolder { return undefined; } - if (loading.includes(factory.implements)) { - throw new Error( - `Circular dependency of api factory for ${factory.implements}`, - ); + if (loading.includes(factory.api)) { + throw new Error(`Circular dependency of api factory for ${factory.api}`); } - const deps = this.loadDeps(ref, factory.deps, [ - ...loading, - factory.implements, - ]); + const deps = this.loadDeps(ref, factory.deps, [...loading, factory.api]); const api = factory.factory(deps); this.apis.set(ref, api); return api as T; diff --git a/packages/core-api/src/apis/helpers.ts b/packages/core-api/src/apis/helpers.ts index dda6c57fb0..7d616acd01 100644 --- a/packages/core-api/src/apis/helpers.ts +++ b/packages/core-api/src/apis/helpers.ts @@ -40,7 +40,7 @@ export function createApiFactory< ): ApiFactory { if ('id' in factory) { return { - implements: factory, + api: factory, deps: {} as TypesToApiRefs, factory: () => instance!, }; diff --git a/packages/core-api/src/apis/types.ts b/packages/core-api/src/apis/types.ts index 5b2956cfa1..61c229b18e 100644 --- a/packages/core-api/src/apis/types.ts +++ b/packages/core-api/src/apis/types.ts @@ -31,7 +31,7 @@ export type ApiHolder = { }; export type ApiFactory = { - implements: ApiRef; + api: ApiRef; deps: TypesToApiRefs; factory(deps: Deps): Api; }; diff --git a/packages/core-api/src/app/App.tsx b/packages/core-api/src/app/App.tsx index 1897a12d16..9dd2fb138f 100644 --- a/packages/core-api/src/app/App.tsx +++ b/packages/core-api/src/app/App.tsx @@ -298,12 +298,12 @@ export class PrivateAppImpl implements BackstageApp { const registry = new ApiFactoryRegistry(); registry.register('static', { - implements: appThemeApiRef, + api: appThemeApiRef, deps: {}, factory: () => AppThemeSelector.createWithStorage(this.themes), }); registry.register('static', { - implements: configApiRef, + api: configApiRef, deps: {}, factory: () => { if (!this.configApi) { @@ -315,7 +315,7 @@ export class PrivateAppImpl implements BackstageApp { }, }); registry.register('static', { - implements: identityApiRef, + api: identityApiRef, deps: {}, factory: () => this.identityApi, }); @@ -329,7 +329,7 @@ export class PrivateAppImpl implements BackstageApp { if (!registry.register('default', factory)) { throw new Error( `Plugin ${plugin.getId()} tried to register duplicate or forbidden API factory for ${ - factory.implements + factory.api }`, ); } @@ -339,7 +339,7 @@ export class PrivateAppImpl implements BackstageApp { for (const factory of this.apis) { if (!registry.register('app', factory)) { throw new Error( - `Duplicate or forbidden API factory for ${factory.implements} in app`, + `Duplicate or forbidden API factory for ${factory.api} in app`, ); } } diff --git a/packages/core/src/api-wrappers/defaultApis.ts b/packages/core/src/api-wrappers/defaultApis.ts index 82b60d31e6..a3f0cb0251 100644 --- a/packages/core/src/api-wrappers/defaultApis.ts +++ b/packages/core/src/api-wrappers/defaultApis.ts @@ -48,7 +48,7 @@ import { export const defaultApis = [ createApiFactory({ - implements: discoveryApiRef, + api: discoveryApiRef, deps: { configApi: configApiRef }, factory: ({ configApi }) => UrlPatternDiscovery.compile( @@ -57,20 +57,20 @@ export const defaultApis = [ }), createApiFactory(alertApiRef, new AlertApiForwarder()), createApiFactory({ - implements: errorApiRef, + api: errorApiRef, deps: { alertApi: alertApiRef }, factory: ({ alertApi }) => new ErrorAlerter(alertApi, new ErrorApiForwarder()), }), createApiFactory({ - implements: storageApiRef, + api: storageApiRef, deps: { errorApi: errorApiRef }, factory: ({ errorApi }) => WebStorage.create({ errorApi }), }), createApiFactory(featureFlagsApiRef, new FeatureFlags()), createApiFactory(oauthRequestApiRef, new OAuthRequestManager()), createApiFactory({ - implements: googleAuthApiRef, + api: googleAuthApiRef, deps: { discoveryApi: discoveryApiRef, oauthRequestApi: oauthRequestApiRef, @@ -79,7 +79,7 @@ export const defaultApis = [ GoogleAuth.create({ discoveryApi, oauthRequestApi }), }), createApiFactory({ - implements: microsoftAuthApiRef, + api: microsoftAuthApiRef, deps: { discoveryApi: discoveryApiRef, oauthRequestApi: oauthRequestApiRef, @@ -88,7 +88,7 @@ export const defaultApis = [ MicrosoftAuth.create({ discoveryApi, oauthRequestApi }), }), createApiFactory({ - implements: githubAuthApiRef, + api: githubAuthApiRef, deps: { discoveryApi: discoveryApiRef, oauthRequestApi: oauthRequestApiRef, @@ -97,7 +97,7 @@ export const defaultApis = [ GithubAuth.create({ discoveryApi, oauthRequestApi }), }), createApiFactory({ - implements: oktaAuthApiRef, + api: oktaAuthApiRef, deps: { discoveryApi: discoveryApiRef, oauthRequestApi: oauthRequestApiRef, @@ -106,7 +106,7 @@ export const defaultApis = [ OktaAuth.create({ discoveryApi, oauthRequestApi }), }), createApiFactory({ - implements: gitlabAuthApiRef, + api: gitlabAuthApiRef, deps: { discoveryApi: discoveryApiRef, oauthRequestApi: oauthRequestApiRef, @@ -115,7 +115,7 @@ export const defaultApis = [ GitlabAuth.create({ discoveryApi, oauthRequestApi }), }), createApiFactory({ - implements: auth0AuthApiRef, + api: auth0AuthApiRef, deps: { discoveryApi: discoveryApiRef, oauthRequestApi: oauthRequestApiRef, @@ -124,7 +124,7 @@ export const defaultApis = [ Auth0Auth.create({ discoveryApi, oauthRequestApi }), }), createApiFactory({ - implements: oauth2ApiRef, + api: oauth2ApiRef, deps: { discoveryApi: discoveryApiRef, oauthRequestApi: oauthRequestApiRef, diff --git a/plugins/catalog/src/plugin.ts b/plugins/catalog/src/plugin.ts index 61cdf5c95a..dfe12fd500 100644 --- a/plugins/catalog/src/plugin.ts +++ b/plugins/catalog/src/plugin.ts @@ -26,7 +26,7 @@ export const plugin = createPlugin({ id: 'catalog', apis: [ createApiFactory({ - implements: catalogApiRef, + api: catalogApiRef, deps: { discoveryApi: discoveryApiRef }, factory: ({ discoveryApi }) => new CatalogClient({ discoveryApi }), }), diff --git a/plugins/circleci/dev/index.tsx b/plugins/circleci/dev/index.tsx index ed7dd5de9c..4bf67d5cb2 100644 --- a/plugins/circleci/dev/index.tsx +++ b/plugins/circleci/dev/index.tsx @@ -20,9 +20,9 @@ import { circleCIApiRef, CircleCIApi } from '../src/api'; createDevApp() .registerPlugin(plugin) - .registerApiFactory({ + .registerApi({ + api: circleCIApiRef, deps: {}, factory: () => new CircleCIApi(), - implements: circleCIApiRef, }) .render(); diff --git a/plugins/circleci/src/plugin.ts b/plugins/circleci/src/plugin.ts index 06c6381c37..86be898366 100644 --- a/plugins/circleci/src/plugin.ts +++ b/plugins/circleci/src/plugin.ts @@ -23,7 +23,7 @@ export const plugin = createPlugin({ id: 'circleci', apis: [ createApiFactory({ - implements: circleCIApiRef, + api: circleCIApiRef, deps: { configApi: configApiRef }, factory: ({ configApi }) => new CircleCIApi( diff --git a/plugins/graphiql/dev/index.tsx b/plugins/graphiql/dev/index.tsx index 93b7b35334..b93995a5dc 100644 --- a/plugins/graphiql/dev/index.tsx +++ b/plugins/graphiql/dev/index.tsx @@ -21,7 +21,7 @@ import { plugin, GraphQLEndpoints, graphQlBrowseApiRef } from '../src'; createDevApp() .registerPlugin(plugin) .registerApi({ - implements: graphQlBrowseApiRef, + api: graphQlBrowseApiRef, deps: { errorApi: errorApiRef, githubAuthApi: githubAuthApiRef, diff --git a/plugins/jenkins/src/plugin.ts b/plugins/jenkins/src/plugin.ts index fe24e1b63d..4d1af322c4 100644 --- a/plugins/jenkins/src/plugin.ts +++ b/plugins/jenkins/src/plugin.ts @@ -32,7 +32,7 @@ export const plugin = createPlugin({ id: 'jenkins', apis: [ createApiFactory({ - implements: jenkinsApiRef, + api: jenkinsApiRef, deps: { configApi: configApiRef }, factory: ({ configApi }) => new JenkinsApi( diff --git a/plugins/lighthouse/dev/index.tsx b/plugins/lighthouse/dev/index.tsx index 6fa39577f2..bf761965f1 100644 --- a/plugins/lighthouse/dev/index.tsx +++ b/plugins/lighthouse/dev/index.tsx @@ -21,7 +21,7 @@ import { lighthouseApiRef, LighthouseRestApi } from '../src'; createDevApp() .registerPlugin(plugin) .registerApi({ - implements: lighthouseApiRef, + api: lighthouseApiRef, deps: {}, factory: () => new LighthouseRestApi('http://localhost:3003'), }) diff --git a/plugins/lighthouse/src/plugin.ts b/plugins/lighthouse/src/plugin.ts index 5700a9991f..677b5f682a 100644 --- a/plugins/lighthouse/src/plugin.ts +++ b/plugins/lighthouse/src/plugin.ts @@ -24,7 +24,7 @@ export const plugin = createPlugin({ id: 'lighthouse', apis: [ createApiFactory({ - implements: lighthouseApiRef, + api: lighthouseApiRef, deps: { configApi: configApiRef }, factory: ({ configApi }) => LighthouseRestApi.fromConfig(configApi), }), diff --git a/plugins/rollbar/src/plugin.ts b/plugins/rollbar/src/plugin.ts index 21432572e1..c3ca6173ff 100644 --- a/plugins/rollbar/src/plugin.ts +++ b/plugins/rollbar/src/plugin.ts @@ -29,7 +29,7 @@ export const plugin = createPlugin({ id: 'rollbar', apis: [ createApiFactory({ - implements: rollbarApiRef, + api: rollbarApiRef, deps: { discoveryApi: discoveryApiRef }, factory: ({ discoveryApi }) => new RollbarClient({ discoveryApi }), }), diff --git a/plugins/scaffolder/src/plugin.ts b/plugins/scaffolder/src/plugin.ts index 15ec749f2f..41f7a03249 100644 --- a/plugins/scaffolder/src/plugin.ts +++ b/plugins/scaffolder/src/plugin.ts @@ -28,7 +28,7 @@ export const plugin = createPlugin({ id: 'scaffolder', apis: [ createApiFactory({ - implements: scaffolderApiRef, + api: scaffolderApiRef, deps: { discoveryApi: discoveryApiRef }, factory: ({ discoveryApi }) => new ScaffolderApi({ discoveryApi }), }), diff --git a/plugins/techdocs/dev/index.tsx b/plugins/techdocs/dev/index.tsx index 9902cf6526..12974ef8b7 100644 --- a/plugins/techdocs/dev/index.tsx +++ b/plugins/techdocs/dev/index.tsx @@ -21,12 +21,12 @@ import { techdocsStorageApiRef } from '../src'; createDevApp() .registerApi({ + api: techdocsStorageApiRef, deps: {}, factory: () => new TechDocsDevStorageApi({ apiOrigin: 'http://localhost:3000/api', }), - implements: techdocsStorageApiRef, }) .registerPlugin(plugin) .render(); diff --git a/plugins/techdocs/src/plugin.ts b/plugins/techdocs/src/plugin.ts index 673089be75..d00fcac485 100644 --- a/plugins/techdocs/src/plugin.ts +++ b/plugins/techdocs/src/plugin.ts @@ -56,7 +56,7 @@ export const plugin = createPlugin({ id: 'techdocs', apis: [ createApiFactory({ - implements: techdocsStorageApiRef, + api: techdocsStorageApiRef, deps: { configApi: configApiRef }, factory: ({ configApi }) => new TechDocsStorageApi({ From b3770859eb87aba78b97f72bf6f436dfa6ae517e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 7 Sep 2020 11:20:01 +0200 Subject: [PATCH 24/34] create-app: update apis.ts for auto DI --- .../default-app/packages/app/src/apis.ts | 86 +++---------------- 1 file changed, 12 insertions(+), 74 deletions(-) diff --git a/packages/create-app/templates/default-app/packages/app/src/apis.ts b/packages/create-app/templates/default-app/packages/app/src/apis.ts index ba4343801f..e0503e504f 100644 --- a/packages/create-app/templates/default-app/packages/app/src/apis.ts +++ b/packages/create-app/templates/default-app/packages/app/src/apis.ts @@ -1,79 +1,17 @@ import { - ApiRegistry, - alertApiRef, - errorApiRef, - AlertApiForwarder, - ConfigApi, - ErrorApiForwarder, - ErrorAlerter, discoveryApiRef, UrlPatternDiscovery, - oauthRequestApiRef, - OAuthRequestManager, - storageApiRef, - WebStorage, + createApiFactory, + configApiRef, } from '@backstage/core'; -import { - lighthouseApiRef, - LighthouseRestApi, -} from '@backstage/plugin-lighthouse'; - -import { - GithubActionsClient, - githubActionsApiRef, -} from '@backstage/plugin-github-actions'; - -import { - techdocsStorageApiRef, - TechDocsStorageApi, -} from '@backstage/plugin-techdocs'; - -import { catalogApiRef, CatalogClient } from '@backstage/plugin-catalog'; -import { CircleCIApi, circleCIApiRef } from '@backstage/plugin-circleci'; - -import { scaffolderApiRef, ScaffolderApi } from '@backstage/plugin-scaffolder'; - - - -export const apis = (config: ConfigApi) => { - // eslint-disable-next-line no-console - console.log(`Creating APIs for ${config.getString('app.title')}`); - - const backendUrl = config.getString('backend.baseUrl'); - const techdocsStorageUrl = config.getString('techdocs.storageUrl'); - - const builder = ApiRegistry.builder(); - - const discoveryApi = builder.add( - discoveryApiRef, - UrlPatternDiscovery.compile(`${backendUrl}/{{ pluginId }}`), - ); - const alertApi = builder.add(alertApiRef, new AlertApiForwarder()); - const errorApi = builder.add( - errorApiRef, - new ErrorAlerter(alertApi, new ErrorApiForwarder()), - ); - - builder.add(storageApiRef, WebStorage.create({ errorApi })); - builder.add(oauthRequestApiRef, new OAuthRequestManager()); - - builder.add(catalogApiRef, new CatalogClient({ discoveryApi })); - builder.add(githubActionsApiRef, new GithubActionsClient()); - - builder.add(lighthouseApiRef, new LighthouseRestApi('http://localhost:3003')); - - builder.add( - circleCIApiRef, - new CircleCIApi(`${backendUrl}/proxy/circleci/api`), - ); - - builder.add(scaffolderApiRef, new ScaffolderApi({ discoveryApi })); - - builder.add( - techdocsStorageApiRef, - new TechDocsStorageApi({ apiOrigin: techdocsStorageUrl }), - ); - - return builder.build(); -}; +export const apis = [ + createApiFactory({ + api: discoveryApiRef, + deps: { configApi: configApiRef }, + factory: ({ configApi }) => + UrlPatternDiscovery.compile( + `${configApi.getString('backend.baseUrl')}/{{ pluginId }}`, + ), + }), +]; From 0178f37706297d9778edd06af741bf311d7a98fb Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 7 Sep 2020 15:58:21 +0200 Subject: [PATCH 25/34] dev-utils: added test for DevApp --- packages/dev-utils/src/devApp/render.test.tsx | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 packages/dev-utils/src/devApp/render.test.tsx diff --git a/packages/dev-utils/src/devApp/render.test.tsx b/packages/dev-utils/src/devApp/render.test.tsx new file mode 100644 index 0000000000..fbebf2039b --- /dev/null +++ b/packages/dev-utils/src/devApp/render.test.tsx @@ -0,0 +1,43 @@ +/* + * 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 React from 'react'; +import { render } from '@testing-library/react'; +import { useApi, configApiRef } from '@backstage/core'; +import { createDevApp } from './render'; + +const anyEnv = (process.env = { ...process.env }) as any; + +describe('DevAppBuilder', () => { + it('should be able to render a component in a dev app', async () => { + anyEnv.APP_CONFIG = [ + { context: 'test', data: { app: { title: 'Test App' } } }, + ]; + + const MyComponent = () => { + const configApi = useApi(configApiRef); + return
My App: {configApi.getString('app.title')}
; + }; + + const DevApp = createDevApp() + .addRootChild() + .build(); + + const rendered = render(); + + expect(await rendered.findByText('My App: Test App')).toBeInTheDocument(); + }); +}); From 0fa4c72a92d1e419fbad5df08d18b1cc66733d2d Mon Sep 17 00:00:00 2001 From: Omer Farooq <17722640+o-farooq@users.noreply.github.com> Date: Wed, 9 Sep 2020 00:25:46 +1200 Subject: [PATCH 26/34] revert yarn.lock upgrade Storybook to version 6 update storybook renderer layout docs: update create app command and link revert yarn.lock changes revert yarn.lock revert yarn --- docs/features/techdocs/getting-started.md | 2 +- microsite/blog/2020-04-30-how-to-quickly-set-up-backstage.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/features/techdocs/getting-started.md b/docs/features/techdocs/getting-started.md index 414b3baae8..6cc6f43e72 100644 --- a/docs/features/techdocs/getting-started.md +++ b/docs/features/techdocs/getting-started.md @@ -28,7 +28,7 @@ installed: To create a new Backstage application for TechDocs, run the following command: ```bash -npx @backstage/cli create-app +npx @backstage/create-app ``` You will then be prompted to enter a name for your application. Once that's diff --git a/microsite/blog/2020-04-30-how-to-quickly-set-up-backstage.md b/microsite/blog/2020-04-30-how-to-quickly-set-up-backstage.md index 65ee02f6a0..dff567eaf3 100644 --- a/microsite/blog/2020-04-30-how-to-quickly-set-up-backstage.md +++ b/microsite/blog/2020-04-30-how-to-quickly-set-up-backstage.md @@ -34,7 +34,7 @@ You get to take full advantage of a platform that we at Spotify have been using Just run the backstage-cli: ```bash -npx @backstage/cli create-app +npx @backstage/create-app ``` Name your app, and we will create everything you need: @@ -50,7 +50,7 @@ yarn start And you are good to go! 👍 -Read the full documentation on how to [create an app](/docs/getting-started/create-an-app.md) on GitHub. +Read the full documentation on how to [create an app](/docs/getting-started/create-an-app) on GitHub. ## What do I get? (Let's get technical...) From 1b9673799f21eb9595857386832da663bc3490be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20=C3=85lund?= Date: Tue, 8 Sep 2020 14:39:49 +0200 Subject: [PATCH 27/34] Remove Explore from sidebar (#2327) * Remove Explore from sidebar * Also in app --- packages/app/src/components/Root/Root.tsx | 2 -- .../templates/default-app/packages/app/src/sidebar.tsx | 2 -- 2 files changed, 4 deletions(-) diff --git a/packages/app/src/components/Root/Root.tsx b/packages/app/src/components/Root/Root.tsx index ab95f623af..ae0d24fa5e 100644 --- a/packages/app/src/components/Root/Root.tsx +++ b/packages/app/src/components/Root/Root.tsx @@ -18,7 +18,6 @@ import React, { FC, useContext } from 'react'; import PropTypes from 'prop-types'; import { Link, makeStyles } from '@material-ui/core'; import HomeIcon from '@material-ui/icons/Home'; -import ExploreIcon from '@material-ui/icons/Explore'; import ExtensionIcon from '@material-ui/icons/Extension'; import BuildIcon from '@material-ui/icons/BuildRounded'; import RuleIcon from '@material-ui/icons/AssignmentTurnedIn'; @@ -91,7 +90,6 @@ const Root: FC<{}> = ({ children }) => ( {/* Global nav, not org-specific */} - diff --git a/packages/create-app/templates/default-app/packages/app/src/sidebar.tsx b/packages/create-app/templates/default-app/packages/app/src/sidebar.tsx index fa9a397751..9e343b86ac 100644 --- a/packages/create-app/templates/default-app/packages/app/src/sidebar.tsx +++ b/packages/create-app/templates/default-app/packages/app/src/sidebar.tsx @@ -2,7 +2,6 @@ import React from 'react'; import HomeIcon from '@material-ui/icons/Home'; import LibraryBooks from '@material-ui/icons/LibraryBooks'; import CreateComponentIcon from '@material-ui/icons/AddCircleOutline'; -import ExploreIcon from '@material-ui/icons/Explore'; import BuildIcon from '@material-ui/icons/BuildRounded'; import RuleIcon from '@material-ui/icons/AssignmentTurnedIn'; import MapIcon from '@material-ui/icons/MyLocation'; @@ -23,7 +22,6 @@ export const AppSidebar = () => ( {/* Global nav, not org-specific */} - From 6cdad09d3b9fb6dc2e94d0281a8af4e3f8bcdd73 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 8 Sep 2020 16:34:15 +0200 Subject: [PATCH 28/34] core: fix InfoCard type troubles --- .../core/src/layout/InfoCard/InfoCard.tsx | 57 +++++++++---------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/packages/core/src/layout/InfoCard/InfoCard.tsx b/packages/core/src/layout/InfoCard/InfoCard.tsx index 983356dd4a..6914d396b1 100644 --- a/packages/core/src/layout/InfoCard/InfoCard.tsx +++ b/packages/core/src/layout/InfoCard/InfoCard.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React, { FC, ReactNode } from 'react'; +import React, { ReactNode } from 'react'; import { Card, CardActions, @@ -23,7 +23,6 @@ import { CardHeaderProps, Divider, withStyles, - createStyles, makeStyles, } from '@material-ui/core'; import classNames from 'classnames'; @@ -31,37 +30,26 @@ import { ErrorBoundary } from '../ErrorBoundary'; import { BottomLink, BottomLinkProps } from '../BottomLink'; const useStyles = makeStyles(theme => ({ - header: { - padding: theme.spacing(2, 2, 2, 2.5), - }, noPadding: { padding: 0, '&:last-child': { paddingBottom: 0, }, }, + header: { + padding: theme.spacing(2, 2, 2, 2.5), + }, + headerTitle: { + fontWeight: 700, + }, + headerSubheader: { + paddingTop: theme.spacing(1), + }, + headerAvatar: {}, + headerAction: {}, + headerContent: {}, })); -const useBoldHeaderStyles = makeStyles(theme => - createStyles({ - title: { - fontWeight: 700, - }, - subheader: { - paddingTop: theme.spacing(1), - }, - root: {}, - avatar: {}, - action: {}, - content: {}, - }), -); - -const BoldHeader = ({ classes, ...props }: CardHeaderProps) => { - const styles = useBoldHeaderStyles({ classes }); - return ; -}; - const CardActionsTopRight = withStyles(theme => ({ root: { display: 'inline-block', @@ -137,6 +125,8 @@ const VARIANT_STYLES = { * ... */ type Props = { + title?: ReactNode; + subheader?: ReactNode; divider?: boolean; deepLink?: BottomLinkProps; slackChannel?: string; @@ -152,9 +142,9 @@ type Props = { actionsTopRight?: ReactNode; className?: string; noPadding?: boolean; -} & Pick; +}; -export const InfoCard: FC = ({ +export const InfoCard = ({ title, subheader, divider, @@ -170,7 +160,7 @@ export const InfoCard: FC = ({ actionsTopRight, className, noPadding, -}) => { +}: Props): JSX.Element => { const classes = useStyles(); /** @@ -201,8 +191,15 @@ export const InfoCard: FC = ({ {title && ( <> - Date: Tue, 8 Sep 2020 14:57:15 -0400 Subject: [PATCH 29/34] Update index.js (#2332) --- microsite/pages/en/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite/pages/en/index.js b/microsite/pages/en/index.js index 7a58ede25f..e233826224 100644 --- a/microsite/pages/en/index.js +++ b/microsite/pages/en/index.js @@ -297,7 +297,7 @@ class Index extends React.Component { /> - Backstage TechDocs (Coming Soon) + Backstage TechDocs Docs like code From cfdccbda2344fcdb17b7b2bce478b18e42c5c099 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20=C3=85lund?= Date: Tue, 8 Sep 2020 21:12:17 +0200 Subject: [PATCH 30/34] Updating demo page (#2335) * Update demos.js * Update demos.js * Update demos.js * Update demos.js * Update demos.js Co-authored-by: AlleyWei <64219471+AlleyWei@users.noreply.github.com> --- microsite/pages/en/demos.js | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/microsite/pages/en/demos.js b/microsite/pages/en/demos.js index 9f9dcec819..0cb200892c 100644 --- a/microsite/pages/en/demos.js +++ b/microsite/pages/en/demos.js @@ -78,6 +78,39 @@ const Background = props => { + + + + Make documentation easy + + Documentation! Everyone needs it, no one wants to create it, and + no one can ever find it. Backstage follows a “docs like code” + approach: you write documentation in Markdown files right + alongside your code. This makes documentation easier to create, + maintain, find — and, you know, actually use. This demo video + showcases Spotify’s internal version of TechDocs. Learn more about{' '} + + TechDocs + + . + + + Watch now + + + + + + + + From cdf7f07f756ec10c55dd09aaaff49fccebcd1fb9 Mon Sep 17 00:00:00 2001 From: Gary Niemen <65337273+garyniemen@users.noreply.github.com> Date: Tue, 8 Sep 2020 21:14:05 +0200 Subject: [PATCH 31/34] techdocs-blog (#2333) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * techdocs-blog * Remove extra heading Co-authored-by: Stefan Ålund --- .../blog/2020-09-08-announcing-tech-docs.md | 120 ++++++++++++++++++ .../assets/announcing-techdocs/discover1.png | Bin 0 -> 63966 bytes .../assets/announcing-techdocs/discover2.png | Bin 0 -> 56872 bytes .../announcing-techdocs/docs-in-backstage.png | Bin 0 -> 53879 bytes .../announcing-techdocs/feedback-loop1.png | Bin 0 -> 42103 bytes .../announcing-techdocs/feedback-loop2.png | Bin 0 -> 34396 bytes .../announcing-techdocs/github-issues.png | Bin 0 -> 26095 bytes .../assets/announcing-techdocs/metrics.png | Bin 0 -> 52455 bytes 8 files changed, 120 insertions(+) create mode 100644 microsite/blog/2020-09-08-announcing-tech-docs.md create mode 100644 microsite/blog/assets/announcing-techdocs/discover1.png create mode 100644 microsite/blog/assets/announcing-techdocs/discover2.png create mode 100644 microsite/blog/assets/announcing-techdocs/docs-in-backstage.png create mode 100644 microsite/blog/assets/announcing-techdocs/feedback-loop1.png create mode 100644 microsite/blog/assets/announcing-techdocs/feedback-loop2.png create mode 100644 microsite/blog/assets/announcing-techdocs/github-issues.png create mode 100644 microsite/blog/assets/announcing-techdocs/metrics.png diff --git a/microsite/blog/2020-09-08-announcing-tech-docs.md b/microsite/blog/2020-09-08-announcing-tech-docs.md new file mode 100644 index 0000000000..76c6a8539b --- /dev/null +++ b/microsite/blog/2020-09-08-announcing-tech-docs.md @@ -0,0 +1,120 @@ +--- +title: Announcing Tech Docs: Spotify’s docs-like-code for Backstage +author: Gary Niemen +authorURL: https://github.com/garyniemen +--- + +Since we [open sourced Backstage](https://backstage.io/blog/2020/03/16/announcing-backstage), one of the most requested features has been for a technical documentation plugin. Well, good news. The first open source version of TechDocs is here. Now let’s start collaborating and making it better, together. + + + +Internally, we call it TechDocs. It’s the most used plugin at Spotify by far — accounting for about 20% of our Backstage traffic (even though it is just one of 130+ plugins). Its popularity is evidence of something simple: We made documentation so easy to create, find, and use — people actually use it. + +We are quite sure the main reason for the success of TechDocs is our docs-like-code approach — engineers write their technical documentation in Markdown files that live together with the code. During CI, a documentation site is created using MkDocs, and all sites are rendered centrally in a Backstage plugin. On top of the static documentation, we incorporate additional metadata about the documentation site — such as owner, open GitHub Issues, Slack support channel, and Stack Overflow Enterprise tags. + +![available-templates](assets/announcing-techdocs/docs-in-backstage.png) + +Watch this video to see [Spotify’s internal version of TechDocs](https://backstage.io/demos) in action. + +But this is just one way to do it. Today we’re most excited for what the open version of TechDocs can become. + +## Okay, let’s start collaborating + +If you go to [GitHub](https://github.com/spotify/backstage/tree/master/plugins) now, you’ll find everything you need to start collaborating with us to build out the docs-like-code Backstage plugin — we’ll call it TechDocs in the open as well. + +You’ll find the code in [techdocs](https://github.com/spotify/backstage/tree/master/plugins/techdocs) (frontend) and [techdocs-backend](https://github.com/spotify/backstage/tree/master/plugins/techdocs-backend). (There are also two separate packages [techdocs-cli](https://github.com/spotify/backstage/tree/master/packages/techdocs-cli) and [techdocs-container](https://github.com/spotify/backstage/tree/master/packages/techdocs-container).) + +You’ll find issues to work on in the [issues queue](https://github.com/spotify/backstage/issues?q=is%3Aissue+is%3Aopen+label%3A%22docs-like-code%22+label%3A%22help+wanted%22), typically starting with TechDocs: and labeled with docs-like-code, some labeled good first issue. Feel free to add your own issues, of course. + +![available-templates](assets/announcing-techdocs/github-issues.png) + +What we have on GitHub so far is a first iteration of TechDocs that you can use end-to-end — in other words, from docs written in Markdown in GitHub to a published site on Backstage. + +More specifically, with this first iteration, you can: + +* Run TechDocs locally and read documentation. +* Configure your entity (e.g. service, website) so that Backstage builds your documentation and serves it in TechDocs. Documentation is displayed on the Docs tab in the Service Catalog and on its own page. +* Get documentation set up for free in your project when you create a new component out of one of the non-experimental templates (labeled with recommended). If you are looking for a standalone documentation project, use the docs-template. +* Choose your own storage solution for the documentation. +* Define your own API to interface with your documentation solution. + + +For a full overview, including getting started instructions, check out our [TechDocs Documentation](https://backstage.io/docs/features/techdocs/techdocs-overview). + +But before you go there, let me tell you a bit about the TechDocs story — and why we believe TechDocs is such a powerful yet simple solution for great documentation. + +## The TechDocs story + +Here is the TechDocs story. It’s not an uncommon one (we have learned from many other companies). + +About a year and a half ago, we conducted a company-wide productivity survey. The third largest problem according to all our engineers? Not being able to find the technical information they needed to do their work. And it’s not surprising. There was no standard way to produce and consume technical documentation, so teams were going their own way — using Confluence, Google Docs, README files, custom built websites, GitHub Pages, and so on and on. And those searching for information were left to hunt for it in all those different places until they found what they were looking for (if they ever did). Worse, if you did happen to find the documentation that you needed, there was no way to know whether the information was up-to-date or correct. In other words, there was no way to know whether you could trust what you found. We did have technical writers at the company, but they were mostly scattered across the company solving documentation problems within their own particular domain. + +So this is the fertile soil on which TechDocs was built. + +After a Hack Week implementation attracted interest from high up in the company, we formed a cross-functional team made up of technical writers and engineers with the mission to solve internal technical documentation at Spotify. And we started to build TechDocs. We went for a docs-like-code approach, fiercely optimizing for engineers and engineering workflows. We also went for an opinionated approach, telling everybody: This is the standard way to do technical documentation at Spotify. The sense was that engineers appreciated a documentation solution that was in line with their workflow and, after all the frustration of multiple tools, were relieved to be told “this is the way to do it”. + +For more information about this journey, take a look at my 20-minute talk from DevRelCon London from last December: [The Hero’s Journey: How we are solving internal technical documentation at Spotify](https://www.linkedin.com/posts/garyniemen_how-we-are-solving-internal-technical-documentation-activity-6646078605594030080-4L31). + +## Key problem areas that we are solving + +We have come a long way, fast — both in our implementation and in our thinking. Here are some of the key problem areas that we are addressing. Note that they are in various stages of implementation, and we won’t be able to release everything within our minimum plugin. In fact, see this as an appetite taster. What we hope is that we can build together. + +### Stuck to unstuck + +Very early on, we decided that the main problem we were trying to solve was to help engineers (when using technical documentation) go from stuck to unstuck, and fast. This became our guiding principle. Is what we are building helping engineers get unstuck faster? From this, it follows that we need to promote quality documentation on the one hand, and provide a high level of discoverability on the other. One without the other is not going to cut it. + +### Feedback loops + +What we want to build is a thriving community of technical documentation creators, contributors, and readers. We want this because, we believe, this is the way to drive up the quality of the documentation. More readers, more feedback, more doc updates. And driving up the quality of the corpus of technical documentation leads to trust which in turn leads to more engagement and, hence, more of a thriving community. + +To get this working, we recognised that we need to remove ‘friction from the system’ — we need to build in efficient feedback loops. For example, help engineers get their doc site up by providing documentation improvement hints and build information as close as possible to where they are already working. And for readers, make it easy to give feedback. And then for doc site owners, ensure that they are notified when there is feedback and incentivised to make the fix. + +![available-templates](assets/announcing-techdocs/feedback-loop1.png) + +![available-templates](assets/announcing-techdocs/feedback-loop2.png) + +### Trust + +How do I know whether to trust this piece of documentation? This is a question we want to be able to answer for those using technical documentation in Backstage. It’s not an easy nut to crack. It is almost, one could say, the hard problem of technical documentation. For example, some might say ‘last updated’ is a key factor. But what about stable, good quality documentation that has no need to be updated? What about page views? Yes, this is a good sign that the documentation is being found and viewed, but it doesn’t say anything about whether the documentation can be trusted. How about a button: Did this documentation help? This is good, but will people use it? Will we get enough data to show trust? We have lofty ambitions of one day providing a trust score on the doc site informed by a super-intelligent algorithm. But we are not there yet. For now, we have landed on surfacing when the documentation was last updated, top five contributors, the support channel, owning team, and number of open GitHub Issues. But going forward we are definitely up for solving the hard problem. We think there’s much more work to be done here and look forward to seeing ideas from the community. + +### Discoverability and search + +How to find stuff? That is another big question. As mentioned above, it’s all well and good having quality documentation, but it’s no use whatsoever if you can’t find it. If you know what you are looking for, then you can use a search engine. If you don’t know what you are looking for, then you are going to need more — like a well designed information architecture, a user friendly browse experience, and even intelligent suggestions based on your role and what you have searched for previously. + +In this problem area, we made use of Elasticsearch, the open source search engine that was already being used in Backstage, to implement documentation search across all documentation sites and per documentation site. In terms of discoverability, we implemented a documentation home page in Backstage that surfaces Spotify’s most important documents and uses metrics to list the company’s most used doc sites as well as the documentation equivalent of a “your daily mix” playlist. + +![available-templates](assets/announcing-techdocs/discover1.png) + +![available-templates](assets/announcing-techdocs/discover2.png) + +There is much more to do in the area of discoverability and search. + +### Use case variations + +The standard use case for TechDocs is: One component in Backstage equals one GitHub repository, equals one doc site. This use case comes in two flavours: the repository is a code repository with docs or a docs-only repository. Then, to meet the needs of one large part of the Spotify engineering organisation that uses monorepos (multi-component repositories), we added a third use case. We built an MkDocs plugin that enabled doc site creators to include documentation from doc folders in other parts of the repository. So this use case is: One main component in Backstage equals a monorepo with distributed documentation, equals one doc site. + +These three use cases satisfy most of the needs, but we have had plenty of requests for additional use cases, for example, the ability to create multiple doc sites from a multi-component repository and the ability to create one doc site from documentation in multiple repositories. + +### Metrics + +There are many good arguments for standardizing the way that technical documentation is produced and consumed. One of them is metrics. If we have one way of producing technical documentation (in our case, GitHub Enterprise) and one place where it shows up (in our case, Backstage), we are in a strong position to build up metrics that help all the various stakeholders — for example, us building TechDocs, teams creating documentation sites, and engineers trying to get unstuck. Just imagine how much harder this would be if technical documentation was produced and consumed in a plethora of places, such as Confluence, Google Docs, README files, custom web sites, and GitHub Pages. + +One thing we have recently completed is a Manage page in Backstage for doc site owners. Here teams can see all the documentation that they own, the number of GitHub Issues per doc site or page, and last updated. We have also built a large dashboard using the open source analytics software Redash to inform our own product development process. + +![available-templates](assets/announcing-techdocs/metrics.png) + +Again, there is a lot more that can be done in the area of metrics. Did I mention the trust score? + +### Code-like-docs + +Code-like-docs, what? Okay, it’s just my little play on words. This is what I mean. One request that we keep getting is to be able to have code in the documentation fetched from and in sync with code in GitHub. In this way, you can avoid code in the documentation going stale. MkDocs does have an extension for this — but it has some limitations. For example, the code has to be in the /docs folder with the Markdown files. We are working on developing a wider and more flexible solution. + +### Golden Paths + +At Spotify, we have the concept of [Golden Paths](https://engineering.atspotify.com/2020/08/17/how-we-use-golden-paths-to-solve-fragmentation-in-our-software-ecosystem/) — one for each engineering discipline. My favourite definition of Golden Path is that it is the “opinionated and supported path”. Each Golden Path has an accompanying Golden Path tutorial that walks you through the opinionated and supported path. + +The Golden Path tutorials are Spotify’s most used and important documents and have shown themselves to be the most challenging to manage within a docs-like-code environment. One reason for this is that they are long, divided into many parts, and ownership is typically spread among many different teams. We have had to make use of GitHub codeowners to handle ownership and had to create datasets and data pipelines to be able to attach GitHub Issues to the specific parts or files that a team owns. Another challenge of the Golden Path tutorials is that parts are often dependent on other parts. We are just starting to look into how we can solve these dependency challenges in order to remove friction for engineers writing tutorial documentation. + +--- + +So that’s it for now. As you can see, we have come a long way AND there is much more to do. We are looking forward to continuing our docs-like-code journey out in the open with new, enthusiastic technical documentation friends. diff --git a/microsite/blog/assets/announcing-techdocs/discover1.png b/microsite/blog/assets/announcing-techdocs/discover1.png new file mode 100644 index 0000000000000000000000000000000000000000..af828104d79aa43fdc2c7bd680ccb8a23d101f92 GIT binary patch literal 63966 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 literal 0 HcmV?d00001 diff --git a/microsite/blog/assets/announcing-techdocs/discover2.png b/microsite/blog/assets/announcing-techdocs/discover2.png new file mode 100644 index 0000000000000000000000000000000000000000..11f6fe8347d71abf961212b0234a2703262c8ea5 GIT binary patch literal 56872 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 z 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 literal 0 HcmV?d00001 diff --git a/microsite/blog/assets/announcing-techdocs/docs-in-backstage.png b/microsite/blog/assets/announcing-techdocs/docs-in-backstage.png new file mode 100644 index 0000000000000000000000000000000000000000..9f4880b9118f4af2d2aa9febba10429bb2f7048d GIT binary patch literal 53879 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�^_&F`EGjkU7Q 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 literal 0 HcmV?d00001 diff --git a/microsite/blog/assets/announcing-techdocs/feedback-loop1.png b/microsite/blog/assets/announcing-techdocs/feedback-loop1.png new file mode 100644 index 0000000000000000000000000000000000000000..9733beb9e5a6b4c58f00c1f29040876fedcb5f89 GIT binary patch literal 42103 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 UV~yDo%-} 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

xYVECGbl$y_64YMJs*v;JL+(JOtfLy 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 literal 0 HcmV?d00001 diff --git a/microsite/blog/assets/announcing-techdocs/metrics.png b/microsite/blog/assets/announcing-techdocs/metrics.png new file mode 100644 index 0000000000000000000000000000000000000000..71c5f840a068f8cc72ba7fc704dad21659ad8d85 GIT binary patch literal 52455 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 Date: Tue, 8 Sep 2020 16:01:05 -0400 Subject: [PATCH 32/34] Update 2020-09-08-announcing-tech-docs.md --- microsite/blog/2020-09-08-announcing-tech-docs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite/blog/2020-09-08-announcing-tech-docs.md b/microsite/blog/2020-09-08-announcing-tech-docs.md index 76c6a8539b..f4271d7204 100644 --- a/microsite/blog/2020-09-08-announcing-tech-docs.md +++ b/microsite/blog/2020-09-08-announcing-tech-docs.md @@ -1,5 +1,5 @@ --- -title: Announcing Tech Docs: Spotify’s docs-like-code for Backstage +title: Announcing TechDocs: Spotify’s docs-like-code for Backstage author: Gary Niemen authorURL: https://github.com/garyniemen --- From be0e619b1e6be6e04e013dcf4e5a8225845846d8 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 8 Sep 2020 22:18:37 +0200 Subject: [PATCH 33/34] plugins/app-backend: publish package --- plugins/app-backend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index e6c3dde7b6..f4080abc42 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -4,7 +4,7 @@ "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", - "private": true, + "private": false, "publishConfig": { "access": "public", "main": "dist/index.cjs.js", From 07d4ad84d89c33a6b5a9d2a0097a74a9c2ba494a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 8 Sep 2020 22:24:58 +0200 Subject: [PATCH 34/34] microsite: prettier --- .../blog/2020-09-08-announcing-tech-docs.md | 17 ++++++++--------- microsite/pages/en/index.js | 4 +--- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/microsite/blog/2020-09-08-announcing-tech-docs.md b/microsite/blog/2020-09-08-announcing-tech-docs.md index f4271d7204..7947e089f6 100644 --- a/microsite/blog/2020-09-08-announcing-tech-docs.md +++ b/microsite/blog/2020-09-08-announcing-tech-docs.md @@ -14,7 +14,7 @@ We are quite sure the main reason for the success of TechDocs is our docs-like-c ![available-templates](assets/announcing-techdocs/docs-in-backstage.png) -Watch this video to see [Spotify’s internal version of TechDocs](https://backstage.io/demos) in action. +Watch this video to see [Spotify’s internal version of TechDocs](https://backstage.io/demos) in action. But this is just one way to do it. Today we’re most excited for what the open version of TechDocs can become. @@ -32,12 +32,11 @@ What we have on GitHub so far is a first iteration of TechDocs that you can use More specifically, with this first iteration, you can: -* Run TechDocs locally and read documentation. -* Configure your entity (e.g. service, website) so that Backstage builds your documentation and serves it in TechDocs. Documentation is displayed on the Docs tab in the Service Catalog and on its own page. -* Get documentation set up for free in your project when you create a new component out of one of the non-experimental templates (labeled with recommended). If you are looking for a standalone documentation project, use the docs-template. -* Choose your own storage solution for the documentation. -* Define your own API to interface with your documentation solution. - +- Run TechDocs locally and read documentation. +- Configure your entity (e.g. service, website) so that Backstage builds your documentation and serves it in TechDocs. Documentation is displayed on the Docs tab in the Service Catalog and on its own page. +- Get documentation set up for free in your project when you create a new component out of one of the non-experimental templates (labeled with recommended). If you are looking for a standalone documentation project, use the docs-template. +- Choose your own storage solution for the documentation. +- Define your own API to interface with your documentation solution. For a full overview, including getting started instructions, check out our [TechDocs Documentation](https://backstage.io/docs/features/techdocs/techdocs-overview). @@ -59,7 +58,7 @@ For more information about this journey, take a look at my 20-minute talk from D We have come a long way, fast — both in our implementation and in our thinking. Here are some of the key problem areas that we are addressing. Note that they are in various stages of implementation, and we won’t be able to release everything within our minimum plugin. In fact, see this as an appetite taster. What we hope is that we can build together. -### Stuck to unstuck +### Stuck to unstuck Very early on, we decided that the main problem we were trying to solve was to help engineers (when using technical documentation) go from stuck to unstuck, and fast. This became our guiding principle. Is what we are building helping engineers get unstuck faster? From this, it follows that we need to promote quality documentation on the one hand, and provide a high level of discoverability on the other. One without the other is not going to cut it. @@ -86,7 +85,7 @@ In this problem area, we made use of Elasticsearch, the open source search engin ![available-templates](assets/announcing-techdocs/discover1.png) ![available-templates](assets/announcing-techdocs/discover2.png) - + There is much more to do in the area of discoverability and search. ### Use case variations diff --git a/microsite/pages/en/index.js b/microsite/pages/en/index.js index e233826224..2cc7ba6a11 100644 --- a/microsite/pages/en/index.js +++ b/microsite/pages/en/index.js @@ -296,9 +296,7 @@ class Index extends React.Component { src={`${baseUrl}animations/backstage-techdocs-icon-1.gif`} /> - - Backstage TechDocs - + Backstage TechDocs Docs like code