Merge pull request #24814 from backstage/camilaibs/nbs10-deprecate-more-legacy-system-helpers

[NBS 1.0] deprecate legacy service builder
This commit is contained in:
Patrik Oldsberg
2024-05-21 14:40:02 +02:00
committed by GitHub
37 changed files with 232 additions and 863 deletions
+12
View File
@@ -0,0 +1,12 @@
---
'@backstage/plugin-user-settings-backend': patch
'@backstage/plugin-devtools-backend': patch
'@backstage/plugin-techdocs-backend': patch
'@backstage/plugin-catalog-backend': patch
'@backstage/plugin-search-backend': patch
'@backstage/plugin-proxy-backend': patch
'@backstage/plugin-auth-backend': patch
'@backstage/plugin-app-backend': patch
---
Updated local development setup.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-common': patch
---
We are deprecating the legacy `createServiceBuilder` factory, so if you are still using it, please checkout the migration guide and [migrate](https://backstage.io/docs/backend-system/building-plugins-and-modules/migrating) your plugin to use the new backend system.
@@ -214,3 +214,44 @@ The above module can then be installed by the integrator alongside the kubernete
backend.add(import('@backstage/plugin-kubernetes-backend'));
backend.add(import('@internal/gke-cluster-supplier'));
```
### Dev Server
Follow the steps below to run your migrated plugin on a local development server:
1. First, delete the `src/run.ts` and `src/service/standaloneServer.ts` files in case they exist (the `backstage-cli` previously used these files to run legacy backend plugins locally, but they are no longer required).
2. Next, create a new development backend in the `dev/index.ts` file. The dev server is a lite version of a backend app that is mainly used to run your plugin locally, so a simple `kubernetes` backend local development server would look like this:
```ts title="in dev/index.js"
// This package should be installed as a `dev` dependency
import { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
// Path to the file where the plugin is export as default
backend.add(import('../src'));
backend.start();
```
The development server created above will be automatically configured with the default dependency factories, but if you need to mock some of the services your plugin relies on, such as the `rootConfig` service, you can use one of the `mockServices` factories:
```ts title="in dev/index.js"
//...
// This package should be installed as `devDependecies`
import { mockServices } from '@backstage/backend-test-utils';
const backend = createBackend();
// ...
backend.add(
mockServices.rootConfig.factory({
data: {
// your config mocked values goes here
},
}),
);
// ...
```
Checkout the [custom service implementations](https://backstage.io/docs/backend-system/building-backends/index#custom-service-implementations) documentation and also the [core service configurations](https://backstage.io/docs/backend-system/core-services/index) page in case you'd like to create your own custom mock factory for one or more services.
3. Now you can finally start your plugin locally by running `yarn start` from the root folder of your plugin.
+2 -2
View File
@@ -265,7 +265,7 @@ export function createRootLogger(
env?: NodeJS.ProcessEnv,
): winston.Logger;
// @public
// @public @deprecated
export function createServiceBuilder(_module: NodeModule): ServiceBuilder;
// @public
@@ -599,7 +599,7 @@ export type LegacyRootDatabaseService = {
forPlugin(pluginId: string): PluginDatabaseManager;
};
// @public
// @public @deprecated
export function loadBackendConfig(options: {
logger: LoggerService;
remote?: LoadConfigOptionsRemote;
+1
View File
@@ -29,6 +29,7 @@ import { setRootLoggerRedactionList } from './logging/createRootLogger';
* This function should only be called once, during the initialization of the backend.
*
* @public
* @deprecated Use {@link @backstage/backend-app-api#loadBackendConfig} instead.
*/
export async function loadBackendConfig(options: {
logger: LoggerService;
@@ -19,8 +19,8 @@ import { ServiceBuilder } from './types';
/**
* Creates a new service builder.
*
* @public
* @deprecated We are going to deprecated this old way of creating services in a near future, if you are using this service helper, please checkout the {@link https://backstage.io/docs/backend-system/building-backends/migrating | backend} and {@link https://backstage.io/docs/backend-system/building-plugins-and-modules/migrating | plugin} migration guides.
*/
export function createServiceBuilder(_module: NodeModule): ServiceBuilder {
return new ServiceBuilderImpl(_module);
+13 -1
View File
@@ -13,7 +13,19 @@ yarn --cwd packages/backend add @backstage/plugin-app-backend app
By adding the app package as a dependency we ensure that it is built as part of the backend, and that it can be resolved at runtime.
Now add the plugin router to your app, creating it for example like this:
Now add the plugin to your app, creating it for example like this:
### New Backend
```ts
import { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
backend.add(import('@backstage/plugin-app-backend/alpha'));
backend.start();
```
### Old Backend
```ts
const router = await createRouter({
@@ -1,5 +1,5 @@
/*
* Copyright 2020 The Backstage Authors
* Copyright 2024 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.
@@ -14,19 +14,14 @@
* limitations under the License.
*/
import { getRootLogger } from '@backstage/backend-common';
import { startStandaloneServer } from './service/standaloneServer';
import { createBackend } from '@backstage/backend-defaults';
import { mockServices } from '@backstage/backend-test-utils';
const logger = getRootLogger();
startStandaloneServer({ logger }).catch(err => {
logger.error(err);
process.exit(1);
});
process.on('SIGINT', () => {
logger.info('CTRL+C pressed; exiting.');
process.exit(0);
});
module.hot?.accept();
const backend = createBackend();
backend.add(
mockServices.rootConfig.factory({
data: { app: { packageName: 'example-app' } },
}),
);
backend.add(import('../src/alpha'));
backend.start();
+1
View File
@@ -66,6 +66,7 @@
},
"devDependencies": {
"@backstage/backend-app-api": "workspace:^",
"@backstage/backend-defaults": "workspace:^",
"@backstage/backend-test-utils": "workspace:^",
"@backstage/cli": "workspace:^",
"@backstage/types": "workspace:^",
@@ -1,51 +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 { Server } from 'http';
import { createServiceBuilder } from '@backstage/backend-common';
import { Config } from '@backstage/config';
import { createRouter } from './router';
import { LoggerService } from '@backstage/backend-plugin-api';
export interface ServerOptions {
port: number;
enableCors: boolean;
config: Config;
logger: LoggerService;
}
export async function startStandaloneServer(
options: ServerOptions,
): Promise<Server> {
const logger = options.logger.child({ service: 'app-backend' });
logger.debug('Starting application server...');
const router = await createRouter({
logger,
config: options.config,
appPackageName: 'example-app',
});
const service = createServiceBuilder(module)
.setPort(options.port)
.addRouter('', router);
return await service.start().catch(err => {
logger.error(err);
process.exit(1);
});
}
module.hot?.accept();
@@ -1,66 +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 {
createServiceBuilder,
loadBackendConfig,
ServerTokenManager,
HostDiscovery,
DatabaseManager,
} from '@backstage/backend-common';
import { Server } from 'http';
import { LoggerService } from '@backstage/backend-plugin-api';
import { createRouter } from './router';
import { ConfigReader } from '@backstage/config';
export interface ServerOptions {
logger: LoggerService;
}
export async function startStandaloneServer(
options: ServerOptions,
): Promise<Server> {
const logger = options.logger.child({ service: 'auth-backend' });
const config = await loadBackendConfig({ logger, argv: process.argv });
const discovery = HostDiscovery.fromConfig(config);
const manager = DatabaseManager.fromConfig(
new ConfigReader({
backend: {
database: { client: 'better-sqlite3', connection: ':memory:' },
},
}),
);
const database = manager.forPlugin('auth');
logger.debug('Starting application server...');
const router = await createRouter({
logger,
config,
database,
discovery,
tokenManager: ServerTokenManager.noop(),
});
const service = createServiceBuilder(module)
.enableCors({ origin: 'http://localhost:3000', credentials: true })
.addRouter('/auth', router);
return await service.start().catch(err => {
logger.error(err);
process.exit(1);
});
}
+21
View File
@@ -0,0 +1,21 @@
/*
* Copyright 2024 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 { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
backend.add(import('../src/alpha'));
backend.start();
+1
View File
@@ -91,6 +91,7 @@
"zod": "^3.22.4"
},
"devDependencies": {
"@backstage/backend-defaults": "workspace:^",
"@backstage/backend-test-utils": "workspace:^",
"@backstage/cli": "workspace:^",
"@backstage/plugin-permission-common": "workspace:^",
-33
View File
@@ -1,33 +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 { getRootLogger } from '@backstage/backend-common';
import yn from 'yn';
import { startStandaloneServer } from './service/standaloneServer';
const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007;
const enableCors = yn(process.env.PLUGIN_CORS, { default: false });
const logger = getRootLogger();
startStandaloneServer({ port, enableCors, logger }).catch(err => {
logger.error(err);
process.exit(1);
});
process.on('SIGINT', () => {
logger.info('CTRL+C pressed; exiting.');
process.exit(0);
});
@@ -1,86 +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 {
createServiceBuilder,
DatabaseManager,
HostDiscovery,
loadBackendConfig,
ServerTokenManager,
UrlReaders,
} from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import { ServerPermissionClient } from '@backstage/plugin-permission-node';
import { Server } from 'http';
import { applyDatabaseMigrations } from '../database/migrations';
import { CatalogBuilder } from './CatalogBuilder';
import { LoggerService } from '@backstage/backend-plugin-api';
export interface ServerOptions {
port: number;
enableCors: boolean;
logger: LoggerService;
}
// TODO(freben): Migrate to the next catalog when it's in place
export async function startStandaloneServer(
options: ServerOptions,
): Promise<Server> {
const logger = options.logger.child({ service: 'catalog-backend' });
const config = await loadBackendConfig({ logger, argv: process.argv });
const reader = UrlReaders.default({ logger, config });
const manager = DatabaseManager.fromConfig(
new ConfigReader({
backend: {
database: { client: 'better-sqlite3', connection: ':memory:' },
},
}),
);
const database = manager.forPlugin('catalog');
const discovery = HostDiscovery.fromConfig(config);
const tokenManager = ServerTokenManager.fromConfig(config, {
logger,
});
const permissions = ServerPermissionClient.fromConfig(config, {
discovery,
tokenManager,
});
logger.debug('Creating application...');
await applyDatabaseMigrations(await database.getClient());
const builder = CatalogBuilder.create({
logger,
database,
config,
reader,
permissions,
});
const catalog = await builder.build();
logger.debug('Starting application server...');
let service = createServiceBuilder(module)
.setPort(options.port)
.addRouter('/catalog', catalog.router);
if (options.enableCors) {
service = service.enableCors({ origin: 'http://localhost:3000' });
}
return await service.start().catch(err => {
logger.error(err);
process.exit(1);
});
}
module.hot?.accept();
+21
View File
@@ -0,0 +1,21 @@
/*
* Copyright 2024 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 { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
backend.add(import('../src'));
backend.start();
+1
View File
@@ -52,6 +52,7 @@
"yn": "^4.0.0"
},
"devDependencies": {
"@backstage/backend-defaults": "workspace:^",
"@backstage/backend-test-utils": "workspace:^",
"@backstage/cli": "workspace:^",
"@types/ping": "^0.4.1",
-33
View File
@@ -1,33 +0,0 @@
/*
* 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 { getRootLogger } from '@backstage/backend-common';
import yn from 'yn';
import { startStandaloneServer } from './service/standaloneServer';
const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007;
const enableCors = yn(process.env.PLUGIN_CORS, { default: false });
const logger = getRootLogger();
startStandaloneServer({ port, enableCors, logger }).catch(err => {
logger.error(err);
process.exit(1);
});
process.on('SIGINT', () => {
logger.info('CTRL+C pressed; exiting.');
process.exit(0);
});
@@ -1,69 +0,0 @@
/*
* 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 {
createServiceBuilder,
HostDiscovery,
loadBackendConfig,
ServerTokenManager,
} from '@backstage/backend-common';
import { Server } from 'http';
import { ServerPermissionClient } from '@backstage/plugin-permission-node';
import { createRouter } from './router';
import { LoggerService } from '@backstage/backend-plugin-api';
export interface ServerOptions {
port: number;
enableCors: boolean;
logger: LoggerService;
}
export async function startStandaloneServer(
options: ServerOptions,
): Promise<Server> {
const logger = options.logger.child({ service: 'devtools-backend-backend' });
const config = await loadBackendConfig({ logger, argv: process.argv });
const discovery = HostDiscovery.fromConfig(config);
const tokenManager = ServerTokenManager.fromConfig(config, {
logger,
});
const permissions = ServerPermissionClient.fromConfig(config, {
discovery,
tokenManager,
});
logger.debug('Starting application server...');
const router = await createRouter({
logger,
config,
permissions,
discovery,
});
let service = createServiceBuilder(module)
.setPort(options.port)
.addRouter('/devtools-backend', router);
if (options.enableCors) {
service = service.enableCors({ origin: 'http://localhost:3000' });
}
return await service.start().catch(err => {
logger.error(err);
process.exit(1);
});
}
module.hot?.accept();
@@ -0,0 +1,21 @@
/*
* Copyright 2024 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 { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
backend.add(import('../src'));
backend.start();
@@ -43,6 +43,7 @@
"yn": "^4.0.0"
},
"devDependencies": {
"@backstage/backend-defaults": "workspace:^",
"@backstage/cli": "workspace:^",
"@types/supertest": "^2.0.8",
"@types/uuid": "^9.0.0",
@@ -1,33 +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 { getRootLogger } from '@backstage/backend-common';
import yn from 'yn';
import { startStandaloneServer } from './service/standaloneServer';
const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007;
const enableCors = yn(process.env.PLUGIN_CORS, { default: false });
const logger = getRootLogger();
startStandaloneServer({ port, enableCors, logger }).catch(err => {
logger.error(err);
process.exit(1);
});
process.on('SIGINT', () => {
logger.info('CTRL+C pressed; exiting.');
process.exit(0);
});
@@ -1,61 +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 {
createServiceBuilder,
HostDiscovery,
loadBackendConfig,
} from '@backstage/backend-common';
import { DefaultIdentityClient } from '@backstage/plugin-auth-node';
import { Server } from 'http';
import { createRouter } from './router';
import { LoggerService } from '@backstage/backend-plugin-api';
export interface ServerOptions {
port: number;
enableCors: boolean;
logger: LoggerService;
}
export async function startStandaloneServer(
options: ServerOptions,
): Promise<Server> {
const logger = options.logger.child({ service: 'todo-list-backend' });
logger.debug('Starting application server...');
const config = await loadBackendConfig({ logger, argv: process.argv });
const discovery = HostDiscovery.fromConfig(config);
const router = await createRouter({
logger,
identity: DefaultIdentityClient.create({
discovery,
issuer: await discovery.getExternalBaseUrl('auth'),
}),
});
let service = createServiceBuilder(module)
.setPort(options.port)
.addRouter('/todo-list', router);
if (options.enableCors) {
service = service.enableCors({ origin: 'http://localhost:3000' });
}
return await service.start().catch(err => {
logger.error(err);
process.exit(1);
});
}
module.hot?.accept();
+21
View File
@@ -0,0 +1,21 @@
/*
* Copyright 2024 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 { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
backend.add(import('../src/alpha'));
backend.start();
-33
View File
@@ -1,33 +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 { getRootLogger } from '@backstage/backend-common';
import yn from 'yn';
import { startStandaloneServer } from './service/standaloneServer';
const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007;
const enableCors = yn(process.env.PLUGIN_CORS, { default: false });
const logger = getRootLogger();
startStandaloneServer({ port, enableCors, logger }).catch(err => {
logger.error(err);
process.exit(1);
});
process.on('SIGINT', () => {
logger.info('CTRL+C pressed; exiting.');
process.exit(0);
});
@@ -1,61 +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 {
createServiceBuilder,
loadBackendConfig,
HostDiscovery,
} from '@backstage/backend-common';
import { Server } from 'http';
import { Logger } from 'winston';
import { createRouter } from './router';
export interface ServerOptions {
port: number;
enableCors: boolean;
logger: Logger;
}
export async function startStandaloneServer(
options: ServerOptions,
): Promise<Server> {
const logger = options.logger.child({ service: 'proxy-backend' });
logger.debug('Creating application...');
const config = await loadBackendConfig({ logger, argv: process.argv });
const discovery = HostDiscovery.fromConfig(config);
const router = await createRouter({
config,
logger,
discovery,
});
let service = createServiceBuilder(module)
.setPort(options.port)
.addRouter('/proxy', router);
if (options.enableCors) {
service = service.enableCors({ origin: 'http://localhost:3000' });
}
logger.debug('Starting application server...');
return await service.start().catch(err => {
logger.error(err);
process.exit(1);
});
}
module.hot?.accept();
@@ -14,20 +14,8 @@
* limitations under the License.
*/
import { getRootLogger } from '@backstage/backend-common';
import yn from 'yn';
import { startStandaloneServer } from './service/standaloneServer';
import { createBackend } from '@backstage/backend-defaults';
const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007;
const enableCors = yn(process.env.PLUGIN_CORS, { default: false });
const logger = getRootLogger();
startStandaloneServer({ port, enableCors, logger }).catch(err => {
logger.error(err);
process.exit(1);
});
process.on('SIGINT', () => {
logger.info('CTRL+C pressed; exiting.');
process.exit(0);
});
const backend = createBackend();
backend.add(import('../src/alpha'));
backend.start();
+1
View File
@@ -49,6 +49,7 @@
},
"dependencies": {
"@backstage/backend-common": "workspace:^",
"@backstage/backend-defaults": "workspace:^",
"@backstage/backend-openapi-utils": "workspace:^",
"@backstage/backend-plugin-api": "workspace:^",
"@backstage/config": "workspace:^",
@@ -1,79 +0,0 @@
/*
* Copyright 2021 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 {
createServiceBuilder,
loadBackendConfig,
ServerTokenManager,
HostDiscovery,
} from '@backstage/backend-common';
import { Server } from 'http';
import { Logger } from 'winston';
import { createRouter } from './router';
import {
LunrSearchEngine,
IndexBuilder,
} from '@backstage/plugin-search-backend-node';
import { ServerPermissionClient } from '@backstage/plugin-permission-node';
export interface ServerOptions {
port: number;
enableCors: boolean;
logger: Logger;
}
export async function startStandaloneServer(
options: ServerOptions,
): Promise<Server> {
const logger = options.logger.child({ service: 'search-backend' });
const config = await loadBackendConfig({ logger, argv: process.argv });
const searchEngine = new LunrSearchEngine({ logger });
const indexBuilder = new IndexBuilder({ logger, searchEngine });
const discovery = HostDiscovery.fromConfig(config);
const tokenManager = ServerTokenManager.fromConfig(config, {
logger,
});
const permissions = ServerPermissionClient.fromConfig(config, {
discovery,
tokenManager,
});
logger.debug('Starting application server...');
// TODO: stub out some documents/indices?
const router = await createRouter({
engine: indexBuilder.getSearchEngine(),
types: indexBuilder.getDocumentTypes(),
discovery,
permissions,
config,
logger,
});
let service = createServiceBuilder(module)
.setPort(options.port)
.addRouter('/search', router);
if (options.enableCors) {
service = service.enableCors({ origin: 'http://localhost:3000' });
}
return await service.start().catch(err => {
logger.error(err);
process.exit(1);
});
}
module.hot?.accept();
+21
View File
@@ -0,0 +1,21 @@
/*
* Copyright 2024 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 { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
backend.add(import('../src/alpha'));
backend.start();
+1
View File
@@ -73,6 +73,7 @@
"winston": "^3.2.1"
},
"devDependencies": {
"@backstage/backend-defaults": "workspace:^",
"@backstage/backend-test-utils": "workspace:^",
"@backstage/cli": "workspace:^",
"@types/dockerode": "^3.3.0",
@@ -1,105 +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 {
CacheManager,
createServiceBuilder,
DockerContainerRunner,
HostDiscovery,
UrlReader,
} from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import {
DirectoryPreparer,
Generators,
Preparers,
Publisher,
TechdocsGenerator,
} from '@backstage/plugin-techdocs-node';
import Docker from 'dockerode';
import { Server } from 'http';
import { Logger } from 'winston';
import { createRouter } from './router';
export interface ServerOptions {
port: number;
enableCors: boolean;
logger: Logger;
}
export async function startStandaloneServer(
options: ServerOptions,
): Promise<Server> {
const logger = options.logger.child({ service: 'techdocs-backend' });
const config = new ConfigReader({
techdocs: {
publisher: {
type: 'local',
},
},
});
const discovery = HostDiscovery.fromConfig(config);
const mockUrlReader: jest.Mocked<UrlReader> = {
readUrl: jest.fn(),
readTree: jest.fn(),
search: jest.fn(),
};
logger.debug('Creating application...');
const preparers = new Preparers();
const directoryPreparer = DirectoryPreparer.fromConfig(config, {
logger,
reader: mockUrlReader,
});
preparers.register('dir', directoryPreparer);
const dockerClient = new Docker();
const containerRunner = new DockerContainerRunner({ dockerClient });
const generators = new Generators();
const techdocsGenerator = TechdocsGenerator.fromConfig(config, {
logger,
containerRunner,
});
generators.register('techdocs', techdocsGenerator);
const publisher = await Publisher.fromConfig(config, { logger, discovery });
const cache = CacheManager.fromConfig(config).forPlugin('techdocs');
logger.debug('Starting application server...');
const router = await createRouter({
preparers,
generators,
logger,
publisher,
config,
discovery,
cache,
});
let service = createServiceBuilder(module)
.setPort(options.port)
.addRouter('/techdocs', router);
if (options.enableCors) {
service = service.enableCors({ origin: 'http://localhost:3000' });
}
return await service.start().catch(err => {
logger.error(err);
process.exit(1);
});
}
module.hot?.accept();
@@ -0,0 +1,23 @@
/*
* Copyright 2024 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 { createBackend } from '@backstage/backend-defaults';
import { mockServices } from '@backstage/backend-test-utils';
const backend = createBackend();
backend.add(mockServices.identity.factory());
backend.add(import('../src/alpha'));
backend.start();
@@ -60,6 +60,7 @@
"yn": "^4.0.0"
},
"devDependencies": {
"@backstage/backend-defaults": "workspace:^",
"@backstage/backend-test-utils": "workspace:^",
"@backstage/cli": "workspace:^",
"@types/supertest": "^2.0.8",
-34
View File
@@ -1,34 +0,0 @@
/*
* 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 { getRootLogger } from '@backstage/backend-common';
import yn from 'yn';
import { startStandaloneServer } from './service/standaloneServer';
const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007;
const enableCors = yn(process.env.PLUGIN_CORS, { default: false });
const logger = getRootLogger();
startStandaloneServer({ port, enableCors, logger }).catch(err => {
logger.error(err);
process.exit(1);
});
process.on('SIGINT', () => {
logger.info('CTRL+C pressed; exiting.');
process.exit(0);
});
@@ -1,83 +0,0 @@
/*
* 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 {
createServiceBuilder,
DatabaseManager,
} from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import { IdentityApi } from '@backstage/plugin-auth-node';
import { Server } from 'http';
import { Logger } from 'winston';
import { DatabaseUserSettingsStore } from '../database/DatabaseUserSettingsStore';
import { createRouterInternal } from './router';
export interface ServerOptions {
port: number;
enableCors: boolean;
logger: Logger;
}
export async function startStandaloneServer(
options: ServerOptions,
): Promise<Server> {
const logger = options.logger.child({ service: 'storage-backend' });
const manager = DatabaseManager.fromConfig(
new ConfigReader({
backend: {
database: { client: 'better-sqlite3', connection: ':memory:' },
},
}),
);
const database = manager.forPlugin('user-settings');
logger.debug('Starting application server...');
const identityMock: IdentityApi = {
async getIdentity({ request }) {
const token = request.headers.authorization?.split(' ')[1];
return {
identity: {
type: 'user',
ownershipEntityRefs: [],
userEntityRef: token || 'user:default/john_doe',
},
token: token || 'no-token',
};
},
};
const router = await createRouterInternal({
userSettingsStore: await DatabaseUserSettingsStore.create({ database }),
identity: identityMock,
});
let service = createServiceBuilder(module)
.setPort(options.port)
.addRouter('/user-settings', router);
if (options.enableCors) {
service = service.enableCors({ origin: 'http://localhost:3000' });
}
return await service.start().catch(err => {
logger.error(err);
process.exit(1);
});
}
module.hot?.accept();
+7
View File
@@ -4365,6 +4365,7 @@ __metadata:
dependencies:
"@backstage/backend-app-api": "workspace:^"
"@backstage/backend-common": "workspace:^"
"@backstage/backend-defaults": "workspace:^"
"@backstage/backend-plugin-api": "workspace:^"
"@backstage/backend-test-utils": "workspace:^"
"@backstage/cli": "workspace:^"
@@ -5282,6 +5283,7 @@ __metadata:
resolution: "@backstage/plugin-catalog-backend@workspace:plugins/catalog-backend"
dependencies:
"@backstage/backend-common": "workspace:^"
"@backstage/backend-defaults": "workspace:^"
"@backstage/backend-openapi-utils": "workspace:^"
"@backstage/backend-plugin-api": "workspace:^"
"@backstage/backend-tasks": "workspace:^"
@@ -5601,6 +5603,7 @@ __metadata:
resolution: "@backstage/plugin-devtools-backend@workspace:plugins/devtools-backend"
dependencies:
"@backstage/backend-common": "workspace:^"
"@backstage/backend-defaults": "workspace:^"
"@backstage/backend-plugin-api": "workspace:^"
"@backstage/backend-test-utils": "workspace:^"
"@backstage/cli": "workspace:^"
@@ -7035,6 +7038,7 @@ __metadata:
resolution: "@backstage/plugin-search-backend@workspace:plugins/search-backend"
dependencies:
"@backstage/backend-common": "workspace:^"
"@backstage/backend-defaults": "workspace:^"
"@backstage/backend-openapi-utils": "workspace:^"
"@backstage/backend-plugin-api": "workspace:^"
"@backstage/backend-test-utils": "workspace:^"
@@ -7264,6 +7268,7 @@ __metadata:
resolution: "@backstage/plugin-techdocs-backend@workspace:plugins/techdocs-backend"
dependencies:
"@backstage/backend-common": "workspace:^"
"@backstage/backend-defaults": "workspace:^"
"@backstage/backend-plugin-api": "workspace:^"
"@backstage/backend-test-utils": "workspace:^"
"@backstage/catalog-client": "workspace:^"
@@ -7447,6 +7452,7 @@ __metadata:
resolution: "@backstage/plugin-user-settings-backend@workspace:plugins/user-settings-backend"
dependencies:
"@backstage/backend-common": "workspace:^"
"@backstage/backend-defaults": "workspace:^"
"@backstage/backend-plugin-api": "workspace:^"
"@backstage/backend-test-utils": "workspace:^"
"@backstage/cli": "workspace:^"
@@ -9501,6 +9507,7 @@ __metadata:
resolution: "@internal/plugin-todo-list-backend@workspace:plugins/example-todo-list-backend"
dependencies:
"@backstage/backend-common": "workspace:^"
"@backstage/backend-defaults": "workspace:^"
"@backstage/backend-plugin-api": "workspace:^"
"@backstage/cli": "workspace:^"
"@backstage/errors": "workspace:^"