diff --git a/packages/techdocs-cli-embedded-app/app-config.yaml b/packages/techdocs-cli-embedded-app/app-config.yaml index 56e63ff97c..6ede05b587 100644 --- a/packages/techdocs-cli-embedded-app/app-config.yaml +++ b/packages/techdocs-cli-embedded-app/app-config.yaml @@ -7,4 +7,3 @@ backend: techdocs: builder: 'external' - requestUrl: http://localhost:3000/api diff --git a/packages/techdocs-cli-embedded-app/src/apis.ts b/packages/techdocs-cli-embedded-app/src/apis.ts index 1fe6ba8086..d230a9f83c 100644 --- a/packages/techdocs-cli-embedded-app/src/apis.ts +++ b/packages/techdocs-cli-embedded-app/src/apis.ts @@ -64,17 +64,11 @@ class TechDocsDevStorageApi implements TechDocsStorageApi { } async getApiOrigin() { - return ( - this.configApi.getOptionalString('techdocs.requestUrl') ?? - (await this.discoveryApi.getBaseUrl('techdocs')) - ); + return await this.discoveryApi.getBaseUrl('techdocs'); } async getStorageUrl() { - return ( - this.configApi.getOptionalString('techdocs.storageUrl') ?? - `${await this.discoveryApi.getBaseUrl('techdocs')}/static/docs` - ); + return `${await this.discoveryApi.getBaseUrl('techdocs')}/static/docs`; } async getBuilder() { @@ -134,10 +128,7 @@ class TechDocsDevApi implements TechDocsApi { } async getApiOrigin() { - return ( - this.configApi.getOptionalString('techdocs.requestUrl') ?? - (await this.discoveryApi.getBaseUrl('techdocs')) - ); + return await this.discoveryApi.getBaseUrl('techdocs'); } async getEntityMetadata(_entityId: any) { diff --git a/packages/techdocs-cli-embedded-app/src/components/TechDocsPage/TechDocsPage.tsx b/packages/techdocs-cli-embedded-app/src/components/TechDocsPage/TechDocsPage.tsx index f2dcefc00e..56686dd081 100644 --- a/packages/techdocs-cli-embedded-app/src/components/TechDocsPage/TechDocsPage.tsx +++ b/packages/techdocs-cli-embedded-app/src/components/TechDocsPage/TechDocsPage.tsx @@ -35,8 +35,8 @@ import { Content } from '@backstage/core-components'; import { Reader, - TechDocsPage, - TechDocsPageHeader, + TechDocsReaderPage, + TechDocsReaderPageHeader, } from '@backstage/plugin-techdocs'; const useStyles = makeStyles((theme: Theme) => ({ @@ -146,19 +146,19 @@ const DefaultTechDocsPage = () => { }; return ( - + {({ entityRef, onReady }) => ( <> - - + )} - + ); }; diff --git a/packages/techdocs-cli-embedded-app/src/config.ts b/packages/techdocs-cli-embedded-app/src/config.ts index 482ceb41ec..ae801dac2a 100644 --- a/packages/techdocs-cli-embedded-app/src/config.ts +++ b/packages/techdocs-cli-embedded-app/src/config.ts @@ -22,7 +22,6 @@ const PRODUCTION_CONFIG = { }, techdocs: { builder: 'external', - requestUrl: 'http://localhost:3000/api', }, }; @@ -32,7 +31,6 @@ const DEVELOPMENT_CONFIG = { }, techdocs: { builder: 'external', - requestUrl: 'http://localhost:7007/api', }, }; diff --git a/plugins/techdocs-backend/src/service/router.test.ts b/plugins/techdocs-backend/src/service/router.test.ts index 2e707c9513..f3f9892f44 100644 --- a/plugins/techdocs-backend/src/service/router.test.ts +++ b/plugins/techdocs-backend/src/service/router.test.ts @@ -21,7 +21,6 @@ import { PluginEndpointDiscovery, } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; -import { NotModifiedError } from '@backstage/errors'; import { GeneratorBuilder, PreparerBuilder, @@ -31,12 +30,7 @@ import express, { Response } from 'express'; import request from 'supertest'; import { DocsSynchronizer, DocsSynchronizerSyncOpts } from './DocsSynchronizer'; import { CachedEntityLoader } from './CachedEntityLoader'; -import { - createEventStream, - createHttpResponse, - createRouter, - RouterOptions, -} from './router'; +import { createEventStream, createRouter, RouterOptions } from './router'; import { TechDocsCache } from '../cache'; import { DocsBuildStrategy } from './DocsBuildStrategy'; @@ -160,120 +154,6 @@ describe('createRouter', () => { }); describe('GET /sync/:namespace/:kind/:name', () => { - describe('accept application/json', () => { - it('should return not found if entity is not found', async () => { - const app = await createApp(outOfTheBoxOptions); - - MockCachedEntityLoader.prototype.load.mockResolvedValue(undefined); - - const response = await request(app) - .get('/sync/default/Component/test') - .send(); - - expect(response.status).toBe(404); - }); - - it('should return not found if entity has no uid', async () => { - const app = await createApp(outOfTheBoxOptions); - - MockCachedEntityLoader.prototype.load.mockResolvedValue( - entityWithoutMetadata, - ); - - const response = await request(app) - .get('/sync/default/Component/test') - .send(); - - expect(response.status).toBe(404); - }); - - it('should not check for an update when shouldBuild returns false', async () => { - const app = await createApp(outOfTheBoxOptions); - - docsBuildStrategy.shouldBuild.mockResolvedValue(false); - MockCachedEntityLoader.prototype.load.mockResolvedValue(entity); - MockDocsSynchronizer.prototype.doCacheSync.mockImplementation( - async ({ responseHandler }) => - responseHandler.finish({ updated: false }), - ); - - const response = await request(app) - .get('/sync/default/Component/test') - .send(); - - expect(response.status).toBe(304); - }); - - it('should error if build is required and is missing preparer', async () => { - const app = await createApp(recommendedOptions); - - docsBuildStrategy.shouldBuild.mockResolvedValue(true); - MockCachedEntityLoader.prototype.load.mockResolvedValue(entity); - - const response = await request(app) - .get('/sync/default/Component/test') - .send(); - - expect(response.status).toBe(500); - expect(response.text).toMatch( - /Invalid configuration\. docsBuildStrategy\.shouldBuild returned 'true', but no 'preparer' was provided to the router initialization./, - ); - - expect(MockDocsSynchronizer.prototype.doSync).toBeCalledTimes(0); - }); - - it('should execute synchronization', async () => { - const app = await createApp(outOfTheBoxOptions); - - docsBuildStrategy.shouldBuild.mockResolvedValue(true); - MockCachedEntityLoader.prototype.load.mockResolvedValue(entity); - MockDocsSynchronizer.prototype.doSync.mockImplementation( - async ({ responseHandler }) => - responseHandler.finish({ updated: true }), - ); - - await request(app).get('/sync/default/Component/test').send(); - - expect(MockDocsSynchronizer.prototype.doSync).toBeCalledTimes(1); - expect(MockDocsSynchronizer.prototype.doSync).toBeCalledWith({ - responseHandler: { - log: expect.any(Function), - error: expect.any(Function), - finish: expect.any(Function), - }, - entity, - generators, - preparers, - }); - }); - - it('should return on updated', async () => { - const app = await createApp(outOfTheBoxOptions); - - docsBuildStrategy.shouldBuild.mockResolvedValue(true); - MockCachedEntityLoader.prototype.load.mockResolvedValue(entity); - MockDocsSynchronizer.prototype.doSync.mockImplementation( - async ({ responseHandler }) => { - const { log, finish } = responseHandler; - - log('Some log'); - - finish({ updated: true }); - }, - ); - - const response = await request(app) - .get('/sync/default/Component/test') - .send(); - - expect(response.status).toBe(201); - expect(response.get('content-type')).toMatch(/application\/json/); - expect(response.text).toEqual( - '{"message":"Docs updated or did not need updating"}', - ); - }); - }); - describe('accept text/event-stream', () => { it('should return not found if entity is not found', async () => { const app = await createApp(outOfTheBoxOptions); @@ -559,48 +439,3 @@ data: {"updated":true} expect(res.end).toBeCalledTimes(1); }); }); - -describe('createHttpResponse', () => { - const res: jest.Mocked = { - status: jest.fn(), - json: jest.fn(), - } as any; - - let handlers: DocsSynchronizerSyncOpts; - - beforeEach(() => { - res.status.mockImplementation(() => res); - handlers = createHttpResponse(res); - }); - afterEach(() => { - jest.resetAllMocks(); - }); - - it('should return CREATED if updated', async () => { - handlers.finish({ updated: true }); - - expect(res.status).toBeCalledTimes(1); - expect(res.status).toBeCalledWith(201); - - expect(res.json).toBeCalledTimes(1); - expect(res.json).toBeCalledWith({ - message: 'Docs updated or did not need updating', - }); - }); - - it('should return NOT_MODIFIED if not updated', async () => { - expect(() => handlers.finish({ updated: false })).toThrowError( - NotModifiedError, - ); - }); - - it('should throw custom error', async () => { - expect(() => handlers.error(new Error('Some Error'))).toThrowError( - /Some Error/, - ); - }); - - it('should ignore logs', async () => { - expect(() => handlers.log('Some Message')).not.toThrow(); - }); -}); diff --git a/plugins/techdocs-backend/src/service/standaloneServer.ts b/plugins/techdocs-backend/src/service/standaloneServer.ts index 4ab4c084e0..f0ee42ba4a 100644 --- a/plugins/techdocs-backend/src/service/standaloneServer.ts +++ b/plugins/techdocs-backend/src/service/standaloneServer.ts @@ -60,11 +60,10 @@ export async function startStandaloneServer( logger.debug('Creating application...'); const preparers = new Preparers(); - const directoryPreparer = new DirectoryPreparer( - config, + const directoryPreparer = DirectoryPreparer.fromConfig(config, { logger, - mockUrlReader, - ); + reader: mockUrlReader, + }); preparers.register('dir', directoryPreparer); const dockerClient = new Docker(); diff --git a/plugins/techdocs-node/src/stages/publish/awsS3.test.ts b/plugins/techdocs-node/src/stages/publish/awsS3.test.ts index 326e587a83..537fc52b27 100644 --- a/plugins/techdocs-node/src/stages/publish/awsS3.test.ts +++ b/plugins/techdocs-node/src/stages/publish/awsS3.test.ts @@ -54,7 +54,6 @@ const createPublisherFromConfig = ({ } = {}) => { const mockConfig = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7007', publisher: { type: 'awsS3', awsS3: { diff --git a/plugins/techdocs-node/src/stages/publish/azureBlobStorage.test.ts b/plugins/techdocs-node/src/stages/publish/azureBlobStorage.test.ts index 3e5e420e4b..7af5338d88 100644 --- a/plugins/techdocs-node/src/stages/publish/azureBlobStorage.test.ts +++ b/plugins/techdocs-node/src/stages/publish/azureBlobStorage.test.ts @@ -51,7 +51,6 @@ const createPublisherFromConfig = ({ } = {}) => { const config = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7007', publisher: { type: 'azureBlobStorage', azureBlobStorage: { diff --git a/plugins/techdocs-node/src/stages/publish/googleStorage.test.ts b/plugins/techdocs-node/src/stages/publish/googleStorage.test.ts index 6dac092cec..6471d89a06 100644 --- a/plugins/techdocs-node/src/stages/publish/googleStorage.test.ts +++ b/plugins/techdocs-node/src/stages/publish/googleStorage.test.ts @@ -52,7 +52,6 @@ const createPublisherFromConfig = ({ } = {}) => { const config = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7007', publisher: { type: 'googleGcs', googleGcs: { diff --git a/plugins/techdocs-node/src/stages/publish/openStackSwift.test.ts b/plugins/techdocs-node/src/stages/publish/openStackSwift.test.ts index aeb4e120f5..619431fdd7 100644 --- a/plugins/techdocs-node/src/stages/publish/openStackSwift.test.ts +++ b/plugins/techdocs-node/src/stages/publish/openStackSwift.test.ts @@ -84,7 +84,6 @@ beforeEach(() => { mockFs.restore(); const mockConfig = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7007', publisher: { type: 'openStackSwift', openStackSwift: { @@ -114,7 +113,6 @@ describe('OpenStackSwiftPublish', () => { it('should reject incorrect config', async () => { const mockConfig = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7007', publisher: { type: 'openStackSwift', openStackSwift: { diff --git a/plugins/techdocs-node/src/stages/publish/publish.test.ts b/plugins/techdocs-node/src/stages/publish/publish.test.ts index a47da828a7..4537313edf 100644 --- a/plugins/techdocs-node/src/stages/publish/publish.test.ts +++ b/plugins/techdocs-node/src/stages/publish/publish.test.ts @@ -37,11 +37,7 @@ describe('Publisher', () => { }); it('should create local publisher by default', async () => { - const mockConfig = new ConfigReader({ - techdocs: { - requestUrl: 'http://localhost:7007', - }, - }); + const mockConfig = new ConfigReader({}); const publisher = await Publisher.fromConfig(mockConfig, { logger, @@ -53,7 +49,6 @@ describe('Publisher', () => { it('should create local publisher from config', async () => { const mockConfig = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7007', publisher: { type: 'local', }, @@ -70,7 +65,6 @@ describe('Publisher', () => { it('should create google gcs publisher from config', async () => { const mockConfig = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7007', publisher: { type: 'googleGcs', googleGcs: { @@ -91,7 +85,6 @@ describe('Publisher', () => { it('should create AWS S3 publisher from config', async () => { const mockConfig = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7007', publisher: { type: 'awsS3', awsS3: { @@ -115,7 +108,6 @@ describe('Publisher', () => { it('should create Azure Blob Storage publisher from config', async () => { const mockConfig = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7007', publisher: { type: 'azureBlobStorage', azureBlobStorage: { @@ -143,7 +135,6 @@ describe('Publisher', () => { const mockConfig = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7007', publisher: { type: 'azureBlobStorage', azureBlobStorage: { @@ -166,7 +157,6 @@ describe('Publisher', () => { it('should create Open Stack Swift publisher from config', async () => { const mockConfig = new ConfigReader({ techdocs: { - requestUrl: 'http://localhost:7007', publisher: { type: 'openStackSwift', openStackSwift: { diff --git a/plugins/techdocs/src/client.test.ts b/plugins/techdocs/src/client.test.ts index a88c724cc8..71ad57d12a 100644 --- a/plugins/techdocs/src/client.test.ts +++ b/plugins/techdocs/src/client.test.ts @@ -35,9 +35,7 @@ const mockEntity = { describe('TechDocsStorageClient', () => { const mockBaseUrl = 'http://backstage:9191/api/techdocs'; - const configApi = new MockConfigApi({ - techdocs: { requestUrl: 'http://backstage:9191/api/techdocs' }, - }); + const configApi = new MockConfigApi({}); const discoveryApi = UrlPatternDiscovery.compile(mockBaseUrl); const identityApi: jest.Mocked = { getCredentials: jest.fn(), diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPage.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPage.tsx index ff44d429df..1bfd0e6f51 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPage.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPage.tsx @@ -18,11 +18,13 @@ import React, { useCallback, useState } from 'react'; import { useOutlet } from 'react-router'; import { useParams } from 'react-router-dom'; import useAsync from 'react-use/lib/useAsync'; +import { Reader } from './Reader'; +import { TechDocsReaderPageHeader } from './TechDocsReaderPageHeader'; import { techdocsApiRef } from '../../api'; import { TechDocsEntityMetadata, TechDocsMetadata } from '../../types'; import { CompoundEntityRef } from '@backstage/catalog-model'; import { useApi, useApp } from '@backstage/core-plugin-api'; -import { Page } from '@backstage/core-components'; +import { Page, Content } from '@backstage/core-components'; /** * Helper function that gives the children of {@link TechDocsReaderPage} access to techdocs and entity metadata @@ -78,7 +80,32 @@ export const TechDocsReaderPage = (props: TechDocsReaderPageProps) => { if (entityMetadataError) return ; - if (!children) return outlet; + if (!children) + return ( + outlet || ( + + + + + + + ) + ); return (