diff --git a/.changeset/thirty-papayas-attack.md b/.changeset/thirty-papayas-attack.md new file mode 100644 index 0000000000..93a31bb6b5 --- /dev/null +++ b/.changeset/thirty-papayas-attack.md @@ -0,0 +1,40 @@ +--- +'@backstage/create-app': patch +'@backstage/techdocs-common': minor +'@backstage/plugin-techdocs-backend': minor +--- + +techdocs-backend: Simplified file, removing individual preparers and generators. +techdocs-backend: UrlReader is now available to use in preparers. + +In your Backstage app, `packages/backend/plugins/techdocs.ts` file has now been simplified, +to remove registering individual preparers and generators. + +Please update the file when upgrading the version of `@backstage/plugin-techdocs-backend` package. + +```typescript +const preparers = await Preparers.fromConfig(config, { + logger, + reader, +}); + +const generators = await Generators.fromConfig(config, { + logger, +}); + +const publisher = await Publisher.fromConfig(config, { + logger, + discovery, +}); +``` + +You should be able to remove unnecessary imports, and just do + +```typescript +import { + createRouter, + Preparers, + Generators, + Publisher, +} from '@backstage/plugin-techdocs-backend'; +``` diff --git a/docs/features/techdocs/getting-started.md b/docs/features/techdocs/getting-started.md index c82bc8b95b..e1ddfd23f9 100644 --- a/docs/features/techdocs/getting-started.md +++ b/docs/features/techdocs/getting-started.md @@ -72,12 +72,8 @@ add the following ```typescript import { createRouter, - DirectoryPreparer, Preparers, Generators, - TechdocsGenerator, - CommonGitPreparer, - UrlPreparer, Publisher, } from '@backstage/plugin-techdocs-backend'; import { PluginEnvironment } from '../types'; @@ -90,30 +86,25 @@ export default async function createPlugin({ reader, }: PluginEnvironment) { // Preparers are responsible for fetching source files for documentation. - const preparers = new Preparers(); - - const directoryPreparer = new DirectoryPreparer(logger); - preparers.register('dir', directoryPreparer); - - const commonGitPreparer = new CommonGitPreparer(logger); - preparers.register('github', commonGitPreparer); - preparers.register('gitlab', commonGitPreparer); - preparers.register('azure/api', commonGitPreparer); - - const urlPreparer = new UrlPreparer(reader, logger); - preparers.register('url', urlPreparer); + const preparers = await Preparers.fromConfig(config, { + logger, + reader, + }); // Generators are used for generating documentation sites. - const generators = new Generators(); - const techdocsGenerator = new TechdocsGenerator(logger, config); - generators.register('techdocs', techdocsGenerator); + const generators = await Generators.fromConfig(config, { + logger, + }); - // Publishers are used for + // Publisher is used for // 1. Publishing generated files to storage // 2. Fetching files from storage and passing them to TechDocs frontend. - const publisher = Publisher.fromConfig(config, logger, discovery); + const publisher = await Publisher.fromConfig(config, { + logger, + discovery, + }); - // Docker client used by the generators. + // Docker client (conditionally) used by the generators, based on techdocs.generators config. const dockerClient = new Docker(); return await createRouter({ diff --git a/packages/backend/src/plugins/techdocs.ts b/packages/backend/src/plugins/techdocs.ts index 4822de9c5c..afe92cc347 100644 --- a/packages/backend/src/plugins/techdocs.ts +++ b/packages/backend/src/plugins/techdocs.ts @@ -15,12 +15,8 @@ */ import { createRouter, - DirectoryPreparer, Preparers, Generators, - TechdocsGenerator, - CommonGitPreparer, - UrlPreparer, Publisher, } from '@backstage/plugin-techdocs-backend'; import { PluginEnvironment } from '../types'; @@ -33,30 +29,25 @@ export default async function createPlugin({ reader, }: PluginEnvironment) { // Preparers are responsible for fetching source files for documentation. - const preparers = new Preparers(); - - const directoryPreparer = new DirectoryPreparer(logger); - preparers.register('dir', directoryPreparer); - - const commonGitPreparer = new CommonGitPreparer(logger); - preparers.register('github', commonGitPreparer); - preparers.register('gitlab', commonGitPreparer); - preparers.register('azure/api', commonGitPreparer); - - const urlPreparer = new UrlPreparer(reader, logger); - preparers.register('url', urlPreparer); + const preparers = await Preparers.fromConfig(config, { + logger, + reader, + }); // Generators are used for generating documentation sites. - const generators = new Generators(); - const techdocsGenerator = new TechdocsGenerator(logger, config); - generators.register('techdocs', techdocsGenerator); + const generators = await Generators.fromConfig(config, { + logger, + }); - // Publishers are used for + // Publisher is used for // 1. Publishing generated files to storage // 2. Fetching files from storage and passing them to TechDocs frontend. - const publisher = Publisher.fromConfig(config, logger, discovery); + const publisher = await Publisher.fromConfig(config, { + logger, + discovery, + }); - // Docker client used by the generators. + // Docker client (conditionally) used by the generators, based on techdocs.generators config. const dockerClient = new Docker(); return await createRouter({ diff --git a/packages/create-app/templates/default-app/packages/backend/src/plugins/techdocs.ts b/packages/create-app/templates/default-app/packages/backend/src/plugins/techdocs.ts index 1bbb5ff24b..5c7ec50ae6 100644 --- a/packages/create-app/templates/default-app/packages/backend/src/plugins/techdocs.ts +++ b/packages/create-app/templates/default-app/packages/backend/src/plugins/techdocs.ts @@ -1,10 +1,7 @@ import { createRouter, - DirectoryPreparer, Preparers, Generators, - TechdocsGenerator, - CommonGitPreparer, Publisher, } from '@backstage/plugin-techdocs-backend'; import { PluginEnvironment } from '../types'; @@ -14,22 +11,28 @@ export default async function createPlugin({ logger, config, discovery, + reader, }: PluginEnvironment) { - const generators = new Generators(); - const techdocsGenerator = new TechdocsGenerator(logger, config); + // Preparers are responsible for fetching source files for documentation. + const preparers = await Preparers.fromConfig(config, { + logger, + reader, + }); - generators.register('techdocs', techdocsGenerator); + // Generators are used for generating documentation sites. + const generators = await Generators.fromConfig(config, { + logger, + }); - const preparers = new Preparers(); - const directoryPreparer = new DirectoryPreparer(logger); - const commonGitPreparer = new CommonGitPreparer(logger); - - preparers.register('dir', directoryPreparer); - preparers.register('github', commonGitPreparer); - preparers.register('gitlab', commonGitPreparer); - - const publisher = Publisher.fromConfig(config, logger, discovery); + // Publisher is used for + // 1. Publishing generated files to storage + // 2. Fetching files from storage and passing them to TechDocs frontend. + const publisher = await Publisher.fromConfig(config, { + logger, + discovery, + }); + // Docker client (conditionally) used by the generators, based on techdocs.generators config. const dockerClient = new Docker(); return await createRouter({ diff --git a/packages/techdocs-common/src/stages/generate/generators.ts b/packages/techdocs-common/src/stages/generate/generators.ts index f28a169942..cbfa5e7553 100644 --- a/packages/techdocs-common/src/stages/generate/generators.ts +++ b/packages/techdocs-common/src/stages/generate/generators.ts @@ -14,18 +14,32 @@ * limitations under the License. */ +import { Logger } from 'winston'; +import { Entity } from '@backstage/catalog-model'; +import { Config } from '@backstage/config'; +import { TechdocsGenerator } from '.'; import { GeneratorBase, SupportedGeneratorKey, GeneratorBuilder, } from './types'; - -import { Entity } from '@backstage/catalog-model'; import { getGeneratorKey } from './helpers'; export class Generators implements GeneratorBuilder { private generatorMap = new Map(); + static async fromConfig( + config: Config, + { logger }: { logger: Logger }, + ): Promise { + const generators = new Generators(); + + const techdocsGenerator = new TechdocsGenerator(logger, config); + generators.register('techdocs', techdocsGenerator); + + return generators; + } + register(generatorKey: SupportedGeneratorKey, generator: GeneratorBase) { this.generatorMap.set(generatorKey, generator); } diff --git a/packages/techdocs-common/src/stages/prepare/preparers.ts b/packages/techdocs-common/src/stages/prepare/preparers.ts index 52a47957e8..4a2d60eb31 100644 --- a/packages/techdocs-common/src/stages/prepare/preparers.ts +++ b/packages/techdocs-common/src/stages/prepare/preparers.ts @@ -13,14 +13,45 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import { PreparerBase, RemoteProtocol, PreparerBuilder } from './types'; +import { Logger } from 'winston'; +import { UrlReader } from '@backstage/backend-common'; import { Entity } from '@backstage/catalog-model'; +import { Config } from '@backstage/config'; +import { DirectoryPreparer, CommonGitPreparer, UrlPreparer } from '.'; +import { PreparerBase, RemoteProtocol, PreparerBuilder } from './types'; import { parseReferenceAnnotation } from '../../helpers'; +type factoryOptions = { + logger: Logger; + reader: UrlReader; +}; + export class Preparers implements PreparerBuilder { private preparerMap = new Map(); + static async fromConfig( + // @ts-ignore + // Config not used now, but will be used in urlPreparer when it starts using + // @backstage/integration to get the tokens for providers. + config: Config, + { logger, reader }: factoryOptions, + ): Promise { + const preparers = new Preparers(); + + const directoryPreparer = new DirectoryPreparer(logger); + preparers.register('dir', directoryPreparer); + + const commonGitPreparer = new CommonGitPreparer(logger); + preparers.register('github', commonGitPreparer); + preparers.register('gitlab', commonGitPreparer); + preparers.register('azure/api', commonGitPreparer); + + const urlPreparer = new UrlPreparer(reader, logger); + preparers.register('url', urlPreparer); + + return preparers; + } + register(protocol: RemoteProtocol, preparer: PreparerBase) { this.preparerMap.set(protocol, preparer); } diff --git a/packages/techdocs-common/src/stages/publish/publish.test.ts b/packages/techdocs-common/src/stages/publish/publish.test.ts index dbced6db29..c61b9aa3ec 100644 --- a/packages/techdocs-common/src/stages/publish/publish.test.ts +++ b/packages/techdocs-common/src/stages/publish/publish.test.ts @@ -23,24 +23,27 @@ import { LocalPublish } from './local'; import { GoogleGCSPublish } from './googleStorage'; const logger = getVoidLogger(); -const testDiscovery: jest.Mocked = { +const discovery: jest.Mocked = { getBaseUrl: jest.fn().mockResolvedValueOnce('http://localhost:7000'), getExternalBaseUrl: jest.fn(), }; describe('Publisher', () => { - it('should create local publisher by default', () => { + it('should create local publisher by default', async () => { const mockConfig = new ConfigReader({ techdocs: { requestUrl: 'http://localhost:7000', }, }); - const publisher = Publisher.fromConfig(mockConfig, logger, testDiscovery); + const publisher = await Publisher.fromConfig(mockConfig, { + logger, + discovery, + }); expect(publisher).toBeInstanceOf(LocalPublish); }); - it('should create local publisher from config', () => { + it('should create local publisher from config', async () => { const mockConfig = new ConfigReader({ techdocs: { requestUrl: 'http://localhost:7000', @@ -50,11 +53,14 @@ describe('Publisher', () => { }, }); - const publisher = Publisher.fromConfig(mockConfig, logger, testDiscovery); + const publisher = await Publisher.fromConfig(mockConfig, { + logger, + discovery, + }); expect(publisher).toBeInstanceOf(LocalPublish); }); - it('should create google gcs publisher from config', () => { + it('should create google gcs publisher from config', async () => { const mockConfig = new ConfigReader({ techdocs: { requestUrl: 'http://localhost:7000', @@ -69,7 +75,10 @@ describe('Publisher', () => { }, }); - const publisher = Publisher.fromConfig(mockConfig, logger, testDiscovery); + const publisher = await Publisher.fromConfig(mockConfig, { + logger, + discovery, + }); expect(publisher).toBeInstanceOf(GoogleGCSPublish); }); }); diff --git a/packages/techdocs-common/src/stages/publish/publish.ts b/packages/techdocs-common/src/stages/publish/publish.ts index 04a9d89996..95b5cf83e2 100644 --- a/packages/techdocs-common/src/stages/publish/publish.ts +++ b/packages/techdocs-common/src/stages/publish/publish.ts @@ -21,16 +21,20 @@ import { PublisherType, PublisherBase } from './types'; import { LocalPublish } from './local'; import { GoogleGCSPublish } from './googleStorage'; +type factoryOptions = { + logger: Logger; + discovery: PluginEndpointDiscovery; +}; + /** * Factory class to create a TechDocs publisher based on defined publisher type in app config. * Uses `techdocs.publisher.type`. */ export class Publisher { - static fromConfig( + static async fromConfig( config: Config, - logger: Logger, - discovery: PluginEndpointDiscovery, - ): PublisherBase { + { logger, discovery }: factoryOptions, + ): Promise { const publisherType = (config.getOptionalString( 'techdocs.publisher.type', ) ?? 'local') as PublisherType; diff --git a/plugins/techdocs-backend/src/service/standaloneServer.ts b/plugins/techdocs-backend/src/service/standaloneServer.ts index 3faf736ca0..65a286feef 100644 --- a/plugins/techdocs-backend/src/service/standaloneServer.ts +++ b/plugins/techdocs-backend/src/service/standaloneServer.ts @@ -59,7 +59,7 @@ export async function startStandaloneServer( const techdocsGenerator = new TechdocsGenerator(logger, config); generators.register('techdocs', techdocsGenerator); - const publisher = Publisher.fromConfig(config, logger, discovery); + const publisher = await Publisher.fromConfig(config, { logger, discovery }); const dockerClient = new Docker();