Merge pull request #12484 from backstage/mob/backend-system
Alpha Backend Framework 🚀
This commit is contained in:
@@ -0,0 +1 @@
|
||||
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
|
||||
@@ -0,0 +1,19 @@
|
||||
# @backstage/backend-app-api
|
||||
|
||||
**This package is HIGHLY EXPERIMENTAL, do not use this for production**
|
||||
|
||||
This package provides the core API used by Backstage backend apps.
|
||||
|
||||
## Installation
|
||||
|
||||
Add the library to your backend app package:
|
||||
|
||||
```bash
|
||||
# From your Backstage root directory
|
||||
yarn add --cwd packages/backend @backstage/backend-app-api
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md)
|
||||
- [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md)
|
||||
@@ -0,0 +1,25 @@
|
||||
## API Report File for "@backstage/backend-app-api"
|
||||
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
import { AnyServiceFactory } from '@backstage/backend-plugin-api';
|
||||
import { BackendRegistrable } from '@backstage/backend-plugin-api';
|
||||
|
||||
// @public (undocumented)
|
||||
export interface Backend {
|
||||
// (undocumented)
|
||||
add(extension: BackendRegistrable): void;
|
||||
// (undocumented)
|
||||
start(): Promise<void>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export function createBackend(options?: CreateBackendOptions): Backend;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface CreateBackendOptions {
|
||||
// (undocumented)
|
||||
apis: AnyServiceFactory[];
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"name": "@backstage/backend-app-api",
|
||||
"description": "Core API used by Backstage backend apps",
|
||||
"version": "0.0.0",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"main": "dist/index.cjs.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"alphaTypes": "dist/index.alpha.d.ts"
|
||||
},
|
||||
"backstage": {
|
||||
"role": "node-library"
|
||||
},
|
||||
"homepage": "https://backstage.io",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/backstage/backstage",
|
||||
"directory": "packages/backend-app-api"
|
||||
},
|
||||
"keywords": [
|
||||
"backstage"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"build": "backstage-cli package build --experimental-type-build",
|
||||
"lint": "backstage-cli package lint",
|
||||
"test": "backstage-cli package test",
|
||||
"prepack": "backstage-cli package prepack",
|
||||
"postpack": "backstage-cli package postpack",
|
||||
"clean": "backstage-cli package clean",
|
||||
"start": "backstage-cli package start"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/backend-plugin-api": "^0.0.0",
|
||||
"@backstage/backend-common": "^0.14.1-next.2",
|
||||
"@backstage/backend-tasks": "^0.3.3-next.2",
|
||||
"@backstage/plugin-permission-node": "^0.6.3-next.1",
|
||||
"express": "^4.17.1",
|
||||
"express-promise-router": "^4.1.0",
|
||||
"winston": "^3.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.18.0-next.2"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"alpha"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Core API used by Backstage backend apps.
|
||||
*
|
||||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
export * from './wiring';
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 { CacheManager } from '@backstage/backend-common';
|
||||
import {
|
||||
configServiceRef,
|
||||
createServiceFactory,
|
||||
cacheServiceRef,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
// TODO: Work out some naming and implementation patterns for these
|
||||
export const cacheFactory = createServiceFactory({
|
||||
service: cacheServiceRef,
|
||||
deps: {
|
||||
configFactory: configServiceRef,
|
||||
},
|
||||
factory: async ({ configFactory }) => {
|
||||
const config = await configFactory('root');
|
||||
const cacheManager = CacheManager.fromConfig(config);
|
||||
return async (pluginId: string) => {
|
||||
return cacheManager.forPlugin(pluginId);
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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 { loadBackendConfig } from '@backstage/backend-common';
|
||||
import {
|
||||
configServiceRef,
|
||||
createServiceFactory,
|
||||
loggerToWinstonLogger,
|
||||
loggerServiceRef,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
export const configFactory = createServiceFactory({
|
||||
service: configServiceRef,
|
||||
deps: {
|
||||
loggerFactory: loggerServiceRef,
|
||||
},
|
||||
factory: async ({ loggerFactory }) => {
|
||||
const logger = await loggerFactory('root');
|
||||
const config = await loadBackendConfig({
|
||||
argv: process.argv,
|
||||
logger: loggerToWinstonLogger(logger),
|
||||
});
|
||||
return async () => {
|
||||
return config;
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 { DatabaseManager } from '@backstage/backend-common';
|
||||
import {
|
||||
configServiceRef,
|
||||
createServiceFactory,
|
||||
databaseServiceRef,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
export const databaseFactory = createServiceFactory({
|
||||
service: databaseServiceRef,
|
||||
deps: {
|
||||
configFactory: configServiceRef,
|
||||
},
|
||||
factory: async ({ configFactory }) => {
|
||||
const config = await configFactory('root');
|
||||
const databaseManager = DatabaseManager.fromConfig(config);
|
||||
return async (pluginId: string) => {
|
||||
return databaseManager.forPlugin(pluginId);
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 { SingleHostDiscovery } from '@backstage/backend-common';
|
||||
import {
|
||||
configServiceRef,
|
||||
createServiceFactory,
|
||||
discoveryServiceRef,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
export const discoveryFactory = createServiceFactory({
|
||||
service: discoveryServiceRef,
|
||||
deps: {
|
||||
configFactory: configServiceRef,
|
||||
},
|
||||
factory: async ({ configFactory }) => {
|
||||
const config = await configFactory('root');
|
||||
const discovery = SingleHostDiscovery.fromConfig(config);
|
||||
return async () => {
|
||||
return discovery;
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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 {
|
||||
createServiceFactory,
|
||||
httpRouterServiceRef,
|
||||
configServiceRef,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import Router from 'express-promise-router';
|
||||
import { Handler } from 'express';
|
||||
import { createServiceBuilder } from '@backstage/backend-common';
|
||||
|
||||
export const httpRouterFactory = createServiceFactory({
|
||||
service: httpRouterServiceRef,
|
||||
deps: {
|
||||
configFactory: configServiceRef,
|
||||
},
|
||||
factory: async ({ configFactory }) => {
|
||||
const rootRouter = Router();
|
||||
|
||||
const service = createServiceBuilder(module)
|
||||
.loadConfig(await configFactory('root'))
|
||||
.addRouter('', rootRouter);
|
||||
|
||||
await service.start();
|
||||
|
||||
return async (pluginId?: string) => {
|
||||
const path = pluginId ? `/api/${pluginId}` : '';
|
||||
return {
|
||||
use(handler: Handler) {
|
||||
rootRouter.use(path, handler);
|
||||
},
|
||||
};
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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 { cacheFactory } from './cacheService';
|
||||
import { configFactory } from './configService';
|
||||
import { databaseFactory } from './databaseService';
|
||||
import { discoveryFactory } from './discoveryService';
|
||||
import { loggerFactory } from './loggerService';
|
||||
import { permissionsFactory } from './permissionsService';
|
||||
import { schedulerFactory } from './schedulerService';
|
||||
import { tokenManagerFactory } from './tokenManagerService';
|
||||
import { urlReaderFactory } from './urlReaderService';
|
||||
import { httpRouterFactory } from './httpRouterService';
|
||||
|
||||
export const defaultServiceFactories = [
|
||||
cacheFactory,
|
||||
configFactory,
|
||||
databaseFactory,
|
||||
discoveryFactory,
|
||||
loggerFactory,
|
||||
permissionsFactory,
|
||||
schedulerFactory,
|
||||
tokenManagerFactory,
|
||||
urlReaderFactory,
|
||||
httpRouterFactory,
|
||||
];
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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 { createRootLogger } from '@backstage/backend-common';
|
||||
import {
|
||||
createServiceFactory,
|
||||
Logger,
|
||||
loggerServiceRef,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { Logger as WinstonLogger } from 'winston';
|
||||
|
||||
class BackstageLogger implements Logger {
|
||||
static fromWinston(logger: WinstonLogger): BackstageLogger {
|
||||
return new BackstageLogger(logger);
|
||||
}
|
||||
|
||||
private constructor(private readonly winston: WinstonLogger) {}
|
||||
|
||||
info(message: string, ...meta: any[]): void {
|
||||
this.winston.info(message, ...meta);
|
||||
}
|
||||
|
||||
child(fields: { [name: string]: string }): Logger {
|
||||
return new BackstageLogger(this.winston.child(fields));
|
||||
}
|
||||
}
|
||||
|
||||
export const loggerFactory = createServiceFactory({
|
||||
service: loggerServiceRef,
|
||||
deps: {},
|
||||
factory: async () => {
|
||||
const root = BackstageLogger.fromWinston(createRootLogger());
|
||||
return async (pluginId: string) => {
|
||||
return root.child({ pluginId });
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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 {
|
||||
configServiceRef,
|
||||
createServiceFactory,
|
||||
discoveryServiceRef,
|
||||
permissionsServiceRef,
|
||||
tokenManagerServiceRef,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { ServerPermissionClient } from '@backstage/plugin-permission-node';
|
||||
|
||||
export const permissionsFactory = createServiceFactory({
|
||||
service: permissionsServiceRef,
|
||||
deps: {
|
||||
configFactory: configServiceRef,
|
||||
discoveryFactory: discoveryServiceRef,
|
||||
tokenManagerFactory: tokenManagerServiceRef,
|
||||
},
|
||||
factory: async ({ configFactory, discoveryFactory, tokenManagerFactory }) => {
|
||||
const config = await configFactory('root');
|
||||
const discovery = await discoveryFactory('root');
|
||||
const tokenManager = await tokenManagerFactory('root');
|
||||
const permissions = ServerPermissionClient.fromConfig(config, {
|
||||
discovery,
|
||||
tokenManager,
|
||||
});
|
||||
return async (_pluginId: string) => {
|
||||
return permissions;
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 {
|
||||
configServiceRef,
|
||||
createServiceFactory,
|
||||
schedulerServiceRef,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { TaskScheduler } from '@backstage/backend-tasks';
|
||||
|
||||
export const schedulerFactory = createServiceFactory({
|
||||
service: schedulerServiceRef,
|
||||
deps: {
|
||||
configFactory: configServiceRef,
|
||||
},
|
||||
factory: async ({ configFactory }) => {
|
||||
const config = await configFactory('root');
|
||||
const taskScheduler = TaskScheduler.fromConfig(config);
|
||||
return async (pluginId: string) => {
|
||||
return taskScheduler.forPlugin(pluginId);
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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 {
|
||||
configServiceRef,
|
||||
loggerServiceRef,
|
||||
createServiceFactory,
|
||||
tokenManagerServiceRef,
|
||||
loggerToWinstonLogger,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { ServerTokenManager } from '@backstage/backend-common';
|
||||
|
||||
export const tokenManagerFactory = createServiceFactory({
|
||||
service: tokenManagerServiceRef,
|
||||
deps: {
|
||||
configFactory: configServiceRef,
|
||||
loggerFactory: loggerServiceRef,
|
||||
},
|
||||
factory: async ({ configFactory, loggerFactory }) => {
|
||||
const logger = await loggerFactory('root');
|
||||
const config = await configFactory('root');
|
||||
return async (_pluginId: string) => {
|
||||
// doesn't the logger want to be inferred from the plugin tho here?
|
||||
// maybe ... also why do we recreate it every time otherwise
|
||||
// we should memoize on a per plugin right? so I think it's should be fine to re-use the plugin one
|
||||
// we shouldn't recreate on a per plugin basis.
|
||||
// hm - on the other hand, is this really ever called more than once?
|
||||
// not this function right. should only be called when the plugin requests this serviceRef
|
||||
// yeah so no need to worry about memo probably
|
||||
// but we still want to scope the logger to the ServrTokenmanagfer>?
|
||||
// mm sure maybe
|
||||
// maybe in this case it doesn't provide so much value b
|
||||
// oh hang on - isn't it up to THE MANAGER to make a child internally if it wants to do that
|
||||
// so that it becomes a property intrinsic to that class, no matter how it's constructed
|
||||
// or is that too much responsibility for it - making the constructor complex so to speak, making it harder to tweak that behavior
|
||||
// this is not ultra efficient :)
|
||||
|
||||
// I think the naming here is wrong to be gonest
|
||||
// this isn't like the cache manager or the database manager
|
||||
// the manager name is confusuion i think
|
||||
// aye perhaps
|
||||
return ServerTokenManager.fromConfig(config, {
|
||||
logger: loggerToWinstonLogger(logger),
|
||||
});
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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 { UrlReaders } from '@backstage/backend-common';
|
||||
import {
|
||||
configServiceRef,
|
||||
createServiceFactory,
|
||||
loggerServiceRef,
|
||||
loggerToWinstonLogger,
|
||||
urlReaderServiceRef,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
export const urlReaderFactory = createServiceFactory({
|
||||
service: urlReaderServiceRef,
|
||||
deps: {
|
||||
configFactory: configServiceRef,
|
||||
loggerFactory: loggerServiceRef,
|
||||
},
|
||||
factory: async ({ configFactory, loggerFactory }) => {
|
||||
return async (pluginId: string) => {
|
||||
const logger = await loggerFactory(pluginId);
|
||||
return UrlReaders.default({
|
||||
logger: loggerToWinstonLogger(logger),
|
||||
config: await configFactory(pluginId),
|
||||
});
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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 {
|
||||
BackendRegistrable,
|
||||
ExtensionPoint,
|
||||
ServiceRef,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { BackendRegisterInit, ServiceHolder } from './types';
|
||||
|
||||
type ServiceOrExtensionPoint = ExtensionPoint<unknown> | ServiceRef<unknown>;
|
||||
|
||||
export class BackendInitializer {
|
||||
#started = false;
|
||||
#extensions = new Map<BackendRegistrable, unknown>();
|
||||
#registerInits = new Array<BackendRegisterInit>();
|
||||
#extensionPoints = new Map<ServiceOrExtensionPoint, unknown>();
|
||||
#serviceHolder: ServiceHolder;
|
||||
|
||||
constructor(serviceHolder: ServiceHolder) {
|
||||
this.#serviceHolder = serviceHolder;
|
||||
}
|
||||
|
||||
async #getInitDeps(
|
||||
deps: { [name: string]: ServiceOrExtensionPoint },
|
||||
pluginId: string,
|
||||
) {
|
||||
return Object.fromEntries(
|
||||
await Promise.all(
|
||||
Object.entries(deps).map(async ([name, ref]) => [
|
||||
name,
|
||||
this.#extensionPoints.get(ref) ||
|
||||
(await this.#serviceHolder.get(ref as ServiceRef<unknown>)!(
|
||||
pluginId,
|
||||
)),
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
add<TOptions>(extension: BackendRegistrable, options?: TOptions) {
|
||||
if (this.#started) {
|
||||
throw new Error(
|
||||
'extension can not be added after the backend has started',
|
||||
);
|
||||
}
|
||||
this.#extensions.set(extension, options);
|
||||
}
|
||||
|
||||
async start(): Promise<void> {
|
||||
console.log(`Starting backend`);
|
||||
if (this.#started) {
|
||||
throw new Error('Backend has already started');
|
||||
}
|
||||
this.#started = true;
|
||||
|
||||
for (const [extension] of this.#extensions) {
|
||||
const provides = new Set<ServiceRef<unknown>>();
|
||||
|
||||
let registerInit: BackendRegisterInit | undefined = undefined;
|
||||
|
||||
console.log('Registering', extension.id);
|
||||
extension.register({
|
||||
registerExtensionPoint: (extensionPointRef, impl) => {
|
||||
if (registerInit) {
|
||||
throw new Error('registerExtensionPoint called after registerInit');
|
||||
}
|
||||
if (this.#extensionPoints.has(extensionPointRef)) {
|
||||
throw new Error(`API ${extensionPointRef.id} already registered`);
|
||||
}
|
||||
this.#extensionPoints.set(extensionPointRef, impl);
|
||||
provides.add(extensionPointRef);
|
||||
},
|
||||
registerInit: registerOptions => {
|
||||
if (registerInit) {
|
||||
throw new Error('registerInit must only be called once');
|
||||
}
|
||||
registerInit = {
|
||||
id: extension.id,
|
||||
provides,
|
||||
consumes: new Set(Object.values(registerOptions.deps)),
|
||||
deps: registerOptions.deps,
|
||||
init: registerOptions.init as BackendRegisterInit['init'],
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
if (!registerInit) {
|
||||
throw new Error(
|
||||
`registerInit was not called by register in ${extension.id}`,
|
||||
);
|
||||
}
|
||||
|
||||
this.#registerInits.push(registerInit);
|
||||
}
|
||||
|
||||
this.validateSetup();
|
||||
|
||||
const orderedRegisterResults = this.#resolveInitOrder(this.#registerInits);
|
||||
|
||||
for (const registerInit of orderedRegisterResults) {
|
||||
const deps = await this.#getInitDeps(registerInit.deps, registerInit.id);
|
||||
await registerInit.init(deps);
|
||||
}
|
||||
}
|
||||
|
||||
private validateSetup() {}
|
||||
|
||||
#resolveInitOrder(registerInits: Array<BackendRegisterInit>) {
|
||||
let registerInitsToOrder = registerInits.slice();
|
||||
const orderedRegisterInits = new Array<BackendRegisterInit>();
|
||||
|
||||
// TODO: Validate duplicates
|
||||
|
||||
while (registerInitsToOrder.length > 0) {
|
||||
const toRemove = new Set<unknown>();
|
||||
|
||||
for (const registerInit of registerInitsToOrder) {
|
||||
const unInitializedDependents = [];
|
||||
|
||||
for (const serviceRef of registerInit.provides) {
|
||||
if (
|
||||
registerInitsToOrder.some(
|
||||
init => init !== registerInit && init.consumes.has(serviceRef),
|
||||
)
|
||||
) {
|
||||
unInitializedDependents.push(serviceRef);
|
||||
}
|
||||
}
|
||||
|
||||
if (unInitializedDependents.length === 0) {
|
||||
console.log(`DEBUG: pushed ${registerInit.id} to results`);
|
||||
orderedRegisterInits.push(registerInit);
|
||||
toRemove.add(registerInit);
|
||||
}
|
||||
}
|
||||
|
||||
registerInitsToOrder = registerInitsToOrder.filter(r => !toRemove.has(r));
|
||||
}
|
||||
return orderedRegisterInits;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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 {
|
||||
AnyServiceFactory,
|
||||
BackendRegistrable,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { BackendInitializer } from './BackendInitializer';
|
||||
import { ServiceRegistry } from './ServiceRegistry';
|
||||
import { Backend } from './types';
|
||||
|
||||
export class BackstageBackend implements Backend {
|
||||
#services: ServiceRegistry;
|
||||
#initializer: BackendInitializer;
|
||||
|
||||
constructor(apiFactories: AnyServiceFactory[]) {
|
||||
this.#services = new ServiceRegistry(apiFactories);
|
||||
this.#initializer = new BackendInitializer(this.#services);
|
||||
}
|
||||
|
||||
add(extension: BackendRegistrable): void {
|
||||
this.#initializer.add(extension);
|
||||
}
|
||||
|
||||
async start(): Promise<void> {
|
||||
await this.#initializer.start();
|
||||
}
|
||||
|
||||
// async stop(): Promise<void> {
|
||||
// await this.#initializer.stop();
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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 {
|
||||
AnyServiceFactory,
|
||||
FactoryFunc,
|
||||
ServiceRef,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
|
||||
export class ServiceRegistry {
|
||||
readonly #implementations: Map<string, Map<string, unknown>>;
|
||||
readonly #factories: Map<string, AnyServiceFactory>;
|
||||
|
||||
constructor(factories: AnyServiceFactory[]) {
|
||||
this.#factories = new Map(factories.map(f => [f.service.id, f]));
|
||||
this.#implementations = new Map();
|
||||
}
|
||||
|
||||
get<T>(ref: ServiceRef<T>): FactoryFunc<T> | undefined {
|
||||
const factory = this.#factories.get(ref.id);
|
||||
if (!factory) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return async (pluginId: string): Promise<T> => {
|
||||
let implementations = this.#implementations.get(ref.id);
|
||||
if (implementations) {
|
||||
if (implementations.has(pluginId)) {
|
||||
return implementations.get(pluginId) as T;
|
||||
}
|
||||
} else {
|
||||
implementations = new Map();
|
||||
this.#implementations.set(ref.id, implementations);
|
||||
}
|
||||
|
||||
const factoryDeps = Object.fromEntries(
|
||||
Object.entries(factory.deps).map(([name, serviceRef]) => [
|
||||
name,
|
||||
this.get(serviceRef)!, // TODO: throw
|
||||
]),
|
||||
);
|
||||
|
||||
const factoryFunc = await factory.factory(factoryDeps);
|
||||
const implementation = await factoryFunc(pluginId);
|
||||
|
||||
implementations.set(pluginId, implementation);
|
||||
|
||||
return implementation as T;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export type { Backend, CreateBackendOptions } from './types';
|
||||
export { createBackend } from './types';
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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 {
|
||||
AnyServiceFactory,
|
||||
BackendRegistrable,
|
||||
FactoryFunc,
|
||||
ServiceRef,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { defaultServiceFactories } from '../services/implementations';
|
||||
import { BackstageBackend } from './BackstageBackend';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface Backend {
|
||||
add(extension: BackendRegistrable): void;
|
||||
start(): Promise<void>;
|
||||
}
|
||||
|
||||
export interface BackendRegisterInit {
|
||||
id: string;
|
||||
consumes: Set<ServiceRef<unknown>>;
|
||||
provides: Set<ServiceRef<unknown>>;
|
||||
deps: { [name: string]: ServiceRef<unknown> };
|
||||
init: (deps: { [name: string]: unknown }) => Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface CreateBackendOptions {
|
||||
apis: AnyServiceFactory[];
|
||||
}
|
||||
|
||||
export type ServiceHolder = {
|
||||
get<T>(api: ServiceRef<T>): FactoryFunc<T> | undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function createBackend(options?: CreateBackendOptions): Backend {
|
||||
// TODO: merge with provided APIs
|
||||
return new BackstageBackend([
|
||||
...defaultServiceFactories,
|
||||
...(options?.apis ?? []),
|
||||
]);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
|
||||
@@ -0,0 +1,5 @@
|
||||
# example-backend-next
|
||||
|
||||
This is an example backend for the new **EXPERIMENTAL** Backstage backend system.
|
||||
|
||||
Do not use this in your own projects.
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "example-backend-next",
|
||||
"version": "0.0.0",
|
||||
"main": "dist/index.cjs.js",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
"private": true,
|
||||
"backstage": {
|
||||
"role": "backend"
|
||||
},
|
||||
"homepage": "https://backstage.io",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/backstage/backstage",
|
||||
"directory": "packages/backend-next"
|
||||
},
|
||||
"keywords": [
|
||||
"backstage"
|
||||
],
|
||||
"scripts": {
|
||||
"start": "backstage-cli package start",
|
||||
"build": "backstage-cli package build",
|
||||
"lint": "backstage-cli package lint",
|
||||
"test": "backstage-cli package test",
|
||||
"clean": "backstage-cli package clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/backend-app-api": "^0.0.0",
|
||||
"@backstage/plugin-catalog-backend": "^1.2.1-next.2",
|
||||
"@backstage/plugin-scaffolder-backend": "^1.4.0-next.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.18.0-next.2"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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 { createBackend } from '@backstage/backend-app-api';
|
||||
import { catalogPlugin } from '@backstage/plugin-catalog-backend';
|
||||
import { scaffolderCatalogModule } from '@backstage/plugin-scaffolder-backend';
|
||||
|
||||
const backend = createBackend({
|
||||
apis: [],
|
||||
});
|
||||
|
||||
backend.add(catalogPlugin({}));
|
||||
backend.add(scaffolderCatalogModule({}));
|
||||
backend.start();
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
|
||||
@@ -0,0 +1,19 @@
|
||||
# @backstage/backend-plugin-api
|
||||
|
||||
**This package is HIGHLY EXPERIMENTAL, do not use this for production**
|
||||
|
||||
This package provides the core API used by Backstage backend plugins.
|
||||
|
||||
## Installation
|
||||
|
||||
Add the library to your backend plugin package:
|
||||
|
||||
```bash
|
||||
# From your Backstage root directory
|
||||
yarn add --cwd plugin/<plugin>-backend @backstage/backend-plugin-api
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md)
|
||||
- [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md)
|
||||
@@ -0,0 +1,197 @@
|
||||
## API Report File for "@backstage/backend-plugin-api"
|
||||
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
import { Config } from '@backstage/config';
|
||||
import { Handler } from 'express';
|
||||
import { Logger as Logger_2 } from 'winston';
|
||||
import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
|
||||
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
|
||||
import { PluginCacheManager } from '@backstage/backend-common';
|
||||
import { PluginDatabaseManager } from '@backstage/backend-common';
|
||||
import { PluginEndpointDiscovery } from '@backstage/backend-common';
|
||||
import { PluginTaskScheduler } from '@backstage/backend-tasks';
|
||||
import { TokenManager } from '@backstage/backend-common';
|
||||
import { TransportStreamOptions } from 'winston-transport';
|
||||
import { UrlReader } from '@backstage/backend-common';
|
||||
|
||||
// @public (undocumented)
|
||||
export type AnyServiceFactory = ServiceFactory<
|
||||
unknown,
|
||||
unknown,
|
||||
{
|
||||
[key in string]: unknown;
|
||||
}
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface BackendInitRegistry {
|
||||
// (undocumented)
|
||||
registerExtensionPoint<TExtensionPoint>(
|
||||
ref: ServiceRef<TExtensionPoint>,
|
||||
impl: TExtensionPoint,
|
||||
): void;
|
||||
// (undocumented)
|
||||
registerInit<
|
||||
Deps extends {
|
||||
[name in string]: unknown;
|
||||
},
|
||||
>(options: {
|
||||
deps: {
|
||||
[name in keyof Deps]: ServiceRef<Deps[name]>;
|
||||
};
|
||||
init: (deps: Deps) => Promise<void>;
|
||||
}): void;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface BackendModuleConfig<TOptions> {
|
||||
// (undocumented)
|
||||
moduleId: string;
|
||||
// (undocumented)
|
||||
pluginId: string;
|
||||
// (undocumented)
|
||||
register(
|
||||
reg: Omit<BackendInitRegistry, 'registerExtensionPoint'>,
|
||||
options: TOptions,
|
||||
): void;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface BackendPluginConfig<TOptions> {
|
||||
// (undocumented)
|
||||
id: string;
|
||||
// (undocumented)
|
||||
register(reg: BackendInitRegistry, options: TOptions): void;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface BackendRegistrable {
|
||||
// (undocumented)
|
||||
id: string;
|
||||
// (undocumented)
|
||||
register(reg: BackendInitRegistry): void;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export const cacheServiceRef: ServiceRef<PluginCacheManager>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const configServiceRef: ServiceRef<Config>;
|
||||
|
||||
// @public (undocumented)
|
||||
export function createBackendModule<TOptions>(
|
||||
config: BackendModuleConfig<TOptions>,
|
||||
): (option: TOptions) => BackendRegistrable;
|
||||
|
||||
// @public (undocumented)
|
||||
export function createBackendPlugin<TOptions>(
|
||||
config: BackendPluginConfig<TOptions>,
|
||||
): (option: TOptions) => BackendRegistrable;
|
||||
|
||||
// @public (undocumented)
|
||||
export function createExtensionPoint<T>(options: {
|
||||
id: string;
|
||||
}): ExtensionPoint<T>;
|
||||
|
||||
// @public (undocumented)
|
||||
export function createServiceFactory<
|
||||
Api,
|
||||
Impl extends Api,
|
||||
Deps extends {
|
||||
[name in string]: unknown;
|
||||
},
|
||||
>(factory: ServiceFactory<Api, Impl, Deps>): ServiceFactory<Api, Api, {}>;
|
||||
|
||||
// @public (undocumented)
|
||||
export function createServiceRef<T>(options: { id: string }): ServiceRef<T>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const databaseServiceRef: ServiceRef<PluginDatabaseManager>;
|
||||
|
||||
// @public (undocumented)
|
||||
export type DepsToDepFactories<T> = {
|
||||
[key in keyof T]: (pluginId: string) => Promise<T[key]>;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export const discoveryServiceRef: ServiceRef<PluginEndpointDiscovery>;
|
||||
|
||||
// @public
|
||||
export type ExtensionPoint<T> = {
|
||||
id: string;
|
||||
T: T;
|
||||
toString(): string;
|
||||
$$ref: 'extension-point';
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type FactoryFunc<Impl> = (pluginId: string) => Promise<Impl>;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface HttpRouterService {
|
||||
// (undocumented)
|
||||
use(handler: Handler): void;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export const httpRouterServiceRef: ServiceRef<HttpRouterService>;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface Logger {
|
||||
// (undocumented)
|
||||
child(fields: { [name: string]: string }): Logger;
|
||||
// (undocumented)
|
||||
info(message: string): void;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export const loggerServiceRef: ServiceRef<Logger>;
|
||||
|
||||
// @public (undocumented)
|
||||
export function loggerToWinstonLogger(
|
||||
logger: Logger,
|
||||
opts?: TransportStreamOptions,
|
||||
): Logger_2;
|
||||
|
||||
// @public (undocumented)
|
||||
export const permissionsServiceRef: ServiceRef<
|
||||
PermissionAuthorizer | PermissionEvaluator
|
||||
>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const schedulerServiceRef: ServiceRef<PluginTaskScheduler>;
|
||||
|
||||
// @public (undocumented)
|
||||
export type ServiceFactory<
|
||||
TApi,
|
||||
TImpl extends TApi,
|
||||
TDeps extends {
|
||||
[name in string]: unknown;
|
||||
},
|
||||
> = {
|
||||
service: ServiceRef<TApi>;
|
||||
deps: TypesToServiceRef<TDeps>;
|
||||
factory(deps: DepsToDepFactories<TDeps>): Promise<FactoryFunc<TImpl>>;
|
||||
};
|
||||
|
||||
// @public
|
||||
export type ServiceRef<T> = {
|
||||
id: string;
|
||||
T: T;
|
||||
toString(): string;
|
||||
$$ref: 'service';
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export const tokenManagerServiceRef: ServiceRef<TokenManager>;
|
||||
|
||||
// @public (undocumented)
|
||||
export type TypesToServiceRef<T> = {
|
||||
[key in keyof T]: ServiceRef<T[key]>;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export const urlReaderServiceRef: ServiceRef<UrlReader>;
|
||||
```
|
||||
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"name": "@backstage/backend-plugin-api",
|
||||
"description": "Core API used by Backstage backend plugins",
|
||||
"version": "0.0.0",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"main": "dist/index.cjs.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"alphaTypes": "dist/index.alpha.d.ts"
|
||||
},
|
||||
"backstage": {
|
||||
"role": "node-library"
|
||||
},
|
||||
"homepage": "https://backstage.io",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/backstage/backstage",
|
||||
"directory": "packages/backend-plugin-api"
|
||||
},
|
||||
"keywords": [
|
||||
"backstage"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"build": "backstage-cli package build --experimental-type-build",
|
||||
"lint": "backstage-cli package lint",
|
||||
"test": "backstage-cli package test",
|
||||
"prepack": "backstage-cli package prepack",
|
||||
"postpack": "backstage-cli package postpack",
|
||||
"clean": "backstage-cli package clean",
|
||||
"start": "backstage-cli package start"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/config": "^1.0.1",
|
||||
"@backstage/backend-common": "^0.14.1-next.2",
|
||||
"@backstage/plugin-permission-common": "^0.6.3-next.0",
|
||||
"@backstage/backend-tasks": "^0.3.3-next.2",
|
||||
"@types/express": "^4.17.6",
|
||||
"express": "^4.17.1",
|
||||
"winston": "^3.2.1",
|
||||
"winston-transport": "^4.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.18.0-next.2"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"alpha"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Core API used by Backstage backend plugins.
|
||||
*
|
||||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
export * from './services';
|
||||
export * from './wiring';
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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 { createServiceRef } from '../system/types';
|
||||
import { PluginCacheManager } from '@backstage/backend-common';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const cacheServiceRef = createServiceRef<PluginCacheManager>({
|
||||
id: 'core.cache',
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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 { Config } from '@backstage/config';
|
||||
import { createServiceRef } from '../system/types';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const configServiceRef = createServiceRef<Config>({
|
||||
id: 'core.config',
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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 { PluginDatabaseManager } from '@backstage/backend-common';
|
||||
import { createServiceRef } from '../system/types';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const databaseServiceRef = createServiceRef<PluginDatabaseManager>({
|
||||
id: 'core.database',
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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 { createServiceRef } from '../system/types';
|
||||
import { PluginEndpointDiscovery } from '@backstage/backend-common';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const discoveryServiceRef = createServiceRef<PluginEndpointDiscovery>({
|
||||
id: 'core.discovery',
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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 { createServiceRef } from '../system/types';
|
||||
import { Handler } from 'express';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface HttpRouterService {
|
||||
use(handler: Handler): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const httpRouterServiceRef = createServiceRef<HttpRouterService>({
|
||||
id: 'core.httpRouter',
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { configServiceRef } from './configServiceRef';
|
||||
export { httpRouterServiceRef } from './httpRouterServiceRef';
|
||||
export type { HttpRouterService } from './httpRouterServiceRef';
|
||||
export { loggerServiceRef } from './loggerServiceRef';
|
||||
export type { Logger } from './loggerServiceRef';
|
||||
export { urlReaderServiceRef } from './urlReaderServiceRef';
|
||||
export { cacheServiceRef } from './cacheServiceRef';
|
||||
export { databaseServiceRef } from './databaseServiceRef';
|
||||
export { discoveryServiceRef } from './discoveryServiceRef';
|
||||
export { tokenManagerServiceRef } from './tokenManagerServiceRef';
|
||||
export { permissionsServiceRef } from './permissionsServiceRef';
|
||||
export { schedulerServiceRef } from './schedulerServiceRef';
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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 { createServiceRef } from '../system/types';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface Logger {
|
||||
info(message: string): void;
|
||||
child(fields: { [name: string]: string }): Logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const loggerServiceRef = createServiceRef<Logger>({
|
||||
id: 'core.logger',
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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 { createServiceRef } from '../system/types';
|
||||
import {
|
||||
PermissionAuthorizer,
|
||||
PermissionEvaluator,
|
||||
} from '@backstage/plugin-permission-common';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const permissionsServiceRef = createServiceRef<
|
||||
PermissionEvaluator | PermissionAuthorizer
|
||||
>({
|
||||
id: 'core.permissions',
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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 { createServiceRef } from '../system/types';
|
||||
import { PluginTaskScheduler } from '@backstage/backend-tasks';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const schedulerServiceRef = createServiceRef<PluginTaskScheduler>({
|
||||
id: 'core.scheduler',
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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 { createServiceRef } from '../system/types';
|
||||
import { TokenManager } from '@backstage/backend-common';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const tokenManagerServiceRef = createServiceRef<TokenManager>({
|
||||
id: 'core.tokenManager',
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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 { createServiceRef } from '../system/types';
|
||||
import { UrlReader } from '@backstage/backend-common';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const urlReaderServiceRef = createServiceRef<UrlReader>({
|
||||
id: 'core.urlReader',
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { loggerToWinstonLogger } from './loggerToWinstonLogger';
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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 { Logger as BackstageLogger } from '../definitions';
|
||||
import { Logger as WinstonLogger, createLogger } from 'winston';
|
||||
import Transport, { TransportStreamOptions } from 'winston-transport';
|
||||
|
||||
class BackstageLoggerTransport extends Transport {
|
||||
constructor(
|
||||
private readonly backstageLogger: BackstageLogger,
|
||||
opts?: TransportStreamOptions,
|
||||
) {
|
||||
super(opts);
|
||||
}
|
||||
|
||||
log(info: { message: string }, callback: VoidFunction) {
|
||||
// TODO: add support for levels and fields
|
||||
this.backstageLogger.info(info.message);
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export function loggerToWinstonLogger(
|
||||
logger: BackstageLogger,
|
||||
opts?: TransportStreamOptions,
|
||||
): WinstonLogger {
|
||||
return createLogger({
|
||||
transports: [new BackstageLoggerTransport(logger, opts)],
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export * from './definitions';
|
||||
export * from './helpers';
|
||||
export * from './system';
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export type {
|
||||
ServiceRef,
|
||||
TypesToServiceRef,
|
||||
DepsToDepFactories,
|
||||
FactoryFunc,
|
||||
ServiceFactory,
|
||||
AnyServiceFactory,
|
||||
} from './types';
|
||||
export { createServiceRef, createServiceFactory } from './types';
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type ServiceRef<T> = {
|
||||
id: string;
|
||||
|
||||
/**
|
||||
* Utility for getting the type of the service, using `typeof serviceRef.T`.
|
||||
* Attempting to actually read this value will result in an exception.
|
||||
*/
|
||||
T: T;
|
||||
|
||||
toString(): string;
|
||||
|
||||
$$ref: 'service';
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export type TypesToServiceRef<T> = { [key in keyof T]: ServiceRef<T[key]> };
|
||||
|
||||
/** @public */
|
||||
export type DepsToDepFactories<T> = {
|
||||
[key in keyof T]: (pluginId: string) => Promise<T[key]>;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export type FactoryFunc<Impl> = (pluginId: string) => Promise<Impl>;
|
||||
|
||||
/** @public */
|
||||
export type ServiceFactory<
|
||||
TApi,
|
||||
TImpl extends TApi,
|
||||
TDeps extends { [name in string]: unknown },
|
||||
> = {
|
||||
service: ServiceRef<TApi>;
|
||||
deps: TypesToServiceRef<TDeps>;
|
||||
factory(deps: DepsToDepFactories<TDeps>): Promise<FactoryFunc<TImpl>>;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export type AnyServiceFactory = ServiceFactory<
|
||||
unknown,
|
||||
unknown,
|
||||
{ [key in string]: unknown }
|
||||
>;
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function createServiceRef<T>(options: { id: string }): ServiceRef<T> {
|
||||
return {
|
||||
id: options.id,
|
||||
get T(): T {
|
||||
throw new Error(`tried to read ServiceRef.T of ${this}`);
|
||||
},
|
||||
toString() {
|
||||
return `serviceRef{${options.id}}`;
|
||||
},
|
||||
$$ref: 'service', // TODO: declare
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function createServiceFactory<
|
||||
Api,
|
||||
Impl extends Api,
|
||||
Deps extends { [name in string]: unknown },
|
||||
>(factory: ServiceFactory<Api, Impl, Deps>): ServiceFactory<Api, Api, {}> {
|
||||
return factory;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export type { BackendRegistrable } from './types';
|
||||
export * from './types';
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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 { ServiceRef } from '../services/system/types';
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type ExtensionPoint<T> = {
|
||||
id: string;
|
||||
|
||||
/**
|
||||
* Utility for getting the type of the extension point, using `typeof extensionPoint.T`.
|
||||
* Attempting to actually read this value will result in an exception.
|
||||
*/
|
||||
T: T;
|
||||
|
||||
toString(): string;
|
||||
|
||||
$$ref: 'extension-point';
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export function createExtensionPoint<T>(options: {
|
||||
id: string;
|
||||
}): ExtensionPoint<T> {
|
||||
return {
|
||||
id: options.id,
|
||||
get T(): T {
|
||||
throw new Error(`tried to read ExtensionPoint.T of ${this}`);
|
||||
},
|
||||
toString() {
|
||||
return `extensionPoint{${options.id}}`;
|
||||
},
|
||||
$$ref: 'extension-point', // TODO: declare
|
||||
};
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface BackendInitRegistry {
|
||||
registerExtensionPoint<TExtensionPoint>(
|
||||
ref: ServiceRef<TExtensionPoint>,
|
||||
impl: TExtensionPoint,
|
||||
): void;
|
||||
registerInit<Deps extends { [name in string]: unknown }>(options: {
|
||||
deps: { [name in keyof Deps]: ServiceRef<Deps[name]> };
|
||||
init: (deps: Deps) => Promise<void>;
|
||||
}): void;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface BackendRegistrable {
|
||||
id: string;
|
||||
register(reg: BackendInitRegistry): void;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface BackendPluginConfig<TOptions> {
|
||||
id: string;
|
||||
register(reg: BackendInitRegistry, options: TOptions): void;
|
||||
}
|
||||
|
||||
// TODO: Make option optional in the returned factory if they are indeed optional
|
||||
/** @public */
|
||||
export function createBackendPlugin<TOptions>(
|
||||
config: BackendPluginConfig<TOptions>,
|
||||
): (option: TOptions) => BackendRegistrable {
|
||||
return options => ({
|
||||
id: config.id,
|
||||
register(register) {
|
||||
return config.register(register, options);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface BackendModuleConfig<TOptions> {
|
||||
pluginId: string;
|
||||
moduleId: string;
|
||||
register(
|
||||
reg: Omit<BackendInitRegistry, 'registerExtensionPoint'>,
|
||||
options: TOptions,
|
||||
): void;
|
||||
}
|
||||
|
||||
// TODO: Make option optional in the returned factory if they are indeed optional
|
||||
/** @public */
|
||||
export function createBackendModule<TOptions>(
|
||||
config: BackendModuleConfig<TOptions>,
|
||||
): (option: TOptions) => BackendRegistrable {
|
||||
return options => ({
|
||||
id: `${config.pluginId}.${config.moduleId}`,
|
||||
register(register) {
|
||||
// TODO: Hide registerExtensionPoint
|
||||
return config.register(register, options);
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user