From 45857bffae0f6c504a0b9b0519ae9b15616b985c Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 26 Sep 2022 16:17:27 +0200 Subject: [PATCH 01/10] backend-app-api: export rootLoggerFactory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- .changeset/yellow-lemons-march.md | 5 +++++ packages/backend-app-api/api-report.md | 3 +++ .../backend-app-api/src/services/implementations/index.ts | 1 + .../src/services/implementations/rootLoggerService.ts | 2 +- 4 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 .changeset/yellow-lemons-march.md diff --git a/.changeset/yellow-lemons-march.md b/.changeset/yellow-lemons-march.md new file mode 100644 index 0000000000..24d9e760ad --- /dev/null +++ b/.changeset/yellow-lemons-march.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': patch +--- + +Properly export `rootLoggerFactory`. diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md index ea149a44f2..e5d7f9dedd 100644 --- a/packages/backend-app-api/api-report.md +++ b/packages/backend-app-api/api-report.md @@ -69,6 +69,9 @@ export const permissionsFactory: ( options?: undefined, ) => ServiceFactory; +// @public (undocumented) +export const rootLoggerFactory: (options?: undefined) => ServiceFactory; + // @public (undocumented) export const schedulerFactory: ( options?: undefined, diff --git a/packages/backend-app-api/src/services/implementations/index.ts b/packages/backend-app-api/src/services/implementations/index.ts index 048c952b4e..714122ca11 100644 --- a/packages/backend-app-api/src/services/implementations/index.ts +++ b/packages/backend-app-api/src/services/implementations/index.ts @@ -19,6 +19,7 @@ export { configFactory } from './configService'; export { databaseFactory } from './databaseService'; export { discoveryFactory } from './discoveryService'; export { loggerFactory } from './loggerService'; +export { rootLoggerFactory } from './rootLoggerService'; export { permissionsFactory } from './permissionsService'; export { schedulerFactory } from './schedulerService'; export { tokenManagerFactory } from './tokenManagerService'; diff --git a/packages/backend-app-api/src/services/implementations/rootLoggerService.ts b/packages/backend-app-api/src/services/implementations/rootLoggerService.ts index d7da11723e..a65a8d9126 100644 --- a/packages/backend-app-api/src/services/implementations/rootLoggerService.ts +++ b/packages/backend-app-api/src/services/implementations/rootLoggerService.ts @@ -39,7 +39,7 @@ class BackstageLogger implements Logger { } /** @public */ -export const loggerFactory = createServiceFactory({ +export const rootLoggerFactory = createServiceFactory({ service: rootLoggerServiceRef, deps: {}, async factory() { From 72549952d1ee43344a9da44b9be94050cebc3037 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 26 Sep 2022 16:18:05 +0200 Subject: [PATCH 02/10] backend-test-utils: fix handling of root scoped services MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- .changeset/curvy-lemons-change.md | 5 +++++ .../src/next/wiring/TestBackend.ts | 12 ++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 .changeset/curvy-lemons-change.md diff --git a/.changeset/curvy-lemons-change.md b/.changeset/curvy-lemons-change.md new file mode 100644 index 0000000000..29e31a7b60 --- /dev/null +++ b/.changeset/curvy-lemons-change.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-test-utils': patch +--- + +Fixed handling of root scoped services in `startTestBackend`. diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.ts b/packages/backend-test-utils/src/next/wiring/TestBackend.ts index f93b34cdd8..677ba930cc 100644 --- a/packages/backend-test-utils/src/next/wiring/TestBackend.ts +++ b/packages/backend-test-utils/src/next/wiring/TestBackend.ts @@ -63,10 +63,18 @@ export async function startTestBackend< if (Array.isArray(serviceDef)) { // if type is ExtensionPoint? // do something differently? + const [ref, impl] = serviceDef; + if (ref.scope === 'plugin') { + return createServiceFactory({ + service: ref, + deps: {}, + factory: async () => async () => impl, + }); + } return createServiceFactory({ - service: serviceDef[0], + service: ref, deps: {}, - factory: async () => async () => serviceDef[1], + factory: async () => impl, }); } return serviceDef as ServiceFactory; From 8336d42b404bab1753cc88d813ac9125540a2220 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 26 Sep 2022 16:18:39 +0200 Subject: [PATCH 03/10] backend-plugin-api: fix spelling mistakes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- packages/backend-plugin-api/src/wiring/factories.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/backend-plugin-api/src/wiring/factories.test.ts b/packages/backend-plugin-api/src/wiring/factories.test.ts index 110d7b4f3f..6a1e7d33bc 100644 --- a/packages/backend-plugin-api/src/wiring/factories.test.ts +++ b/packages/backend-plugin-api/src/wiring/factories.test.ts @@ -31,7 +31,7 @@ describe('createExtensionPoint', () => { }); describe('createBackendPlugin', () => { - it('should create an BackendPlugin', () => { + it('should create a BackendPlugin', () => { const plugin = createBackendPlugin({ id: 'x', register(_reg, _options: { a: string }) {}, @@ -71,7 +71,7 @@ describe('createBackendPlugin', () => { }); describe('createBackendModule', () => { - it('should create an BackendModule', () => { + it('should create a BackendModule', () => { const mod = createBackendModule({ pluginId: 'x', moduleId: 'y', From 571ff04b0cacb74bb8da9402b327793266567e67 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 26 Sep 2022 16:22:38 +0200 Subject: [PATCH 04/10] app-backend: initial port to new backend system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- plugins/app-backend/api-report.md | 12 ++ plugins/app-backend/package.json | 10 +- plugins/app-backend/src/index.ts | 2 + .../app-backend/src/service/appPlugin.test.ts | 81 +++++++++++++ plugins/app-backend/src/service/appPlugin.ts | 107 ++++++++++++++++++ yarn.lock | 11 ++ 6 files changed, 221 insertions(+), 2 deletions(-) create mode 100644 plugins/app-backend/src/service/appPlugin.test.ts create mode 100644 plugins/app-backend/src/service/appPlugin.ts diff --git a/plugins/app-backend/api-report.md b/plugins/app-backend/api-report.md index 0383129823..cfeebc6cd9 100644 --- a/plugins/app-backend/api-report.md +++ b/plugins/app-backend/api-report.md @@ -3,11 +3,23 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import express from 'express'; import { Logger } from 'winston'; import { PluginDatabaseManager } from '@backstage/backend-common'; +// @alpha +export const appPlugin: (options: AppPluginOptions) => BackendFeature; + +// @alpha (undocumented) +export type AppPluginOptions = { + appPackageName: string; + staticFallbackHandler?: express.Handler; + disableConfigInjection?: boolean; + disableStaticFallbackCache?: boolean; +}; + // @public (undocumented) export function createRouter(options: RouterOptions): Promise; diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index ffd40b89c0..d79ab46b12 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -8,7 +8,8 @@ "publishConfig": { "access": "public", "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "types": "dist/index.d.ts", + "alphaTypes": "dist/index.alpha.d.ts" }, "backstage": { "role": "backend-plugin" @@ -24,7 +25,7 @@ ], "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build", + "build": "backstage-cli package build --experimental-type-build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -33,6 +34,7 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/config-loader": "workspace:^", "@backstage/types": "workspace:^", @@ -49,16 +51,20 @@ "yn": "^4.0.0" }, "devDependencies": { + "@backstage/backend-app-api": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@backstage/types": "workspace:^", "@types/supertest": "^2.0.8", + "get-port": "^6.1.2", "mock-fs": "^5.1.0", "msw": "^0.47.0", + "node-fetch": "^2.6.7", "supertest": "^6.1.3" }, "files": [ "dist", + "alpha", "migrations/**/*.{js,d.ts}", "static" ] diff --git a/plugins/app-backend/src/index.ts b/plugins/app-backend/src/index.ts index c91416eac1..167dc041fc 100644 --- a/plugins/app-backend/src/index.ts +++ b/plugins/app-backend/src/index.ts @@ -21,3 +21,5 @@ */ export * from './service/router'; +export { appPlugin } from './service/appPlugin'; +export type { AppPluginOptions } from './service/appPlugin'; diff --git a/plugins/app-backend/src/service/appPlugin.test.ts b/plugins/app-backend/src/service/appPlugin.test.ts new file mode 100644 index 0000000000..03ed4e8845 --- /dev/null +++ b/plugins/app-backend/src/service/appPlugin.test.ts @@ -0,0 +1,81 @@ +/* + * Copyright 2022 The Backstage Authors + * + * 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 mockFs from 'mock-fs'; +import { resolve as resolvePath } from 'path'; +import fetch from 'node-fetch'; +import { configServiceRef } from '@backstage/backend-plugin-api'; +import { startTestBackend } from '@backstage/backend-test-utils'; +import { appPlugin } from './appPlugin'; +import { + databaseFactory, + httpRouterFactory, + loggerFactory, + rootLoggerFactory, +} from '@backstage/backend-app-api'; +import { ConfigReader } from '@backstage/config'; +import getPort from 'get-port'; + +describe('appPlugin', () => { + beforeAll(() => { + mockFs({ + [resolvePath(process.cwd(), 'node_modules/app')]: { + 'package.json': '{}', + dist: { + static: {}, + 'index.html': 'winning', + }, + }, + }); + }); + + afterAll(() => { + mockFs.restore(); + }); + + it('boots', async () => { + const port = await getPort(); + await startTestBackend({ + services: [ + [ + configServiceRef, + new ConfigReader({ + backend: { + listen: { port }, + database: { client: 'better-sqlite3', connection: ':memory:' }, + }, + }), + ], + loggerFactory(), + rootLoggerFactory(), + databaseFactory(), + httpRouterFactory(), + ], + features: [ + appPlugin({ + appPackageName: 'app', + disableStaticFallbackCache: true, + }), + ], + }); + + await expect( + fetch(`http://localhost:${port}/api/app/derp.html`).then(res => + res.text(), + ), + ).resolves.toBe('winning'); + }); +}); diff --git a/plugins/app-backend/src/service/appPlugin.ts b/plugins/app-backend/src/service/appPlugin.ts new file mode 100644 index 0000000000..185279f0f0 --- /dev/null +++ b/plugins/app-backend/src/service/appPlugin.ts @@ -0,0 +1,107 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import express from 'express'; +import { + configServiceRef, + createBackendPlugin, + databaseServiceRef, + loggerServiceRef, + loggerToWinstonLogger, + httpRouterServiceRef, +} from '@backstage/backend-plugin-api'; +import { createRouter } from './router'; + +/** @alpha */ +export type AppPluginOptions = { + /** + * The name of the app package (in most Backstage repositories, this is the + * "name" field in `packages/app/package.json`) that content should be served + * from. The same app package should be added as a dependency to the backend + * package in order for it to be accessible at runtime. + * + * In a typical setup with a single app package, this would be set to 'app'. + */ + appPackageName: string; + + /** + * A request handler to handle requests for static content that are not present in the app bundle. + * + * This can be used to avoid issues with clients on older deployment versions trying to access lazy + * loaded content that is no longer present. Typically the requests would fall back to a long-term + * object store where all recently deployed versions of the app are present. + * + * Another option is to provide a `database` that will take care of storing the static assets instead. + * + * If both `database` and `staticFallbackHandler` are provided, the `database` will attempt to serve + * static assets first, and if they are not found, the `staticFallbackHandler` will be called. + */ + staticFallbackHandler?: express.Handler; + + /** + * Disables the configuration injection. This can be useful if you're running in an environment + * with a read-only filesystem, or for some other reason don't want configuration to be injected. + * + * Note that this will cause the configuration used when building the app bundle to be used, unless + * a separate configuration loading strategy is set up. + * + * This also disables configuration injection though `APP_CONFIG_` environment variables. + */ + disableConfigInjection?: boolean; + + /** + * By default the app backend plugin will cache previously deployed static assets in the database. + * If you disable this, it is recommended to set a `staticFallbackHandler` instead. + */ + disableStaticFallbackCache?: boolean; +}; + +/** + * The App plugin is responsible for serving the frontend app bundle and static assets. + * @alpha + */ +export const appPlugin = createBackendPlugin({ + id: 'app', + register(env, options: AppPluginOptions) { + env.registerInit({ + deps: { + logger: loggerServiceRef, + config: configServiceRef, + database: databaseServiceRef, + httpRouter: httpRouterServiceRef, + }, + async init({ logger, config, database, httpRouter }) { + const { + appPackageName, + staticFallbackHandler, + disableConfigInjection, + disableStaticFallbackCache, + } = options; + const winstonLogger = loggerToWinstonLogger(logger); + + const router = await createRouter({ + logger: winstonLogger, + config, + database: disableStaticFallbackCache ? undefined : database, + appPackageName, + staticFallbackHandler, + disableConfigInjection, + }); + httpRouter.use(router); + }, + }); + }, +}); diff --git a/yarn.lock b/yarn.lock index 0b643f5711..6ef0daf878 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3932,7 +3932,9 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-app-backend@workspace:plugins/app-backend" dependencies: + "@backstage/backend-app-api": "workspace:^" "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" @@ -3943,6 +3945,7 @@ __metadata: express: ^4.17.1 express-promise-router: ^4.1.0 fs-extra: 10.1.0 + get-port: ^6.1.2 globby: ^11.0.0 helmet: ^6.0.0 knex: ^2.0.0 @@ -3950,6 +3953,7 @@ __metadata: luxon: ^3.0.0 mock-fs: ^5.1.0 msw: ^0.47.0 + node-fetch: ^2.6.7 supertest: ^6.1.3 winston: ^3.2.1 yn: ^4.0.0 @@ -23132,6 +23136,13 @@ __metadata: languageName: node linkType: hard +"get-port@npm:^6.1.2": + version: 6.1.2 + resolution: "get-port@npm:6.1.2" + checksum: e3c3d591492a11393455ef220f24c812a28f7da56ec3e4a2512d931a1f196d42850b50ac6138349a44622eda6dc3c0ccd8495cd91376d968e2d9e6f6f849e0a9 + languageName: node + linkType: hard + "get-stdin@npm:^8.0.0": version: 8.0.0 resolution: "get-stdin@npm:8.0.0" From 0027a749cdefd1379470da1799e033827b2b33ca Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 26 Sep 2022 16:40:11 +0200 Subject: [PATCH 05/10] backend-app-api: added index plugin option for http router service MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- .changeset/fair-tools-melt.md | 5 +++++ packages/backend-app-api/api-report.md | 7 ++++++- .../services/implementations/httpRouterService.ts | 15 +++++++++++++-- .../src/services/implementations/index.ts | 1 + 4 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 .changeset/fair-tools-melt.md diff --git a/.changeset/fair-tools-melt.md b/.changeset/fair-tools-melt.md new file mode 100644 index 0000000000..e63e4d5181 --- /dev/null +++ b/.changeset/fair-tools-melt.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': patch +--- + +Added possibility to configure index plugin of the HTTP router service. diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md index e5d7f9dedd..4d9fbea4a5 100644 --- a/packages/backend-app-api/api-report.md +++ b/packages/backend-app-api/api-report.md @@ -58,9 +58,14 @@ export const discoveryFactory: ( // @public (undocumented) export const httpRouterFactory: ( - options?: undefined, + options?: HttpRouterFactoryOptions | undefined, ) => ServiceFactory; +// @public (undocumented) +export type HttpRouterFactoryOptions = { + indexPlugin?: string; +}; + // @public (undocumented) export const loggerFactory: (options?: undefined) => ServiceFactory; diff --git a/packages/backend-app-api/src/services/implementations/httpRouterService.ts b/packages/backend-app-api/src/services/implementations/httpRouterService.ts index be4af664c4..c470443edc 100644 --- a/packages/backend-app-api/src/services/implementations/httpRouterService.ts +++ b/packages/backend-app-api/src/services/implementations/httpRouterService.ts @@ -24,6 +24,16 @@ import Router from 'express-promise-router'; import { Handler } from 'express'; import { createServiceBuilder } from '@backstage/backend-common'; +/** + * @public + */ +export type HttpRouterFactoryOptions = { + /** + * The plugin ID used for the index route. Defaults to 'app' + */ + indexPlugin?: string; +}; + /** @public */ export const httpRouterFactory = createServiceFactory({ service: httpRouterServiceRef, @@ -31,8 +41,9 @@ export const httpRouterFactory = createServiceFactory({ config: configServiceRef, plugin: pluginMetadataServiceRef, }, - async factory({ config }) { + async factory({ config }, options?: HttpRouterFactoryOptions) { const rootRouter = Router(); + const defaultPluginId = options?.indexPlugin ?? 'app'; const service = createServiceBuilder(module) .loadConfig(config) @@ -42,7 +53,7 @@ export const httpRouterFactory = createServiceFactory({ return async ({ plugin }) => { const pluginId = plugin.getId(); - const path = pluginId ? `/api/${pluginId}` : ''; + const path = pluginId === defaultPluginId ? '' : `/api/${pluginId}`; return { use(handler: Handler) { rootRouter.use(path, handler); diff --git a/packages/backend-app-api/src/services/implementations/index.ts b/packages/backend-app-api/src/services/implementations/index.ts index 714122ca11..608399bad9 100644 --- a/packages/backend-app-api/src/services/implementations/index.ts +++ b/packages/backend-app-api/src/services/implementations/index.ts @@ -25,3 +25,4 @@ export { schedulerFactory } from './schedulerService'; export { tokenManagerFactory } from './tokenManagerService'; export { urlReaderFactory } from './urlReaderService'; export { httpRouterFactory } from './httpRouterService'; +export type { HttpRouterFactoryOptions } from './httpRouterService'; From 96d288a02d798fed102a0e6d801f8b7a37921bda Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 26 Sep 2022 16:40:58 +0200 Subject: [PATCH 06/10] backend-defaults: added root logger service to default services MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- .changeset/large-dingos-juggle.md | 5 +++++ packages/backend-defaults/src/CreateBackend.ts | 2 ++ 2 files changed, 7 insertions(+) create mode 100644 .changeset/large-dingos-juggle.md diff --git a/.changeset/large-dingos-juggle.md b/.changeset/large-dingos-juggle.md new file mode 100644 index 0000000000..8566a0f305 --- /dev/null +++ b/.changeset/large-dingos-juggle.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-defaults': patch +--- + +Added root logger service to the set of default services. diff --git a/packages/backend-defaults/src/CreateBackend.ts b/packages/backend-defaults/src/CreateBackend.ts index 5130d6733b..b95bd6f35b 100644 --- a/packages/backend-defaults/src/CreateBackend.ts +++ b/packages/backend-defaults/src/CreateBackend.ts @@ -24,6 +24,7 @@ import { httpRouterFactory, loggerFactory, permissionsFactory, + rootLoggerFactory, schedulerFactory, tokenManagerFactory, urlReaderFactory, @@ -36,6 +37,7 @@ export const defaultServiceFactories = [ databaseFactory, discoveryFactory, loggerFactory, + rootLoggerFactory, permissionsFactory, schedulerFactory, tokenManagerFactory, From fff524b44db978d7f4a3c304331b3cdf8184e70e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 26 Sep 2022 16:49:55 +0200 Subject: [PATCH 07/10] app-backend: make "app" the default app package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- plugins/app-backend/api-report.md | 2 +- plugins/app-backend/src/service/appPlugin.test.ts | 3 +++ plugins/app-backend/src/service/appPlugin.ts | 6 +++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/plugins/app-backend/api-report.md b/plugins/app-backend/api-report.md index cfeebc6cd9..b52132ef51 100644 --- a/plugins/app-backend/api-report.md +++ b/plugins/app-backend/api-report.md @@ -14,7 +14,7 @@ export const appPlugin: (options: AppPluginOptions) => BackendFeature; // @alpha (undocumented) export type AppPluginOptions = { - appPackageName: string; + appPackageName?: string; staticFallbackHandler?: express.Handler; disableConfigInjection?: boolean; disableStaticFallbackCache?: boolean; diff --git a/plugins/app-backend/src/service/appPlugin.test.ts b/plugins/app-backend/src/service/appPlugin.test.ts index 03ed4e8845..f4a2b142e8 100644 --- a/plugins/app-backend/src/service/appPlugin.test.ts +++ b/plugins/app-backend/src/service/appPlugin.test.ts @@ -77,5 +77,8 @@ describe('appPlugin', () => { res.text(), ), ).resolves.toBe('winning'); + await expect( + fetch(`http://localhost:${port}`).then(res => res.text()), + ).resolves.toBe('winning'); }); }); diff --git a/plugins/app-backend/src/service/appPlugin.ts b/plugins/app-backend/src/service/appPlugin.ts index 185279f0f0..f88bcb14f1 100644 --- a/plugins/app-backend/src/service/appPlugin.ts +++ b/plugins/app-backend/src/service/appPlugin.ts @@ -33,9 +33,9 @@ export type AppPluginOptions = { * from. The same app package should be added as a dependency to the backend * package in order for it to be accessible at runtime. * - * In a typical setup with a single app package, this would be set to 'app'. + * In a typical setup with a single app package, this will default to 'app'. */ - appPackageName: string; + appPackageName?: string; /** * A request handler to handle requests for static content that are not present in the app bundle. @@ -96,7 +96,7 @@ export const appPlugin = createBackendPlugin({ logger: winstonLogger, config, database: disableStaticFallbackCache ? undefined : database, - appPackageName, + appPackageName: appPackageName ?? 'app', staticFallbackHandler, disableConfigInjection, }); From 11c9e0ad333b79d738163799c889a6bc45da842b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 26 Sep 2022 16:53:58 +0200 Subject: [PATCH 08/10] changesets: add changeset for app-backend alpha plugin export MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- .changeset/quiet-ligers-draw.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/quiet-ligers-draw.md diff --git a/.changeset/quiet-ligers-draw.md b/.changeset/quiet-ligers-draw.md new file mode 100644 index 0000000000..30f5845a54 --- /dev/null +++ b/.changeset/quiet-ligers-draw.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-app-backend': patch +--- + +Added alpha plugin implementation for the new backend system. Available at `@backstage/plugin-app-backend/alpha`. From de7587254f4b658c803dc4f22569622c2c40afc4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 26 Sep 2022 16:55:59 +0200 Subject: [PATCH 09/10] backend-app-api: fix for root router overriding api routes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- .../services/implementations/httpRouterService.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/backend-app-api/src/services/implementations/httpRouterService.ts b/packages/backend-app-api/src/services/implementations/httpRouterService.ts index c470443edc..d9fc807b1a 100644 --- a/packages/backend-app-api/src/services/implementations/httpRouterService.ts +++ b/packages/backend-app-api/src/services/implementations/httpRouterService.ts @@ -42,21 +42,27 @@ export const httpRouterFactory = createServiceFactory({ plugin: pluginMetadataServiceRef, }, async factory({ config }, options?: HttpRouterFactoryOptions) { - const rootRouter = Router(); const defaultPluginId = options?.indexPlugin ?? 'app'; + const apiRouter = Router(); + const rootRouter = Router(); + const service = createServiceBuilder(module) .loadConfig(config) + .addRouter('/api', apiRouter) .addRouter('', rootRouter); await service.start(); return async ({ plugin }) => { const pluginId = plugin.getId(); - const path = pluginId === defaultPluginId ? '' : `/api/${pluginId}`; return { use(handler: Handler) { - rootRouter.use(path, handler); + if (pluginId === defaultPluginId) { + rootRouter.use(handler); + } else { + apiRouter.use(`/${pluginId}`, handler); + } }, }; }; From 21ceffe99d37a61fe3c0d73d5f25b15fd61dd6d6 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 26 Sep 2022 16:56:18 +0200 Subject: [PATCH 10/10] backend-next: add app-backend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- packages/backend-next/package.json | 1 + packages/backend-next/src/index.ts | 2 ++ yarn.lock | 1 + 3 files changed, 4 insertions(+) diff --git a/packages/backend-next/package.json b/packages/backend-next/package.json index 4e989c81cf..7e83203cea 100644 --- a/packages/backend-next/package.json +++ b/packages/backend-next/package.json @@ -26,6 +26,7 @@ }, "dependencies": { "@backstage/backend-defaults": "workspace:^", + "@backstage/plugin-app-backend": "workspace:^", "@backstage/plugin-catalog-backend": "workspace:^", "@backstage/plugin-scaffolder-backend": "workspace:^" }, diff --git a/packages/backend-next/src/index.ts b/packages/backend-next/src/index.ts index c6b7da8fa7..8196b28452 100644 --- a/packages/backend-next/src/index.ts +++ b/packages/backend-next/src/index.ts @@ -17,9 +17,11 @@ import { catalogPlugin } from '@backstage/plugin-catalog-backend'; import { scaffolderCatalogModule } from '@backstage/plugin-scaffolder-backend'; import { createBackend } from '@backstage/backend-defaults'; +import { appPlugin } from '@backstage/plugin-app-backend'; const backend = createBackend(); backend.add(catalogPlugin()); backend.add(scaffolderCatalogModule()); +backend.add(appPlugin({ appPackageName: 'example-app' })); backend.start(); diff --git a/yarn.lock b/yarn.lock index 6ef0daf878..a1d37af851 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21756,6 +21756,7 @@ __metadata: dependencies: "@backstage/backend-defaults": "workspace:^" "@backstage/cli": "workspace:^" + "@backstage/plugin-app-backend": "workspace:^" "@backstage/plugin-catalog-backend": "workspace:^" "@backstage/plugin-scaffolder-backend": "workspace:^" languageName: unknown