From 7faad9566649a8a96bffc99ce62b71b1e7955c5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Thu, 19 Jan 2023 09:38:57 +0100 Subject: [PATCH 1/5] add a doc for migrating backends to the new backend system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .../building-backends/08-migrating.md | 235 ++++++++++++++++++ 1 file changed, 235 insertions(+) diff --git a/docs/backend-system/building-backends/08-migrating.md b/docs/backend-system/building-backends/08-migrating.md index 84f801f15d..f038580d96 100644 --- a/docs/backend-system/building-backends/08-migrating.md +++ b/docs/backend-system/building-backends/08-migrating.md @@ -7,3 +7,238 @@ description: How to migrate existing backends to the new backend system --- # Overview + +This section describes how to migrate an existing Backstage backend service +package (typically in `packages/backend`) to use the new backend system. + +One of the main benefits of the new backend system is that it abstracts away the +way that plugins and their dependencies are wired up, leading to a significantly +simplified backend package that rarely if ever needs to change when plugins or +their dependencies evolve. You generally don't have to convert all of your +internal plugins and support classes themselves to the backend system first - +the migration here will mostly deal with wiring and using compatibility wrappers +where possible in the backend package itself. We hope that you will find that +you end up with a much smaller, easier to understand, and easier to maintain +package as a result of these steps, and then being able to [migrate +plugins](../building-plugins-and-modules/08-migrating.md) as a separate +endeavour later. + +# Overall Structure + +Your typical backend package has a few overall component parts: + +- An `index.ts` file that houses all of the creation and wiring together of all + of the plugins and their dependencies +- A `types.ts` file that defines the "environment", i.e. the various + dependencies that get created by the backend and passed down into each plugin +- A `plugins` folder which has one file for each plugin, e.g. + `plugins/catalog.ts` + +The index file has this overall shape: + +```ts +import todo from './plugins/todo'; // repeated for N plugins + +function makeCreateEnv(config: Config) { + return (plugin: string): PluginEnvironment => { + // ... build per-plugin environment + }; +} + +async function main() { + // ... early init + const createEnv = makeCreateEnv(config); + const todoEnv = useHotMemoize(module, () => createEnv('todo')); // repeated for N plugins + const apiRouter = Router(); + apiRouter.use('/todo', await todo(todoEnv)); // repeated for N plugins + // ... return composite router +} + +module.hot?.accept(); +main().catch(...); +``` + +# Migrating the Index File + +This migration will try to leave the `plugins` folder unchanged initially, first +focusing on removing the environment type and reducing the index file to its +bare minimum. Then as a later step, we can reduce the `plugins` folder bit by +bit, replacing those files generally with one-liners in the index file instead. + +Let's start by establishing the basis of your new index file. You may want to +comment out its old contents, or renaming the old file to `index.backup.ts` for +reference and making a new blank one to work on - whichever works best for you. +These are our new blank contents in the index file: + +```ts +// packages/backend/src/index.ts +import { createBackend } from '@backstage/backend-defaults'; + +const backend = createBackend(); +backend.start(); +``` + +Note that the environment builder and the `main` dance are entirely gone. + +We'll also want to add some backend system packages as dependencies. Run the +following command: + +```bash +# from the repository root +yarn add --cwd packages/backend @backstage/backend-common @backstage/backend-defaults @backstage/backend-plugin-api +``` + +You should now be able to start this up with the familiar `yarn workspace +backend start` command locally and seeing some logs scroll by. But it'll just be +a blank service with no real features added. So let's stop it with `Ctrl+C` and +reintroduce some plugins into the mix. + +```diff + import { createBackend } from '@backstage/backend-defaults'; ++import { legacyPlugin } from '@backstage/backend-common'; + + const backend = createBackend(); ++backend.add(legacyPlugin('todo', import('./plugins/todo'))); + backend.start(); +``` + +The `todo` plugin used above is just an example and you may not have it enabled +in your own backend. Feel free to change it to some other plugin that you +actually have in your `plugins` folder, for example +`backend.add(legacyPlugin('catalog', import('./plugins/catalog')))`. + +The `legacyPlugin` helper makes it easy to bridge the gap between the old-style +plugin files and the new backend system. It ensures that the dependencies that +you used to have to declare by hand in your env are gathered behind the scenes, +then passes them into the relevant `createPlugin` export function, and makes +sure that the route handler it returns is passed into the HTTP router with the +given prefix. + +# Handling Custom Environments + +In the simple case, what we did above is sufficient, TypeScript is happy, and +the backend runs with the new feature. If they do, feel free to skip this entire +section. + +Sometimes though, type errors can be reported on the newly added line, saying +that parts of the `PluginEnvironment` type do not match. This happens when the +environment was changed from the defaults, perhaps with your own custom +additions. If this is the case in your installation, you still aren't out of +luck - you can build a customized `legacyPlugin` function. + +```diff + import { createBackend } from '@backstage/backend-defaults'; +-import { legacyPlugin } from '@backstage/backend-common'; ++import { makeLegacyPlugin, loggerToWinstonLogger } from '@backstage/backend-common'; ++import { coreServices } from '@backstage/backend-plugin-api'; + ++const legacyPlugin = makeLegacyPlugin( ++ { ++ cache: coreServices.cache, ++ config: coreServices.config, ++ database: coreServices.database, ++ discovery: coreServices.discovery, ++ logger: coreServices.logger, ++ permissions: coreServices.permissions, ++ scheduler: coreServices.scheduler, ++ tokenManager: coreServices.tokenManager, ++ reader: coreServices.urlReader, ++ identity: coreServices.identity, ++ // ... and your own additions ++ }, ++ { ++ logger: log => loggerToWinstonLogger(log), ++ }, ++); + + const backend = createBackend(); + backend.add(legacyPlugin('todo', import('./plugins/todo'))); + backend.start(); +``` + +The first argument to `makeLegacyPlugin` is the mapping from environment keys to +references to actual [backend system services](../architecture/03-services.md). +The second argument allows you to "tweak" the types of those services to +something more fitting to your env. For example, you'll see that the logger +service API type was changed from the raw Winston logger of old, to a different, +custom API, so we use a helper function to transform that particular one. + +To make additions as mentioned above to the environment, you will start to get +into the weeds of how the backend system wiring works. You'll need to have a +service reference, and a service factory that performs the actual creation of +your service. For now, let's add them directly in the same file, and then you +can move them out into a separate file at a later time. + +In this example, we'll assume that your added environment item is named "example". + +```diff +-import { coreServices } from '@backstage/backend-plugin-api'; ++import { coreServices, createServiceFactory } from '@backstage/backend-plugin-api'; ++import { ExampleApi, ExampleImpl } from ''; + ++const exampleServiceRef = createServiceRef({ ++ id: 'example', ++ scope: 'plugin', // can be 'root' or 'plugin' ++ defaultFactory: async service => createServiceFactory({ ++ service, ++ // optional; just an example of how dependencies work ++ deps: { ++ logger: coreServices.logger, ++ }, ++ // here instances of the declared dependencies are injected ++ async factory({ logger }) { ++ // return your ExampleImpl ++ }, ++ }), ++}); + + const legacyPlugin = makeLegacyPlugin( + { + // ... the above core services still go here ++ example: exampleServiceRef + }, + { + logger: log => loggerToWinstonLogger(log), + }, + ); +``` + +After this, your backend will know how to instantiate your thing on demand. + +# Cleaning Up the Plugins Folder + +For plugins that are private and your own, you can follow a [dedicated migration +guide](../building-plugins-and-modules/08-migrating.md) as you see fit, at a +later time. + +For third party backend plugins, in particular the larger core plugins that are +maintained by the Backstage maintainers, you may find that they have already +been migrated to the new backend system. Let's try to clean up the `plugins` +folder a bit. + +Each plugin file is under your control, and it was added as part of following +their installation instructions. You were then free to start tweaking those +files and adding customizations. The simplest case is when you did NOT perform +any customizations at all. For those plugins, you can in general just delete the +corresponding file in the `plugins` folder, and instead importing the backend +plugin from the package directly. + +```diff + import { createBackend } from '@backstage/backend-defaults'; + import { legacyPlugin } from '@backstage/backend-common'; ++import { catalogPlugin } from '@backstage/plugin-catalog-backend'; + + const backend = createBackend(); + backend.add(legacyPlugin('todo', import('./plugins/todo'))); ++backend.add(catalogPlugin()); + backend.start(); +``` + +This will install a fully functioning catalog backend plugin, in its default +state (not amended with any custom processors or providers, for example). You +still need to have the `@backstage/plugin-catalog-backend` dependency in your +`package.json`. You also need to have your app-config set up properly like +before; that subsystem works the same as it used to even though its +instantiation now happens behind the scenes. + +You can now delete `plugins/catalog.ts`. From f3024f617d256523183a0b06dfb742797e8e9980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Thu, 19 Jan 2023 11:37:06 +0100 Subject: [PATCH 2/5] Update docs/backend-system/building-backends/08-migrating.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Patrik Oldsberg Signed-off-by: Fredrik Adelöw --- docs/backend-system/building-backends/08-migrating.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/backend-system/building-backends/08-migrating.md b/docs/backend-system/building-backends/08-migrating.md index f038580d96..86f8515d87 100644 --- a/docs/backend-system/building-backends/08-migrating.md +++ b/docs/backend-system/building-backends/08-migrating.md @@ -85,7 +85,7 @@ following command: ```bash # from the repository root -yarn add --cwd packages/backend @backstage/backend-common @backstage/backend-defaults @backstage/backend-plugin-api +yarn add --cwd packages/backend @backstage/backend-defaults @backstage/backend-plugin-api ``` You should now be able to start this up with the familiar `yarn workspace From 4727161be97d4e7899207f819e0d844e2033e292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Thu, 19 Jan 2023 13:19:06 +0100 Subject: [PATCH 3/5] more updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .../architecture/03-services.md | 9 ++ .../building-backends/08-migrating.md | 151 ++++++++++++------ 2 files changed, 115 insertions(+), 45 deletions(-) diff --git a/docs/backend-system/architecture/03-services.md b/docs/backend-system/architecture/03-services.md index 27fea27db9..71bd95dd1e 100644 --- a/docs/backend-system/architecture/03-services.md +++ b/docs/backend-system/architecture/03-services.md @@ -101,3 +101,12 @@ const backend = createBackend({ ], }); ``` + +### Migrating Your Own Utilities Into Services + +As your backends grow in complexity, you may have started writing utility +classes with shared backend functionality, that you pass down into your plugins. +Maybe you have placed them into your `PluginEnvironment` in +`packages/backend/src/types.ts`. If this applies to you, you'll probably be +interested in migrating those to become proper backend services according to the +new backend system, so that they can be dependency injected into your backends. diff --git a/docs/backend-system/building-backends/08-migrating.md b/docs/backend-system/building-backends/08-migrating.md index 86f8515d87..3a59599518 100644 --- a/docs/backend-system/building-backends/08-migrating.md +++ b/docs/backend-system/building-backends/08-migrating.md @@ -51,7 +51,7 @@ async function main() { const todoEnv = useHotMemoize(module, () => createEnv('todo')); // repeated for N plugins const apiRouter = Router(); apiRouter.use('/todo', await todo(todoEnv)); // repeated for N plugins - // ... return composite router + // ... wire up and start http server } module.hot?.accept(); @@ -166,31 +166,17 @@ custom API, so we use a helper function to transform that particular one. To make additions as mentioned above to the environment, you will start to get into the weeds of how the backend system wiring works. You'll need to have a service reference, and a service factory that performs the actual creation of -your service. For now, let's add them directly in the same file, and then you -can move them out into a separate file at a later time. +your service. Please see [the services +article](../architecture/03-services.md#defining-a-service) to learn how to +create a service ref and its default factory. You can place that code directly +in the index file for now if you want, or near the actual implementation class +in question. -In this example, we'll assume that your added environment item is named "example". +In this example, we'll assume that your added environment field is named +`example`, and the created ref is named `exampleServiceRef`. ```diff --import { coreServices } from '@backstage/backend-plugin-api'; -+import { coreServices, createServiceFactory } from '@backstage/backend-plugin-api'; -+import { ExampleApi, ExampleImpl } from ''; - -+const exampleServiceRef = createServiceRef({ -+ id: 'example', -+ scope: 'plugin', // can be 'root' or 'plugin' -+ defaultFactory: async service => createServiceFactory({ -+ service, -+ // optional; just an example of how dependencies work -+ deps: { -+ logger: coreServices.logger, -+ }, -+ // here instances of the declared dependencies are injected -+ async factory({ logger }) { -+ // return your ExampleImpl -+ }, -+ }), -+}); ++import { exampleServiceRef } from ''; // if the definition is elsewhere const legacyPlugin = makeLegacyPlugin( { @@ -203,7 +189,13 @@ In this example, we'll assume that your added environment item is named "example ); ``` -After this, your backend will know how to instantiate your thing on demand. +After this, your backend will know how to instantiate your thing on demand and +place it in the legacy plugin environment. + +> NOTE: If you happen to be dealing with a service ref that does NOT have a +> default implementation, but rather has a separate service factory, then you +> will also need to import that factory and pass it to the `services` array +> argument of `createBackend`. # Cleaning Up the Plugins Folder @@ -213,32 +205,101 @@ later time. For third party backend plugins, in particular the larger core plugins that are maintained by the Backstage maintainers, you may find that they have already -been migrated to the new backend system. Let's try to clean up the `plugins` -folder a bit. +been migrated to the new backend system. This section describes some specific +such migrations you can make. -Each plugin file is under your control, and it was added as part of following -their installation instructions. You were then free to start tweaking those -files and adding customizations. The simplest case is when you did NOT perform -any customizations at all. For those plugins, you can in general just delete the -corresponding file in the `plugins` folder, and instead importing the backend -plugin from the package directly. +> NOTE: For each of these, note that your backend still needs to have a +> dependency (e.g. in `packages/backend/package.json`) to those plugin packages, +> and they still need to be configured properly in your app-config. Those +> mechanisms still work just the same as they used to in the old backend system. + +## The App Plugin + +The app backend plugin that serves the frontend from the backend can trivially +be used in its new form. ```diff - import { createBackend } from '@backstage/backend-defaults'; - import { legacyPlugin } from '@backstage/backend-common'; -+import { catalogPlugin } from '@backstage/plugin-catalog-backend'; + // packages/backend/src/index.ts ++import { appPlugin } from '@backstage/plugin-app-backend'; const backend = createBackend(); - backend.add(legacyPlugin('todo', import('./plugins/todo'))); -+backend.add(catalogPlugin()); - backend.start(); ++backend.add(appPlugin({ appPackageName: 'app' })); ``` -This will install a fully functioning catalog backend plugin, in its default -state (not amended with any custom processors or providers, for example). You -still need to have the `@backstage/plugin-catalog-backend` dependency in your -`package.json`. You also need to have your app-config set up properly like -before; that subsystem works the same as it used to even though its -instantiation now happens behind the scenes. +This is an example of how options can be passed into some backend plugins. The +app plugin specifically needs to know the name of the package that holds the +frontend code. This is the `"name"` field in that package's `package.json`, +typically found in your `packages/app` folder. By default it's just plain "app". -You can now delete `plugins/catalog.ts`. +You should be able to delete the `plugins/app.ts` file at this point. + +## The Catalog Plugin + +A basic installation of the catalog plugin looks as follows. + +```diff + // packages/backend/src/index.ts ++import { catalogPlugin } from '@backstage/plugin-catalog-backend'; ++import { scaffolderCatalogModule } from '@backstage/plugin-scaffolder-backend'; + + const backend = createBackend(); ++backend.add(catalogPlugin()); ++backend.add(scaffolderCatalogModule()); +``` + +Note that this also installs a module from the scaffolder, namely the one which +enables the use of the `Template` kind. In the unlikely event that you do not +use templates at all, you can remove those lines. + +If you have other customizations made to `plugins/catalog.ts`, such as adding +custom processors or entity providers, read on. Otherwise, you should be able to +just delete the `plugins/catalog.ts` file at this point. + +You will use the [extension points](../architecture/05-extension-points.md) +mechanism to extend or tweak the functionality of the catalog. To do that, +you'll make your own bespoke [module](../architecture/06-modules.md) which +depends on the appropriate extension point and interacts with it. + +```diff + // packages/backend/src/index.ts ++import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; ++import { createBackendModule } from '@backstage/backend-plugin-api'; + ++const catalogExtensionsModule = createBackendModule({ ++ pluginId: 'catalog', // name of the plugin that the module is targeting ++ moduleId: 'extensions', // you can choose this one freely ++ register(env) { ++ env.registerInit({ ++ deps: { ++ catalog: catalogProcessingExtensionPoint, ++ // ... and other dependencies as needed ++ }, ++ init({ catalog /* ..., other dependencies */ }) { ++ // Here you have the opportunity to interact with the catalog extension ++ // point before the catalog plugin itself gets instantiated ++ catalog.addEntityProvider(new MyEntityProvider()); // just an example ++ catalog.addProcessor(new MyProcessor()); // just an example ++ }, ++ }); ++ }, ++}); + + const backend = createBackend(); + backend.add(catalogPlugin()); + backend.add(scaffolderCatalogModule()); ++backend.add(catalogExtensionsModule()); +``` + +This also requires that you have a dependency on the catalog node package, if +you didn't already have one. + +```bash +# from the repository root +yarn add --cwd packages/backend @backstage/plugin-catalog-node +``` + +Here we've placed the module directly in the backend index file just to get +going easily, but feel free to move it out to where it fits best. As you migrate +your entire plugin flora to the new backend system, you will probably make more +and more of these modules as "first class" things, living right next to the +implementations that they represent, and being exported from there. From 1d742a373389773d9c546cafe90d8c3734a45258 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Thu, 19 Jan 2023 13:40:59 +0100 Subject: [PATCH 4/5] Update docs/backend-system/building-backends/08-migrating.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Patrik Oldsberg Signed-off-by: Fredrik Adelöw --- docs/backend-system/architecture/03-services.md | 9 --------- docs/backend-system/building-backends/08-migrating.md | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/docs/backend-system/architecture/03-services.md b/docs/backend-system/architecture/03-services.md index 71bd95dd1e..27fea27db9 100644 --- a/docs/backend-system/architecture/03-services.md +++ b/docs/backend-system/architecture/03-services.md @@ -101,12 +101,3 @@ const backend = createBackend({ ], }); ``` - -### Migrating Your Own Utilities Into Services - -As your backends grow in complexity, you may have started writing utility -classes with shared backend functionality, that you pass down into your plugins. -Maybe you have placed them into your `PluginEnvironment` in -`packages/backend/src/types.ts`. If this applies to you, you'll probably be -interested in migrating those to become proper backend services according to the -new backend system, so that they can be dependency injected into your backends. diff --git a/docs/backend-system/building-backends/08-migrating.md b/docs/backend-system/building-backends/08-migrating.md index 3a59599518..9552ca325c 100644 --- a/docs/backend-system/building-backends/08-migrating.md +++ b/docs/backend-system/building-backends/08-migrating.md @@ -165,7 +165,7 @@ custom API, so we use a helper function to transform that particular one. To make additions as mentioned above to the environment, you will start to get into the weeds of how the backend system wiring works. You'll need to have a -service reference, and a service factory that performs the actual creation of +service reference and a service factory that performs the actual creation of your service. Please see [the services article](../architecture/03-services.md#defining-a-service) to learn how to create a service ref and its default factory. You can place that code directly From b8a04e4eeea2558b5b25a6561b33d39bf3407004 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Thu, 19 Jan 2023 14:12:20 +0100 Subject: [PATCH 5/5] nerf sections and add last plugins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .../building-backends/08-migrating.md | 155 ++++++++++++++++-- 1 file changed, 141 insertions(+), 14 deletions(-) diff --git a/docs/backend-system/building-backends/08-migrating.md b/docs/backend-system/building-backends/08-migrating.md index 9552ca325c..fcac599227 100644 --- a/docs/backend-system/building-backends/08-migrating.md +++ b/docs/backend-system/building-backends/08-migrating.md @@ -6,7 +6,7 @@ sidebar_label: Migration Guide description: How to migrate existing backends to the new backend system --- -# Overview +## Overview This section describes how to migrate an existing Backstage backend service package (typically in `packages/backend`) to use the new backend system. @@ -23,7 +23,7 @@ package as a result of these steps, and then being able to [migrate plugins](../building-plugins-and-modules/08-migrating.md) as a separate endeavour later. -# Overall Structure +## Overall Structure Your typical backend package has a few overall component parts: @@ -58,7 +58,7 @@ module.hot?.accept(); main().catch(...); ``` -# Migrating the Index File +## Migrating the Index File This migration will try to leave the `plugins` folder unchanged initially, first focusing on removing the environment type and reducing the index file to its @@ -114,11 +114,11 @@ then passes them into the relevant `createPlugin` export function, and makes sure that the route handler it returns is passed into the HTTP router with the given prefix. -# Handling Custom Environments +## Handling Custom Environments In the simple case, what we did above is sufficient, TypeScript is happy, and the backend runs with the new feature. If they do, feel free to skip this entire -section. +section, and deleting `types.ts`. Sometimes though, type errors can be reported on the newly added line, saying that parts of the `PluginEnvironment` type do not match. This happens when the @@ -197,7 +197,7 @@ place it in the legacy plugin environment. > will also need to import that factory and pass it to the `services` array > argument of `createBackend`. -# Cleaning Up the Plugins Folder +## Cleaning Up the Plugins Folder For plugins that are private and your own, you can follow a [dedicated migration guide](../building-plugins-and-modules/08-migrating.md) as you see fit, at a @@ -213,7 +213,7 @@ such migrations you can make. > and they still need to be configured properly in your app-config. Those > mechanisms still work just the same as they used to in the old backend system. -## The App Plugin +### The App Plugin The app backend plugin that serves the frontend from the backend can trivially be used in its new form. @@ -233,7 +233,7 @@ typically found in your `packages/app` folder. By default it's just plain "app". You should be able to delete the `plugins/app.ts` file at this point. -## The Catalog Plugin +### The Catalog Plugin A basic installation of the catalog plugin looks as follows. @@ -253,10 +253,10 @@ use templates at all, you can remove those lines. If you have other customizations made to `plugins/catalog.ts`, such as adding custom processors or entity providers, read on. Otherwise, you should be able to -just delete the `plugins/catalog.ts` file at this point. +just delete that file at this point. You will use the [extension points](../architecture/05-extension-points.md) -mechanism to extend or tweak the functionality of the catalog. To do that, +mechanism to extend or tweak the functionality of the plugin. To do that, you'll make your own bespoke [module](../architecture/06-modules.md) which depends on the appropriate extension point and interacts with it. @@ -275,8 +275,8 @@ depends on the appropriate extension point and interacts with it. + // ... and other dependencies as needed + }, + init({ catalog /* ..., other dependencies */ }) { -+ // Here you have the opportunity to interact with the catalog extension -+ // point before the catalog plugin itself gets instantiated ++ // Here you have the opportunity to interact with the extension ++ // point before the plugin itself gets instantiated + catalog.addEntityProvider(new MyEntityProvider()); // just an example + catalog.addProcessor(new MyProcessor()); // just an example + }, @@ -290,8 +290,8 @@ depends on the appropriate extension point and interacts with it. +backend.add(catalogExtensionsModule()); ``` -This also requires that you have a dependency on the catalog node package, if -you didn't already have one. +This also requires that you have a dependency on the corresponding node package, +if you didn't already have one. ```bash # from the repository root @@ -303,3 +303,130 @@ going easily, but feel free to move it out to where it fits best. As you migrate your entire plugin flora to the new backend system, you will probably make more and more of these modules as "first class" things, living right next to the implementations that they represent, and being exported from there. + +### The Events Plugin + +A basic installation of the events plugin looks as follows. + +```diff + // packages/backend/src/index.ts ++import { eventsPlugin } from '@backstage/plugin-events-backend'; + + const backend = createBackend(); ++backend.add(eventsPlugin()); +``` + +If you have other customizations made to `plugins/events.ts`, such as adding +custom subscribers, read on. Otherwise, you should be able to just delete that +file at this point. + +You will use the [extension points](../architecture/05-extension-points.md) +mechanism to extend or tweak the functionality of the plugin. To do that, +you'll make your own bespoke [module](../architecture/06-modules.md) which +depends on the appropriate extension point and interacts with it. + +```diff + // packages/backend/src/index.ts ++import { eventsExtensionPoint } from '@backstage/plugin-events-node'; ++import { createBackendModule } from '@backstage/backend-plugin-api'; + ++const eventsExtensionsModule = createBackendModule({ ++ pluginId: 'events', // name of the plugin that the module is targeting ++ moduleId: 'extensions', // you can choose this one freely ++ register(env) { ++ env.registerInit({ ++ deps: { ++ events: eventsExtensionPoint, ++ // ... and other dependencies as needed ++ }, ++ init({ events /* ..., other dependencies */ }) { ++ // Here you have the opportunity to interact with the extension ++ // point before the plugin itself gets instantiated ++ events.addSubscribers(new MySubscriber()); // just an example ++ }, ++ }); ++ }, ++}); + + const backend = createBackend(); + backend.add(eventsPlugin()); ++backend.add(eventsExtensionsModule()); +``` + +This also requires that you have a dependency on the corresponding node package, +if you didn't already have one. + +```bash +# from the repository root +yarn add --cwd packages/backend @backstage/plugin-events-node +``` + +Here we've placed the module directly in the backend index file just to get +going easily, but feel free to move it out to where it fits best. As you migrate +your entire plugin flora to the new backend system, you will probably make more +and more of these modules as "first class" things, living right next to the +implementations that they represent, and being exported from there. + +### The Scaffolder Plugin + +A basic installation of the scaffolder plugin looks as follows. + +```diff + // packages/backend/src/index.ts ++import { scaffolderPlugin } from '@backstage/plugin-scaffolder-backend'; + + const backend = createBackend(); ++backend.add(scaffolderPlugin()); +``` + +If you have other customizations made to `plugins/scaffolder.ts`, such as adding +custom actions, read on. Otherwise, you should be able to just delete that file +at this point. + +You will use the [extension points](../architecture/05-extension-points.md) +mechanism to extend or tweak the functionality of the plugin. To do that, +you'll make your own bespoke [module](../architecture/06-modules.md) which +depends on the appropriate extension point and interacts with it. + +```diff + // packages/backend/src/index.ts + // TODO: This might be moved to @backstage/plugin-scaffolder-node ++import { scaffolderActionsExtensionPoint } from '@backstage/plugin-scaffolder-backend/alpha'; ++import { createBackendModule } from '@backstage/backend-plugin-api'; + ++const scaffolderExtensionsModule = createBackendModule({ ++ pluginId: 'scaffolder', // name of the plugin that the module is targeting ++ moduleId: 'extensions', // you can choose this one freely ++ register(env) { ++ env.registerInit({ ++ deps: { ++ scaffolder: scaffolderActionsExtensionPoint, ++ // ... and other dependencies as needed ++ }, ++ init({ scaffolder /* ..., other dependencies */ }) { ++ // Here you have the opportunity to interact with the extension ++ // point before the plugin itself gets instantiated ++ scaffolder.addActions(new MyAction()); // just an example ++ }, ++ }); ++ }, ++}); + + const backend = createBackend(); + backend.add(scaffolderPlugin()); ++backend.add(scaffolderExtensionsModule()); +``` + +This also requires that you have a dependency on the corresponding node package, +if you didn't already have one. + +```bash +# from the repository root +yarn add --cwd packages/backend @backstage/plugin-scaffolder-node +``` + +Here we've placed the module directly in the backend index file just to get +going easily, but feel free to move it out to where it fits best. As you migrate +your entire plugin flora to the new backend system, you will probably make more +and more of these modules as "first class" things, living right next to the +implementations that they represent, and being exported from there.