Merge remote-tracking branch 'origin/master' into reconfigure
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/backend-plugin-api': minor
|
||||
---
|
||||
|
||||
Introduced new package for creating backend plugins using the new alpha backend plugin framework.
|
||||
This package is still considered **EXPERIMENTAL** and things will change without warning. Do not use this for production.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend': minor
|
||||
---
|
||||
|
||||
Added a new `/v2/dry-run` endpoint that allows for a synchronous dry run of a provided template. A `supportsDryRun` option has been added to `createTemplateAction`, which signals whether the action should be executed during dry runs. When enabled, the action context will have the new `isDryRun` property set to signal if the action is being executed during a dry run.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend-module-ldap': patch
|
||||
---
|
||||
|
||||
Fix mapping between users and groups for FreeIPA when using the LdapOrgProcessor
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-node': minor
|
||||
---
|
||||
|
||||
Added alpha exports for the new experimental backend system.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-node': major
|
||||
---
|
||||
|
||||
This package houses stable types from the `@backstage/plugin-catalog-backend` package and is intended for creation of catalog modules. Prefer importing from this package over the `@backstage/plugin-catalog-backend` package.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
---
|
||||
|
||||
Don't resolve symlinks, treat them as binary files and copy them as-is
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder': minor
|
||||
---
|
||||
|
||||
A new template editor has been added which is accessible via the context menu on the top right hand corner of the Create page. It allows you to load a template from a local directory, edit it with a preview, execute it in dry-run mode, and view the results. Note that the [File System Access API](https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API) must be supported by your browser for this to be available.
|
||||
|
||||
To support the new template editor the `ScaffolderApi` now has an optional `dryRun` method, which is implemented by the default `ScaffolderClient`.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': minor
|
||||
---
|
||||
|
||||
Export experimental `catalogPlugin` for the new backend system. This export is not considered stable and should not be used in production.
|
||||
@@ -176,7 +176,6 @@
|
||||
"curvy-weeks-matter",
|
||||
"eight-suits-fail",
|
||||
"eighty-windows-brush",
|
||||
"eleven-mice-collect",
|
||||
"five-fireants-run",
|
||||
"forty-seals-complain",
|
||||
"great-roses-pump",
|
||||
@@ -196,7 +195,6 @@
|
||||
"nervous-humans-sip",
|
||||
"old-onions-hear",
|
||||
"plenty-clouds-guess",
|
||||
"polite-eagles-invite",
|
||||
"polite-lions-sell",
|
||||
"popular-pots-yell",
|
||||
"pretty-masks-live",
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
'@backstage/catalog-model': patch
|
||||
'@backstage/cli': patch
|
||||
'@backstage/config-loader': patch
|
||||
'@backstage/plugin-catalog-backend-module-aws': patch
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
'@backstage/plugin-catalog-import': patch
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
'@backstage/plugin-proxy-backend': patch
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Updated dependency `yaml` to `^2.0.0`.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/plugin-adr': patch
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
---
|
||||
|
||||
Updated dependency `octokit` to `^2.0.0`.
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
CatalogBuilder supports now subscription to processing engine errors.
|
||||
|
||||
```ts
|
||||
subscribe(options: {
|
||||
onProcessingError: (event: { unprocessedEntity: Entity, error: Error }) => Promise<void> | void;
|
||||
});
|
||||
```
|
||||
|
||||
If you want to get notified on errors while processing the entities, you call CatalogBuilder.subscribe
|
||||
to get notifications with the parameters defined as above.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend': minor
|
||||
---
|
||||
|
||||
Export experimental `scaffolderCatalogExtension` for the new backend system. This export is not considered stable and should not be used in production.
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/backend-app-api': minor
|
||||
---
|
||||
|
||||
Add initial plumbing for creating backends using the experimental backend framework.
|
||||
|
||||
This package is highly **EXPERIMENTAL** and should not be used in production.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
Many symbol declarations have been moved to `@backstage/plugin-catalog-node`. This has no affect on users of this package as they are all re-exported. Modules that build on top of the catalog backend plugin should switch all of their imports to the `@backstage/plugin-catalog-node` package and remove the dependency on `@backstage/plugin-catalog-backend`.
|
||||
@@ -26,4 +26,4 @@ jobs:
|
||||
installation-id: ${{ secrets.BACKSTAGE_GOALIE_INSTALLATION_ID }}
|
||||
project-id: PVT_kwDOBFKqdc02LQ
|
||||
excluded-users: ${{ secrets.OOO_USERS }}
|
||||
owning-teams: '@backstage/techdocs'
|
||||
owning-teams: '@backstage/techdocs-core'
|
||||
|
||||
@@ -57,7 +57,7 @@ The recommended way of instantiating the catalog backend classes is to use the
|
||||
`CatalogBuilder`, as illustrated in the
|
||||
[example backend here](https://github.com/backstage/backstage/blob/master/packages/backend/src/plugins/catalog.ts).
|
||||
We will create a new
|
||||
[`EntityProvider`](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/src/api/provider.ts)
|
||||
[`EntityProvider`](https://github.com/backstage/backstage/blob/master/plugins/catalog-node/src/api/provider.ts)
|
||||
subclass that can be added to this catalog builder.
|
||||
|
||||
Let's make a simple provider that can refresh a set of entities based on a
|
||||
@@ -79,7 +79,7 @@ import { Entity } from '@backstage/catalog-model';
|
||||
import {
|
||||
EntityProvider,
|
||||
EntityProviderConnection,
|
||||
} from '@backstage/plugin-catalog-backend';
|
||||
} from '@backstage/plugin-catalog-node';
|
||||
|
||||
/**
|
||||
* Provides entities from fictional frobs service.
|
||||
@@ -354,7 +354,7 @@ The recommended way of instantiating the catalog backend classes is to use the
|
||||
`CatalogBuilder`, as illustrated in the
|
||||
[example backend here](https://github.com/backstage/backstage/blob/master/packages/backend/src/plugins/catalog.ts).
|
||||
We will create a new
|
||||
[`CatalogProcessor`](https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/src/api/processor.ts)
|
||||
[`CatalogProcessor`](https://github.com/backstage/backstage/blob/master/plugins/catalog-node/src/api/processor.ts)
|
||||
subclass that can be added to this catalog builder.
|
||||
|
||||
It is up to you where you put the code for this new processor class. For quick
|
||||
@@ -371,7 +371,7 @@ import {
|
||||
CatalogProcessor,
|
||||
CatalogProcessorEmit,
|
||||
LocationSpec,
|
||||
} from '@backstage/plugin-catalog-backend';
|
||||
} from '@backstage/plugin-catalog-node';
|
||||
|
||||
// A processor that reads from the fictional System-X
|
||||
export class SystemXReaderProcessor implements CatalogProcessor {
|
||||
@@ -455,7 +455,7 @@ import {
|
||||
CatalogProcessorCache,
|
||||
CatalogProcessorParser,
|
||||
LocationSpec,
|
||||
} from '@backstage/plugin-catalog-backend';
|
||||
} from '@backstage/plugin-catalog-node';
|
||||
|
||||
// It's recommended to always bump the CACHE_KEY version if you make
|
||||
// changes to the processor implementation or CacheItem.
|
||||
|
||||
@@ -12,6 +12,10 @@ groups - directly from an LDAP compatible service. The result is a hierarchy of
|
||||
[`Group`](../../features/software-catalog/descriptor-format.md#kind-group) kind
|
||||
entities that mirror your org setup.
|
||||
|
||||
## Supported vendors
|
||||
|
||||
Backstage in general supports OpenLDAP compatible vendors, as well as Active Directory and FreeIPA. If you are using a vendor that does not seem to be supported, please [file an issue](https://github.com/backstage/backstage/issues/new?assignees=&labels=enhancement&template=feature_template.md).
|
||||
|
||||
## Installation
|
||||
|
||||
This guide will use the Entity Provider method. If you for some reason prefer
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -47,7 +47,7 @@
|
||||
"@types/jest": "^26.0.7",
|
||||
"@types/json-schema": "^7.0.5",
|
||||
"@types/lodash": "^4.14.151",
|
||||
"yaml": "^1.9.2"
|
||||
"yaml": "^2.0.0"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
"webpack": "^5.66.0",
|
||||
"webpack-dev-server": "^4.7.3",
|
||||
"webpack-node-externals": "^3.0.0",
|
||||
"yaml": "^1.10.0",
|
||||
"yaml": "^2.0.0",
|
||||
"yml-loader": "^2.1.0",
|
||||
"yn": "^4.0.0",
|
||||
"zod": "^3.11.6"
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"typescript-json-schema": "^0.54.0",
|
||||
"yaml": "^1.9.2",
|
||||
"yaml": "^2.0.0",
|
||||
"yup": "^0.32.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -155,7 +155,7 @@ describe('includeTransform', () => {
|
||||
await expect(
|
||||
includeTransform({ $include: 'invalid.yaml' }, root),
|
||||
).rejects.toThrow(
|
||||
'failed to parse included file invalid.yaml, YAMLSyntaxError: Flow sequence contains an unexpected }',
|
||||
/failed to parse included file invalid.yaml, YAMLParseError: Flow sequence in block collection must be sufficiently indented and end with a \] at line 1, column 7:\s+foo: \[\}/,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "4.0.0-alpha.57",
|
||||
"git-url-parse": "^12.0.0",
|
||||
"octokit": "^1.7.1",
|
||||
"octokit": "^2.0.0",
|
||||
"react-markdown": "^8.0.0",
|
||||
"react-router-dom": "6.0.0-beta.0",
|
||||
"react-use": "^17.2.4",
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
"@backstage/cli": "^0.18.0-next.1",
|
||||
"@types/lodash": "^4.14.151",
|
||||
"aws-sdk-mock": "^5.2.1",
|
||||
"yaml": "^1.9.2"
|
||||
"yaml": "^2.0.0"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
|
||||
@@ -23,6 +23,7 @@ import { errorString } from './util';
|
||||
import {
|
||||
ActiveDirectoryVendor,
|
||||
DefaultLdapVendor,
|
||||
FreeIpaVendor,
|
||||
LdapVendor,
|
||||
} from './vendors';
|
||||
|
||||
@@ -199,6 +200,8 @@ export class LdapClient {
|
||||
.then(root => {
|
||||
if (root && root.raw?.forestFunctionality) {
|
||||
return ActiveDirectoryVendor;
|
||||
} else if (root && root.raw?.ipaDomainLevel) {
|
||||
return FreeIpaVendor;
|
||||
}
|
||||
return DefaultLdapVendor;
|
||||
})
|
||||
|
||||
@@ -32,7 +32,11 @@ import {
|
||||
resolveRelations,
|
||||
} from './read';
|
||||
import { RecursivePartial } from './util';
|
||||
import { ActiveDirectoryVendor, DefaultLdapVendor } from './vendors';
|
||||
import {
|
||||
ActiveDirectoryVendor,
|
||||
DefaultLdapVendor,
|
||||
FreeIpaVendor,
|
||||
} from './vendors';
|
||||
|
||||
function user(data: RecursivePartial<UserEntity>): UserEntity {
|
||||
return merge(
|
||||
@@ -195,6 +199,62 @@ describe('readLdapUsers', () => {
|
||||
new Map([['dn-value', new Set(['x', 'y', 'z'])]]),
|
||||
);
|
||||
});
|
||||
|
||||
it('transfers all attributes from FreeIPA', async () => {
|
||||
client.getVendor.mockResolvedValue(FreeIpaVendor);
|
||||
client.searchStreaming.mockImplementation(async (_dn, _opts, fn) => {
|
||||
await fn(
|
||||
searchEntry({
|
||||
uid: ['uid-value'],
|
||||
description: ['description-value'],
|
||||
cn: ['cn-value'],
|
||||
mail: ['mail-value'],
|
||||
avatarUrl: ['avatarUrl-value'],
|
||||
memberOf: ['x', 'y', 'z'],
|
||||
dn: ['dn-value'],
|
||||
ipaUniqueID: ['uuid-value'],
|
||||
}),
|
||||
);
|
||||
});
|
||||
const config: UserConfig = {
|
||||
dn: 'ddd',
|
||||
options: {},
|
||||
map: {
|
||||
rdn: 'uid',
|
||||
name: 'uid',
|
||||
description: 'description',
|
||||
displayName: 'cn',
|
||||
email: 'mail',
|
||||
picture: 'avatarUrl',
|
||||
memberOf: 'memberOf',
|
||||
},
|
||||
};
|
||||
const { users, userMemberOf } = await readLdapUsers(client, config);
|
||||
expect(users).toEqual([
|
||||
expect.objectContaining({
|
||||
metadata: {
|
||||
name: 'uid-value',
|
||||
description: 'description-value',
|
||||
annotations: {
|
||||
[LDAP_DN_ANNOTATION]: 'dn-value',
|
||||
[LDAP_RDN_ANNOTATION]: 'uid-value',
|
||||
[LDAP_UUID_ANNOTATION]: 'uuid-value',
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
profile: {
|
||||
displayName: 'cn-value',
|
||||
email: 'mail-value',
|
||||
picture: 'avatarUrl-value',
|
||||
},
|
||||
memberOf: [],
|
||||
},
|
||||
}),
|
||||
]);
|
||||
expect(userMemberOf).toEqual(
|
||||
new Map([['dn-value', new Set(['x', 'y', 'z'])]]),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('readLdapGroups', () => {
|
||||
|
||||
@@ -63,6 +63,16 @@ export const ActiveDirectoryVendor: LdapVendor = {
|
||||
},
|
||||
};
|
||||
|
||||
export const FreeIpaVendor: LdapVendor = {
|
||||
dnAttributeName: 'dn',
|
||||
uuidAttributeName: 'ipaUniqueID',
|
||||
decodeStringAttribute: (entry, name) => {
|
||||
return decode(entry, name, value => {
|
||||
return value.toString();
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
// Decode an attribute to a consumer
|
||||
function decode(
|
||||
entry: SearchEntry,
|
||||
|
||||
@@ -5,18 +5,34 @@
|
||||
```ts
|
||||
/// <reference types="node" />
|
||||
|
||||
import { BackendRegistrable } from '@backstage/backend-plugin-api';
|
||||
import { CatalogApi } from '@backstage/catalog-client';
|
||||
import { CatalogEntityDocument } from '@backstage/plugin-catalog-common';
|
||||
import { CompoundEntityRef } from '@backstage/catalog-model';
|
||||
import { CatalogProcessor } from '@backstage/plugin-catalog-node';
|
||||
import { CatalogProcessorCache } from '@backstage/plugin-catalog-node';
|
||||
import { CatalogProcessorEmit } from '@backstage/plugin-catalog-node';
|
||||
import { CatalogProcessorEntityResult } from '@backstage/plugin-catalog-node';
|
||||
import { CatalogProcessorErrorResult } from '@backstage/plugin-catalog-node';
|
||||
import { CatalogProcessorLocationResult } from '@backstage/plugin-catalog-node';
|
||||
import { CatalogProcessorParser } from '@backstage/plugin-catalog-node';
|
||||
import { CatalogProcessorRefreshKeysResult } from '@backstage/plugin-catalog-node';
|
||||
import { CatalogProcessorRelationResult } from '@backstage/plugin-catalog-node';
|
||||
import { CatalogProcessorResult } from '@backstage/plugin-catalog-node';
|
||||
import { ConditionalPolicyDecision } from '@backstage/plugin-permission-common';
|
||||
import { Conditions } from '@backstage/plugin-permission-node';
|
||||
import { Config } from '@backstage/config';
|
||||
import { DeferredEntity } from '@backstage/plugin-catalog-node';
|
||||
import { DocumentCollatorFactory } from '@backstage/plugin-search-common';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { EntityPolicy } from '@backstage/catalog-model';
|
||||
import { EntityProvider } from '@backstage/plugin-catalog-node';
|
||||
import { EntityProviderConnection } from '@backstage/plugin-catalog-node';
|
||||
import { EntityProviderMutation } from '@backstage/plugin-catalog-node';
|
||||
import { EntityRelationSpec } from '@backstage/plugin-catalog-node';
|
||||
import { GetEntitiesRequest } from '@backstage/catalog-client';
|
||||
import { JsonValue } from '@backstage/types';
|
||||
import { LocationEntityV1alpha1 } from '@backstage/catalog-model';
|
||||
import { LocationSpec } from '@backstage/plugin-catalog-node';
|
||||
import { Logger } from 'winston';
|
||||
import { Permission } from '@backstage/plugin-permission-common';
|
||||
import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
|
||||
@@ -26,6 +42,7 @@ import { PermissionEvaluator } from '@backstage/plugin-permission-common';
|
||||
import { PermissionRule } from '@backstage/plugin-permission-node';
|
||||
import { PluginDatabaseManager } from '@backstage/backend-common';
|
||||
import { PluginEndpointDiscovery } from '@backstage/backend-common';
|
||||
import { processingResult } from '@backstage/plugin-catalog-node';
|
||||
import { Readable } from 'stream';
|
||||
import { ResourcePermission } from '@backstage/plugin-permission-common';
|
||||
import { Router } from 'express';
|
||||
@@ -144,6 +161,13 @@ export class CatalogBuilder {
|
||||
processingInterval: ProcessingIntervalFunction,
|
||||
): CatalogBuilder;
|
||||
setProcessingIntervalSeconds(seconds: number): CatalogBuilder;
|
||||
// (undocumented)
|
||||
subscribe(options: {
|
||||
onProcessingError: (event: {
|
||||
unprocessedEntity: Entity;
|
||||
errors: Error[];
|
||||
}) => Promise<void> | void;
|
||||
}): void;
|
||||
}
|
||||
|
||||
// @alpha
|
||||
@@ -199,6 +223,9 @@ export type CatalogEnvironment = {
|
||||
export type CatalogPermissionRule<TParams extends unknown[] = unknown[]> =
|
||||
PermissionRule<Entity, EntitiesSearchFilter, 'catalog-entity', TParams>;
|
||||
|
||||
// @alpha
|
||||
export const catalogPlugin: (option: unknown) => BackendRegistrable;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface CatalogProcessingEngine {
|
||||
// (undocumented)
|
||||
@@ -207,86 +234,25 @@ export interface CatalogProcessingEngine {
|
||||
stop(): Promise<void>;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export type CatalogProcessor = {
|
||||
getProcessorName(): string;
|
||||
readLocation?(
|
||||
location: LocationSpec,
|
||||
optional: boolean,
|
||||
emit: CatalogProcessorEmit,
|
||||
parser: CatalogProcessorParser,
|
||||
cache: CatalogProcessorCache,
|
||||
): Promise<boolean>;
|
||||
preProcessEntity?(
|
||||
entity: Entity,
|
||||
location: LocationSpec,
|
||||
emit: CatalogProcessorEmit,
|
||||
originLocation: LocationSpec,
|
||||
cache: CatalogProcessorCache,
|
||||
): Promise<Entity>;
|
||||
validateEntityKind?(entity: Entity): Promise<boolean>;
|
||||
postProcessEntity?(
|
||||
entity: Entity,
|
||||
location: LocationSpec,
|
||||
emit: CatalogProcessorEmit,
|
||||
cache: CatalogProcessorCache,
|
||||
): Promise<Entity>;
|
||||
};
|
||||
export { CatalogProcessor };
|
||||
|
||||
// @public
|
||||
export interface CatalogProcessorCache {
|
||||
get<ItemType extends JsonValue>(key: string): Promise<ItemType | undefined>;
|
||||
set<ItemType extends JsonValue>(key: string, value: ItemType): Promise<void>;
|
||||
}
|
||||
export { CatalogProcessorCache };
|
||||
|
||||
// @public (undocumented)
|
||||
export type CatalogProcessorEmit = (generated: CatalogProcessorResult) => void;
|
||||
export { CatalogProcessorEmit };
|
||||
|
||||
// @public (undocumented)
|
||||
export type CatalogProcessorEntityResult = {
|
||||
type: 'entity';
|
||||
entity: Entity;
|
||||
location: LocationSpec;
|
||||
};
|
||||
export { CatalogProcessorEntityResult };
|
||||
|
||||
// @public (undocumented)
|
||||
export type CatalogProcessorErrorResult = {
|
||||
type: 'error';
|
||||
error: Error;
|
||||
location: LocationSpec;
|
||||
};
|
||||
export { CatalogProcessorErrorResult };
|
||||
|
||||
// @public (undocumented)
|
||||
export type CatalogProcessorLocationResult = {
|
||||
type: 'location';
|
||||
location: LocationSpec;
|
||||
};
|
||||
export { CatalogProcessorLocationResult };
|
||||
|
||||
// @public
|
||||
export type CatalogProcessorParser = (options: {
|
||||
data: Buffer;
|
||||
location: LocationSpec;
|
||||
}) => AsyncIterable<CatalogProcessorResult>;
|
||||
export { CatalogProcessorParser };
|
||||
|
||||
// @public (undocumented)
|
||||
export type CatalogProcessorRefreshKeysResult = {
|
||||
type: 'refresh';
|
||||
key: string;
|
||||
};
|
||||
export { CatalogProcessorRefreshKeysResult };
|
||||
|
||||
// @public (undocumented)
|
||||
export type CatalogProcessorRelationResult = {
|
||||
type: 'relation';
|
||||
relation: EntityRelationSpec;
|
||||
};
|
||||
export { CatalogProcessorRelationResult };
|
||||
|
||||
// @public (undocumented)
|
||||
export type CatalogProcessorResult =
|
||||
| CatalogProcessorLocationResult
|
||||
| CatalogProcessorEntityResult
|
||||
| CatalogProcessorRelationResult
|
||||
| CatalogProcessorErrorResult
|
||||
| CatalogProcessorRefreshKeysResult;
|
||||
export { CatalogProcessorResult };
|
||||
|
||||
// @public (undocumented)
|
||||
export class CodeOwnersProcessor implements CatalogProcessor {
|
||||
@@ -394,11 +360,7 @@ export type DefaultCatalogCollatorFactoryOptions = {
|
||||
catalogClient?: CatalogApi;
|
||||
};
|
||||
|
||||
// @public
|
||||
export type DeferredEntity = {
|
||||
entity: Entity;
|
||||
locationKey?: string;
|
||||
};
|
||||
export { DeferredEntity };
|
||||
|
||||
// @public
|
||||
export type EntitiesSearchFilter = {
|
||||
@@ -419,35 +381,13 @@ export type EntityFilter =
|
||||
}
|
||||
| EntitiesSearchFilter;
|
||||
|
||||
// @public
|
||||
export interface EntityProvider {
|
||||
connect(connection: EntityProviderConnection): Promise<void>;
|
||||
getProviderName(): string;
|
||||
}
|
||||
export { EntityProvider };
|
||||
|
||||
// @public
|
||||
export interface EntityProviderConnection {
|
||||
applyMutation(mutation: EntityProviderMutation): Promise<void>;
|
||||
}
|
||||
export { EntityProviderConnection };
|
||||
|
||||
// @public
|
||||
export type EntityProviderMutation =
|
||||
| {
|
||||
type: 'full';
|
||||
entities: DeferredEntity[];
|
||||
}
|
||||
| {
|
||||
type: 'delta';
|
||||
added: DeferredEntity[];
|
||||
removed: DeferredEntity[];
|
||||
};
|
||||
export { EntityProviderMutation };
|
||||
|
||||
// @public
|
||||
export type EntityRelationSpec = {
|
||||
source: CompoundEntityRef;
|
||||
type: string;
|
||||
target: CompoundEntityRef;
|
||||
};
|
||||
export { EntityRelationSpec };
|
||||
|
||||
// @public (undocumented)
|
||||
export class FileReaderProcessor implements CatalogProcessor {
|
||||
@@ -487,12 +427,7 @@ export type LocationEntityProcessorOptions = {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
};
|
||||
|
||||
// @public
|
||||
export type LocationSpec = {
|
||||
type: string;
|
||||
target: string;
|
||||
presence?: 'optional' | 'required';
|
||||
};
|
||||
export { LocationSpec };
|
||||
|
||||
// @public (undocumented)
|
||||
export function locationSpecToLocationEntity(opts: {
|
||||
@@ -593,28 +528,7 @@ export type PlaceholderResolverResolveUrl = (
|
||||
// @public
|
||||
export type ProcessingIntervalFunction = () => number;
|
||||
|
||||
// @public
|
||||
export const processingResult: Readonly<{
|
||||
readonly notFoundError: (
|
||||
atLocation: LocationSpec,
|
||||
message: string,
|
||||
) => CatalogProcessorResult;
|
||||
readonly inputError: (
|
||||
atLocation: LocationSpec,
|
||||
message: string,
|
||||
) => CatalogProcessorResult;
|
||||
readonly generalError: (
|
||||
atLocation: LocationSpec,
|
||||
message: string,
|
||||
) => CatalogProcessorResult;
|
||||
readonly location: (newLocation: LocationSpec) => CatalogProcessorResult;
|
||||
readonly entity: (
|
||||
atLocation: LocationSpec,
|
||||
newEntity: Entity,
|
||||
) => CatalogProcessorResult;
|
||||
readonly relation: (spec: EntityRelationSpec) => CatalogProcessorResult;
|
||||
readonly refresh: (key: string) => CatalogProcessorResult;
|
||||
}>;
|
||||
export { processingResult };
|
||||
|
||||
// @public (undocumented)
|
||||
export class UrlReaderProcessor implements CatalogProcessor {
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
"clean": "backstage-cli package clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/backend-plugin-api": "^0.0.0",
|
||||
"@backstage/plugin-catalog-node": "^0.0.0",
|
||||
"@backstage/backend-common": "^0.14.1-next.2",
|
||||
"@backstage/catalog-client": "^1.0.4-next.1",
|
||||
"@backstage/catalog-model": "^1.1.0-next.2",
|
||||
@@ -63,7 +65,7 @@
|
||||
"prom-client": "^14.0.1",
|
||||
"uuid": "^8.0.0",
|
||||
"winston": "^3.2.1",
|
||||
"yaml": "^1.9.2",
|
||||
"yaml": "^2.0.0",
|
||||
"yn": "^4.0.0",
|
||||
"zod": "^3.11.6"
|
||||
},
|
||||
|
||||
@@ -35,7 +35,6 @@ import {
|
||||
ListParentsResult,
|
||||
RefreshByKeyOptions,
|
||||
} from './types';
|
||||
import { DeferredEntity } from '../processing/types';
|
||||
import { ProcessingIntervalFunction } from '../processing/refresh';
|
||||
import { rethrowError, timestampToDateTime } from './conversion';
|
||||
import { initDatabaseMetrics } from './metrics';
|
||||
@@ -48,6 +47,7 @@ import {
|
||||
|
||||
import { generateStableHash } from './util';
|
||||
import { isDatabaseConflictError } from '@backstage/backend-common';
|
||||
import { DeferredEntity } from '@backstage/plugin-catalog-node';
|
||||
|
||||
// The number of items that are sent per batch to the database layer, when
|
||||
// doing .batchInsert calls to knex. This needs to be low enough to not cause
|
||||
|
||||
@@ -17,9 +17,12 @@
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { JsonObject } from '@backstage/types';
|
||||
import { DateTime } from 'luxon';
|
||||
import { EntityRelationSpec } from '../api';
|
||||
import { DeferredEntity, RefreshKeyData } from '../processing/types';
|
||||
import {
|
||||
EntityRelationSpec,
|
||||
DeferredEntity,
|
||||
} from '@backstage/plugin-catalog-node';
|
||||
import { DbRelationsRow } from './tables';
|
||||
import { RefreshKeyData } from '../processing/types';
|
||||
|
||||
/**
|
||||
* An abstraction for transactions of the underlying database technology.
|
||||
|
||||
@@ -20,7 +20,26 @@
|
||||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
export * from './api';
|
||||
export type {
|
||||
DeferredEntity,
|
||||
LocationSpec,
|
||||
EntityRelationSpec,
|
||||
CatalogProcessor,
|
||||
CatalogProcessorParser,
|
||||
CatalogProcessorCache,
|
||||
CatalogProcessorEmit,
|
||||
CatalogProcessorLocationResult,
|
||||
CatalogProcessorEntityResult,
|
||||
CatalogProcessorRelationResult,
|
||||
CatalogProcessorErrorResult,
|
||||
CatalogProcessorRefreshKeysResult,
|
||||
CatalogProcessorResult,
|
||||
EntityProvider,
|
||||
EntityProviderConnection,
|
||||
EntityProviderMutation,
|
||||
} from '@backstage/plugin-catalog-node';
|
||||
export { processingResult } from '@backstage/plugin-catalog-node';
|
||||
|
||||
export * from './catalog';
|
||||
export * from './ingestion';
|
||||
export * from './modules';
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { DefaultCatalogRulesEnforcer } from './CatalogRules';
|
||||
import { LocationSpec } from '../api';
|
||||
import { LocationSpec } from '@backstage/plugin-catalog-node';
|
||||
|
||||
const entity = {
|
||||
user: {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import { Config } from '@backstage/config';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import path from 'path';
|
||||
import { LocationSpec } from '../api';
|
||||
import { LocationSpec } from '@backstage/plugin-catalog-node';
|
||||
|
||||
/**
|
||||
* Rules to apply to catalog entities.
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { RecursivePartial } from '../util/RecursivePartial';
|
||||
import { LocationSpec } from '../api';
|
||||
import { LocationSpec } from '@backstage/plugin-catalog-node';
|
||||
|
||||
/** @public */
|
||||
export type LocationAnalyzer = {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import { getVoidLogger } from '@backstage/backend-common';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { CodeOwnersProcessor } from './CodeOwnersProcessor';
|
||||
import { LocationSpec } from '../../api';
|
||||
import { LocationSpec } from '@backstage/plugin-catalog-node';
|
||||
|
||||
const mockCodeOwnersText = () => `
|
||||
* @acme/team-foo @acme/team-bar
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
ScmIntegrations,
|
||||
} from '@backstage/integration';
|
||||
import { Logger } from 'winston';
|
||||
import { CatalogProcessor, LocationSpec } from '../../api';
|
||||
import { CatalogProcessor, LocationSpec } from '@backstage/plugin-catalog-node';
|
||||
import { findCodeOwnerByTarget } from './lib';
|
||||
|
||||
const ALLOWED_KINDS = ['API', 'Component', 'Domain', 'Resource', 'System'];
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { ScmIntegrations } from '@backstage/integration';
|
||||
import { LocationSpec } from '../../api';
|
||||
import { LocationSpec } from '@backstage/plugin-catalog-node';
|
||||
import { AnnotateLocationEntityProcessor } from './AnnotateLocationEntityProcessor';
|
||||
|
||||
describe('AnnotateLocationEntityProcessor', () => {
|
||||
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
CatalogProcessor,
|
||||
CatalogProcessorEmit,
|
||||
LocationSpec,
|
||||
} from '../../api';
|
||||
} from '@backstage/plugin-catalog-node';
|
||||
|
||||
/** @public */
|
||||
export class AnnotateLocationEntityProcessor implements CatalogProcessor {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { AnnotateScmSlugEntityProcessor } from './AnnotateScmSlugEntityProcessor';
|
||||
import { LocationSpec } from '../../api';
|
||||
import { LocationSpec } from '@backstage/plugin-catalog-node';
|
||||
|
||||
describe('AnnotateScmSlugEntityProcessor', () => {
|
||||
describe('github', () => {
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
} from '@backstage/integration';
|
||||
import parseGitUrl from 'git-url-parse';
|
||||
import { identity, merge, pickBy } from 'lodash';
|
||||
import { CatalogProcessor, LocationSpec } from '../../api';
|
||||
import { CatalogProcessor, LocationSpec } from '@backstage/plugin-catalog-node';
|
||||
|
||||
const GITHUB_ACTIONS_ANNOTATION = 'github.com/project-slug';
|
||||
const GITLAB_ACTIONS_ANNOTATION = 'gitlab.com/project-slug';
|
||||
|
||||
@@ -53,7 +53,7 @@ import {
|
||||
CatalogProcessorEmit,
|
||||
LocationSpec,
|
||||
processingResult,
|
||||
} from '../../api';
|
||||
} from '@backstage/plugin-catalog-node';
|
||||
|
||||
/** @public */
|
||||
export class BuiltinKindsEntityProcessor implements CatalogProcessor {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import path from 'path';
|
||||
import { ConfigLocationEntityProvider } from './ConfigLocationEntityProvider';
|
||||
import { EntityProviderConnection } from '../../api';
|
||||
import { EntityProviderConnection } from '@backstage/plugin-catalog-node';
|
||||
|
||||
describe('ConfigLocationEntityProvider', () => {
|
||||
it('should apply mutation with the correct paths in the config', async () => {
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
import { Config } from '@backstage/config';
|
||||
import path from 'path';
|
||||
import { getEntityLocationRef } from '../../processing/util';
|
||||
import { EntityProvider, EntityProviderConnection } from '../../api';
|
||||
import {
|
||||
EntityProvider,
|
||||
EntityProviderConnection,
|
||||
} from '@backstage/plugin-catalog-node';
|
||||
import { locationSpecToLocationEntity } from '../../util/conversion';
|
||||
|
||||
export class ConfigLocationEntityProvider implements EntityProvider {
|
||||
|
||||
@@ -20,7 +20,10 @@ import { Knex } from 'knex';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { DbLocationsRow } from '../../database/tables';
|
||||
import { getEntityLocationRef } from '../../processing/util';
|
||||
import { EntityProvider, EntityProviderConnection } from '../../api';
|
||||
import {
|
||||
EntityProvider,
|
||||
EntityProviderConnection,
|
||||
} from '@backstage/plugin-catalog-node';
|
||||
import { locationSpecToLocationEntity } from '../../util/conversion';
|
||||
import { LocationInput, LocationStore } from '../../service/types';
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
CatalogProcessorEntityResult,
|
||||
CatalogProcessorErrorResult,
|
||||
CatalogProcessorResult,
|
||||
} from '../../api';
|
||||
} from '@backstage/plugin-catalog-node';
|
||||
import path from 'path';
|
||||
import { defaultEntityDataParser } from '../util/parse';
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
CatalogProcessorParser,
|
||||
LocationSpec,
|
||||
processingResult,
|
||||
} from '../../api';
|
||||
} from '@backstage/plugin-catalog-node';
|
||||
|
||||
const glob = promisify(g);
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
} from '@backstage/integration';
|
||||
import path from 'path';
|
||||
import { toAbsoluteUrl } from './LocationEntityProcessor';
|
||||
import { LocationSpec } from '../../api';
|
||||
import { LocationSpec } from '@backstage/plugin-catalog-node';
|
||||
|
||||
describe('LocationEntityProcessor', () => {
|
||||
describe('toAbsoluteUrl', () => {
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
CatalogProcessor,
|
||||
CatalogProcessorEmit,
|
||||
LocationSpec,
|
||||
} from '../../api';
|
||||
} from '@backstage/plugin-catalog-node';
|
||||
|
||||
export function toAbsoluteUrl(
|
||||
integrations: ScmIntegrationRegistry,
|
||||
|
||||
@@ -17,7 +17,7 @@ import { UrlReader } from '@backstage/backend-common';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { ScmIntegrations } from '@backstage/integration';
|
||||
import { CatalogProcessorResult } from '../../api';
|
||||
import { CatalogProcessorResult } from '@backstage/plugin-catalog-node';
|
||||
import {
|
||||
jsonPlaceholderResolver,
|
||||
PlaceholderProcessor,
|
||||
@@ -414,7 +414,7 @@ describe('yamlPlaceholderResolver', () => {
|
||||
it('rejects invalid yaml', async () => {
|
||||
read.mockResolvedValue(Buffer.from('a: 1\n----\n', 'utf-8'));
|
||||
await expect(yamlPlaceholderResolver(params)).rejects.toThrow(
|
||||
'Placeholder $a found an error in the data at ./file.yaml, YAMLSemanticError: Implicit map keys need to be followed by map values',
|
||||
/Placeholder \$a found an error in the data at .\/file.yaml, YAMLParseError: Implicit map keys need to be followed by map values at line 2, column 1:\s+a: 1/,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import {
|
||||
CatalogProcessorEmit,
|
||||
LocationSpec,
|
||||
processingResult,
|
||||
} from '../../api';
|
||||
} from '@backstage/plugin-catalog-node';
|
||||
|
||||
/** @public */
|
||||
export type PlaceholderResolverRead = (url: string) => Promise<Buffer>;
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
CatalogProcessorEntityResult,
|
||||
CatalogProcessorErrorResult,
|
||||
CatalogProcessorResult,
|
||||
} from '../../api';
|
||||
} from '@backstage/plugin-catalog-node';
|
||||
import { defaultEntityDataParser } from '../util/parse';
|
||||
import { UrlReaderProcessor } from './UrlReaderProcessor';
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user