diff --git a/.changeset/popular-bobcats-occur.md b/.changeset/popular-bobcats-occur.md new file mode 100644 index 0000000000..bdf311029b --- /dev/null +++ b/.changeset/popular-bobcats-occur.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-app-backend': minor +--- + +**BREAKING**: Removed support for the old backend system. + +As part of this change the plugin export from `/alpha` as been removed. If you are currently importing `@backstage/plugin-app-backend/alpha`, please update your import to `@backstage/plugin-app-backend`. diff --git a/packages/backend-legacy/package.json b/packages/backend-legacy/package.json index a740f80004..719f3fbcef 100644 --- a/packages/backend-legacy/package.json +++ b/packages/backend-legacy/package.json @@ -35,7 +35,6 @@ "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", "@backstage/integration": "workspace:^", - "@backstage/plugin-app-backend": "workspace:^", "@backstage/plugin-auth-backend": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "@backstage/plugin-catalog-backend": "workspace:^", @@ -67,7 +66,6 @@ "azure-devops-node-api": "^14.0.0", "better-sqlite3": "^11.0.0", "dockerode": "^4.0.0", - "example-app": "link:../app", "express": "^4.17.1", "express-prom-bundle": "^7.0.0", "express-promise-router": "^4.1.0", diff --git a/packages/backend-legacy/src/index.ts b/packages/backend-legacy/src/index.ts index 4632cddc56..507a1f2aee 100644 --- a/packages/backend-legacy/src/index.ts +++ b/packages/backend-legacy/src/index.ts @@ -44,7 +44,6 @@ import kubernetes from './plugins/kubernetes'; import scaffolder from './plugins/scaffolder'; import search from './plugins/search'; import techdocs from './plugins/techdocs'; -import app from './plugins/app'; import permission from './plugins/permission'; import { PluginEnvironment } from './types'; import { ServerPermissionClient } from '@backstage/plugin-permission-node'; @@ -131,7 +130,6 @@ async function main() { const searchEnv = useHotMemoize(module, () => createEnv('search')); const techdocsEnv = useHotMemoize(module, () => createEnv('techdocs')); const kubernetesEnv = useHotMemoize(module, () => createEnv('kubernetes')); - const appEnv = useHotMemoize(module, () => createEnv('app')); const permissionEnv = useHotMemoize(module, () => createEnv('permission')); const eventsEnv = useHotMemoize(module, () => createEnv('events')); @@ -150,8 +148,7 @@ async function main() { .loadConfig(config) .addRouter('', await healthcheck(healthcheckEnv)) .addRouter('', metricsHandler()) - .addRouter('/api', apiRouter) - .addRouter('', await app(appEnv)); + .addRouter('/api', apiRouter); await service.start().catch(err => { logger.error(err); diff --git a/packages/backend-legacy/src/plugins/app.ts b/packages/backend-legacy/src/plugins/app.ts deleted file mode 100644 index 03d1ad95e7..0000000000 --- a/packages/backend-legacy/src/plugins/app.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2020 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 { createRouter } from '@backstage/plugin-app-backend'; -import { Router } from 'express'; -import { PluginEnvironment } from '../types'; - -export default async function createPlugin( - env: PluginEnvironment, -): Promise { - return await createRouter({ - logger: env.logger, - config: env.config, - database: env.database, - appPackageName: 'example-app', - }); -} diff --git a/plugins/app-backend/dev/index.ts b/plugins/app-backend/dev/index.ts index 03f1931337..bb4368d842 100644 --- a/plugins/app-backend/dev/index.ts +++ b/plugins/app-backend/dev/index.ts @@ -23,5 +23,5 @@ backend.add( data: { app: { packageName: 'example-app' } }, }), ); -backend.add(import('../src/alpha')); +backend.add(import('../src')); backend.start(); diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index a5e97727fc..cbb4bd078d 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -26,16 +26,12 @@ "license": "Apache-2.0", "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts", "./package.json": "./package.json" }, "main": "src/index.ts", "types": "src/index.ts", "typesVersions": { "*": { - "alpha": [ - "src/alpha.ts" - ], "package.json": [ "package.json" ] @@ -64,7 +60,6 @@ "@backstage/plugin-app-node": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "@backstage/types": "workspace:^", - "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", "fs-extra": "^11.2.0", @@ -81,6 +76,7 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@backstage/types": "workspace:^", + "@types/express": "^4.17.6", "@types/supertest": "^2.0.8", "supertest": "^7.0.0" }, diff --git a/plugins/app-backend/report-alpha.api.md b/plugins/app-backend/report-alpha.api.md deleted file mode 100644 index 78c4b97232..0000000000 --- a/plugins/app-backend/report-alpha.api.md +++ /dev/null @@ -1,13 +0,0 @@ -## API Report File for "@backstage/plugin-app-backend" - -> 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'; - -// @alpha (undocumented) -const _appPlugin: BackendFeature; -export default _appPlugin; - -// (No @packageDocumentation comment for this package) -``` diff --git a/plugins/app-backend/report.api.md b/plugins/app-backend/report.api.md index 35e7ea383d..08776e8fa9 100644 --- a/plugins/app-backend/report.api.md +++ b/plugins/app-backend/report.api.md @@ -3,36 +3,9 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { AuthService } from '@backstage/backend-plugin-api'; import { BackendFeature } from '@backstage/backend-plugin-api'; -import { ConfigSchema } from '@backstage/config-loader'; -import { DatabaseService } from '@backstage/backend-plugin-api'; -import express from 'express'; -import { HttpAuthService } from '@backstage/backend-plugin-api'; -import { LoggerService } from '@backstage/backend-plugin-api'; -import { RootConfigService } from '@backstage/backend-plugin-api'; // @public const appPlugin: BackendFeature; export default appPlugin; - -// @public @deprecated (undocumented) -export function createRouter(options: RouterOptions): Promise; - -// @public @deprecated (undocumented) -export interface RouterOptions { - appPackageName: string; - // (undocumented) - auth?: AuthService; - // (undocumented) - config: RootConfigService; - database?: DatabaseService; - disableConfigInjection?: boolean; - // (undocumented) - httpAuth?: HttpAuthService; - // (undocumented) - logger: LoggerService; - schema?: ConfigSchema; - staticFallbackHandler?: express.Handler; -} ``` diff --git a/plugins/app-backend/src/alpha.ts b/plugins/app-backend/src/alpha.ts deleted file mode 100644 index eb661bc295..0000000000 --- a/plugins/app-backend/src/alpha.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2023 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 { appPlugin } from './service/appPlugin'; - -/** @alpha */ -const _appPlugin = appPlugin; -export default _appPlugin; diff --git a/plugins/app-backend/src/service/router.test.ts b/plugins/app-backend/src/service/router.test.ts index cdb150e06c..12b471c1f2 100644 --- a/plugins/app-backend/src/service/router.test.ts +++ b/plugins/app-backend/src/service/router.test.ts @@ -14,14 +14,14 @@ * limitations under the License. */ -import { AppConfig, ConfigReader } from '@backstage/config'; +import { AppConfig } from '@backstage/config'; import express from 'express'; import Router from 'express-promise-router'; import { resolve as resolvePath } from 'path'; import request from 'supertest'; import { createRouter } from './router'; import { loadConfigSchema } from '@backstage/config-loader'; -import { mockServices } from '@backstage/backend-test-utils'; +import { mockServices, TestDatabases } from '@backstage/backend-test-utils'; jest.mock('../lib/config', () => ({ injectConfig: jest.fn(), @@ -34,12 +34,24 @@ global.__non_webpack_require__ = { }; describe('createRouter', () => { + const databases = TestDatabases.create({ ids: ['SQLITE_3'] }); + let app: express.Express; beforeAll(async () => { + const knex = databases.init('SQLITE_3'); const router = await createRouter({ logger: mockServices.logger.mock(), - config: new ConfigReader({}), + database: mockServices.database.mock({ + getClient: () => knex, + }), + auth: mockServices.auth(), + httpAuth: mockServices.httpAuth(), + config: mockServices.rootConfig({ + data: { + app: { disableStaticFallbackCache: true }, + }, + }), appPackageName: 'example-app', }); app = express().use(router); @@ -97,7 +109,14 @@ describe('createRouter with static fallback handler', () => { const router = await createRouter({ logger: mockServices.logger.mock(), - config: new ConfigReader({}), + database: mockServices.database.mock(), + auth: mockServices.auth(), + httpAuth: mockServices.httpAuth(), + config: mockServices.rootConfig({ + data: { + app: { disableStaticFallbackCache: true }, + }, + }), appPackageName: 'example-app', staticFallbackHandler, }); @@ -132,8 +151,16 @@ describe('createRouter config schema test', () => { it('uses an external schema', async () => { await createRouter({ logger: mockServices.logger.mock(), - config: new ConfigReader({ - test: 'value', + database: mockServices.database.mock(), + auth: mockServices.auth(), + httpAuth: mockServices.httpAuth(), + config: mockServices.rootConfig({ + data: { + app: { + disableStaticFallbackCache: true, + }, + test: 'value', + }, }), appPackageName: 'example-app', schema: await loadConfigSchema({ @@ -173,8 +200,16 @@ describe('createRouter config schema test', () => { it('uses no external schema', async () => { await createRouter({ logger: mockServices.logger.mock(), - config: new ConfigReader({ - test: 'value', + database: mockServices.database.mock(), + auth: mockServices.auth(), + httpAuth: mockServices.httpAuth(), + config: mockServices.rootConfig({ + data: { + app: { + disableStaticFallbackCache: true, + }, + test: 'value', + }, }), appPackageName: 'example-app', }); diff --git a/plugins/app-backend/src/service/router.ts b/plugins/app-backend/src/service/router.ts index 4926383638..cf2ad886d7 100644 --- a/plugins/app-backend/src/service/router.ts +++ b/plugins/app-backend/src/service/router.ts @@ -19,7 +19,7 @@ import { resolvePackagePath, RootConfigService, } from '@backstage/backend-plugin-api'; -import { AppConfig } from '@backstage/config'; +import type { AppConfig } from '@backstage/config'; import helmet from 'helmet'; import express, { Request, Response } from 'express'; import Router from 'express-promise-router'; @@ -35,7 +35,7 @@ import { CACHE_CONTROL_NO_CACHE, CACHE_CONTROL_REVALIDATE_CACHE, } from '../lib/headers'; -import { ConfigSchema } from '@backstage/config-loader'; +import type { ConfigSchema } from '@backstage/config-loader'; import { AuthService, HttpAuthService, @@ -48,21 +48,20 @@ import { injectConfig, readFrontendConfig } from '../lib/config'; type Mime = { lookup(arg0: string): string }; /** - * @public - * @deprecated Please migrate to the new backend system as this will be removed in the future. + * @internal */ export interface RouterOptions { config: RootConfigService; logger: LoggerService; - auth?: AuthService; - httpAuth?: HttpAuthService; + auth: AuthService; + httpAuth: HttpAuthService; /** * If a database is provided it will be used to cache previously deployed static assets. * * This is a built-in alternative to using a `staticFallbackHandler`. */ - database?: DatabaseService; + database: DatabaseService; /** * The name of the app package that content should be served from. The same app package should be @@ -86,17 +85,6 @@ export interface RouterOptions { */ 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; - /** * * Provides a ConfigSchema. @@ -106,8 +94,7 @@ export interface RouterOptions { } /** - * @public - * @deprecated Please migrate to the new backend system as this will be removed in the future. + * @internal */ export async function createRouter( options: RouterOptions, @@ -122,9 +109,9 @@ export async function createRouter( schema, } = options; - const disableConfigInjection = - options.disableConfigInjection ?? - config.getOptionalBoolean('app.disableConfigInjection'); + const disableConfigInjection = config.getOptionalBoolean( + 'app.disableConfigInjection', + ); const disableStaticFallbackCache = config.getOptionalBoolean( 'app.disableStaticFallbackCache', ); @@ -153,13 +140,12 @@ export async function createRouter( schema, }); - const assetStore = - options.database && !disableStaticFallbackCache - ? await StaticAssetsStore.create({ - logger, - database: options.database, - }) - : undefined; + const assetStore = !disableStaticFallbackCache + ? await StaticAssetsStore.create({ + logger, + database: options.database, + }) + : undefined; const router = Router(); @@ -167,10 +153,9 @@ export async function createRouter( const publicDistDir = resolvePath(appDistDir, 'public'); - const enablePublicEntryPoint = - (await fs.pathExists(publicDistDir)) && auth && httpAuth; + const enablePublicEntryPoint = await fs.pathExists(publicDistDir); - if (enablePublicEntryPoint && auth && httpAuth) { + if (enablePublicEntryPoint) { logger.info( `App is running in protected mode, serving public content from ${publicDistDir}`, ); diff --git a/yarn.lock b/yarn.lock index 378e56eb4a..0ab2120a81 100644 --- a/yarn.lock +++ b/yarn.lock @@ -28814,12 +28814,6 @@ __metadata: languageName: node linkType: soft -"example-app@link:../app::locator=example-backend-legacy%40workspace%3Apackages%2Fbackend-legacy": - version: 0.0.0-use.local - resolution: "example-app@link:../app::locator=example-backend-legacy%40workspace%3Apackages%2Fbackend-legacy" - languageName: node - linkType: soft - "example-app@workspace:packages/app": version: 0.0.0-use.local resolution: "example-app@workspace:packages/app" @@ -28898,7 +28892,6 @@ __metadata: "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@backstage/integration": "workspace:^" - "@backstage/plugin-app-backend": "workspace:^" "@backstage/plugin-auth-backend": "workspace:^" "@backstage/plugin-auth-node": "workspace:^" "@backstage/plugin-catalog-backend": "workspace:^" @@ -28934,7 +28927,6 @@ __metadata: azure-devops-node-api: ^14.0.0 better-sqlite3: ^11.0.0 dockerode: ^4.0.0 - example-app: "link:../app" express: ^4.17.1 express-prom-bundle: ^7.0.0 express-promise-router: ^4.1.0