From fa0533e6049f933619c0cd8451e0b3ada24fcfa3 Mon Sep 17 00:00:00 2001 From: Hasan Oezdemir <21654050+nodify-at@users.noreply.github.com> Date: Tue, 31 May 2022 13:05:43 +0200 Subject: [PATCH 01/59] feature: provide error listeners for catalog processing engines to notify the callers if an entity can not be processed. Signed-off-by: Hasan Oezdemir <21654050+nodify-at@users.noreply.github.com> --- .changeset/shaggy-spiders-notice.md | 6 ++++ plugins/catalog-backend/api-report.md | 28 +++++++++++++++++++ .../DefaultCatalogProcessingEngine.ts | 14 +++++++++- .../catalog-backend/src/processing/index.ts | 7 ++++- .../catalog-backend/src/processing/types.ts | 14 ++++++++++ 5 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 .changeset/shaggy-spiders-notice.md diff --git a/.changeset/shaggy-spiders-notice.md b/.changeset/shaggy-spiders-notice.md new file mode 100644 index 0000000000..6b50c964e3 --- /dev/null +++ b/.changeset/shaggy-spiders-notice.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Provide a new listener `CatalogProcessingErrorListener` for the processing engines to notify the caller if an entity can not be processed. Processing engine +will collect the errors and passes the entity and the results to the given listeners. diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index cb8a5abb8a..3ac5094b31 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -15,6 +15,7 @@ import { DocumentCollatorFactory } from '@backstage/plugin-search-common'; import { Entity } from '@backstage/catalog-model'; import { EntityPolicy } from '@backstage/catalog-model'; import { GetEntitiesRequest } from '@backstage/catalog-client'; +import { JsonObject } from '@backstage/types'; import { JsonValue } from '@backstage/types'; import { LocationEntityV1alpha1 } from '@backstage/catalog-model'; import { Logger } from 'winston'; @@ -201,12 +202,24 @@ export type CatalogPermissionRule = // @public (undocumented) export interface CatalogProcessingEngine { + // (undocumented) + addErrorListener?(errorListener: CatalogProcessingErrorListener): void; // (undocumented) start(): Promise; // (undocumented) stop(): Promise; } +// @public +export interface CatalogProcessingErrorListener { + // (undocumented) + onError( + unprocessedEntity: Entity, + result: EntityProcessingResult, + resultHash: String, + ): Promise; +} + // @public (undocumented) export type CatalogProcessor = { getProcessorName(): string; @@ -412,6 +425,21 @@ export type EntityFilter = } | EntitiesSearchFilter; +// @public +export type EntityProcessingResult = + | { + ok: true; + state: JsonObject; + completedEntity: Entity; + deferredEntities: DeferredEntity[]; + relations: EntityRelationSpec[]; + errors: Error[]; + } + | { + ok: false; + errors: Error[]; + }; + // @public export interface EntityProvider { connect(connection: EntityProviderConnection): Promise; diff --git a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts index b7ef5c9344..7ebb55273b 100644 --- a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts @@ -23,9 +23,10 @@ import { ProcessingDatabase, RefreshStateItem } from '../database/types'; import { createCounterMetric, createSummaryMetric } from '../util/metrics'; import { CatalogProcessingEngine, + CatalogProcessingErrorListener, CatalogProcessingOrchestrator, EntityProcessingResult, -} from '../processing/types'; +} from './types'; import { Stitcher } from '../stitching/Stitcher'; import { startTaskPipeline } from './TaskPipeline'; @@ -33,6 +34,7 @@ const CACHE_TTL = 5; export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { private readonly tracker = progressTracker(); + private readonly errorListeners: CatalogProcessingErrorListener[] = []; private stopFunc?: () => void; constructor( @@ -122,6 +124,7 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { ); let hashBuilder = this.createHash().update(errorsString); + if (result.ok) { const { entityRefs: parents } = await this.processingDatabase.transaction(tx => @@ -154,6 +157,11 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { // just store the errors and trigger a stich so that they become visible to // the outside. if (!result.ok) { + // notify the error listeners if the entity can not be processed. + this.errorListeners.forEach(listener => + listener.onError(unprocessedEntity, result, resultHash), + ); + await this.processingDatabase.transaction(async tx => { await this.processingDatabase.updateProcessedEntityErrors(tx, { id, @@ -223,6 +231,10 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { this.stopFunc = undefined; } } + + addErrorListener(errorListener: CatalogProcessingErrorListener) { + this.errorListeners.push(errorListener); + } } // Helps wrap the timing and logging behaviors diff --git a/plugins/catalog-backend/src/processing/index.ts b/plugins/catalog-backend/src/processing/index.ts index b392c3aa76..c5e139c0ad 100644 --- a/plugins/catalog-backend/src/processing/index.ts +++ b/plugins/catalog-backend/src/processing/index.ts @@ -14,7 +14,12 @@ * limitations under the License. */ -export type { CatalogProcessingEngine, DeferredEntity } from './types'; +export type { + CatalogProcessingEngine, + EntityProcessingResult, + DeferredEntity, + CatalogProcessingErrorListener, +} from './types'; export { createRandomProcessingInterval } from './refresh'; export type { ProcessingIntervalFunction } from './refresh'; diff --git a/plugins/catalog-backend/src/processing/types.ts b/plugins/catalog-backend/src/processing/types.ts index b178522c14..54118f8422 100644 --- a/plugins/catalog-backend/src/processing/types.ts +++ b/plugins/catalog-backend/src/processing/types.ts @@ -66,4 +66,18 @@ export type DeferredEntity = { export interface CatalogProcessingEngine { start(): Promise; stop(): Promise; + addErrorListener?(errorListener: CatalogProcessingErrorListener): void; +} + +/** + * An error listener for catalog processing engine. It can be used to listen and track entity errors. + * + * @public + */ +export interface CatalogProcessingErrorListener { + onError( + unprocessedEntity: Entity, + result: EntityProcessingResult, + resultHash: String, + ): Promise; } From 751323a50b70832e4f3a0297b739f70022c4d872 Mon Sep 17 00:00:00 2001 From: Hasan Oezdemir <21654050+nodify-at@users.noreply.github.com> Date: Tue, 5 Jul 2022 16:29:41 +0200 Subject: [PATCH 02/59] feature: refactor processing engine to remove listeners publicly and provide a subscription via catalog builder Signed-off-by: Hasan Oezdemir <21654050+nodify-at@users.noreply.github.com> --- plugins/catalog-backend/api-report.md | 8 ++++--- .../DefaultCatalogProcessingEngine.ts | 14 +++++------- .../catalog-backend/src/processing/types.ts | 3 +-- .../src/service/CatalogBuilder.ts | 22 ++++++++++++++++++- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index 3ac5094b31..ad898d2e22 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -145,6 +145,10 @@ export class CatalogBuilder { processingInterval: ProcessingIntervalFunction, ): CatalogBuilder; setProcessingIntervalSeconds(seconds: number): CatalogBuilder; + // @alpha (undocumented) + subscribe( + catalogProcessingErrorListeners: CatalogProcessingErrorListener[], + ): void; } // @alpha @@ -202,15 +206,13 @@ export type CatalogPermissionRule = // @public (undocumented) export interface CatalogProcessingEngine { - // (undocumented) - addErrorListener?(errorListener: CatalogProcessingErrorListener): void; // (undocumented) start(): Promise; // (undocumented) stop(): Promise; } -// @public +// @alpha export interface CatalogProcessingErrorListener { // (undocumented) onError( diff --git a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts index 7ebb55273b..69295a0662 100644 --- a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts @@ -34,7 +34,6 @@ const CACHE_TTL = 5; export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { private readonly tracker = progressTracker(); - private readonly errorListeners: CatalogProcessingErrorListener[] = []; private stopFunc?: () => void; constructor( @@ -44,6 +43,7 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { private readonly stitcher: Stitcher, private readonly createHash: () => Hash, private readonly pollingIntervalMs: number = 1000, + private readonly catalogProcessingErrorListener?: CatalogProcessingErrorListener, ) {} async start() { @@ -157,9 +157,11 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { // just store the errors and trigger a stich so that they become visible to // the outside. if (!result.ok) { - // notify the error listeners if the entity can not be processed. - this.errorListeners.forEach(listener => - listener.onError(unprocessedEntity, result, resultHash), + // notify the error listener if the entity can not be processed. + this.catalogProcessingErrorListener?.onError( + unprocessedEntity, + result, + resultHash, ); await this.processingDatabase.transaction(async tx => { @@ -231,10 +233,6 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { this.stopFunc = undefined; } } - - addErrorListener(errorListener: CatalogProcessingErrorListener) { - this.errorListeners.push(errorListener); - } } // Helps wrap the timing and logging behaviors diff --git a/plugins/catalog-backend/src/processing/types.ts b/plugins/catalog-backend/src/processing/types.ts index 54118f8422..e6c58cf36f 100644 --- a/plugins/catalog-backend/src/processing/types.ts +++ b/plugins/catalog-backend/src/processing/types.ts @@ -66,13 +66,12 @@ export type DeferredEntity = { export interface CatalogProcessingEngine { start(): Promise; stop(): Promise; - addErrorListener?(errorListener: CatalogProcessingErrorListener): void; } /** * An error listener for catalog processing engine. It can be used to listen and track entity errors. * - * @public + * @alpha */ export interface CatalogProcessingErrorListener { onError( diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.ts b/plugins/catalog-backend/src/service/CatalogBuilder.ts index 0d4ddc8e71..be427998fc 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.ts @@ -56,7 +56,10 @@ import { } from '../modules/core/PlaceholderProcessor'; import { defaultEntityDataParser } from '../modules/util/parse'; import { LocationAnalyzer } from '../ingestion/types'; -import { CatalogProcessingEngine } from '../processing/types'; +import { + CatalogProcessingEngine, + CatalogProcessingErrorListener, +} from '../processing'; import { DefaultProcessingDatabase } from '../database/DefaultProcessingDatabase'; import { applyDatabaseMigrations } from '../database/migrations'; import { DefaultCatalogProcessingEngine } from '../processing/DefaultCatalogProcessingEngine'; @@ -133,6 +136,7 @@ export class CatalogBuilder { private processors: CatalogProcessor[]; private processorsReplace: boolean; private parser: CatalogProcessorParser | undefined; + private catalogProcessingErrorListeners?: CatalogProcessingErrorListener[]; private processingInterval: ProcessingIntervalFunction = createRandomProcessingInterval({ minSeconds: 100, @@ -447,6 +451,14 @@ export class CatalogBuilder { orchestrator, stitcher, () => createHash('sha1'), + 1000, + { + onError: async (unprocessedEntity, result, resultHash) => { + this.catalogProcessingErrorListeners?.forEach(listener => + listener.onError(unprocessedEntity, result, resultHash), + ); + }, + }, ); const locationAnalyzer = @@ -478,6 +490,14 @@ export class CatalogBuilder { }; } + /** + * @alpha + * @param catalogProcessingErrorListeners - a list of listeners to get notified if an error occurs while processing an entity + */ + subscribe(catalogProcessingErrorListeners: CatalogProcessingErrorListener[]) { + this.catalogProcessingErrorListeners = catalogProcessingErrorListeners; + } + private buildEntityPolicy(): EntityPolicy { const entityPolicies: EntityPolicy[] = this.entityPoliciesReplace ? [new SchemaValidEntityPolicy(), ...this.entityPolicies] From d6e1616358fbcd69e05cd5f064fd4d8572bc7282 Mon Sep 17 00:00:00 2001 From: Hasan Oezdemir <21654050+nodify-at@users.noreply.github.com> Date: Wed, 6 Jul 2022 15:46:20 +0200 Subject: [PATCH 03/59] feature: refactor processing engine, remove typing and provide an option to subscribe to errors while processing the entities. Signed-off-by: Hasan Oezdemir <21654050+nodify-at@users.noreply.github.com> --- plugins/catalog-backend/api-report.md | 21 ++++-------- .../DefaultCatalogProcessingEngine.ts | 29 +++++++++++------ .../catalog-backend/src/processing/index.ts | 1 - .../catalog-backend/src/processing/types.ts | 13 -------- .../src/service/CatalogBuilder.ts | 32 +++++++++---------- 5 files changed, 42 insertions(+), 54 deletions(-) diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index ad898d2e22..8af2643dc0 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -145,10 +145,13 @@ export class CatalogBuilder { processingInterval: ProcessingIntervalFunction, ): CatalogBuilder; setProcessingIntervalSeconds(seconds: number): CatalogBuilder; - // @alpha (undocumented) - subscribe( - catalogProcessingErrorListeners: CatalogProcessingErrorListener[], - ): void; + // (undocumented) + subscribe(options: { + onProcessingError: (event: { + unprocessedEntity: Entity; + errors: Error[]; + }) => Promise | void; + }): void; } // @alpha @@ -212,16 +215,6 @@ export interface CatalogProcessingEngine { stop(): Promise; } -// @alpha -export interface CatalogProcessingErrorListener { - // (undocumented) - onError( - unprocessedEntity: Entity, - result: EntityProcessingResult, - resultHash: String, - ): Promise; -} - // @public (undocumented) export type CatalogProcessor = { getProcessorName(): string; diff --git a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts index 69295a0662..b632b48825 100644 --- a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import { stringifyEntityRef } from '@backstage/catalog-model'; -import { assertError, serializeError } from '@backstage/errors'; +import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; +import { assertError, serializeError, stringifyError } from '@backstage/errors'; import { Hash } from 'crypto'; import stableStringify from 'fast-json-stable-stringify'; import { Logger } from 'winston'; @@ -23,7 +23,6 @@ import { ProcessingDatabase, RefreshStateItem } from '../database/types'; import { createCounterMetric, createSummaryMetric } from '../util/metrics'; import { CatalogProcessingEngine, - CatalogProcessingErrorListener, CatalogProcessingOrchestrator, EntityProcessingResult, } from './types'; @@ -43,7 +42,10 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { private readonly stitcher: Stitcher, private readonly createHash: () => Hash, private readonly pollingIntervalMs: number = 1000, - private readonly catalogProcessingErrorListener?: CatalogProcessingErrorListener, + private readonly onProcessingError?: (event: { + unprocessedEntity: Entity; + errors: Error[]; + }) => Promise | void, ) {} async start() { @@ -158,11 +160,20 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { // the outside. if (!result.ok) { // notify the error listener if the entity can not be processed. - this.catalogProcessingErrorListener?.onError( - unprocessedEntity, - result, - resultHash, - ); + Promise.resolve(undefined) + .then(() => + this.onProcessingError?.({ + unprocessedEntity, + errors: result.errors, + }), + ) + .catch(error => { + this.logger.debug( + `Processing error listener threw an exception, ${stringifyError( + error, + )}`, + ); + }); await this.processingDatabase.transaction(async tx => { await this.processingDatabase.updateProcessedEntityErrors(tx, { diff --git a/plugins/catalog-backend/src/processing/index.ts b/plugins/catalog-backend/src/processing/index.ts index c5e139c0ad..d96e7b5b9b 100644 --- a/plugins/catalog-backend/src/processing/index.ts +++ b/plugins/catalog-backend/src/processing/index.ts @@ -18,7 +18,6 @@ export type { CatalogProcessingEngine, EntityProcessingResult, DeferredEntity, - CatalogProcessingErrorListener, } from './types'; export { createRandomProcessingInterval } from './refresh'; diff --git a/plugins/catalog-backend/src/processing/types.ts b/plugins/catalog-backend/src/processing/types.ts index e6c58cf36f..b178522c14 100644 --- a/plugins/catalog-backend/src/processing/types.ts +++ b/plugins/catalog-backend/src/processing/types.ts @@ -67,16 +67,3 @@ export interface CatalogProcessingEngine { start(): Promise; stop(): Promise; } - -/** - * An error listener for catalog processing engine. It can be used to listen and track entity errors. - * - * @alpha - */ -export interface CatalogProcessingErrorListener { - onError( - unprocessedEntity: Entity, - result: EntityProcessingResult, - resultHash: String, - ): Promise; -} diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.ts b/plugins/catalog-backend/src/service/CatalogBuilder.ts index be427998fc..390dc817d1 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.ts @@ -17,6 +17,7 @@ import { PluginDatabaseManager, UrlReader } from '@backstage/backend-common'; import { DefaultNamespaceEntityPolicy, + Entity, EntityPolicies, EntityPolicy, FieldFormatEntityPolicy, @@ -56,10 +57,7 @@ import { } from '../modules/core/PlaceholderProcessor'; import { defaultEntityDataParser } from '../modules/util/parse'; import { LocationAnalyzer } from '../ingestion/types'; -import { - CatalogProcessingEngine, - CatalogProcessingErrorListener, -} from '../processing'; +import { CatalogProcessingEngine } from '../processing'; import { DefaultProcessingDatabase } from '../database/DefaultProcessingDatabase'; import { applyDatabaseMigrations } from '../database/migrations'; import { DefaultCatalogProcessingEngine } from '../processing/DefaultCatalogProcessingEngine'; @@ -136,7 +134,10 @@ export class CatalogBuilder { private processors: CatalogProcessor[]; private processorsReplace: boolean; private parser: CatalogProcessorParser | undefined; - private catalogProcessingErrorListeners?: CatalogProcessingErrorListener[]; + private onProcessingError?: (event: { + unprocessedEntity: Entity; + errors: Error[]; + }) => Promise | void; private processingInterval: ProcessingIntervalFunction = createRandomProcessingInterval({ minSeconds: 100, @@ -452,12 +453,8 @@ export class CatalogBuilder { stitcher, () => createHash('sha1'), 1000, - { - onError: async (unprocessedEntity, result, resultHash) => { - this.catalogProcessingErrorListeners?.forEach(listener => - listener.onError(unprocessedEntity, result, resultHash), - ); - }, + event => { + this.onProcessingError?.(event); }, ); @@ -490,12 +487,13 @@ export class CatalogBuilder { }; } - /** - * @alpha - * @param catalogProcessingErrorListeners - a list of listeners to get notified if an error occurs while processing an entity - */ - subscribe(catalogProcessingErrorListeners: CatalogProcessingErrorListener[]) { - this.catalogProcessingErrorListeners = catalogProcessingErrorListeners; + subscribe(options: { + onProcessingError: (event: { + unprocessedEntity: Entity; + errors: Error[]; + }) => Promise | void; + }) { + this.onProcessingError = options.onProcessingError; } private buildEntityPolicy(): EntityPolicy { From 72622d914368cc78395688954780deec97b90859 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 6 Jul 2022 14:18:17 +0000 Subject: [PATCH 04/59] fix(deps): update dependency yaml to v2 Signed-off-by: Renovate Bot --- .changeset/renovate-33c3cf4.md | 14 ++++++++++++++ packages/catalog-model/package.json | 2 +- packages/cli/package.json | 2 +- packages/config-loader/package.json | 2 +- plugins/catalog-backend-module-aws/package.json | 2 +- plugins/catalog-backend/package.json | 2 +- plugins/catalog-import/package.json | 2 +- plugins/catalog-react/package.json | 2 +- plugins/proxy-backend/package.json | 2 +- plugins/scaffolder-backend/package.json | 4 ++-- plugins/scaffolder/package.json | 2 +- yarn.lock | 4 ++-- 12 files changed, 27 insertions(+), 13 deletions(-) create mode 100644 .changeset/renovate-33c3cf4.md diff --git a/.changeset/renovate-33c3cf4.md b/.changeset/renovate-33c3cf4.md new file mode 100644 index 0000000000..8389a89ea1 --- /dev/null +++ b/.changeset/renovate-33c3cf4.md @@ -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`. diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index a58fdcf4d5..460dafa43a 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -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", diff --git a/packages/cli/package.json b/packages/cli/package.json index aead136ec6..a4742ff8ff 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -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" diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index 3ca4b1455f..638e3dc8e0 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -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": { diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index c768bbe9e4..4b4e60cf4d 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -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", diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index ebed76ca90..1e3c4cf1a3 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -63,7 +63,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" }, diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 042e85f792..49f248ed41 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -53,7 +53,7 @@ "react-hook-form": "^7.12.2", "react-router": "6.0.0-beta.0", "react-use": "^17.2.4", - "yaml": "^1.10.0" + "yaml": "^2.0.0" }, "peerDependencies": { "@types/react": "^16.13.1 || ^17.0.0", diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 3f3ee5f402..560690245f 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -55,7 +55,7 @@ "qs": "^6.9.4", "react-router": "6.0.0-beta.0", "react-use": "^17.2.4", - "yaml": "^1.10.0", + "yaml": "^2.0.0", "zen-observable": "^0.8.15" }, "peerDependencies": { diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 7eba901c54..e21173910e 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -41,7 +41,7 @@ "morgan": "^1.10.0", "uuid": "^8.0.0", "winston": "^3.2.1", - "yaml": "^1.9.2", + "yaml": "^2.0.0", "yn": "^4.0.0", "yup": "^0.32.9" }, diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index a70e60f714..e889dc0ebf 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -70,7 +70,7 @@ "p-limit": "^3.1.0", "uuid": "^8.2.0", "winston": "^3.2.1", - "yaml": "^1.10.0", + "yaml": "^2.0.0", "vm2": "^3.9.6", "zen-observable": "^0.8.15", "zod": "^3.11.6" @@ -90,7 +90,7 @@ "mock-fs": "^5.1.0", "msw": "^0.43.0", "supertest": "^6.1.3", - "yaml": "^1.10.0" + "yaml": "^2.0.0" }, "files": [ "dist", diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index e6223d1952..ad46f47433 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -72,7 +72,7 @@ "react-router-dom": "6.0.0-beta.0", "react-use": "^17.2.4", "use-immer": "^0.7.0", - "yaml": "^1.9.2", + "yaml": "^2.0.0", "zen-observable": "^0.8.15" }, "peerDependencies": { diff --git a/yarn.lock b/yarn.lock index f06a187ebf..2dfadeaf70 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26467,12 +26467,12 @@ yaml-ast-parser@0.0.43, yaml-ast-parser@^0.0.43: resolved "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz#e8a23e6fb4c38076ab92995c5dca33f3d3d7c9bb" integrity sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A== -yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2, yaml@^1.9.2: +yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: version "1.10.2" resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== -yaml@^2.1.1: +yaml@^2.0.0, yaml@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/yaml/-/yaml-2.1.1.tgz#1e06fb4ca46e60d9da07e4f786ea370ed3c3cfec" integrity sha512-o96x3OPo8GjWeSLF+wOAbrPfhFOGY0W00GNaxCDv+9hkcDJEnev1yh8S7pgHF0ik6zc8sQLuL8hjHjJULZp8bw== From faa728689776013a152ad2d2b240664132c6b2d4 Mon Sep 17 00:00:00 2001 From: Hasan Oezdemir <21654050+nodify-at@users.noreply.github.com> Date: Wed, 6 Jul 2022 17:27:04 +0200 Subject: [PATCH 05/59] feature: remove public annotation from EntityProcessingResult to mark it as an internal type and improve the change set to describe the subscription method Signed-off-by: Hasan Oezdemir <21654050+nodify-at@users.noreply.github.com> --- .changeset/shaggy-spiders-notice.md | 12 ++++++++++-- plugins/catalog-backend/api-report.md | 16 ---------------- plugins/catalog-backend/src/processing/index.ts | 6 +----- plugins/catalog-backend/src/processing/types.ts | 2 +- 4 files changed, 12 insertions(+), 24 deletions(-) diff --git a/.changeset/shaggy-spiders-notice.md b/.changeset/shaggy-spiders-notice.md index 6b50c964e3..513f6cd521 100644 --- a/.changeset/shaggy-spiders-notice.md +++ b/.changeset/shaggy-spiders-notice.md @@ -2,5 +2,13 @@ '@backstage/plugin-catalog-backend': patch --- -Provide a new listener `CatalogProcessingErrorListener` for the processing engines to notify the caller if an entity can not be processed. Processing engine -will collect the errors and passes the entity and the results to the given listeners. +CatalogBuilder supports now subscription to processing engine errors. + +```ts +subscribe(options: { + onProcessingError: (event: { unprocessedEntity: Entity, error: Error }) => Promise | 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. diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index 8af2643dc0..5a2020f3e0 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -15,7 +15,6 @@ import { DocumentCollatorFactory } from '@backstage/plugin-search-common'; import { Entity } from '@backstage/catalog-model'; import { EntityPolicy } from '@backstage/catalog-model'; import { GetEntitiesRequest } from '@backstage/catalog-client'; -import { JsonObject } from '@backstage/types'; import { JsonValue } from '@backstage/types'; import { LocationEntityV1alpha1 } from '@backstage/catalog-model'; import { Logger } from 'winston'; @@ -420,21 +419,6 @@ export type EntityFilter = } | EntitiesSearchFilter; -// @public -export type EntityProcessingResult = - | { - ok: true; - state: JsonObject; - completedEntity: Entity; - deferredEntities: DeferredEntity[]; - relations: EntityRelationSpec[]; - errors: Error[]; - } - | { - ok: false; - errors: Error[]; - }; - // @public export interface EntityProvider { connect(connection: EntityProviderConnection): Promise; diff --git a/plugins/catalog-backend/src/processing/index.ts b/plugins/catalog-backend/src/processing/index.ts index d96e7b5b9b..b392c3aa76 100644 --- a/plugins/catalog-backend/src/processing/index.ts +++ b/plugins/catalog-backend/src/processing/index.ts @@ -14,11 +14,7 @@ * limitations under the License. */ -export type { - CatalogProcessingEngine, - EntityProcessingResult, - DeferredEntity, -} from './types'; +export type { CatalogProcessingEngine, DeferredEntity } from './types'; export { createRandomProcessingInterval } from './refresh'; export type { ProcessingIntervalFunction } from './refresh'; diff --git a/plugins/catalog-backend/src/processing/types.ts b/plugins/catalog-backend/src/processing/types.ts index b178522c14..a314c52c6c 100644 --- a/plugins/catalog-backend/src/processing/types.ts +++ b/plugins/catalog-backend/src/processing/types.ts @@ -29,7 +29,7 @@ export type EntityProcessingRequest = { /** * The result of processing an entity. - * @public + * @internal */ export type EntityProcessingResult = | { From 51fb0a1d80051355ad689b56c4695f4af26efb46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 6 Jul 2022 16:39:19 +0200 Subject: [PATCH 06/59] fixup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .../src/lib/transform/include.test.ts | 2 +- .../modules/core/PlaceholderProcessor.test.ts | 2 +- .../src/modules/util/parse.test.ts | 34 ++++++++++++------- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/packages/config-loader/src/lib/transform/include.test.ts b/packages/config-loader/src/lib/transform/include.test.ts index 91df723621..0913b31f66 100644 --- a/packages/config-loader/src/lib/transform/include.test.ts +++ b/packages/config-loader/src/lib/transform/include.test.ts @@ -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: \[\}/, ); }); diff --git a/plugins/catalog-backend/src/modules/core/PlaceholderProcessor.test.ts b/plugins/catalog-backend/src/modules/core/PlaceholderProcessor.test.ts index adff97336e..50cbdf9dd4 100644 --- a/plugins/catalog-backend/src/modules/core/PlaceholderProcessor.test.ts +++ b/plugins/catalog-backend/src/modules/core/PlaceholderProcessor.test.ts @@ -376,7 +376,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/, ); }); diff --git a/plugins/catalog-backend/src/modules/util/parse.test.ts b/plugins/catalog-backend/src/modules/util/parse.test.ts index e87de1c9a3..eda1723198 100644 --- a/plugins/catalog-backend/src/modules/util/parse.test.ts +++ b/plugins/catalog-backend/src/modules/util/parse.test.ts @@ -156,12 +156,16 @@ describe('parseEntityYaml', () => { ); // Parse errors are always per document - expect(results).toEqual([ - processingResult.generalError( - testLoc, - 'YAML error at my-loc-type:my-loc-target, YAMLSemanticError: Plain value cannot start with reserved character `', - ), - ]); + expect(results.length).toBe(1); + expect(results[0]).toEqual({ + type: 'error', + location: testLoc, + error: expect.objectContaining({ + message: expect.stringMatching( + /YAML error at my-loc-type:my-loc-target, YAMLParseError: Plain value cannot start with reserved character ` at line 1, column 1:/, + ), + }), + }); }); it('should emit parsing errors for individual documents', () => { @@ -185,7 +189,8 @@ describe('parseEntityYaml', () => { ), ); - expect(results).toEqual([ + expect(results.length).toBe(2); + expect(results[0]).toEqual( processingResult.entity(testLoc, { apiVersion: 'backstage.io/v1alpha1', kind: 'Component', @@ -196,11 +201,16 @@ describe('parseEntityYaml', () => { type: 'website', }, }), - processingResult.generalError( - testLoc, - 'YAML error at my-loc-type:my-loc-target, YAMLSemanticError: Nested mappings are not allowed in compact mappings', - ), - ]); + ); + expect(results[1]).toEqual({ + type: 'error', + location: testLoc, + error: expect.objectContaining({ + message: expect.stringMatching( + /YAML error at my-loc-type:my-loc-target, YAMLParseError: Nested mappings are not allowed in compact mappings at line 9, column 19:\s+apiVersion: backstage.io\/v1alpha1/, + ), + }), + }); }); it('must be an object at root', () => { From 5185c58bf5461933f4ab1ef628e4637c99f18370 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 7 Jul 2022 19:20:52 +0200 Subject: [PATCH 07/59] chore: copy symlinks as is, rather than copying the realpath into the place Signed-off-by: blam --- .../actions/builtin/fetch/template.test.ts | 15 +++++++++++++++ .../scaffolder/actions/builtin/fetch/template.ts | 5 +++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.test.ts index 8f641fe2e2..06def076ea 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.test.ts @@ -186,6 +186,10 @@ describe('fetch:template', () => { }, '.${{ values.name }}': '${{ values.itemList | dump }}', 'a-binary-file.png': aBinaryFile, + symlink: mockFs.symlink({ + path: 'a-binary-file.png', + }), + '{% if values.showDummyFile %}dummy-file.txt{% else %}{% endif %}': 'dummy file', '${{ "dummy-file2.txt" if values.showDummyFile else "" }}': @@ -265,6 +269,17 @@ describe('fetch:template', () => { .then(fObj => fObj.mode), ).resolves.toEqual(parseInt('100755', 8)); }); + it('copies file symlinks as-is without processing them', async () => { + await expect( + fs + .lstat(`${workspacePath}/target/symlink`) + .then(i => i.isSymbolicLink()), + ).resolves.toBe(true); + + await expect( + fs.realpath(`${workspacePath}/target/symlink`), + ).resolves.toBe(`${workspacePath}/target/a-binary-file.png`); + }); }); describe('copyWithoutRender', () => { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.ts index c6d6b86e7b..a1afabc39e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.ts @@ -229,10 +229,11 @@ export function createFetchTemplateAction(options: { await fs.ensureDir(outputPath); } else { const inputFilePath = resolveSafeChildPath(templateDir, location); + const stats = await fs.promises.lstat(inputFilePath); - if (await isBinaryFile(inputFilePath)) { + if (stats.isSymbolicLink() || (await isBinaryFile(inputFilePath))) { ctx.logger.info( - `Copying binary file ${location} to template output path.`, + `Copying file binary or symbolic link at ${location}, to template output path.`, ); await fs.copy(inputFilePath, outputPath); } else { From ea6dcb84a47544d931954158d1ce2cd402cafa05 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 7 Jul 2022 19:24:47 +0200 Subject: [PATCH 08/59] chore: added changeset Signed-off-by: blam --- .changeset/perfect-donuts-applaud.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/perfect-donuts-applaud.md diff --git a/.changeset/perfect-donuts-applaud.md b/.changeset/perfect-donuts-applaud.md new file mode 100644 index 0000000000..3b663fa2c2 --- /dev/null +++ b/.changeset/perfect-donuts-applaud.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Don't resolve symlinks, treat them as binary files and copy them as-is From ad69e8cbafeba0b87bc1a4a556c026bf1ed0773c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 8 Jul 2022 08:30:42 +0000 Subject: [PATCH 09/59] chore(deps): update dependency puppeteer to v15.3.2 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7275164f34..d972ce908e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21539,9 +21539,9 @@ punycode@^2.1.0, punycode@^2.1.1: integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== puppeteer@^15.0.0: - version "15.3.1" - resolved "https://registry.npmjs.org/puppeteer/-/puppeteer-15.3.1.tgz#0ff9b433a8fc3798f5ec82ea4b31ec47857219cf" - integrity sha512-Z+SpYBiS1zUzMXV7Wnhe2pyuVCFAFRTq1UrUWHB2CkLos5v7bXvXYuZ3Fn5pSN5IObxijyx4opNYKTCRnGni6Q== + version "15.3.2" + resolved "https://registry.npmjs.org/puppeteer/-/puppeteer-15.3.2.tgz#62162739044d570ab9907f85b1e1bbcf52adc79e" + integrity sha512-6z4fTHCHTpG3Yu7zqP0mLfCmkNkgw5KSUfLAwuBabz9Pkqoe0Z08hqUx5GNxhhMgEo4YVOSPBshePA6zliznWQ== dependencies: cross-fetch "3.1.5" debug "4.3.4" From fa17e0fe6eb885291d403c0bd6ce5c768f670054 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 8 Jul 2022 08:44:26 +0000 Subject: [PATCH 10/59] fix(deps): update dependency @azure/storage-blob to v12.11.0 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index ae3b4ae88c..3397f045b3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -359,9 +359,9 @@ uuid "^8.3.0" "@azure/storage-blob@^12.5.0": - version "12.10.0" - resolved "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.10.0.tgz#b92269f45a1765700a900b41ca81a474a6e36ea4" - integrity sha512-FBEPKGnvtQJS8V8Tg1P9obgmVD9AodrIfwtwhBpsjenClhFyugMp3HPJY0tF7rInUB/CivKBCbnQKrUnKxqxzw== + version "12.11.0" + resolved "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.11.0.tgz#2e27902ab293715411ab1f7c8fae422ad0b4b827" + integrity sha512-na+FisoARuaOWaHWpmdtk3FeuTWf2VWamdJ9/TJJzj5ZdXPLC3juoDgFs6XVuJIoK30yuBpyFBEDXVRK4pB7Tg== dependencies: "@azure/abort-controller" "^1.0.0" "@azure/core-http" "^2.0.0" From c9bf1c98b5c5c04a39eaf2b4564a55496320f63b Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 8 Jul 2022 11:04:40 +0200 Subject: [PATCH 11/59] chore: added some tests to ensure that we skip symlinked folders and files Signed-off-by: blam --- .../files/serializeDirectoryContents.test.ts | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/plugins/scaffolder-backend/src/lib/files/serializeDirectoryContents.test.ts b/plugins/scaffolder-backend/src/lib/files/serializeDirectoryContents.test.ts index e1ea676ec5..b24a867504 100644 --- a/plugins/scaffolder-backend/src/lib/files/serializeDirectoryContents.test.ts +++ b/plugins/scaffolder-backend/src/lib/files/serializeDirectoryContents.test.ts @@ -97,6 +97,52 @@ describe('serializeDirectoryContents', () => { ]); }); + it('should ignore symlinked files', async () => { + mockFs({ + root: { + 'a.txt': 'some text', + sym: mockFs.symlink({ + path: './a.txt', + }), + }, + }); + + await expect(serializeDirectoryContents('root')).resolves.toEqual([ + { + path: 'a.txt', + executable: false, + content: Buffer.from('some text', 'utf8'), + }, + ]); + }); + + it('should ignore symlinked folder files', async () => { + mockFs({ + root: { + 'a.txt': 'some text', + linkme: { + 'b.txt': 'lols', + }, + sym: mockFs.symlink({ + path: './linkme', + }), + }, + }); + + await expect(serializeDirectoryContents('root')).resolves.toEqual([ + { + path: 'a.txt', + executable: false, + content: Buffer.from('some text', 'utf8'), + }, + { + path: 'linkme/b.txt', + executable: false, + content: Buffer.from('lols', 'utf8'), + }, + ]); + }); + it('should ignore gitignored files', async () => { mockFs({ root: { From 03d29026859baf18bd94024ecfde45cce90736ce Mon Sep 17 00:00:00 2001 From: Marc Rooding Date: Fri, 8 Jul 2022 08:04:57 +0200 Subject: [PATCH 12/59] Add support for FreeIPA as an LDAP vendor Signed-off-by: Marc Rooding --- docs/integrations/ldap/org.md | 8 ++++++++ plugins/catalog-backend-module-ldap/src/ldap/client.ts | 3 +++ .../catalog-backend-module-ldap/src/ldap/vendors.ts | 10 ++++++++++ 3 files changed, 21 insertions(+) diff --git a/docs/integrations/ldap/org.md b/docs/integrations/ldap/org.md index e7028f34f1..5b49e762a7 100644 --- a/docs/integrations/ldap/org.md +++ b/docs/integrations/ldap/org.md @@ -12,6 +12,14 @@ 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. +## Suported vendors + +Currently, Backstage only supports the following LDAP vendors: + +1. OpenLDAP (default) +2. Active Directory +3. FreeIPA + ## Installation This guide will use the Entity Provider method. If you for some reason prefer diff --git a/plugins/catalog-backend-module-ldap/src/ldap/client.ts b/plugins/catalog-backend-module-ldap/src/ldap/client.ts index a9283ecb94..d9d0faf9a2 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/client.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/client.ts @@ -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; }) diff --git a/plugins/catalog-backend-module-ldap/src/ldap/vendors.ts b/plugins/catalog-backend-module-ldap/src/ldap/vendors.ts index 447df8aaa5..d2df250638 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/vendors.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/vendors.ts @@ -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, From f7f29dbf0e5df219d8708398431e100a87c4c03a Mon Sep 17 00:00:00 2001 From: Marc Rooding Date: Fri, 8 Jul 2022 08:39:49 +0200 Subject: [PATCH 13/59] Add test case for reading an LDAP user from FreeIPA Signed-off-by: Marc Rooding --- .../src/ldap/read.test.ts | 59 ++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts b/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts index 49803b9c39..53f2d33794 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts @@ -32,7 +32,7 @@ import { resolveRelations, } from './read'; import { RecursivePartial } from './util'; -import { ActiveDirectoryVendor, DefaultLdapVendor } from './vendors'; +import { ActiveDirectoryVendor, DefaultLdapVendor, FreeIpaVendor } from './vendors'; function user(data: RecursivePartial): UserEntity { return merge( @@ -195,8 +195,65 @@ 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', () => { const client: jest.Mocked = { searchStreaming: jest.fn(), From ddfd566606f0ca398dcf93fa58df819bf65c31d5 Mon Sep 17 00:00:00 2001 From: Marc Rooding Date: Fri, 8 Jul 2022 08:47:57 +0200 Subject: [PATCH 14/59] Add changeset Signed-off-by: Marc Rooding --- .changeset/hungry-cougars-press.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/hungry-cougars-press.md diff --git a/.changeset/hungry-cougars-press.md b/.changeset/hungry-cougars-press.md new file mode 100644 index 0000000000..c99e1f4c76 --- /dev/null +++ b/.changeset/hungry-cougars-press.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-ldap': patch +--- + +Fix mapping between users and groups for FreeIPA when using the LdapOrgProcessor From 545db2ba6c4e91cf3cb3b9544acca57a3987e510 Mon Sep 17 00:00:00 2001 From: Marc Rooding Date: Fri, 8 Jul 2022 08:56:02 +0200 Subject: [PATCH 15/59] Fix typo in docs Signed-off-by: Marc Rooding --- docs/integrations/ldap/org.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/ldap/org.md b/docs/integrations/ldap/org.md index 5b49e762a7..010f46832d 100644 --- a/docs/integrations/ldap/org.md +++ b/docs/integrations/ldap/org.md @@ -12,7 +12,7 @@ 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. -## Suported vendors +## Supported vendors Currently, Backstage only supports the following LDAP vendors: From 0acd49fb5c29575970a7f6c30d7c4d53aefd424f Mon Sep 17 00:00:00 2001 From: Marc Rooding Date: Fri, 8 Jul 2022 09:27:03 +0200 Subject: [PATCH 16/59] Formatting Signed-off-by: Marc Rooding --- plugins/catalog-backend-module-ldap/src/ldap/read.test.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts b/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts index 53f2d33794..fc451fde97 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts @@ -32,7 +32,11 @@ import { resolveRelations, } from './read'; import { RecursivePartial } from './util'; -import { ActiveDirectoryVendor, DefaultLdapVendor, FreeIpaVendor } from './vendors'; +import { + ActiveDirectoryVendor, + DefaultLdapVendor, + FreeIpaVendor, +} from './vendors'; function user(data: RecursivePartial): UserEntity { return merge( @@ -253,7 +257,6 @@ describe('readLdapUsers', () => { }); }); - describe('readLdapGroups', () => { const client: jest.Mocked = { searchStreaming: jest.fn(), From ddb5c11d4aaa31e176679d48dd8848a9924afa2e Mon Sep 17 00:00:00 2001 From: Camila Maia Date: Fri, 8 Jul 2022 11:16:04 +0200 Subject: [PATCH 17/59] Add tests to gocd Select component Signed-off-by: Camila Maia --- .../src/components/Select/Select.test.tsx | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 plugins/gocd/src/components/Select/Select.test.tsx diff --git a/plugins/gocd/src/components/Select/Select.test.tsx b/plugins/gocd/src/components/Select/Select.test.tsx new file mode 100644 index 0000000000..fb467b946f --- /dev/null +++ b/plugins/gocd/src/components/Select/Select.test.tsx @@ -0,0 +1,75 @@ +/* + * 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 { renderInTestApp } from '@backstage/test-utils'; +import React from 'react'; +import { Item, SelectComponent } from './Select'; +import userEvent from '@testing-library/user-event'; + +describe('Select', () => { + const testLabel = 'Date Select'; + const testItems: Item[] = [ + { label: 'Last month', value: 'lastMonth' }, + { label: 'All', value: 'all' }, + ]; + + const user = userEvent.setup(); + + it('should render', async () => { + const rendered = await renderInTestApp( + undefined} + />, + ); + expect(rendered.getAllByText(testLabel)).toHaveLength(2); + }); + + describe('when the user hasn`t clicked on it', () => { + it('should only render the current select item', async () => { + const rendered = await renderInTestApp( + undefined} + />, + ); + expect(rendered.getByText(testItems[0].label)).toBeInTheDocument(); + expect(rendered.queryByText(testItems[1].label)).toBeNull(); + }); + }); + + describe('when the user clicked on it', () => { + it('should render all the items', async () => { + const rendered = await renderInTestApp( + undefined} + />, + ); + user.tab(); + userEvent.keyboard('{enter}'); + + expect(rendered.getAllByText(testItems[0].label)).toHaveLength(2); + expect(rendered.getByText(testItems[1].label)).toBeInTheDocument(); + }); + }); +}); From c784e91c0ed9b47ad0da84295174c37557d68662 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 8 Jul 2022 09:21:30 +0000 Subject: [PATCH 18/59] fix(deps): update dependency rollup to v2.76.0 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 9580b9ed5d..a7bbc9ee17 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23003,9 +23003,9 @@ rollup@^0.63.4: "@types/node" "*" rollup@^2.60.2: - version "2.75.7" - resolved "https://registry.npmjs.org/rollup/-/rollup-2.75.7.tgz#221ff11887ae271e37dcc649ba32ce1590aaa0b9" - integrity sha512-VSE1iy0eaAYNCxEXaleThdFXqZJ42qDBatAwrfnPlENEZ8erQ+0LYX4JXOLPceWfZpV1VtZwZ3dFCuOZiSyFtQ== + version "2.76.0" + resolved "https://registry.npmjs.org/rollup/-/rollup-2.76.0.tgz#c69fe03db530ac53fcb9523b3caa0d3c0b9491a1" + integrity sha512-9jwRIEY1jOzKLj3nsY/yot41r19ITdQrhs+q3ggNWhr9TQgduHqANvPpS32RNpzGklJu3G1AJfvlZLi/6wFgWA== optionalDependencies: fsevents "~2.3.2" From 511f49ee4353a126e06037f31a43579067a0c4c0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 8 Jul 2022 10:05:19 +0000 Subject: [PATCH 19/59] fix(deps): update dependency octokit to v2 Signed-off-by: Renovate Bot --- .changeset/renovate-d26eca1.md | 6 ++ plugins/adr/package.json | 2 +- plugins/scaffolder-backend/package.json | 2 +- yarn.lock | 90 ++++++++++++++----------- 4 files changed, 57 insertions(+), 43 deletions(-) create mode 100644 .changeset/renovate-d26eca1.md diff --git a/.changeset/renovate-d26eca1.md b/.changeset/renovate-d26eca1.md new file mode 100644 index 0000000000..6ddad0d5fe --- /dev/null +++ b/.changeset/renovate-d26eca1.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-adr': patch +'@backstage/plugin-scaffolder-backend': patch +--- + +Updated dependency `octokit` to `^2.0.0`. diff --git a/plugins/adr/package.json b/plugins/adr/package.json index 80d24e7223..9f25ce4c61 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -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", diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 6f3aea1844..36b7f9597f 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -65,7 +65,7 @@ "morgan": "^1.10.0", "node-fetch": "^2.6.7", "nunjucks": "^3.2.3", - "octokit": "^1.7.1", + "octokit": "^2.0.0", "octokit-plugin-create-pull-request": "^3.10.0", "p-limit": "^3.1.0", "uuid": "^8.2.0", diff --git a/yarn.lock b/yarn.lock index e6480c9628..0a943605b0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4871,20 +4871,20 @@ consola "^2.15.0" node-fetch "^2.6.1" -"@octokit/app@^12.0.4": - version "12.0.5" - resolved "https://registry.npmjs.org/@octokit/app/-/app-12.0.5.tgz#0b25446daffcb36967b26944410eab1ccbba0c06" - integrity sha512-lM3pIfx2h+UbvsXHFVs1ApJ9Rmp8LO4ciFSr5q/9MdHmhsH6WtwayieUn875xwB77IoR9r8czxxxASu2WCtdeA== +"@octokit/app@^13.0.0": + version "13.0.3" + resolved "https://registry.npmjs.org/@octokit/app/-/app-13.0.3.tgz#6a438e2ab555a27f09f48e4887e650bdce0347eb" + integrity sha512-eJA7jtKtTTYTfVxf/gBmxLpYjAud4FXQdMMY89AuMcyFboHS9XsI/zUJ0xXdMW0G4yNKPxqAt+KWsUJivtrXpA== dependencies: - "@octokit/auth-app" "^3.3.0" - "@octokit/auth-unauthenticated" "^2.0.4" - "@octokit/core" "^3.4.0" + "@octokit/auth-app" "^4.0.0" + "@octokit/auth-unauthenticated" "^3.0.0" + "@octokit/core" "^4.0.0" "@octokit/oauth-app" "^3.3.2" "@octokit/plugin-paginate-rest" "^2.13.3" "@octokit/types" "^6.27.1" - "@octokit/webhooks" "^9.0.1" + "@octokit/webhooks" "^10.0.0" -"@octokit/auth-app@^3.3.0", "@octokit/auth-app@^3.4.0": +"@octokit/auth-app@^3.4.0": version "3.6.1" resolved "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-3.6.1.tgz#aa5b02cc211175cbc28ce6c03c73373c1206d632" integrity sha512-6oa6CFphIYI7NxxHrdVOzhG7hkcKyGyYocg7lNDSJVauVOLtylg8hNJzoUyPAYKKK0yUeoZamE/lMs2tG+S+JA== @@ -4982,7 +4982,14 @@ dependencies: "@octokit/types" "^6.0.0" -"@octokit/auth-unauthenticated@^2.0.0", "@octokit/auth-unauthenticated@^2.0.4": +"@octokit/auth-token@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.0.tgz#6f22c5fc56445c496628488ba6810131558fa4a9" + integrity sha512-MDNFUBcJIptB9At7HiV7VCvU3NcL4GnfCQaP8C5lrxWrRPMJBnemYtehaKSOlaM7AYxeRyj9etenu8LVpSpVaQ== + dependencies: + "@octokit/types" "^6.0.3" + +"@octokit/auth-unauthenticated@^2.0.0": version "2.1.0" resolved "https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-2.1.0.tgz#ef97de366836e09f130de4e2205be955f9cf131c" integrity sha512-+baofLfSL0CAv3CfGQ9rxiZZQEX8VNJMGuuS4PgrMRBUL52Ho5+hQYb63UJQshw7EXYMPDZxbXznc0y33cbPqw== @@ -4990,6 +4997,14 @@ "@octokit/request-error" "^2.1.0" "@octokit/types" "^6.0.3" +"@octokit/auth-unauthenticated@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@octokit/auth-unauthenticated/-/auth-unauthenticated-3.0.0.tgz#6ef7039c11c7e0dd46dd1cabff8aa4bff4f976a1" + integrity sha512-d5qrT3f4HJDCg2uVmmTYfuP3WnBVf6OvWAZkV3NmLANqg3/yae7yUxS8XHpOwZdTh1CNVuF9riJ/UugyjDKKhA== + dependencies: + "@octokit/request-error" "^2.1.0" + "@octokit/types" "^6.0.3" + "@octokit/core@^3.2.3": version "3.2.4" resolved "https://registry.npmjs.org/@octokit/core/-/core-3.2.4.tgz#5791256057a962eca972e31818f02454897fd106" @@ -5002,7 +5017,7 @@ before-after-hook "^2.1.0" universal-user-agent "^6.0.0" -"@octokit/core@^3.3.2", "@octokit/core@^3.4.0", "@octokit/core@^3.5.1": +"@octokit/core@^3.3.2", "@octokit/core@^3.5.1": version "3.5.1" resolved "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz#8601ceeb1ec0e1b1b8217b960a413ed8e947809b" integrity sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw== @@ -5015,6 +5030,19 @@ before-after-hook "^2.2.0" universal-user-agent "^6.0.0" +"@octokit/core@^4.0.0": + version "4.0.2" + resolved "https://registry.npmjs.org/@octokit/core/-/core-4.0.2.tgz#4eaf9c5fd39913b541c5e31a2b8fdc3cf50480bc" + integrity sha512-vgVtE02EF9kXFsjmFoKFCwH1wDspPfDgopRbAlavkGuBJPWF+u5n0xgwP4obmdKNvLM+bB7MI7W31c2E13zgDQ== + dependencies: + "@octokit/auth-token" "^3.0.0" + "@octokit/graphql" "^4.5.8" + "@octokit/request" "^6.0.0" + "@octokit/request-error" "^2.0.5" + "@octokit/types" "^6.0.3" + before-after-hook "^2.2.0" + universal-user-agent "^6.0.0" + "@octokit/endpoint@^6.0.1": version "6.0.3" resolved "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.3.tgz#dd09b599662d7e1b66374a177ab620d8cdf73487" @@ -5172,10 +5200,10 @@ "@octokit/types" "^6.0.3" bottleneck "^2.15.3" -"@octokit/plugin-throttling@^3.5.1": - version "3.5.2" - resolved "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-3.5.2.tgz#8b1797a5f14edbca0b8af619394056ed0ed5c9b5" - integrity sha512-Eu7kfJxU8vmHqWGNszWpg+GVp2tnAfax3XQV5CkYPEE69C+KvInJXW9WajgSeW+cxYe0UVdouzCtcreGNuJo7A== +"@octokit/plugin-throttling@^4.0.0": + version "4.0.1" + resolved "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-4.0.1.tgz#06cd4af959a98fe601d780d3476063f249b5eec1" + integrity sha512-CWAM7+3XkkmzwAd4FrI4+ogOd5oAmMJER8/6AYDTb4ErGuvSdSSGeI5jFw6quNj7qNV7TvSWLTnNgRjSdBEE2A== dependencies: "@octokit/types" "^6.0.1" bottleneck "^2.15.3" @@ -5261,21 +5289,11 @@ dependencies: "@octokit/openapi-types" "^12.4.0" -"@octokit/webhooks-methods@^2.0.0": - version "2.0.0" - resolved "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-2.0.0.tgz#1108b9ea661ca6c81e4a8bfa63a09eb27d5bc2db" - integrity sha512-35cfQ4YWlnZnmZKmIxlGPUPLtbkF8lr/A/1Sk1eC0ddLMwQN06dOuLc+dI3YLQS+T+MoNt3DIQ0NynwgKPilig== - "@octokit/webhooks-methods@^3.0.0": version "3.0.0" resolved "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-3.0.0.tgz#4f4443605233f46abc5f85a857ba105095aa1181" integrity sha512-FAIyAchH9JUKXugKMC17ERAXM/56vVJekwXOON46pmUDYfU7uXB4cFY8yc8nYr5ABqVI7KjRKfFt3mZF7OcyUA== -"@octokit/webhooks-types@5.8.0": - version "5.8.0" - resolved "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-5.8.0.tgz#b76d1a3e3ad82cec5680d3c6c3443a620047a6ef" - integrity sha512-8adktjIb76A7viIdayQSFuBEwOzwhDC+9yxZpKNHjfzrlostHCw0/N7JWpWMObfElwvJMk2fY2l1noENCk9wmw== - "@octokit/webhooks-types@6.2.2": version "6.2.2" resolved "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-6.2.2.tgz#adbec417f2061c3148d757bf39f8831af6d45b68" @@ -5291,16 +5309,6 @@ "@octokit/webhooks-types" "6.2.2" aggregate-error "^3.1.0" -"@octokit/webhooks@^9.0.1": - version "9.26.0" - resolved "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-9.26.0.tgz#cf453bb313da3b66f1a90c84464d978e1c625cce" - integrity sha512-foZlsgrTDwAmD5j2Czn6ji10lbWjGDVsUxTIydjG9KTkAWKJrFapXJgO5SbGxRwfPd3OJdhK3nA2YPqVhxLXqA== - dependencies: - "@octokit/request-error" "^2.0.2" - "@octokit/webhooks-methods" "^2.0.0" - "@octokit/webhooks-types" "5.8.0" - aggregate-error "^3.1.0" - "@open-draft/until@^1.0.3": version "1.0.3" resolved "https://registry.npmjs.org/@open-draft/until/-/until-1.0.3.tgz#db9cc719191a62e7d9200f6e7bab21c5b848adca" @@ -19764,18 +19772,18 @@ octokit-plugin-create-pull-request@^3.10.0: dependencies: "@octokit/types" "^6.8.2" -octokit@^1.7.1: - version "1.8.1" - resolved "https://registry.npmjs.org/octokit/-/octokit-1.8.1.tgz#399b0032e89e058084a1a1922e40a02e87d4cd61" - integrity sha512-xBLKFIivbl7wnLwxzLYuDO/JDNYxdyxoSjFrl/QMrY/fwGGQYYklvKUDTUyGMU0aXPrQtJ0IZnG3BXpCkDQzWg== +octokit@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/octokit/-/octokit-2.0.2.tgz#46a8d4da3fd12933fc495971470e191af4d9a54c" + integrity sha512-YQ3ysVawtMVp1Tjf0uITLtUW7kf+SGhelgT0xuk25frUNf7sotGxO5wm7XvnEvNL4nnlp1mF2UxqG05dto2iyg== dependencies: - "@octokit/app" "^12.0.4" + "@octokit/app" "^13.0.0" "@octokit/core" "^3.5.1" "@octokit/oauth-app" "^3.5.1" "@octokit/plugin-paginate-rest" "^2.18.0" "@octokit/plugin-rest-endpoint-methods" "^5.14.0" "@octokit/plugin-retry" "^3.0.9" - "@octokit/plugin-throttling" "^3.5.1" + "@octokit/plugin-throttling" "^4.0.0" "@octokit/types" "^6.35.0" oidc-token-hash@^5.0.1: From 3d5b0042b63cf149eddc3f96253f387e6b569026 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 8 Jul 2022 10:32:54 +0000 Subject: [PATCH 20/59] fix(deps): update dependency @codemirror/view to v6.0.3 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 28396aeae0..09ea7e88de 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2041,9 +2041,9 @@ "@lezer/highlight" "^1.0.0" "@codemirror/view@^6.0.0": - version "6.0.2" - resolved "https://registry.npmjs.org/@codemirror/view/-/view-6.0.2.tgz#27f4d08edd10a3678cf15390b4fba5e2a7220873" - integrity sha512-mnVT/q1JvKPjpmjXJNeCi/xHyaJ3abGJsumIVpdQ1nE1MXAyHf7GHWt8QpWMUvDiqF0j+inkhVR2OviTdFFX7Q== + version "6.0.3" + resolved "https://registry.npmjs.org/@codemirror/view/-/view-6.0.3.tgz#c0f6cf5c66d76cbe64227717708a714338ac76a4" + integrity sha512-1gDBymhbx2DZzwnR/rNUu1LiQqjxBJtFiB+4uLR6tHQ6vKhTIwUsP5uZUQ7SM7JxVx3UihMynnTqjcsC+mczZg== dependencies: "@codemirror/state" "^6.0.0" style-mod "^4.0.0" From a6c224834cb9cba4df630b4de96c95e937945e17 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 8 Jul 2022 13:04:58 +0200 Subject: [PATCH 21/59] workflows/pr: fix owning teams Signed-off-by: Patrik Oldsberg --- .github/workflows/pr.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 1444559a68..4fa8a60577 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -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' From c456746f25a9712361cd11cd631dc0828d8b354f Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 8 Jul 2022 13:51:52 +0200 Subject: [PATCH 22/59] chore: only bump create-app on main release branch Signed-off-by: blam --- scripts/prepare-release.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/prepare-release.js b/scripts/prepare-release.js index e4c987733d..962d54abb0 100755 --- a/scripts/prepare-release.js +++ b/scripts/prepare-release.js @@ -394,10 +394,10 @@ async function main() { if (isMainBranch) { console.log('Main release, updating package versions'); await updatePackageVersions(repo); + await ensureCreateAppChangeset(); } await updateBackstageReleaseVersion(repo, isMainBranch ? 'minor' : 'patch'); - await ensureCreateAppChangeset(); } main().catch(error => { From b4b92e6325b79d601700b9ba671a5c79b149823a Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 8 Jul 2022 13:54:50 +0200 Subject: [PATCH 23/59] chore: moving around some changelog entries to their correct place Signed-off-by: blam --- plugins/scaffolder-backend/CHANGELOG.md | 5 +---- plugins/scaffolder/CHANGELOG.md | 9 +++------ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index ed97db5617..2ac49898d2 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -40,10 +40,6 @@ ## 1.4.0-next.0 -### Minor Changes - -- 3500c13a33: 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. - ### Patch Changes - Updated dependencies @@ -86,6 +82,7 @@ - Added a route under `/v2/tasks` to list tasks by a `userEntityRef` using the `createdBy` query parameter - c042c5eaff: Add an option to not protect the default branch. - f93af969cd: Added the ability to support running of templates that are not in the `default` namespace +- 3500c13a33: 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. ### Patch Changes diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index a8a606c73d..26a08c4b68 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -44,12 +44,6 @@ ## 1.4.0-next.0 -### Minor Changes - -- 3500c13a33: 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`. - ### Patch Changes - 37539e29d8: The template editor now shows the cause of request errors that happen during a dry-run. @@ -92,6 +86,9 @@ - 72dfcbc8bf: Gerrit Integration: Implemented a `RepoUrlPicker` for Gerrit. - f93af969cd: Added the ability to support running of templates that are not in the `default` namespace +- 3500c13a33: 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`. ### Patch Changes From f0feea36c4d9cdd74a01e868b1a9cbd6fd84e8ae Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 8 Jul 2022 13:59:15 +0200 Subject: [PATCH 24/59] remove the old changesets that have already been released Signed-off-by: blam --- .changeset/eleven-mice-collect.md | 5 ----- .changeset/polite-eagles-invite.md | 7 ------- .changeset/pre.json | 2 -- 3 files changed, 14 deletions(-) delete mode 100644 .changeset/eleven-mice-collect.md delete mode 100644 .changeset/polite-eagles-invite.md diff --git a/.changeset/eleven-mice-collect.md b/.changeset/eleven-mice-collect.md deleted file mode 100644 index 66c4591d8e..0000000000 --- a/.changeset/eleven-mice-collect.md +++ /dev/null @@ -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. diff --git a/.changeset/polite-eagles-invite.md b/.changeset/polite-eagles-invite.md deleted file mode 100644 index f9c5073a83..0000000000 --- a/.changeset/polite-eagles-invite.md +++ /dev/null @@ -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`. diff --git a/.changeset/pre.json b/.changeset/pre.json index 7b30cba7ba..1b03a40575 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -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", From 9a6aba1d8579083212fd7be33647242e78ca6f08 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 8 Jul 2022 11:47:30 +0200 Subject: [PATCH 25/59] add new catalog-node package Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- .changeset/loud-lemons-listen.md | 5 + .changeset/twelve-peaches-tickle.md | 5 + plugins/catalog-backend/api-report.md | 165 ++++-------------- plugins/catalog-backend/package.json | 1 + .../src/database/DefaultProcessingDatabase.ts | 2 +- plugins/catalog-backend/src/database/types.ts | 7 +- plugins/catalog-backend/src/index.ts | 21 ++- .../src/ingestion/CatalogRules.test.ts | 2 +- .../src/ingestion/CatalogRules.ts | 2 +- .../catalog-backend/src/ingestion/types.ts | 2 +- .../codeowners/CodeOwnersProcessor.test.ts | 2 +- .../modules/codeowners/CodeOwnersProcessor.ts | 2 +- .../AnnotateLocationEntityProcessor.test.ts | 2 +- .../core/AnnotateLocationEntityProcessor.ts | 2 +- .../AnnotateScmSlugEntityProcessor.test.ts | 2 +- .../core/AnnotateScmSlugEntityProcessor.ts | 2 +- .../core/BuiltinKindsEntityProcessor.ts | 2 +- .../core/ConfigLocationEntityProvider.test.ts | 2 +- .../core/ConfigLocationEntityProvider.ts | 5 +- .../src/modules/core/DefaultLocationStore.ts | 5 +- .../modules/core/FileReaderProcessor.test.ts | 2 +- .../src/modules/core/FileReaderProcessor.ts | 2 +- .../core/LocationEntityProcessor.test.ts | 2 +- .../modules/core/LocationEntityProcessor.ts | 2 +- .../modules/core/PlaceholderProcessor.test.ts | 2 +- .../src/modules/core/PlaceholderProcessor.ts | 2 +- .../modules/core/UrlReaderProcessor.test.ts | 2 +- .../src/modules/core/UrlReaderProcessor.ts | 2 +- .../src/modules/util/parse.test.ts | 2 +- .../catalog-backend/src/modules/util/parse.ts | 2 +- ...faultCatalogProcessingOrchestrator.test.ts | 2 +- .../DefaultCatalogProcessingOrchestrator.ts | 2 +- .../processing/ProcessorCacheManager.test.ts | 2 +- .../src/processing/ProcessorCacheManager.ts | 5 +- .../processing/ProcessorOutputCollector.ts | 8 +- .../src/processing/connectEntityProviders.ts | 2 +- .../catalog-backend/src/processing/index.ts | 2 +- .../catalog-backend/src/processing/types.ts | 15 +- .../catalog-backend/src/processing/util.ts | 2 +- .../src/service/CatalogBuilder.ts | 2 +- .../src/service/DefaultLocationService.ts | 6 +- .../catalog-backend/src/util/conversion.ts | 2 +- plugins/catalog-node/.eslintrc.js | 1 + plugins/catalog-node/README.md | 3 + plugins/catalog-node/api-report.md | 158 +++++++++++++++++ plugins/catalog-node/package.json | 40 +++++ .../src/api/common.ts | 0 .../src/api/index.ts | 0 .../src/api/processingResult.ts | 0 .../src/api/processor.ts | 0 .../src/api/provider.ts | 0 plugins/catalog-node/src/index.ts | 24 +++ plugins/catalog-node/src/processing/index.ts | 17 ++ plugins/catalog-node/src/processing/types.ts | 26 +++ 54 files changed, 393 insertions(+), 184 deletions(-) create mode 100644 .changeset/loud-lemons-listen.md create mode 100644 .changeset/twelve-peaches-tickle.md create mode 100644 plugins/catalog-node/.eslintrc.js create mode 100644 plugins/catalog-node/README.md create mode 100644 plugins/catalog-node/api-report.md create mode 100644 plugins/catalog-node/package.json rename plugins/{catalog-backend => catalog-node}/src/api/common.ts (100%) rename plugins/{catalog-backend => catalog-node}/src/api/index.ts (100%) rename plugins/{catalog-backend => catalog-node}/src/api/processingResult.ts (100%) rename plugins/{catalog-backend => catalog-node}/src/api/processor.ts (100%) rename plugins/{catalog-backend => catalog-node}/src/api/provider.ts (100%) create mode 100644 plugins/catalog-node/src/index.ts create mode 100644 plugins/catalog-node/src/processing/index.ts create mode 100644 plugins/catalog-node/src/processing/types.ts diff --git a/.changeset/loud-lemons-listen.md b/.changeset/loud-lemons-listen.md new file mode 100644 index 0000000000..f232c1491e --- /dev/null +++ b/.changeset/loud-lemons-listen.md @@ -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. diff --git a/.changeset/twelve-peaches-tickle.md b/.changeset/twelve-peaches-tickle.md new file mode 100644 index 0000000000..2a7814ea06 --- /dev/null +++ b/.changeset/twelve-peaches-tickle.md @@ -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`. diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index 09ca4d8dfe..3bd9504bea 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -7,16 +7,31 @@ 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 +41,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'; @@ -207,86 +223,25 @@ export interface CatalogProcessingEngine { stop(): Promise; } -// @public (undocumented) -export type CatalogProcessor = { - getProcessorName(): string; - readLocation?( - location: LocationSpec, - optional: boolean, - emit: CatalogProcessorEmit, - parser: CatalogProcessorParser, - cache: CatalogProcessorCache, - ): Promise; - preProcessEntity?( - entity: Entity, - location: LocationSpec, - emit: CatalogProcessorEmit, - originLocation: LocationSpec, - cache: CatalogProcessorCache, - ): Promise; - validateEntityKind?(entity: Entity): Promise; - postProcessEntity?( - entity: Entity, - location: LocationSpec, - emit: CatalogProcessorEmit, - cache: CatalogProcessorCache, - ): Promise; -}; +export { CatalogProcessor }; -// @public -export interface CatalogProcessorCache { - get(key: string): Promise; - set(key: string, value: ItemType): Promise; -} +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; +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 +349,7 @@ export type DefaultCatalogCollatorFactoryOptions = { catalogClient?: CatalogApi; }; -// @public -export type DeferredEntity = { - entity: Entity; - locationKey?: string; -}; +export { DeferredEntity }; // @public export type EntitiesSearchFilter = { @@ -419,35 +370,13 @@ export type EntityFilter = } | EntitiesSearchFilter; -// @public -export interface EntityProvider { - connect(connection: EntityProviderConnection): Promise; - getProviderName(): string; -} +export { EntityProvider }; -// @public -export interface EntityProviderConnection { - applyMutation(mutation: EntityProviderMutation): Promise; -} +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 +416,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 +517,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 { diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index ebed76ca90..3177782289 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -34,6 +34,7 @@ "clean": "backstage-cli package clean" }, "dependencies": { + "@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", diff --git a/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts index 903dd59e9e..c9b71d096d 100644 --- a/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts @@ -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 diff --git a/plugins/catalog-backend/src/database/types.ts b/plugins/catalog-backend/src/database/types.ts index 8a839c0650..07241f0682 100644 --- a/plugins/catalog-backend/src/database/types.ts +++ b/plugins/catalog-backend/src/database/types.ts @@ -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. diff --git a/plugins/catalog-backend/src/index.ts b/plugins/catalog-backend/src/index.ts index c5c653f0dd..88696498d0 100644 --- a/plugins/catalog-backend/src/index.ts +++ b/plugins/catalog-backend/src/index.ts @@ -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'; diff --git a/plugins/catalog-backend/src/ingestion/CatalogRules.test.ts b/plugins/catalog-backend/src/ingestion/CatalogRules.test.ts index 13430f51dd..2592b8b94b 100644 --- a/plugins/catalog-backend/src/ingestion/CatalogRules.test.ts +++ b/plugins/catalog-backend/src/ingestion/CatalogRules.test.ts @@ -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: { diff --git a/plugins/catalog-backend/src/ingestion/CatalogRules.ts b/plugins/catalog-backend/src/ingestion/CatalogRules.ts index 587a0bd7d5..ce226bd09d 100644 --- a/plugins/catalog-backend/src/ingestion/CatalogRules.ts +++ b/plugins/catalog-backend/src/ingestion/CatalogRules.ts @@ -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. diff --git a/plugins/catalog-backend/src/ingestion/types.ts b/plugins/catalog-backend/src/ingestion/types.ts index 6d1e9a3927..2602bd080f 100644 --- a/plugins/catalog-backend/src/ingestion/types.ts +++ b/plugins/catalog-backend/src/ingestion/types.ts @@ -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 = { diff --git a/plugins/catalog-backend/src/modules/codeowners/CodeOwnersProcessor.test.ts b/plugins/catalog-backend/src/modules/codeowners/CodeOwnersProcessor.test.ts index ac4415549e..71154c5473 100644 --- a/plugins/catalog-backend/src/modules/codeowners/CodeOwnersProcessor.test.ts +++ b/plugins/catalog-backend/src/modules/codeowners/CodeOwnersProcessor.test.ts @@ -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 diff --git a/plugins/catalog-backend/src/modules/codeowners/CodeOwnersProcessor.ts b/plugins/catalog-backend/src/modules/codeowners/CodeOwnersProcessor.ts index 6f6aee7161..63f3d406f5 100644 --- a/plugins/catalog-backend/src/modules/codeowners/CodeOwnersProcessor.ts +++ b/plugins/catalog-backend/src/modules/codeowners/CodeOwnersProcessor.ts @@ -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']; diff --git a/plugins/catalog-backend/src/modules/core/AnnotateLocationEntityProcessor.test.ts b/plugins/catalog-backend/src/modules/core/AnnotateLocationEntityProcessor.test.ts index 3911f7f743..228429c647 100644 --- a/plugins/catalog-backend/src/modules/core/AnnotateLocationEntityProcessor.test.ts +++ b/plugins/catalog-backend/src/modules/core/AnnotateLocationEntityProcessor.test.ts @@ -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', () => { diff --git a/plugins/catalog-backend/src/modules/core/AnnotateLocationEntityProcessor.ts b/plugins/catalog-backend/src/modules/core/AnnotateLocationEntityProcessor.ts index 4af0b8cf61..a86525429e 100644 --- a/plugins/catalog-backend/src/modules/core/AnnotateLocationEntityProcessor.ts +++ b/plugins/catalog-backend/src/modules/core/AnnotateLocationEntityProcessor.ts @@ -29,7 +29,7 @@ import { CatalogProcessor, CatalogProcessorEmit, LocationSpec, -} from '../../api'; +} from '@backstage/plugin-catalog-node'; /** @public */ export class AnnotateLocationEntityProcessor implements CatalogProcessor { diff --git a/plugins/catalog-backend/src/modules/core/AnnotateScmSlugEntityProcessor.test.ts b/plugins/catalog-backend/src/modules/core/AnnotateScmSlugEntityProcessor.test.ts index 7fd6514bb8..6154d82330 100644 --- a/plugins/catalog-backend/src/modules/core/AnnotateScmSlugEntityProcessor.test.ts +++ b/plugins/catalog-backend/src/modules/core/AnnotateScmSlugEntityProcessor.test.ts @@ -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', () => { diff --git a/plugins/catalog-backend/src/modules/core/AnnotateScmSlugEntityProcessor.ts b/plugins/catalog-backend/src/modules/core/AnnotateScmSlugEntityProcessor.ts index c4f7218896..41e75e5e8e 100644 --- a/plugins/catalog-backend/src/modules/core/AnnotateScmSlugEntityProcessor.ts +++ b/plugins/catalog-backend/src/modules/core/AnnotateScmSlugEntityProcessor.ts @@ -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'; diff --git a/plugins/catalog-backend/src/modules/core/BuiltinKindsEntityProcessor.ts b/plugins/catalog-backend/src/modules/core/BuiltinKindsEntityProcessor.ts index 4e8cf3fef7..6e05daf591 100644 --- a/plugins/catalog-backend/src/modules/core/BuiltinKindsEntityProcessor.ts +++ b/plugins/catalog-backend/src/modules/core/BuiltinKindsEntityProcessor.ts @@ -53,7 +53,7 @@ import { CatalogProcessorEmit, LocationSpec, processingResult, -} from '../../api'; +} from '@backstage/plugin-catalog-node'; /** @public */ export class BuiltinKindsEntityProcessor implements CatalogProcessor { diff --git a/plugins/catalog-backend/src/modules/core/ConfigLocationEntityProvider.test.ts b/plugins/catalog-backend/src/modules/core/ConfigLocationEntityProvider.test.ts index d61342e3d0..d40c32dfc9 100644 --- a/plugins/catalog-backend/src/modules/core/ConfigLocationEntityProvider.test.ts +++ b/plugins/catalog-backend/src/modules/core/ConfigLocationEntityProvider.test.ts @@ -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 () => { diff --git a/plugins/catalog-backend/src/modules/core/ConfigLocationEntityProvider.ts b/plugins/catalog-backend/src/modules/core/ConfigLocationEntityProvider.ts index 69827b1380..38f02195f3 100644 --- a/plugins/catalog-backend/src/modules/core/ConfigLocationEntityProvider.ts +++ b/plugins/catalog-backend/src/modules/core/ConfigLocationEntityProvider.ts @@ -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 { diff --git a/plugins/catalog-backend/src/modules/core/DefaultLocationStore.ts b/plugins/catalog-backend/src/modules/core/DefaultLocationStore.ts index 33ab046104..cf5db78203 100644 --- a/plugins/catalog-backend/src/modules/core/DefaultLocationStore.ts +++ b/plugins/catalog-backend/src/modules/core/DefaultLocationStore.ts @@ -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'; diff --git a/plugins/catalog-backend/src/modules/core/FileReaderProcessor.test.ts b/plugins/catalog-backend/src/modules/core/FileReaderProcessor.test.ts index 0c114f49a1..3e92bf2b35 100644 --- a/plugins/catalog-backend/src/modules/core/FileReaderProcessor.test.ts +++ b/plugins/catalog-backend/src/modules/core/FileReaderProcessor.test.ts @@ -19,7 +19,7 @@ import { CatalogProcessorEntityResult, CatalogProcessorErrorResult, CatalogProcessorResult, -} from '../../api'; +} from '@backstage/plugin-catalog-node'; import path from 'path'; import { defaultEntityDataParser } from '../util/parse'; diff --git a/plugins/catalog-backend/src/modules/core/FileReaderProcessor.ts b/plugins/catalog-backend/src/modules/core/FileReaderProcessor.ts index 8ececed59f..af6fba52c0 100644 --- a/plugins/catalog-backend/src/modules/core/FileReaderProcessor.ts +++ b/plugins/catalog-backend/src/modules/core/FileReaderProcessor.ts @@ -24,7 +24,7 @@ import { CatalogProcessorParser, LocationSpec, processingResult, -} from '../../api'; +} from '@backstage/plugin-catalog-node'; const glob = promisify(g); diff --git a/plugins/catalog-backend/src/modules/core/LocationEntityProcessor.test.ts b/plugins/catalog-backend/src/modules/core/LocationEntityProcessor.test.ts index 92ba1fcebf..8f3de7e29b 100644 --- a/plugins/catalog-backend/src/modules/core/LocationEntityProcessor.test.ts +++ b/plugins/catalog-backend/src/modules/core/LocationEntityProcessor.test.ts @@ -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', () => { diff --git a/plugins/catalog-backend/src/modules/core/LocationEntityProcessor.ts b/plugins/catalog-backend/src/modules/core/LocationEntityProcessor.ts index c168f54bf1..3676b4f727 100644 --- a/plugins/catalog-backend/src/modules/core/LocationEntityProcessor.ts +++ b/plugins/catalog-backend/src/modules/core/LocationEntityProcessor.ts @@ -22,7 +22,7 @@ import { CatalogProcessor, CatalogProcessorEmit, LocationSpec, -} from '../../api'; +} from '@backstage/plugin-catalog-node'; export function toAbsoluteUrl( integrations: ScmIntegrationRegistry, diff --git a/plugins/catalog-backend/src/modules/core/PlaceholderProcessor.test.ts b/plugins/catalog-backend/src/modules/core/PlaceholderProcessor.test.ts index 9bfa9027d9..c4d71c87f5 100644 --- a/plugins/catalog-backend/src/modules/core/PlaceholderProcessor.test.ts +++ b/plugins/catalog-backend/src/modules/core/PlaceholderProcessor.test.ts @@ -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, diff --git a/plugins/catalog-backend/src/modules/core/PlaceholderProcessor.ts b/plugins/catalog-backend/src/modules/core/PlaceholderProcessor.ts index be2e9f9f5b..39c9dc59ec 100644 --- a/plugins/catalog-backend/src/modules/core/PlaceholderProcessor.ts +++ b/plugins/catalog-backend/src/modules/core/PlaceholderProcessor.ts @@ -24,7 +24,7 @@ import { CatalogProcessorEmit, LocationSpec, processingResult, -} from '../../api'; +} from '@backstage/plugin-catalog-node'; /** @public */ export type PlaceholderResolverRead = (url: string) => Promise; diff --git a/plugins/catalog-backend/src/modules/core/UrlReaderProcessor.test.ts b/plugins/catalog-backend/src/modules/core/UrlReaderProcessor.test.ts index fb3f48c939..ee68b2aa39 100644 --- a/plugins/catalog-backend/src/modules/core/UrlReaderProcessor.test.ts +++ b/plugins/catalog-backend/src/modules/core/UrlReaderProcessor.test.ts @@ -28,7 +28,7 @@ import { CatalogProcessorEntityResult, CatalogProcessorErrorResult, CatalogProcessorResult, -} from '../../api'; +} from '@backstage/plugin-catalog-node'; import { defaultEntityDataParser } from '../util/parse'; import { UrlReaderProcessor } from './UrlReaderProcessor'; diff --git a/plugins/catalog-backend/src/modules/core/UrlReaderProcessor.ts b/plugins/catalog-backend/src/modules/core/UrlReaderProcessor.ts index 7b62690341..0ecd6d5a42 100644 --- a/plugins/catalog-backend/src/modules/core/UrlReaderProcessor.ts +++ b/plugins/catalog-backend/src/modules/core/UrlReaderProcessor.ts @@ -29,7 +29,7 @@ import { CatalogProcessorResult, LocationSpec, processingResult, -} from '../../api'; +} from '@backstage/plugin-catalog-node'; const CACHE_KEY = 'v1'; diff --git a/plugins/catalog-backend/src/modules/util/parse.test.ts b/plugins/catalog-backend/src/modules/util/parse.test.ts index e87de1c9a3..e9a2a4e464 100644 --- a/plugins/catalog-backend/src/modules/util/parse.test.ts +++ b/plugins/catalog-backend/src/modules/util/parse.test.ts @@ -15,7 +15,7 @@ */ import { parseEntityYaml } from './parse'; -import { processingResult } from '../../api'; +import { processingResult } from '@backstage/plugin-catalog-node'; const testLoc = { target: 'my-loc-target', diff --git a/plugins/catalog-backend/src/modules/util/parse.ts b/plugins/catalog-backend/src/modules/util/parse.ts index 65fad5986f..d3aa915e49 100644 --- a/plugins/catalog-backend/src/modules/util/parse.ts +++ b/plugins/catalog-backend/src/modules/util/parse.ts @@ -22,7 +22,7 @@ import { CatalogProcessorResult, LocationSpec, processingResult, -} from '../../api'; +} from '@backstage/plugin-catalog-node'; /** @public */ export function* parseEntityYaml( diff --git a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.test.ts b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.test.ts index b2d9846391..30c668bb38 100644 --- a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.test.ts +++ b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.test.ts @@ -30,7 +30,7 @@ import { CatalogProcessorParser, LocationSpec, processingResult, -} from '../api'; +} from '@backstage/plugin-catalog-node'; import { CatalogRulesEnforcer } from '../ingestion/CatalogRules'; import { DefaultCatalogProcessingOrchestrator } from './DefaultCatalogProcessingOrchestrator'; import { defaultEntityDataParser } from '../modules/util/parse'; diff --git a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.ts b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.ts index 156503da8e..9effaeb3d9 100644 --- a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.ts +++ b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.ts @@ -37,7 +37,7 @@ import { CatalogProcessorParser, LocationSpec, processingResult, -} from '../api'; +} from '@backstage/plugin-catalog-node'; import { CatalogProcessingOrchestrator, EntityProcessingRequest, diff --git a/plugins/catalog-backend/src/processing/ProcessorCacheManager.test.ts b/plugins/catalog-backend/src/processing/ProcessorCacheManager.test.ts index 602557a224..a15ca3c364 100644 --- a/plugins/catalog-backend/src/processing/ProcessorCacheManager.test.ts +++ b/plugins/catalog-backend/src/processing/ProcessorCacheManager.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { CatalogProcessor } from '../api'; +import { CatalogProcessor } from '@backstage/plugin-catalog-node'; import { ProcessorCacheManager } from './ProcessorCacheManager'; class MyProcessor implements CatalogProcessor { diff --git a/plugins/catalog-backend/src/processing/ProcessorCacheManager.ts b/plugins/catalog-backend/src/processing/ProcessorCacheManager.ts index e54641f572..8e0e382910 100644 --- a/plugins/catalog-backend/src/processing/ProcessorCacheManager.ts +++ b/plugins/catalog-backend/src/processing/ProcessorCacheManager.ts @@ -15,7 +15,10 @@ */ import { JsonObject, JsonValue } from '@backstage/types'; -import { CatalogProcessor, CatalogProcessorCache } from '../api'; +import { + CatalogProcessor, + CatalogProcessorCache, +} from '@backstage/plugin-catalog-node'; import { isObject } from './util'; class SingleProcessorSubCache implements CatalogProcessorCache { diff --git a/plugins/catalog-backend/src/processing/ProcessorOutputCollector.ts b/plugins/catalog-backend/src/processing/ProcessorOutputCollector.ts index 033dfd4ae3..19f3b33df4 100644 --- a/plugins/catalog-backend/src/processing/ProcessorOutputCollector.ts +++ b/plugins/catalog-backend/src/processing/ProcessorOutputCollector.ts @@ -22,14 +22,18 @@ import { } from '@backstage/catalog-model'; import { assertError } from '@backstage/errors'; import { Logger } from 'winston'; -import { CatalogProcessorResult, EntityRelationSpec } from '../api'; +import { + CatalogProcessorResult, + DeferredEntity, + EntityRelationSpec, +} from '@backstage/plugin-catalog-node'; import { locationSpecToLocationEntity } from '../util/conversion'; -import { DeferredEntity, RefreshKeyData } from './types'; import { getEntityLocationRef, getEntityOriginLocationRef, validateEntityEnvelope, } from './util'; +import { RefreshKeyData } from './types'; /** * Helper class for aggregating all of the emitted data from processors. diff --git a/plugins/catalog-backend/src/processing/connectEntityProviders.ts b/plugins/catalog-backend/src/processing/connectEntityProviders.ts index d7015ea52e..70a43de589 100644 --- a/plugins/catalog-backend/src/processing/connectEntityProviders.ts +++ b/plugins/catalog-backend/src/processing/connectEntityProviders.ts @@ -23,7 +23,7 @@ import { EntityProvider, EntityProviderConnection, EntityProviderMutation, -} from '../api'; +} from '@backstage/plugin-catalog-node'; class Connection implements EntityProviderConnection { readonly validateEntityEnvelope = entityEnvelopeSchemaValidator(); diff --git a/plugins/catalog-backend/src/processing/index.ts b/plugins/catalog-backend/src/processing/index.ts index b392c3aa76..5ed8831779 100644 --- a/plugins/catalog-backend/src/processing/index.ts +++ b/plugins/catalog-backend/src/processing/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -export type { CatalogProcessingEngine, DeferredEntity } from './types'; +export type { CatalogProcessingEngine } from './types'; export { createRandomProcessingInterval } from './refresh'; export type { ProcessingIntervalFunction } from './refresh'; diff --git a/plugins/catalog-backend/src/processing/types.ts b/plugins/catalog-backend/src/processing/types.ts index e94125b6f5..20dfc48bae 100644 --- a/plugins/catalog-backend/src/processing/types.ts +++ b/plugins/catalog-backend/src/processing/types.ts @@ -16,7 +16,10 @@ import { Entity } from '@backstage/catalog-model'; import { JsonObject } from '@backstage/types'; -import { EntityRelationSpec } from '../api'; +import { + DeferredEntity, + EntityRelationSpec, +} from '@backstage/plugin-catalog-node'; /** * The request to process an entity. @@ -47,7 +50,6 @@ export type EntityProcessingResult = /** * A string to associate to the entity itself. - * @public */ export type RefreshKeyData = { key: string; @@ -61,15 +63,6 @@ export interface CatalogProcessingOrchestrator { process(request: EntityProcessingRequest): Promise; } -/** - * Entities that are not yet processed. - * @public - */ -export type DeferredEntity = { - entity: Entity; - locationKey?: string; -}; - /** @public */ export interface CatalogProcessingEngine { start(): Promise; diff --git a/plugins/catalog-backend/src/processing/util.ts b/plugins/catalog-backend/src/processing/util.ts index b1948cf559..bd96763a54 100644 --- a/plugins/catalog-backend/src/processing/util.ts +++ b/plugins/catalog-backend/src/processing/util.ts @@ -27,7 +27,7 @@ import { JsonObject, JsonValue } from '@backstage/types'; import { InputError } from '@backstage/errors'; import { ScmIntegrationRegistry } from '@backstage/integration'; import path from 'path'; -import { LocationSpec } from '../api'; +import { LocationSpec } from '@backstage/plugin-catalog-node'; export function isLocationEntity(entity: Entity): entity is LocationEntity { return entity.kind === 'Location'; diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.ts b/plugins/catalog-backend/src/service/CatalogBuilder.ts index 0d4ddc8e71..0e8f859a10 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.ts @@ -36,7 +36,7 @@ import { CatalogProcessor, CatalogProcessorParser, EntityProvider, -} from '../api'; +} from '@backstage/plugin-catalog-node'; import { AnnotateLocationEntityProcessor, BuiltinKindsEntityProcessor, diff --git a/plugins/catalog-backend/src/service/DefaultLocationService.ts b/plugins/catalog-backend/src/service/DefaultLocationService.ts index fc6ffb0825..2c051a6e66 100644 --- a/plugins/catalog-backend/src/service/DefaultLocationService.ts +++ b/plugins/catalog-backend/src/service/DefaultLocationService.ts @@ -21,13 +21,11 @@ import { stringifyEntityRef, } from '@backstage/catalog-model'; import { Location } from '@backstage/catalog-client'; -import { - CatalogProcessingOrchestrator, - DeferredEntity, -} from '../processing/types'; +import { CatalogProcessingOrchestrator } from '../processing/types'; import { LocationInput, LocationService, LocationStore } from './types'; import { locationSpecToMetadataName } from '../util/conversion'; import { InputError } from '@backstage/errors'; +import { DeferredEntity } from '@backstage/plugin-catalog-node'; export class DefaultLocationService implements LocationService { constructor( diff --git a/plugins/catalog-backend/src/util/conversion.ts b/plugins/catalog-backend/src/util/conversion.ts index d61304a419..83302722d2 100644 --- a/plugins/catalog-backend/src/util/conversion.ts +++ b/plugins/catalog-backend/src/util/conversion.ts @@ -23,7 +23,7 @@ import { stringifyLocationRef, } from '@backstage/catalog-model'; import { createHash } from 'crypto'; -import { LocationSpec } from '../api'; +import { LocationSpec } from '@backstage/plugin-catalog-node'; export function locationSpecToMetadataName(location: LocationSpec) { const hash = createHash('sha1') diff --git a/plugins/catalog-node/.eslintrc.js b/plugins/catalog-node/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/catalog-node/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/catalog-node/README.md b/plugins/catalog-node/README.md new file mode 100644 index 0000000000..37106bef06 --- /dev/null +++ b/plugins/catalog-node/README.md @@ -0,0 +1,3 @@ +# plugin-catalog-node + +Houses types and utilities for building catalog modules. diff --git a/plugins/catalog-node/api-report.md b/plugins/catalog-node/api-report.md new file mode 100644 index 0000000000..d3460e4e27 --- /dev/null +++ b/plugins/catalog-node/api-report.md @@ -0,0 +1,158 @@ +## API Report File for "@backstage/plugin-catalog-node" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { CompoundEntityRef } from '@backstage/catalog-model'; +import { Entity } from '@backstage/catalog-model'; +import { JsonValue } from '@backstage/types'; + +// @public (undocumented) +export type CatalogProcessor = { + getProcessorName(): string; + readLocation?( + location: LocationSpec, + optional: boolean, + emit: CatalogProcessorEmit, + parser: CatalogProcessorParser, + cache: CatalogProcessorCache, + ): Promise; + preProcessEntity?( + entity: Entity, + location: LocationSpec, + emit: CatalogProcessorEmit, + originLocation: LocationSpec, + cache: CatalogProcessorCache, + ): Promise; + validateEntityKind?(entity: Entity): Promise; + postProcessEntity?( + entity: Entity, + location: LocationSpec, + emit: CatalogProcessorEmit, + cache: CatalogProcessorCache, + ): Promise; +}; + +// @public +export interface CatalogProcessorCache { + get(key: string): Promise; + set(key: string, value: ItemType): Promise; +} + +// @public (undocumented) +export type CatalogProcessorEmit = (generated: CatalogProcessorResult) => void; + +// @public (undocumented) +export type CatalogProcessorEntityResult = { + type: 'entity'; + entity: Entity; + location: LocationSpec; +}; + +// @public (undocumented) +export type CatalogProcessorErrorResult = { + type: 'error'; + error: Error; + location: LocationSpec; +}; + +// @public (undocumented) +export type CatalogProcessorLocationResult = { + type: 'location'; + location: LocationSpec; +}; + +// @public +export type CatalogProcessorParser = (options: { + data: Buffer; + location: LocationSpec; +}) => AsyncIterable; + +// @public (undocumented) +export type CatalogProcessorRefreshKeysResult = { + type: 'refresh'; + key: string; +}; + +// @public (undocumented) +export type CatalogProcessorRelationResult = { + type: 'relation'; + relation: EntityRelationSpec; +}; + +// @public (undocumented) +export type CatalogProcessorResult = + | CatalogProcessorLocationResult + | CatalogProcessorEntityResult + | CatalogProcessorRelationResult + | CatalogProcessorErrorResult + | CatalogProcessorRefreshKeysResult; + +// @public +export type DeferredEntity = { + entity: Entity; + locationKey?: string; +}; + +// @public +export interface EntityProvider { + connect(connection: EntityProviderConnection): Promise; + getProviderName(): string; +} + +// @public +export interface EntityProviderConnection { + applyMutation(mutation: EntityProviderMutation): Promise; +} + +// @public +export type EntityProviderMutation = + | { + type: 'full'; + entities: DeferredEntity[]; + } + | { + type: 'delta'; + added: DeferredEntity[]; + removed: DeferredEntity[]; + }; + +// @public +export type EntityRelationSpec = { + source: CompoundEntityRef; + type: string; + target: CompoundEntityRef; +}; + +// @public +export type LocationSpec = { + type: string; + target: string; + presence?: 'optional' | 'required'; +}; + +// @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; +}>; +``` diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json new file mode 100644 index 0000000000..a1c96990a0 --- /dev/null +++ b/plugins/catalog-node/package.json @@ -0,0 +1,40 @@ +{ + "name": "@backstage/plugin-catalog-node", + "description": "The plugin-catalog-node module for @backstage/plugin-catalog-backend", + "version": "0.0.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "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" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build --experimental-type-build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/catalog-model": "^1.1.0-next.2", + "@backstage/errors": "1.1.0-next.0", + "@backstage/types": "^1.0.0" + }, + "devDependencies": { + "@backstage/backend-common": "^0.14.1-next.2", + "@backstage/cli": "^0.18.0-next.2" + }, + "files": [ + "dist", + "alpha" + ] +} diff --git a/plugins/catalog-backend/src/api/common.ts b/plugins/catalog-node/src/api/common.ts similarity index 100% rename from plugins/catalog-backend/src/api/common.ts rename to plugins/catalog-node/src/api/common.ts diff --git a/plugins/catalog-backend/src/api/index.ts b/plugins/catalog-node/src/api/index.ts similarity index 100% rename from plugins/catalog-backend/src/api/index.ts rename to plugins/catalog-node/src/api/index.ts diff --git a/plugins/catalog-backend/src/api/processingResult.ts b/plugins/catalog-node/src/api/processingResult.ts similarity index 100% rename from plugins/catalog-backend/src/api/processingResult.ts rename to plugins/catalog-node/src/api/processingResult.ts diff --git a/plugins/catalog-backend/src/api/processor.ts b/plugins/catalog-node/src/api/processor.ts similarity index 100% rename from plugins/catalog-backend/src/api/processor.ts rename to plugins/catalog-node/src/api/processor.ts diff --git a/plugins/catalog-backend/src/api/provider.ts b/plugins/catalog-node/src/api/provider.ts similarity index 100% rename from plugins/catalog-backend/src/api/provider.ts rename to plugins/catalog-node/src/api/provider.ts diff --git a/plugins/catalog-node/src/index.ts b/plugins/catalog-node/src/index.ts new file mode 100644 index 0000000000..6a1accfcbd --- /dev/null +++ b/plugins/catalog-node/src/index.ts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +/** + * The catalog-backend-node module for `@backstage/plugin-catalog-backend`. + * + * @packageDocumentation + */ + +export * from './api'; +export * from './processing'; diff --git a/plugins/catalog-node/src/processing/index.ts b/plugins/catalog-node/src/processing/index.ts new file mode 100644 index 0000000000..90b87aa850 --- /dev/null +++ b/plugins/catalog-node/src/processing/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export type { DeferredEntity } from './types'; diff --git a/plugins/catalog-node/src/processing/types.ts b/plugins/catalog-node/src/processing/types.ts new file mode 100644 index 0000000000..25e76faea3 --- /dev/null +++ b/plugins/catalog-node/src/processing/types.ts @@ -0,0 +1,26 @@ +/* + * 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 { Entity } from '@backstage/catalog-model'; + +/** + * Entities that are not yet processed. + * @public + */ +export type DeferredEntity = { + entity: Entity; + locationKey?: string; +}; From 84529131ffd60a1cee0ce9fe3737054c4345efd5 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 8 Jul 2022 12:57:48 +0200 Subject: [PATCH 26/59] docs: update catalog docs to point to catalog-node Signed-off-by: Patrik Oldsberg --- .../features/software-catalog/external-integrations.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/features/software-catalog/external-integrations.md b/docs/features/software-catalog/external-integrations.md index d6353d1185..30bd4c77bc 100644 --- a/docs/features/software-catalog/external-integrations.md +++ b/docs/features/software-catalog/external-integrations.md @@ -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. From f19b7e2f68f19d6759c4d5fc849262fce9adc11a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 31 May 2022 14:41:35 +0200 Subject: [PATCH 27/59] packages: add initial backend app and plugin API packages Signed-off-by: Patrik Oldsberg --- packages/backend-app-api/.eslintrc.js | 1 + packages/backend-app-api/README.md | 17 +++++++++ packages/backend-app-api/package.json | 44 ++++++++++++++++++++++++ packages/backend-app-api/src/index.ts | 23 +++++++++++++ packages/backend-plugin-api/.eslintrc.js | 1 + packages/backend-plugin-api/README.md | 17 +++++++++ packages/backend-plugin-api/package.json | 44 ++++++++++++++++++++++++ packages/backend-plugin-api/src/index.ts | 23 +++++++++++++ 8 files changed, 170 insertions(+) create mode 100644 packages/backend-app-api/.eslintrc.js create mode 100644 packages/backend-app-api/README.md create mode 100644 packages/backend-app-api/package.json create mode 100644 packages/backend-app-api/src/index.ts create mode 100644 packages/backend-plugin-api/.eslintrc.js create mode 100644 packages/backend-plugin-api/README.md create mode 100644 packages/backend-plugin-api/package.json create mode 100644 packages/backend-plugin-api/src/index.ts diff --git a/packages/backend-app-api/.eslintrc.js b/packages/backend-app-api/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/backend-app-api/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/backend-app-api/README.md b/packages/backend-app-api/README.md new file mode 100644 index 0000000000..295a04c7a1 --- /dev/null +++ b/packages/backend-app-api/README.md @@ -0,0 +1,17 @@ +# @backstage/backend-app-api + +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) diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json new file mode 100644 index 0000000000..fe2d517086 --- /dev/null +++ b/packages/backend-app-api/package.json @@ -0,0 +1,44 @@ +{ + "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": {}, + "devDependencies": { + "@backstage/cli": "^0.17.2-next.0" + }, + "files": [ + "dist", + "alpha" + ] +} diff --git a/packages/backend-app-api/src/index.ts b/packages/backend-app-api/src/index.ts new file mode 100644 index 0000000000..1888a9b037 --- /dev/null +++ b/packages/backend-app-api/src/index.ts @@ -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 {}; diff --git a/packages/backend-plugin-api/.eslintrc.js b/packages/backend-plugin-api/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/backend-plugin-api/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/backend-plugin-api/README.md b/packages/backend-plugin-api/README.md new file mode 100644 index 0000000000..9e28e220a1 --- /dev/null +++ b/packages/backend-plugin-api/README.md @@ -0,0 +1,17 @@ +# @backstage/backend-plugin-api + +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/-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) diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json new file mode 100644 index 0000000000..967ae734ee --- /dev/null +++ b/packages/backend-plugin-api/package.json @@ -0,0 +1,44 @@ +{ + "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": {}, + "devDependencies": { + "@backstage/cli": "^0.17.2-next.0" + }, + "files": [ + "dist", + "alpha" + ] +} diff --git a/packages/backend-plugin-api/src/index.ts b/packages/backend-plugin-api/src/index.ts new file mode 100644 index 0000000000..caef25e2ad --- /dev/null +++ b/packages/backend-plugin-api/src/index.ts @@ -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 plugins. + * + * @packageDocumentation + */ + +export {}; From 4ad817262cd48445bc0260c621405a0fc5621717 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 1 Jun 2022 11:24:40 +0200 Subject: [PATCH 28/59] backend-system: initial high-level API surface split Signed-off-by: Patrik Oldsberg --- packages/backend-app-api/src/wiring/types.ts | 27 ++++++ packages/backend-plugin-api/src/index.ts | 2 +- .../src/services/definitions/types.ts | 52 ++++++++++++ .../src/services/system/types.ts | 31 +++++++ .../backend-plugin-api/src/wiring/index.ts | 17 ++++ .../backend-plugin-api/src/wiring/types.ts | 85 +++++++++++++++++++ 6 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 packages/backend-app-api/src/wiring/types.ts create mode 100644 packages/backend-plugin-api/src/services/definitions/types.ts create mode 100644 packages/backend-plugin-api/src/services/system/types.ts create mode 100644 packages/backend-plugin-api/src/wiring/index.ts create mode 100644 packages/backend-plugin-api/src/wiring/types.ts diff --git a/packages/backend-app-api/src/wiring/types.ts b/packages/backend-app-api/src/wiring/types.ts new file mode 100644 index 0000000000..cf600ba1d0 --- /dev/null +++ b/packages/backend-app-api/src/wiring/types.ts @@ -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. + */ + +export interface BackendApp { + add(registrable: BackendRegistrable): void; +} + +interface CreateBackendOptions { + apis: AnyServiceFactory[]; +} + +export function createBackend(options?: CreateBackendOptions): Backend { + return new BackstageBackend(options?.apis ?? []); +} diff --git a/packages/backend-plugin-api/src/index.ts b/packages/backend-plugin-api/src/index.ts index caef25e2ad..da51896950 100644 --- a/packages/backend-plugin-api/src/index.ts +++ b/packages/backend-plugin-api/src/index.ts @@ -20,4 +20,4 @@ * @packageDocumentation */ -export {}; +export * from './wiring'; diff --git a/packages/backend-plugin-api/src/services/definitions/types.ts b/packages/backend-plugin-api/src/services/definitions/types.ts new file mode 100644 index 0000000000..8e85e1198d --- /dev/null +++ b/packages/backend-plugin-api/src/services/definitions/types.ts @@ -0,0 +1,52 @@ +/* + * 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. + */ + +interface Logger { + log(message: string): void; + child(fields: { [name: string]: string }): Logger; +} + +interface ConfigApi { + getString(key: string): string; +} + +interface HttpRouterApi { + get(path: string): void; +} + +export const loggerApiRef = createServiceRef({ + id: 'core.logger', +}); + +export const configApiRef = createServiceRef({ + id: 'core.config', +}); + +export const httpRouterApiRef = createServiceRef({ + id: 'core.apiRouter', +}); + +// export type PluginEnvironment = { +// logger: Logger; +// cache: PluginCacheManager; +// database: PluginDatabaseManager; +// config: Config; +// reader: UrlReader; +// discovery: PluginEndpointDiscovery; +// tokenManager: TokenManager; +// permissions: PermissionEvaluator | PermissionAuthorizer; +// scheduler: PluginTaskScheduler; +// }; diff --git a/packages/backend-plugin-api/src/services/system/types.ts b/packages/backend-plugin-api/src/services/system/types.ts new file mode 100644 index 0000000000..4b6b284a1d --- /dev/null +++ b/packages/backend-plugin-api/src/services/system/types.ts @@ -0,0 +1,31 @@ +/* + * 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 interface ServiceRef { + id: string; + T: T; + $$ref: 'service'; +} + +export function createServiceRef(options: { id: string }): ServiceRef { + return { + id: options.id, + get T(): T { + throw Error('NO T'); + }, + $$ref: 'service', // TODO: declare + }; +} diff --git a/packages/backend-plugin-api/src/wiring/index.ts b/packages/backend-plugin-api/src/wiring/index.ts new file mode 100644 index 0000000000..259fe2b2ea --- /dev/null +++ b/packages/backend-plugin-api/src/wiring/index.ts @@ -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 { BackendRegistrable } from './types'; diff --git a/packages/backend-plugin-api/src/wiring/types.ts b/packages/backend-plugin-api/src/wiring/types.ts new file mode 100644 index 0000000000..32a5afba0c --- /dev/null +++ b/packages/backend-plugin-api/src/wiring/types.ts @@ -0,0 +1,85 @@ +/* + * 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 interface ExtensionPoint { + id: string; + T: T; + $$ref: 'extension-point'; +} + +export function createExtensionPoint(options: { + id: string; +}): ExtensionPoint { + return { + id: options.id, + get T(): T { + throw Error('NO T'); + }, + $$ref: 'extension-point', // TODO: declare + }; +} + +export interface BackendInitRegistry { + registerExtensionPoint( + ref: ServiceRef, + impl: TExtensionPoint, + ): void; + registerInit(options: { + deps: { [name in keyof Deps]: ServiceRef }; + init: (deps: Deps) => Promise; + }): void; +} + +export interface BackendRegistrable { + id: string; + register(reg: BackendInitRegistry): void; +} + +export interface BackendPluginConfig { + id: string; + register(reg: BackendInitRegistry, options: TOptions): void; +} + +export function createBackendPlugin( + config: BackendPluginConfig, +): (option: TOptions) => BackendRegistrable { + return options => ({ + id: config.id, + register(register) { + return config.register(register, options); + }, + }); +} + +export interface BackendModuleConfig { + pluginId: string; + moduleId: string; + register( + reg: Omit, + options: TOptions, + ): void; +} + +export function createBackendModule( + config: BackendModuleConfig, +): (option: TOptions) => BackendRegistrable { + return options => ({ + id: `${config.pluginId}.${config.moduleId}`, + register(register) { + return config.register(register, options); + }, + }); +} From 39b24c78fec6d84662fac873cc01e85d1c978d0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 15 Jun 2022 14:27:23 +0200 Subject: [PATCH 29/59] Initial work on the backend/next setup for the catalog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Patrik Oldsberg Co-authored-by: blam Co-authored-by: Johan Haals Signed-off-by: Fredrik Adelöw --- packages/backend-app-api/api-report.md | 15 ++ packages/backend-app-api/package.json | 4 +- packages/backend-app-api/src/index.ts | 2 +- .../src/wiring/BackendInitializer.ts | 153 ++++++++++++++++++ .../src/wiring/BackstageBackend.ts | 44 +++++ .../src/wiring/CoreApiRegistry.ts | 65 ++++++++ packages/backend-app-api/src/wiring/types.ts | 25 ++- packages/backend-plugin-api/package.json | 4 +- packages/backend-plugin-api/src/index.ts | 2 + .../src/services/definitions/configApiRef.ts | 22 +++ .../services/definitions/httpRouterApiRef.ts | 25 +++ .../definitions/{types.ts => index.ts} | 31 +--- .../src/services/definitions/loggerApiRef.ts | 26 +++ .../src/services/system/types.ts | 41 ++++- .../backend-plugin-api/src/wiring/index.ts | 3 +- .../backend-plugin-api/src/wiring/types.ts | 21 ++- packages/backend/package.json | 2 + packages/backend/src/next/index.ts | 100 ++++++++++++ yarn.lock | 146 ++++++++++++++++- 19 files changed, 697 insertions(+), 34 deletions(-) create mode 100644 packages/backend-app-api/api-report.md create mode 100644 packages/backend-app-api/src/wiring/BackendInitializer.ts create mode 100644 packages/backend-app-api/src/wiring/BackstageBackend.ts create mode 100644 packages/backend-app-api/src/wiring/CoreApiRegistry.ts create mode 100644 packages/backend-plugin-api/src/services/definitions/configApiRef.ts create mode 100644 packages/backend-plugin-api/src/services/definitions/httpRouterApiRef.ts rename packages/backend-plugin-api/src/services/definitions/{types.ts => index.ts} (66%) create mode 100644 packages/backend-plugin-api/src/services/definitions/loggerApiRef.ts create mode 100644 packages/backend/src/next/index.ts diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md new file mode 100644 index 0000000000..8c64858310 --- /dev/null +++ b/packages/backend-app-api/api-report.md @@ -0,0 +1,15 @@ +## 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'; + +// Warning: (ae-forgotten-export) The symbol "CreateBackendOptions" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "Backend" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "createBackend" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function createBackend(options?: CreateBackendOptions): Backend; +``` diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index fe2d517086..ab88009d64 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -33,7 +33,9 @@ "clean": "backstage-cli package clean", "start": "backstage-cli package start" }, - "dependencies": {}, + "dependencies": { + "@backstage/backend-plugin-api": "^0.0.0" + }, "devDependencies": { "@backstage/cli": "^0.17.2-next.0" }, diff --git a/packages/backend-app-api/src/index.ts b/packages/backend-app-api/src/index.ts index 1888a9b037..33aca2b291 100644 --- a/packages/backend-app-api/src/index.ts +++ b/packages/backend-app-api/src/index.ts @@ -20,4 +20,4 @@ * @packageDocumentation */ -export {}; +export { createBackend } from './wiring/types'; diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.ts b/packages/backend-app-api/src/wiring/BackendInitializer.ts new file mode 100644 index 0000000000..8c2f2714c4 --- /dev/null +++ b/packages/backend-app-api/src/wiring/BackendInitializer.ts @@ -0,0 +1,153 @@ +/* + * 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, ServiceRef } from '@backstage/backend-plugin-api'; +import { BackendRegisterInit, ApiHolder } from './types'; + +export class BackendInitializer { + #started = false; + #extensions = new Map(); + // #stops = []; + #registerInits = new Array(); + #apis = new Map, unknown>(); + #apiHolder: ApiHolder; + + constructor(apiHolder: ApiHolder) { + this.#apiHolder = apiHolder; + } + + async #getInitDeps( + deps: { [name: string]: ServiceRef }, + pluginId: string, + ) { + return Object.fromEntries( + await Promise.all( + Object.entries(deps).map(async ([name, apiRef]) => [ + name, + this.#apis.get(apiRef) || + (await this.#apiHolder.get(apiRef)!(pluginId)), + ]), + ), + ); + } + + add(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 { + 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>(); + + let registerInit: BackendRegisterInit | undefined = undefined; + + console.log('Registering', extension.id); + extension.register({ + registerExtensionPoint: (api, impl) => { + if (registerInit) { + throw new Error('registerInitApi called after registerInit'); + } + if (this.#apis.has(api)) { + throw new Error(`API ${api.id} already registered`); + } + this.#apis.set(api, impl); + provides.add(api); + }, + 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) { + // TODO: DI + const deps = await this.#getInitDeps(registerInit.deps, registerInit.id); + await registerInit.init(deps); + // Maybe return stop? or lifecycle API + // this.#stops.push(); + } + } + + // async stop(): Promise { + // for (const stop of this.#stops) { + // await stop.stop(); + // } + // } + + private validateSetup() {} + + #resolveInitOrder(registerInits: Array) { + let registerInitsToOrder = registerInits.slice(); + const orderedRegisterInits = new Array(); + + // TODO: Validate duplicates + + while (registerInitsToOrder.length > 0) { + const toRemove = new Set(); + + for (const registerInit of registerInitsToOrder) { + const unInitializedDependents = Array.from( + registerInit.provides, + // eslint-disable-next-line no-loop-func + ).filter(r => + registerInitsToOrder.some( + init => init !== registerInit && init.consumes.has(r), + ), + ); + + if (unInitializedDependents.length === 0) { + orderedRegisterInits.push(registerInit); + toRemove.add(registerInit); + } + } + + registerInitsToOrder = registerInitsToOrder.filter(r => !toRemove.has(r)); + } + return orderedRegisterInits; + } +} diff --git a/packages/backend-app-api/src/wiring/BackstageBackend.ts b/packages/backend-app-api/src/wiring/BackstageBackend.ts new file mode 100644 index 0000000000..ae27c4ee05 --- /dev/null +++ b/packages/backend-app-api/src/wiring/BackstageBackend.ts @@ -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 { + BackendRegistrable, + AnyServiceFactory, +} from '@backstage/backend-plugin-api'; +import { BackendInitializer } from './BackendInitializer'; +import { CoreApiRegistry } from './CoreApiRegistry'; +import { Backend } from './types'; + +export class BackstageBackend implements Backend { + #coreApis: CoreApiRegistry; + #initializer: BackendInitializer; + + constructor(apiFactories: AnyServiceFactory[]) { + this.#coreApis = new CoreApiRegistry(apiFactories); + this.#initializer = new BackendInitializer(this.#coreApis); + } + + add(extension: BackendRegistrable): void { + this.#initializer.add(extension); + } + + async start(): Promise { + await this.#initializer.start(); + } + + // async stop(): Promise { + // await this.#initializer.stop(); + // } +} diff --git a/packages/backend-app-api/src/wiring/CoreApiRegistry.ts b/packages/backend-app-api/src/wiring/CoreApiRegistry.ts new file mode 100644 index 0000000000..a144fc448d --- /dev/null +++ b/packages/backend-app-api/src/wiring/CoreApiRegistry.ts @@ -0,0 +1,65 @@ +/* + * 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, + ServiceRef, + FactoryFunc, +} from '@backstage/backend-plugin-api'; + +export class CoreApiRegistry { + readonly #implementations: Map>; + readonly #factories: Map; + + constructor(factories: AnyServiceFactory[]) { + this.#factories = new Map(factories.map(f => [f.service.id, f])); + this.#implementations = new Map(); + } + + get(ref: ServiceRef): FactoryFunc | undefined { + const factory = this.#factories.get(ref.id); + if (!factory) { + return undefined; + } + + return async (pluginId: string): Promise => { + if (this.#implementations.has(ref.id)) { + if (this.#implementations.get(ref.id)!.has(pluginId)) { + return this.#implementations.get(ref.id)!.get(pluginId) as T; + } + this.#implementations.set(ref.id, new Map()); + } else { + this.#implementations.set(ref.id, new Map()); + } + + const factoryDeps = Object.fromEntries( + Object.entries(factory.deps).map(([name, apiRef]) => [ + name, + this.get(apiRef)!, // TODO: throw + ]), + ); + + const factoryFunc = await factory.factory(factoryDeps); + const implementation = await factoryFunc(pluginId); + + this.#implementations.set( + ref.id, + this.#implementations.get(ref.id)!.set(pluginId, implementation), + ); + + return implementation as T; + }; + } +} diff --git a/packages/backend-app-api/src/wiring/types.ts b/packages/backend-app-api/src/wiring/types.ts index cf600ba1d0..44640cbc07 100644 --- a/packages/backend-app-api/src/wiring/types.ts +++ b/packages/backend-app-api/src/wiring/types.ts @@ -14,14 +14,35 @@ * limitations under the License. */ -export interface BackendApp { - add(registrable: BackendRegistrable): void; +import { + BackendRegistrable, + AnyServiceFactory, + ServiceRef, + FactoryFunc, +} from '@backstage/backend-plugin-api'; +import { BackstageBackend } from './BackstageBackend'; + +export interface Backend { + add(extension: BackendRegistrable): void; + start(): Promise; +} + +export interface BackendRegisterInit { + id: string; + consumes: Set>; + provides: Set>; + deps: { [name: string]: ServiceRef }; + init: (deps: { [name: string]: unknown }) => Promise; } interface CreateBackendOptions { apis: AnyServiceFactory[]; } +export type ApiHolder = { + get(api: ServiceRef): FactoryFunc | undefined; +}; + export function createBackend(options?: CreateBackendOptions): Backend { return new BackstageBackend(options?.apis ?? []); } diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index 967ae734ee..ccda227018 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -33,7 +33,9 @@ "clean": "backstage-cli package clean", "start": "backstage-cli package start" }, - "dependencies": {}, + "dependencies": { + "@backstage/config": "^1.0.1" + }, "devDependencies": { "@backstage/cli": "^0.17.2-next.0" }, diff --git a/packages/backend-plugin-api/src/index.ts b/packages/backend-plugin-api/src/index.ts index da51896950..e82218ca69 100644 --- a/packages/backend-plugin-api/src/index.ts +++ b/packages/backend-plugin-api/src/index.ts @@ -21,3 +21,5 @@ */ export * from './wiring'; +export * from './services/system/types'; +export * from './services/definitions'; diff --git a/packages/backend-plugin-api/src/services/definitions/configApiRef.ts b/packages/backend-plugin-api/src/services/definitions/configApiRef.ts new file mode 100644 index 0000000000..cca1445079 --- /dev/null +++ b/packages/backend-plugin-api/src/services/definitions/configApiRef.ts @@ -0,0 +1,22 @@ +/* + * 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'; + +export const configApiRef = createServiceRef({ + id: 'core.config', +}); diff --git a/packages/backend-plugin-api/src/services/definitions/httpRouterApiRef.ts b/packages/backend-plugin-api/src/services/definitions/httpRouterApiRef.ts new file mode 100644 index 0000000000..d54ebd36bf --- /dev/null +++ b/packages/backend-plugin-api/src/services/definitions/httpRouterApiRef.ts @@ -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'; + +export interface HttpRouterApi { + get(path: string): void; +} + +export const httpRouterApiRef = createServiceRef({ + id: 'core.httpRouter', +}); diff --git a/packages/backend-plugin-api/src/services/definitions/types.ts b/packages/backend-plugin-api/src/services/definitions/index.ts similarity index 66% rename from packages/backend-plugin-api/src/services/definitions/types.ts rename to packages/backend-plugin-api/src/services/definitions/index.ts index 8e85e1198d..b11b2f8c4e 100644 --- a/packages/backend-plugin-api/src/services/definitions/types.ts +++ b/packages/backend-plugin-api/src/services/definitions/index.ts @@ -14,31 +14,6 @@ * limitations under the License. */ -interface Logger { - log(message: string): void; - child(fields: { [name: string]: string }): Logger; -} - -interface ConfigApi { - getString(key: string): string; -} - -interface HttpRouterApi { - get(path: string): void; -} - -export const loggerApiRef = createServiceRef({ - id: 'core.logger', -}); - -export const configApiRef = createServiceRef({ - id: 'core.config', -}); - -export const httpRouterApiRef = createServiceRef({ - id: 'core.apiRouter', -}); - // export type PluginEnvironment = { // logger: Logger; // cache: PluginCacheManager; @@ -50,3 +25,9 @@ export const httpRouterApiRef = createServiceRef({ // permissions: PermissionEvaluator | PermissionAuthorizer; // scheduler: PluginTaskScheduler; // }; + +export { configApiRef } from './configApiRef'; +export { httpRouterApiRef } from './httpRouterApiRef'; +export type { HttpRouterApi } from './httpRouterApiRef'; +export { loggerApiRef } from './loggerApiRef'; +export type { Logger } from './loggerApiRef'; diff --git a/packages/backend-plugin-api/src/services/definitions/loggerApiRef.ts b/packages/backend-plugin-api/src/services/definitions/loggerApiRef.ts new file mode 100644 index 0000000000..348ffc9cf4 --- /dev/null +++ b/packages/backend-plugin-api/src/services/definitions/loggerApiRef.ts @@ -0,0 +1,26 @@ +/* + * 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'; + +export interface Logger { + log(message: string): void; + child(fields: { [name: string]: string }): Logger; +} + +export const loggerApiRef = createServiceRef({ + id: 'core.logger', +}); diff --git a/packages/backend-plugin-api/src/services/system/types.ts b/packages/backend-plugin-api/src/services/system/types.ts index 4b6b284a1d..86ad8d42f0 100644 --- a/packages/backend-plugin-api/src/services/system/types.ts +++ b/packages/backend-plugin-api/src/services/system/types.ts @@ -14,17 +14,56 @@ * limitations under the License. */ +/** + * TODO + * + * @public + */ export interface ServiceRef { 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'; } +type TypesToServiceRef = { [key in keyof T]: ServiceRef }; +type DepsToDepFactories = { + [key in keyof T]: (pluginId: string) => Promise; +}; + +export type FactoryFunc = (pluginId: string) => Promise; + +export type ServiceFactory< + TApi, + TImpl extends TApi, + TDeps extends { [name in string]: unknown }, +> = { + service: ServiceRef; + deps: TypesToServiceRef; + factory(deps: DepsToDepFactories): Promise>; +}; + +export type AnyServiceFactory = ServiceFactory< + unknown, + unknown, + { [key in string]: unknown } +>; + export function createServiceRef(options: { id: string }): ServiceRef { return { id: options.id, get T(): T { - throw Error('NO T'); + throw new Error(`tried to read ServiceRef.T of ${this}`); + }, + toString() { + return `serviceRef{${options.id}}`; }, $$ref: 'service', // TODO: declare }; diff --git a/packages/backend-plugin-api/src/wiring/index.ts b/packages/backend-plugin-api/src/wiring/index.ts index 259fe2b2ea..9340dc8fa9 100644 --- a/packages/backend-plugin-api/src/wiring/index.ts +++ b/packages/backend-plugin-api/src/wiring/index.ts @@ -14,4 +14,5 @@ * limitations under the License. */ -export { BackendRegistrable } from './types'; +export type { BackendRegistrable } from './types'; +export * from './types'; diff --git a/packages/backend-plugin-api/src/wiring/types.ts b/packages/backend-plugin-api/src/wiring/types.ts index 32a5afba0c..746d47b355 100644 --- a/packages/backend-plugin-api/src/wiring/types.ts +++ b/packages/backend-plugin-api/src/wiring/types.ts @@ -14,9 +14,25 @@ * limitations under the License. */ +import { ServiceRef } from '../services/system/types'; + +/** + * TODO + * + * @public + */ export interface ExtensionPoint { 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'; } @@ -26,7 +42,10 @@ export function createExtensionPoint(options: { return { id: options.id, get T(): T { - throw Error('NO T'); + throw new Error(`tried to read ExtensionPoint.T of ${this}`); + }, + toString() { + return `extensionPoint{${options.id}}`; }, $$ref: 'extension-point', // TODO: declare }; diff --git a/packages/backend/package.json b/packages/backend/package.json index df6fe5ec3b..7604f1e609 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -26,6 +26,8 @@ "build-image": "docker build ../.. -f Dockerfile --tag example-backend" }, "dependencies": { + "@backstage/backend-plugin-api": "^0.0.0", + "@backstage/backend-app-api": "^0.0.0", "@backstage/backend-common": "^0.14.1-next.2", "@backstage/backend-tasks": "^0.3.3-next.2", "@backstage/catalog-client": "^1.0.4-next.1", diff --git a/packages/backend/src/next/index.ts b/packages/backend/src/next/index.ts new file mode 100644 index 0000000000..221332f6ba --- /dev/null +++ b/packages/backend/src/next/index.ts @@ -0,0 +1,100 @@ +/* + * 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 { + createBackendModule, + createBackendPlugin, + createServiceRef, +} from '@backstage/backend-plugin-api'; +// import { catalogPlugin } from '@backstage/plugin-catalog-backend'; +// import { scaffolderPlugin } from '@backstage/plugin-scaffolder-backend'; + +interface CatalogProcessor { + process(): void; +} + +interface CatalogProcessingInitApi { + addProcessor(processor: CatalogProcessor): void; +} + +export const catalogProcessingInitApiRef = + createServiceRef({ + id: 'catalog.processing', + }); + +class CatalogExtensionPointImpl implements CatalogProcessingInitApi { + #processors = new Array(); + + addProcessor(processor: CatalogProcessor): void { + this.#processors.push(processor); + } + + get processors() { + return this.#processors; + } +} + +export const catalogPlugin = createBackendPlugin({ + id: 'catalog', + register(env) { + const processingExtensions = new CatalogExtensionPointImpl(); + // plugins depending on this API will be initialized before this plugins init method is executed. + env.registerExtensionPoint( + catalogProcessingInitApiRef, + processingExtensions, + ); + + env.registerInit({ + deps: { + // logger: loggerApiRef, + }, + async init() { + console.log('I HAZ', processingExtensions.processors[0].process()); + console.log('I AM le CATALOG!'); + // logger.log('HELLO!'); + }, + }); + }, +}); + +export const scaffolderCatalogExtension = createBackendModule({ + moduleId: 'boop', + pluginId: 'catalog', + register(env) { + env.registerInit({ + deps: { + catalogProcessingInitApi: catalogProcessingInitApiRef, + }, + async init({ catalogProcessingInitApi }) { + catalogProcessingInitApi.addProcessor({ + process() { + console.log('Running scaffolder processor'); + }, + }); + }, + }); + }, +}); + +const backend = createBackend({ + apis: [], +}); + +// backend.add(scaffolderPlugin()); +backend.add(catalogPlugin({})); +backend.add(scaffolderCatalogExtension({})); +backend.start(); diff --git a/yarn.lock b/yarn.lock index e35aee85fb..fe5ff8cb76 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1557,6 +1557,126 @@ lodash "^4.17.21" uuid "^8.0.0" +"@backstage/cli@^0.17.2-next.0": + version "0.17.2" + resolved "https://registry.npmjs.org/@backstage/cli/-/cli-0.17.2.tgz#2387b8d24d8af4828b84baaa62e6b444ec4330e6" + integrity sha512-stRJWmokD7SXnclZ1dsVfA1stUP4PQPkbi3GkwY1zM84y4M20dU+YHde7MrTILMPnhMY+16WdTdfbeqLfXOJrw== + dependencies: + "@backstage/cli-common" "^0.1.9" + "@backstage/config" "^1.0.1" + "@backstage/config-loader" "^1.1.2" + "@backstage/errors" "^1.0.0" + "@backstage/release-manifests" "^0.0.4" + "@backstage/types" "^1.0.0" + "@hot-loader/react-dom-v16" "npm:@hot-loader/react-dom@^16.0.2" + "@hot-loader/react-dom-v17" "npm:@hot-loader/react-dom@^17.0.2" + "@manypkg/get-packages" "^1.1.3" + "@octokit/request" "^5.4.12" + "@rollup/plugin-commonjs" "^22.0.0" + "@rollup/plugin-json" "^4.1.0" + "@rollup/plugin-node-resolve" "^13.0.0" + "@rollup/plugin-yaml" "^3.1.0" + "@spotify/eslint-config-base" "^13.0.0" + "@spotify/eslint-config-react" "^13.0.0" + "@spotify/eslint-config-typescript" "^13.0.0" + "@sucrase/jest-plugin" "^2.1.1" + "@sucrase/webpack-loader" "^2.0.0" + "@svgr/plugin-jsx" "6.2.x" + "@svgr/plugin-svgo" "6.2.x" + "@svgr/rollup" "6.2.x" + "@svgr/webpack" "6.2.x" + "@types/webpack-env" "^1.15.2" + "@typescript-eslint/eslint-plugin" "^5.9.0" + "@typescript-eslint/parser" "^5.9.0" + "@yarnpkg/lockfile" "^1.1.0" + "@yarnpkg/parsers" "^3.0.0-rc.4" + bfj "^7.0.2" + buffer "^6.0.3" + chalk "^4.0.0" + chokidar "^3.3.1" + commander "^9.1.0" + css-loader "^6.5.1" + diff "^5.0.0" + esbuild "^0.14.10" + esbuild-loader "^2.18.0" + eslint "^8.6.0" + eslint-config-prettier "^8.3.0" + eslint-formatter-friendly "^7.0.0" + eslint-plugin-deprecation "^1.3.2" + eslint-plugin-import "^2.25.4" + eslint-plugin-jest "^26.1.2" + eslint-plugin-jsx-a11y "^6.5.1" + eslint-plugin-monorepo "^0.3.2" + eslint-plugin-react "^7.28.0" + eslint-plugin-react-hooks "^4.3.0" + eslint-webpack-plugin "^3.1.1" + express "^4.17.1" + fork-ts-checker-webpack-plugin "^7.0.0-alpha.8" + fs-extra "10.1.0" + glob "^7.1.7" + global-agent "^3.0.0" + handlebars "^4.7.3" + html-webpack-plugin "^5.3.1" + inquirer "^8.2.0" + jest "^27.5.1" + jest-css-modules "^2.1.0" + jest-runtime "^27.5.1" + jest-transform-yaml "^1.0.0" + json-schema "^0.4.0" + lodash "^4.17.21" + mini-css-extract-plugin "^2.4.2" + minimatch "5.1.0" + node-fetch "^2.6.7" + node-libs-browser "^2.2.1" + npm-packlist "^5.0.0" + ora "^5.3.0" + postcss "^8.1.0" + process "^0.11.10" + react-dev-utils "^12.0.0-next.60" + react-hot-loader "^4.13.0" + recursive-readdir "^2.2.2" + replace-in-file "^6.0.0" + rollup "^2.60.2" + rollup-plugin-dts "^4.0.1" + rollup-plugin-esbuild "^4.7.2" + rollup-plugin-postcss "^4.0.0" + rollup-pluginutils "^2.8.2" + run-script-webpack-plugin "^0.0.14" + semver "^7.3.2" + style-loader "^3.3.1" + sucrase "^3.20.2" + tar "^6.1.2" + terser-webpack-plugin "^5.1.3" + util "^0.12.3" + webpack "^5.66.0" + webpack-dev-server "^4.7.3" + webpack-node-externals "^3.0.0" + yaml "^1.10.0" + yml-loader "^2.1.0" + yn "^4.0.0" + zod "^3.11.6" + +"@backstage/config-loader@^1.1.2": + version "1.1.2" + resolved "https://registry.npmjs.org/@backstage/config-loader/-/config-loader-1.1.2.tgz#72cb0d7b2647f5a646bb279360bc34732e06521f" + integrity sha512-c5ZO7xDJn609DBIsYAWGE5kgh+7SPYUmG2ADtVX9SbXaql3VCafGlhc2hAZQa/O12W04qi3GgwGg0bqSFmx5uw== + dependencies: + "@backstage/cli-common" "^0.1.9" + "@backstage/config" "^1.0.1" + "@backstage/errors" "^1.0.0" + "@backstage/types" "^1.0.0" + "@types/json-schema" "^7.0.6" + ajv "^8.10.0" + chokidar "^3.5.2" + fs-extra "10.1.0" + json-schema "^0.4.0" + json-schema-merge-allof "^0.8.1" + json-schema-traverse "^1.0.0" + node-fetch "^2.6.7" + typescript-json-schema "^0.53.0" + yaml "^1.9.2" + yup "^0.32.9" + "@backstage/core-components@^0.9.0", "@backstage/core-components@^0.9.5": version "0.9.5" resolved "https://registry.npmjs.org/@backstage/core-components/-/core-components-0.9.5.tgz#5a0b34867aaee0549bfa67b39a69c09588fa3c7a" @@ -5555,7 +5675,7 @@ dependencies: "@rollup/pluginutils" "^3.0.8" -"@rollup/plugin-node-resolve@^13.0.6": +"@rollup/plugin-node-resolve@^13.0.0", "@rollup/plugin-node-resolve@^13.0.6": version "13.3.0" resolved "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.3.0.tgz#da1c5c5ce8316cef96a2f823d111c1e4e498801c" integrity sha512-Lus8rbUo1eEcnS4yTFKLZrVumLPY+YayBdWXgFSHYhTT2iJbMhoaaBL3xl5NCdeRytErGr8tZ0L71BMRmnlwSw== @@ -20504,6 +20624,11 @@ path-case@^3.0.4: dot-case "^3.0.4" tslib "^2.0.3" +path-equal@1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/path-equal/-/path-equal-1.1.2.tgz#260e7c449c4c2022f68cc5fa6e617e892858250d" + integrity sha512-p5kxPPwCdbf5AdXzT1bUBJomhgBlEjRBavYNr1XUpMFIE4Hnf2roueCMXudZK5tnaAu1tTmp3GPzqwJK45IHEA== + path-equal@^1.1.2: version "1.2.2" resolved "https://registry.npmjs.org/path-equal/-/path-equal-1.2.2.tgz#fa2997f0a829de22ec8f5f86461ca5590d49b832" @@ -23028,6 +23153,11 @@ run-parallel@^1.1.9: resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== +run-script-webpack-plugin@^0.0.14: + version "0.0.14" + resolved "https://registry.npmjs.org/run-script-webpack-plugin/-/run-script-webpack-plugin-0.0.14.tgz#fe2362b32c1dab7a8af7a6f1246fc043690cedd7" + integrity sha512-DXe6lzzEVXjBr/74zd4m4yOfmz5P6GMjzhQxDDsViOmwG7cap8UCE6RgD5rT7zf4wM83a+ToHnpB3v4efUv5IA== + run-script-webpack-plugin@^0.1.0: version "0.1.1" resolved "https://registry.npmjs.org/run-script-webpack-plugin/-/run-script-webpack-plugin-0.1.1.tgz#dad3114be32eb864d2160306e4d9c52a2c1cfd59" @@ -25311,6 +25441,20 @@ typedarray@^0.0.6: resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +typescript-json-schema@^0.53.0: + version "0.53.1" + resolved "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.53.1.tgz#9204547f3e145169b40928998366ff6d28b81d32" + integrity sha512-Hg+RnOKUd38MOzC0rDft03a8xvwO+gCcj1F77smw2tCoZYQpFoLtrXWBGdvCX+REliko5WYel2kux17HPFqjLQ== + dependencies: + "@types/json-schema" "^7.0.9" + "@types/node" "^16.9.2" + glob "^7.1.7" + path-equal "1.1.2" + safe-stable-stringify "^2.2.0" + ts-node "^10.2.1" + typescript "~4.6.0" + yargs "^17.1.1" + typescript-json-schema@^0.54.0: version "0.54.0" resolved "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.54.0.tgz#b3fc42ad90df6a0f6ab57571ebc8b4d41125df4f" From 375a4036645dc829d2af39b0948e3ca43174f418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 15 Jun 2022 15:44:10 +0200 Subject: [PATCH 30/59] Add more service implementations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Patrik Oldsberg Co-authored-by: blam Co-authored-by: Johan Haals Signed-off-by: Fredrik Adelöw --- packages/backend-app-api/package.json | 4 +- .../services/implementations/configService.ts | 37 +++++++++++ .../services/implementations/loggerService.ts | 63 +++++++++++++++++++ .../implementations/urlReaderService.ts | 41 ++++++++++++ .../src/wiring/BackendInitializer.ts | 3 +- .../src/wiring/BackstageBackend.ts | 3 +- .../src/wiring/CoreApiRegistry.ts | 2 +- packages/backend-app-api/src/wiring/types.ts | 9 ++- packages/backend-plugin-api/package.json | 3 +- .../definitions/cacheManagerServiceRef.ts | 22 +++++++ .../services/definitions/cacheServiceRef.ts | 22 +++++++ .../{configApiRef.ts => configServiceRef.ts} | 2 +- .../definitions/databaseServiceRef.ts | 22 +++++++ .../definitions/discoveryServiceRef.ts | 22 +++++++ ...outerApiRef.ts => httpRouterServiceRef.ts} | 2 +- .../src/services/definitions/index.ts | 15 +++-- .../{loggerApiRef.ts => loggerServiceRef.ts} | 4 +- .../definitions/tokenManagerServiceRef.ts | 22 +++++++ .../definitions/urlReaderServiceRef.ts | 22 +++++++ .../src/services/system/types.ts | 8 +++ packages/backend/src/next/index.ts | 19 ++++-- 21 files changed, 325 insertions(+), 22 deletions(-) create mode 100644 packages/backend-app-api/src/services/implementations/configService.ts create mode 100644 packages/backend-app-api/src/services/implementations/loggerService.ts create mode 100644 packages/backend-app-api/src/services/implementations/urlReaderService.ts create mode 100644 packages/backend-plugin-api/src/services/definitions/cacheManagerServiceRef.ts create mode 100644 packages/backend-plugin-api/src/services/definitions/cacheServiceRef.ts rename packages/backend-plugin-api/src/services/definitions/{configApiRef.ts => configServiceRef.ts} (92%) create mode 100644 packages/backend-plugin-api/src/services/definitions/databaseServiceRef.ts create mode 100644 packages/backend-plugin-api/src/services/definitions/discoveryServiceRef.ts rename packages/backend-plugin-api/src/services/definitions/{httpRouterApiRef.ts => httpRouterServiceRef.ts} (91%) rename packages/backend-plugin-api/src/services/definitions/{loggerApiRef.ts => loggerServiceRef.ts} (89%) create mode 100644 packages/backend-plugin-api/src/services/definitions/tokenManagerServiceRef.ts create mode 100644 packages/backend-plugin-api/src/services/definitions/urlReaderServiceRef.ts diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index ab88009d64..02c5450021 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -34,7 +34,9 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-plugin-api": "^0.0.0" + "@backstage/backend-plugin-api": "^0.0.0", + "@backstage/backend-common": "^0.14.0", + "winston": "^3.2.1" }, "devDependencies": { "@backstage/cli": "^0.17.2-next.0" diff --git a/packages/backend-app-api/src/services/implementations/configService.ts b/packages/backend-app-api/src/services/implementations/configService.ts new file mode 100644 index 0000000000..b066989069 --- /dev/null +++ b/packages/backend-app-api/src/services/implementations/configService.ts @@ -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 { loadBackendConfig } from '@backstage/backend-common'; +import { + configServiceRef, + createServiceFactory, + loggerServiceRef, +} from '@backstage/backend-plugin-api'; +import { loggerToWinstonLogger } from './loggerService'; + +export const configService = 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 () => config; + }, +}); diff --git a/packages/backend-app-api/src/services/implementations/loggerService.ts b/packages/backend-app-api/src/services/implementations/loggerService.ts new file mode 100644 index 0000000000..4b6eadfa1f --- /dev/null +++ b/packages/backend-app-api/src/services/implementations/loggerService.ts @@ -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 { createRootLogger } from '@backstage/backend-common'; +import { + createServiceFactory, + Logger, + loggerServiceRef, +} from '@backstage/backend-plugin-api'; +import { Logger as WinstonLogger } from 'winston'; + +class BackstageLogger implements Logger { + constructor( + private readonly options: { + winston: WinstonLogger; + }, + ) {} + + info(message: string, ...meta: any[]): void { + this.options.winston.info(message, ...meta); + } + + child(fields: { [name: string]: string }): Logger { + return new BackstageLogger({ + winston: this.options.winston.child(fields), + }); + } + + toWinston() { + return this.options.winston; + } +} + +export function loggerToWinstonLogger(logger: Logger): WinstonLogger { + return (logger as BackstageLogger).toWinston(); +} + +export const loggerFactory = createServiceFactory({ + service: loggerServiceRef, + deps: {}, + factory: async () => { + const root = new BackstageLogger({ + winston: createRootLogger(), + }); + + return async (pluginId: string) => { + return root.child({ pluginId }); + }; + }, +}); diff --git a/packages/backend-app-api/src/services/implementations/urlReaderService.ts b/packages/backend-app-api/src/services/implementations/urlReaderService.ts new file mode 100644 index 0000000000..afbc80d9ac --- /dev/null +++ b/packages/backend-app-api/src/services/implementations/urlReaderService.ts @@ -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, + urlReaderServiceRef, +} from '@backstage/backend-plugin-api'; +import { loggerToWinstonLogger } from './loggerService'; + +export const urlReaderFactory = createServiceFactory({ + service: urlReaderServiceRef, + deps: { + loggerFactory: loggerServiceRef, + configFactory: configServiceRef, + }, + factory: async ({ loggerFactory, configFactory }) => { + return async (pluginId: string) => { + const logger = await loggerFactory(pluginId); + return UrlReaders.default({ + logger: loggerToWinstonLogger(logger), + config: await configFactory(pluginId), + }); + }; + }, +}); diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.ts b/packages/backend-app-api/src/wiring/BackendInitializer.ts index 8c2f2714c4..a613e88bb1 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.ts @@ -15,7 +15,7 @@ */ import { BackendRegistrable, ServiceRef } from '@backstage/backend-plugin-api'; -import { BackendRegisterInit, ApiHolder } from './types'; +import { ApiHolder, BackendRegisterInit } from './types'; export class BackendInitializer { #started = false; @@ -133,7 +133,6 @@ export class BackendInitializer { for (const registerInit of registerInitsToOrder) { const unInitializedDependents = Array.from( registerInit.provides, - // eslint-disable-next-line no-loop-func ).filter(r => registerInitsToOrder.some( init => init !== registerInit && init.consumes.has(r), diff --git a/packages/backend-app-api/src/wiring/BackstageBackend.ts b/packages/backend-app-api/src/wiring/BackstageBackend.ts index ae27c4ee05..69df1fdf82 100644 --- a/packages/backend-app-api/src/wiring/BackstageBackend.ts +++ b/packages/backend-app-api/src/wiring/BackstageBackend.ts @@ -13,9 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { - BackendRegistrable, AnyServiceFactory, + BackendRegistrable, } from '@backstage/backend-plugin-api'; import { BackendInitializer } from './BackendInitializer'; import { CoreApiRegistry } from './CoreApiRegistry'; diff --git a/packages/backend-app-api/src/wiring/CoreApiRegistry.ts b/packages/backend-app-api/src/wiring/CoreApiRegistry.ts index a144fc448d..4b1e0f5ce0 100644 --- a/packages/backend-app-api/src/wiring/CoreApiRegistry.ts +++ b/packages/backend-app-api/src/wiring/CoreApiRegistry.ts @@ -15,8 +15,8 @@ */ import { AnyServiceFactory, - ServiceRef, FactoryFunc, + ServiceRef, } from '@backstage/backend-plugin-api'; export class CoreApiRegistry { diff --git a/packages/backend-app-api/src/wiring/types.ts b/packages/backend-app-api/src/wiring/types.ts index 44640cbc07..5c2e7a9e96 100644 --- a/packages/backend-app-api/src/wiring/types.ts +++ b/packages/backend-app-api/src/wiring/types.ts @@ -15,11 +15,12 @@ */ import { - BackendRegistrable, AnyServiceFactory, - ServiceRef, + BackendRegistrable, FactoryFunc, + ServiceRef, } from '@backstage/backend-plugin-api'; +import { loggerFactory } from '../services/implementations/loggerService'; import { BackstageBackend } from './BackstageBackend'; export interface Backend { @@ -44,5 +45,7 @@ export type ApiHolder = { }; export function createBackend(options?: CreateBackendOptions): Backend { - return new BackstageBackend(options?.apis ?? []); + // TODO: merge with provided APIs + const defaultApis = [loggerFactory]; + return new BackstageBackend([...defaultApis, ...(options?.apis ?? [])]); } diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index ccda227018..6d75af03a7 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -34,7 +34,8 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/config": "^1.0.1" + "@backstage/config": "^1.0.1", + "@backstage/backend-common": "^0.14.0" }, "devDependencies": { "@backstage/cli": "^0.17.2-next.0" diff --git a/packages/backend-plugin-api/src/services/definitions/cacheManagerServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/cacheManagerServiceRef.ts new file mode 100644 index 0000000000..9dab256704 --- /dev/null +++ b/packages/backend-plugin-api/src/services/definitions/cacheManagerServiceRef.ts @@ -0,0 +1,22 @@ +/* + * 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 { CacheManager } from '@backstage/backend-common'; + +export const cacheManagerServiceRef = createServiceRef({ + id: 'core.cacheManager', +}); diff --git a/packages/backend-plugin-api/src/services/definitions/cacheServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/cacheServiceRef.ts new file mode 100644 index 0000000000..439a2b645d --- /dev/null +++ b/packages/backend-plugin-api/src/services/definitions/cacheServiceRef.ts @@ -0,0 +1,22 @@ +/* + * 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'; + +export const cacheServiceRef = createServiceRef({ + id: 'core.cache', +}); diff --git a/packages/backend-plugin-api/src/services/definitions/configApiRef.ts b/packages/backend-plugin-api/src/services/definitions/configServiceRef.ts similarity index 92% rename from packages/backend-plugin-api/src/services/definitions/configApiRef.ts rename to packages/backend-plugin-api/src/services/definitions/configServiceRef.ts index cca1445079..9a4199967d 100644 --- a/packages/backend-plugin-api/src/services/definitions/configApiRef.ts +++ b/packages/backend-plugin-api/src/services/definitions/configServiceRef.ts @@ -17,6 +17,6 @@ import { Config } from '@backstage/config'; import { createServiceRef } from '../system/types'; -export const configApiRef = createServiceRef({ +export const configServiceRef = createServiceRef({ id: 'core.config', }); diff --git a/packages/backend-plugin-api/src/services/definitions/databaseServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/databaseServiceRef.ts new file mode 100644 index 0000000000..62f7f8a157 --- /dev/null +++ b/packages/backend-plugin-api/src/services/definitions/databaseServiceRef.ts @@ -0,0 +1,22 @@ +/* + * 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'; + +export const databaseServiceRef = createServiceRef({ + id: 'core.database', +}); diff --git a/packages/backend-plugin-api/src/services/definitions/discoveryServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/discoveryServiceRef.ts new file mode 100644 index 0000000000..3dfd5fa62b --- /dev/null +++ b/packages/backend-plugin-api/src/services/definitions/discoveryServiceRef.ts @@ -0,0 +1,22 @@ +/* + * 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'; + +export const discoveryServiceRef = createServiceRef({ + id: 'core.discovery', +}); diff --git a/packages/backend-plugin-api/src/services/definitions/httpRouterApiRef.ts b/packages/backend-plugin-api/src/services/definitions/httpRouterServiceRef.ts similarity index 91% rename from packages/backend-plugin-api/src/services/definitions/httpRouterApiRef.ts rename to packages/backend-plugin-api/src/services/definitions/httpRouterServiceRef.ts index d54ebd36bf..9cf1089119 100644 --- a/packages/backend-plugin-api/src/services/definitions/httpRouterApiRef.ts +++ b/packages/backend-plugin-api/src/services/definitions/httpRouterServiceRef.ts @@ -20,6 +20,6 @@ export interface HttpRouterApi { get(path: string): void; } -export const httpRouterApiRef = createServiceRef({ +export const httpRouterServiceRef = createServiceRef({ id: 'core.httpRouter', }); diff --git a/packages/backend-plugin-api/src/services/definitions/index.ts b/packages/backend-plugin-api/src/services/definitions/index.ts index b11b2f8c4e..8b78d2d0ee 100644 --- a/packages/backend-plugin-api/src/services/definitions/index.ts +++ b/packages/backend-plugin-api/src/services/definitions/index.ts @@ -26,8 +26,13 @@ // scheduler: PluginTaskScheduler; // }; -export { configApiRef } from './configApiRef'; -export { httpRouterApiRef } from './httpRouterApiRef'; -export type { HttpRouterApi } from './httpRouterApiRef'; -export { loggerApiRef } from './loggerApiRef'; -export type { Logger } from './loggerApiRef'; +export { configServiceRef } from './configServiceRef'; +export { httpRouterServiceRef } from './httpRouterServiceRef'; +export type { HttpRouterApi } 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'; diff --git a/packages/backend-plugin-api/src/services/definitions/loggerApiRef.ts b/packages/backend-plugin-api/src/services/definitions/loggerServiceRef.ts similarity index 89% rename from packages/backend-plugin-api/src/services/definitions/loggerApiRef.ts rename to packages/backend-plugin-api/src/services/definitions/loggerServiceRef.ts index 348ffc9cf4..564ce15ded 100644 --- a/packages/backend-plugin-api/src/services/definitions/loggerApiRef.ts +++ b/packages/backend-plugin-api/src/services/definitions/loggerServiceRef.ts @@ -17,10 +17,10 @@ import { createServiceRef } from '../system/types'; export interface Logger { - log(message: string): void; + info(message: string): void; child(fields: { [name: string]: string }): Logger; } -export const loggerApiRef = createServiceRef({ +export const loggerServiceRef = createServiceRef({ id: 'core.logger', }); diff --git a/packages/backend-plugin-api/src/services/definitions/tokenManagerServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/tokenManagerServiceRef.ts new file mode 100644 index 0000000000..c62d4bb634 --- /dev/null +++ b/packages/backend-plugin-api/src/services/definitions/tokenManagerServiceRef.ts @@ -0,0 +1,22 @@ +/* + * 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'; + +export const tokenManagerServiceRef = createServiceRef({ + id: 'core.tokenManager', +}); diff --git a/packages/backend-plugin-api/src/services/definitions/urlReaderServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/urlReaderServiceRef.ts new file mode 100644 index 0000000000..25a9666882 --- /dev/null +++ b/packages/backend-plugin-api/src/services/definitions/urlReaderServiceRef.ts @@ -0,0 +1,22 @@ +/* + * 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'; + +export const urlReaderServiceRef = createServiceRef({ + id: 'core.urlReader', +}); diff --git a/packages/backend-plugin-api/src/services/system/types.ts b/packages/backend-plugin-api/src/services/system/types.ts index 86ad8d42f0..2f59e65320 100644 --- a/packages/backend-plugin-api/src/services/system/types.ts +++ b/packages/backend-plugin-api/src/services/system/types.ts @@ -68,3 +68,11 @@ export function createServiceRef(options: { id: string }): ServiceRef { $$ref: 'service', // TODO: declare }; } + +export function createServiceFactory< + Api, + Impl extends Api, + Deps extends { [name in string]: unknown }, +>(factory: ServiceFactory): ServiceFactory { + return factory; +} diff --git a/packages/backend/src/next/index.ts b/packages/backend/src/next/index.ts index 221332f6ba..45cf414e01 100644 --- a/packages/backend/src/next/index.ts +++ b/packages/backend/src/next/index.ts @@ -19,6 +19,7 @@ import { createBackendModule, createBackendPlugin, createServiceRef, + loggerServiceRef, } from '@backstage/backend-plugin-api'; // import { catalogPlugin } from '@backstage/plugin-catalog-backend'; // import { scaffolderPlugin } from '@backstage/plugin-scaffolder-backend'; @@ -60,12 +61,12 @@ export const catalogPlugin = createBackendPlugin({ env.registerInit({ deps: { - // logger: loggerApiRef, + logger: loggerServiceRef, }, - async init() { + async init({ logger }) { + // const builder = await CatalogBuilder.create(env); + logger.log('boppp'); console.log('I HAZ', processingExtensions.processors[0].process()); - console.log('I AM le CATALOG!'); - // logger.log('HELLO!'); }, }); }, @@ -94,6 +95,16 @@ const backend = createBackend({ apis: [], }); +// logger: Logger; +// cache: PluginCacheManager; +// database: PluginDatabaseManager; +// config: Config; +// reader: UrlReader; +// discovery: PluginEndpointDiscovery; +// tokenManager: TokenManager; +// permissions: PermissionEvaluator | PermissionAuthorizer; +// scheduler: PluginTaskScheduler; + // backend.add(scaffolderPlugin()); backend.add(catalogPlugin({})); backend.add(scaffolderCatalogExtension({})); From d85f7dc1791381f323d3f195a3191e7c7796e1f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 15 Jun 2022 17:03:14 +0200 Subject: [PATCH 31/59] Even more MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Patrik Oldsberg Co-authored-by: blam Co-authored-by: Johan Haals Signed-off-by: Fredrik Adelöw --- packages/backend-app-api/package.json | 2 + .../services/implementations/cacheService.ts | 37 ++++++++++++ .../services/implementations/configService.ts | 11 ++-- .../implementations/databaseService.ts | 36 +++++++++++ .../implementations/discoveryService.ts | 36 +++++++++++ .../src/services/implementations/index.ts | 37 ++++++++++++ .../services/implementations/loggerService.ts | 1 - .../implementations/permissionsService.ts | 45 ++++++++++++++ .../implementations/schedulerService.ts | 36 +++++++++++ .../implementations/tokenManagerService.ts | 60 +++++++++++++++++++ .../implementations/urlReaderService.ts | 4 +- .../src/wiring/BackendInitializer.ts | 21 ++++--- packages/backend-app-api/src/wiring/types.ts | 8 ++- packages/backend-plugin-api/package.json | 4 +- .../src/services/definitions/index.ts | 2 + .../definitions/permissionsServiceRef.ts | 27 +++++++++ ...erServiceRef.ts => schedulerServiceRef.ts} | 6 +- .../definitions/scheldulerServiceRef.ts | 27 +++++++++ packages/backend/src/next/index.ts | 2 +- 19 files changed, 379 insertions(+), 23 deletions(-) create mode 100644 packages/backend-app-api/src/services/implementations/cacheService.ts create mode 100644 packages/backend-app-api/src/services/implementations/databaseService.ts create mode 100644 packages/backend-app-api/src/services/implementations/discoveryService.ts create mode 100644 packages/backend-app-api/src/services/implementations/index.ts create mode 100644 packages/backend-app-api/src/services/implementations/permissionsService.ts create mode 100644 packages/backend-app-api/src/services/implementations/schedulerService.ts create mode 100644 packages/backend-app-api/src/services/implementations/tokenManagerService.ts create mode 100644 packages/backend-plugin-api/src/services/definitions/permissionsServiceRef.ts rename packages/backend-plugin-api/src/services/definitions/{cacheManagerServiceRef.ts => schedulerServiceRef.ts} (80%) create mode 100644 packages/backend-plugin-api/src/services/definitions/scheldulerServiceRef.ts diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index 02c5450021..b0bbb8cc8b 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -36,6 +36,8 @@ "dependencies": { "@backstage/backend-plugin-api": "^0.0.0", "@backstage/backend-common": "^0.14.0", + "@backstage/backend-tasks": "^0.3.2", + "@backstage/plugin-permission-node": "^0.6.2", "winston": "^3.2.1" }, "devDependencies": { diff --git a/packages/backend-app-api/src/services/implementations/cacheService.ts b/packages/backend-app-api/src/services/implementations/cacheService.ts new file mode 100644 index 0000000000..034f85f917 --- /dev/null +++ b/packages/backend-app-api/src/services/implementations/cacheService.ts @@ -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); + }; + }, +}); diff --git a/packages/backend-app-api/src/services/implementations/configService.ts b/packages/backend-app-api/src/services/implementations/configService.ts index b066989069..e9a81ae100 100644 --- a/packages/backend-app-api/src/services/implementations/configService.ts +++ b/packages/backend-app-api/src/services/implementations/configService.ts @@ -22,16 +22,19 @@ import { } from '@backstage/backend-plugin-api'; import { loggerToWinstonLogger } from './loggerService'; -export const configService = createServiceFactory({ +export const configFactory = createServiceFactory({ service: configServiceRef, - deps: { loggerFactory: loggerServiceRef }, + deps: { + loggerFactory: loggerServiceRef, + }, factory: async ({ loggerFactory }) => { const logger = await loggerFactory('root'); const config = await loadBackendConfig({ argv: process.argv, logger: loggerToWinstonLogger(logger), }); - - return async () => config; + return async () => { + return config; + }; }, }); diff --git a/packages/backend-app-api/src/services/implementations/databaseService.ts b/packages/backend-app-api/src/services/implementations/databaseService.ts new file mode 100644 index 0000000000..a52da1e444 --- /dev/null +++ b/packages/backend-app-api/src/services/implementations/databaseService.ts @@ -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); + }; + }, +}); diff --git a/packages/backend-app-api/src/services/implementations/discoveryService.ts b/packages/backend-app-api/src/services/implementations/discoveryService.ts new file mode 100644 index 0000000000..23af1924a0 --- /dev/null +++ b/packages/backend-app-api/src/services/implementations/discoveryService.ts @@ -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; + }; + }, +}); diff --git a/packages/backend-app-api/src/services/implementations/index.ts b/packages/backend-app-api/src/services/implementations/index.ts new file mode 100644 index 0000000000..f520b43cd4 --- /dev/null +++ b/packages/backend-app-api/src/services/implementations/index.ts @@ -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 { 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'; + +export const defaultServiceFactories = [ + cacheFactory, + configFactory, + databaseFactory, + discoveryFactory, + loggerFactory, + permissionsFactory, + schedulerFactory, + tokenManagerFactory, + urlReaderFactory, +]; diff --git a/packages/backend-app-api/src/services/implementations/loggerService.ts b/packages/backend-app-api/src/services/implementations/loggerService.ts index 4b6eadfa1f..ff6af4b643 100644 --- a/packages/backend-app-api/src/services/implementations/loggerService.ts +++ b/packages/backend-app-api/src/services/implementations/loggerService.ts @@ -55,7 +55,6 @@ export const loggerFactory = createServiceFactory({ const root = new BackstageLogger({ winston: createRootLogger(), }); - return async (pluginId: string) => { return root.child({ pluginId }); }; diff --git a/packages/backend-app-api/src/services/implementations/permissionsService.ts b/packages/backend-app-api/src/services/implementations/permissionsService.ts new file mode 100644 index 0000000000..97f0330917 --- /dev/null +++ b/packages/backend-app-api/src/services/implementations/permissionsService.ts @@ -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; + }; + }, +}); diff --git a/packages/backend-app-api/src/services/implementations/schedulerService.ts b/packages/backend-app-api/src/services/implementations/schedulerService.ts new file mode 100644 index 0000000000..130ccb3f5f --- /dev/null +++ b/packages/backend-app-api/src/services/implementations/schedulerService.ts @@ -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); + }; + }, +}); diff --git a/packages/backend-app-api/src/services/implementations/tokenManagerService.ts b/packages/backend-app-api/src/services/implementations/tokenManagerService.ts new file mode 100644 index 0000000000..7f0423e845 --- /dev/null +++ b/packages/backend-app-api/src/services/implementations/tokenManagerService.ts @@ -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, +} from '@backstage/backend-plugin-api'; +import { ServerTokenManager } from '@backstage/backend-common'; +import { loggerToWinstonLogger } from './loggerService'; + +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), + }); + }; + }, +}); diff --git a/packages/backend-app-api/src/services/implementations/urlReaderService.ts b/packages/backend-app-api/src/services/implementations/urlReaderService.ts index afbc80d9ac..7df6ca33a9 100644 --- a/packages/backend-app-api/src/services/implementations/urlReaderService.ts +++ b/packages/backend-app-api/src/services/implementations/urlReaderService.ts @@ -26,10 +26,10 @@ import { loggerToWinstonLogger } from './loggerService'; export const urlReaderFactory = createServiceFactory({ service: urlReaderServiceRef, deps: { - loggerFactory: loggerServiceRef, configFactory: configServiceRef, + loggerFactory: loggerServiceRef, }, - factory: async ({ loggerFactory, configFactory }) => { + factory: async ({ configFactory, loggerFactory }) => { return async (pluginId: string) => { const logger = await loggerFactory(pluginId); return UrlReaders.default({ diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.ts b/packages/backend-app-api/src/wiring/BackendInitializer.ts index a613e88bb1..6338b60bfb 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.ts @@ -15,7 +15,7 @@ */ import { BackendRegistrable, ServiceRef } from '@backstage/backend-plugin-api'; -import { ApiHolder, BackendRegisterInit } from './types'; +import { BackendRegisterInit, ApiHolder } from './types'; export class BackendInitializer { #started = false; @@ -131,15 +131,20 @@ export class BackendInitializer { const toRemove = new Set(); for (const registerInit of registerInitsToOrder) { - const unInitializedDependents = Array.from( - registerInit.provides, - ).filter(r => - registerInitsToOrder.some( - init => init !== registerInit && init.consumes.has(r), - ), - ); + const unInitializedDependents = []; + + for (const api of registerInit.provides) { + if ( + registerInitsToOrder.some( + init => init !== registerInit && init.consumes.has(api), + ) + ) { + unInitializedDependents.push(api); + } + } if (unInitializedDependents.length === 0) { + console.log(`DEBUG: pushed ${registerInit.id} to results`); orderedRegisterInits.push(registerInit); toRemove.add(registerInit); } diff --git a/packages/backend-app-api/src/wiring/types.ts b/packages/backend-app-api/src/wiring/types.ts index 5c2e7a9e96..c1c43a8ba8 100644 --- a/packages/backend-app-api/src/wiring/types.ts +++ b/packages/backend-app-api/src/wiring/types.ts @@ -20,7 +20,7 @@ import { FactoryFunc, ServiceRef, } from '@backstage/backend-plugin-api'; -import { loggerFactory } from '../services/implementations/loggerService'; +import { defaultServiceFactories } from '../services/implementations'; import { BackstageBackend } from './BackstageBackend'; export interface Backend { @@ -46,6 +46,8 @@ export type ApiHolder = { export function createBackend(options?: CreateBackendOptions): Backend { // TODO: merge with provided APIs - const defaultApis = [loggerFactory]; - return new BackstageBackend([...defaultApis, ...(options?.apis ?? [])]); + return new BackstageBackend([ + ...defaultServiceFactories, + ...(options?.apis ?? []), + ]); } diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index 6d75af03a7..b5c724f764 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -35,7 +35,9 @@ }, "dependencies": { "@backstage/config": "^1.0.1", - "@backstage/backend-common": "^0.14.0" + "@backstage/backend-common": "^0.14.0", + "@backstage/plugin-permission-common": "^0.6.2", + "@backstage/backend-tasks": "^0.3.2" }, "devDependencies": { "@backstage/cli": "^0.17.2-next.0" diff --git a/packages/backend-plugin-api/src/services/definitions/index.ts b/packages/backend-plugin-api/src/services/definitions/index.ts index 8b78d2d0ee..30f2e009c5 100644 --- a/packages/backend-plugin-api/src/services/definitions/index.ts +++ b/packages/backend-plugin-api/src/services/definitions/index.ts @@ -36,3 +36,5 @@ export { cacheServiceRef } from './cacheServiceRef'; export { databaseServiceRef } from './databaseServiceRef'; export { discoveryServiceRef } from './discoveryServiceRef'; export { tokenManagerServiceRef } from './tokenManagerServiceRef'; +export { permissionsServiceRef } from './permissionsServiceRef'; +export { schedulerServiceRef } from './schedulerServiceRef'; diff --git a/packages/backend-plugin-api/src/services/definitions/permissionsServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/permissionsServiceRef.ts new file mode 100644 index 0000000000..4355286611 --- /dev/null +++ b/packages/backend-plugin-api/src/services/definitions/permissionsServiceRef.ts @@ -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 { createServiceRef } from '../system/types'; +import { + PermissionAuthorizer, + PermissionEvaluator, +} from '@backstage/plugin-permission-common'; + +export const permissionsServiceRef = createServiceRef< + PermissionEvaluator | PermissionAuthorizer +>({ + id: 'core.permissions', +}); diff --git a/packages/backend-plugin-api/src/services/definitions/cacheManagerServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/schedulerServiceRef.ts similarity index 80% rename from packages/backend-plugin-api/src/services/definitions/cacheManagerServiceRef.ts rename to packages/backend-plugin-api/src/services/definitions/schedulerServiceRef.ts index 9dab256704..3a3abfcc10 100644 --- a/packages/backend-plugin-api/src/services/definitions/cacheManagerServiceRef.ts +++ b/packages/backend-plugin-api/src/services/definitions/schedulerServiceRef.ts @@ -15,8 +15,8 @@ */ import { createServiceRef } from '../system/types'; -import { CacheManager } from '@backstage/backend-common'; +import { PluginTaskScheduler } from '@backstage/backend-tasks'; -export const cacheManagerServiceRef = createServiceRef({ - id: 'core.cacheManager', +export const schedulerServiceRef = createServiceRef({ + id: 'core.scheduler', }); diff --git a/packages/backend-plugin-api/src/services/definitions/scheldulerServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/scheldulerServiceRef.ts new file mode 100644 index 0000000000..4355286611 --- /dev/null +++ b/packages/backend-plugin-api/src/services/definitions/scheldulerServiceRef.ts @@ -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 { createServiceRef } from '../system/types'; +import { + PermissionAuthorizer, + PermissionEvaluator, +} from '@backstage/plugin-permission-common'; + +export const permissionsServiceRef = createServiceRef< + PermissionEvaluator | PermissionAuthorizer +>({ + id: 'core.permissions', +}); diff --git a/packages/backend/src/next/index.ts b/packages/backend/src/next/index.ts index 45cf414e01..83ec4b044a 100644 --- a/packages/backend/src/next/index.ts +++ b/packages/backend/src/next/index.ts @@ -65,7 +65,7 @@ export const catalogPlugin = createBackendPlugin({ }, async init({ logger }) { // const builder = await CatalogBuilder.create(env); - logger.log('boppp'); + logger.info('boppp'); console.log('I HAZ', processingExtensions.processors[0].process()); }, }); From 696ba03bc5d96df83077f23d4ebc573a77b363a1 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Mon, 27 Jun 2022 13:41:15 +0200 Subject: [PATCH 32/59] Wire up catalog backend Signed-off-by: Johan Haals --- packages/backend-app-api/src/index.ts | 1 + packages/backend/src/next/index.ts | 61 +++++++++++++++------------ 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/packages/backend-app-api/src/index.ts b/packages/backend-app-api/src/index.ts index 33aca2b291..d75f5c0941 100644 --- a/packages/backend-app-api/src/index.ts +++ b/packages/backend-app-api/src/index.ts @@ -21,3 +21,4 @@ */ export { createBackend } from './wiring/types'; +export { loggerToWinstonLogger } from './services/implementations/loggerService'; diff --git a/packages/backend/src/next/index.ts b/packages/backend/src/next/index.ts index 83ec4b044a..034ef5e5d2 100644 --- a/packages/backend/src/next/index.ts +++ b/packages/backend/src/next/index.ts @@ -14,19 +14,25 @@ * limitations under the License. */ -import { createBackend } from '@backstage/backend-app-api'; import { + createBackend, + loggerToWinstonLogger, +} from '@backstage/backend-app-api'; +import { + configServiceRef, createBackendModule, createBackendPlugin, createServiceRef, + databaseServiceRef, loggerServiceRef, + permissionsServiceRef, + urlReaderServiceRef, } from '@backstage/backend-plugin-api'; -// import { catalogPlugin } from '@backstage/plugin-catalog-backend'; -// import { scaffolderPlugin } from '@backstage/plugin-scaffolder-backend'; - -interface CatalogProcessor { - process(): void; -} +import { + CatalogBuilder, + CatalogProcessor, +} from '@backstage/plugin-catalog-backend'; +import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend'; interface CatalogProcessingInitApi { addProcessor(processor: CatalogProcessor): void; @@ -62,18 +68,30 @@ export const catalogPlugin = createBackendPlugin({ env.registerInit({ deps: { logger: loggerServiceRef, + config: configServiceRef, + reader: urlReaderServiceRef, + permissions: permissionsServiceRef, + database: databaseServiceRef, }, - async init({ logger }) { - // const builder = await CatalogBuilder.create(env); - logger.info('boppp'); - console.log('I HAZ', processingExtensions.processors[0].process()); + async init({ logger, config, reader, database, permissions }) { + const winstonLogger = loggerToWinstonLogger(logger); + const builder = await CatalogBuilder.create({ + config, + reader, + permissions, + database, + logger: winstonLogger, + }); + builder.addProcessor(processingExtensions.processors); + const { processingEngine } = await builder.build(); + await processingEngine.start(); }, }); }, }); export const scaffolderCatalogExtension = createBackendModule({ - moduleId: 'boop', + moduleId: 'scaffolder.extention', pluginId: 'catalog', register(env) { env.registerInit({ @@ -81,11 +99,9 @@ export const scaffolderCatalogExtension = createBackendModule({ catalogProcessingInitApi: catalogProcessingInitApiRef, }, async init({ catalogProcessingInitApi }) { - catalogProcessingInitApi.addProcessor({ - process() { - console.log('Running scaffolder processor'); - }, - }); + catalogProcessingInitApi.addProcessor( + new ScaffolderEntitiesProcessor(), + ); }, }); }, @@ -95,17 +111,6 @@ const backend = createBackend({ apis: [], }); -// logger: Logger; -// cache: PluginCacheManager; -// database: PluginDatabaseManager; -// config: Config; -// reader: UrlReader; -// discovery: PluginEndpointDiscovery; -// tokenManager: TokenManager; -// permissions: PermissionEvaluator | PermissionAuthorizer; -// scheduler: PluginTaskScheduler; - -// backend.add(scaffolderPlugin()); backend.add(catalogPlugin({})); backend.add(scaffolderCatalogExtension({})); backend.start(); From 118ce976f173f10b405a181c1742b6243feb78e1 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 16 Feb 2022 12:05:48 +0100 Subject: [PATCH 33/59] experiment 1 Signed-off-by: Patrik Oldsberg --- packages/backend/src/experiment1.ts | 350 ++++++++++++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100644 packages/backend/src/experiment1.ts diff --git a/packages/backend/src/experiment1.ts b/packages/backend/src/experiment1.ts new file mode 100644 index 0000000000..10a752927f --- /dev/null +++ b/packages/backend/src/experiment1.ts @@ -0,0 +1,350 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import express, { NextFunction, Request, Response } from 'express'; +import Router from 'express-promise-router'; +/* +Things to consider: + + - Make the router accessible? Allow integrators to add their own middleware + - The backend entrypoint should make it clear what routes are available + - Modules should not be required to have a router + - Internal modules that extend the functionality of plugins? + - Exposed on under the plugin route, access to same resources? + +*/ + +const routes = { + '/': [/* something */], +} as const; + +interface BackendModule { + routes?: () => [string, (request: Request, response: Response, next: NextFunction) => void]; + start?: () => Promise; + stop?: () => Promise; +} + +const theBackend: BackendModule = { + const modules: Module[]; + async start() { + modules.forEach(it => it.start()) + } + routes() { + return modules.reduce((acc, it) => ({...acc, [it.name]: it.routes()}), {}) + } +} + +async function main_version1() { + const backend: BackendModule = createBackend({ + + }) + + // -> modules install routes and other stuff too? + backend.installModule(catalogPlugin.modules.entitiesCatalog({ startEngine: false })) + backend.installModule(catalogPlugin.modules.locationService({...config})) + + const app = express() + + // Probably problematic to have the installation be too deep + app.use('/catalog/entities', catalogPlugin.modules.entitiesCatalog({ startEngine: false })) + + app.use('/catalog', catalogPlugin.modules.entitiesCatalog({ startEngine: false })) + + const entitiesCatalogModule = catalogPlugin.modules.entitiesCatalog({ startEngine: false }) + for (const route of entitiesCatalogModule.routes) { + app.use(route.path, route.handler) + } + + const entitiesCatalogController = createController(catalogPlugin.modules.entitiesCatalog({ startEngine: false })) + app.use('/catalog/entities', entitiesCatalogController.entities) + + app.use('/catalog', createPluginRouter(entitiesCatalogModule.routes())); + // Get router from startup? + // Hiding creation of router might be bad + + Object.entries(backend.routes()).forEach(([module, routes]) => console.log(`Registering route ${route.join(', ')} for module ${module}`))) + + const { router } = await backend.start() + + // Or access the router directly? + const router = backend.getRouter(); + + + + + app.use(router); +} + + +async function main_version2() { + const backend = createBackend({ + modules: [ + catalogPlugin.modules.entitiesCatalog(), + catalogPlugin.modules.locationService(), + ], + }) + + await backend.start() +} + + +async function main_version3() { + const backend = createBackend({ + modules: { + '/catalog': [ + catalogPlugin.modules.entitiesCatalog(), + catalogPlugin.modules.locationService(), + ], + }, + }) + + await backend.start() +} + + +async function main_version4() { + const backend = createBackend({ + modules: { + '/catalog/entities': catalogPlugin.modules.entitiesCatalog(), + '/catalog/locations': catalogPlugin.modules.locationService(), + '/catalog/extensions': roadieCatalogPlugin.modules.catalogExtensions(), + }, + }) + + await backend.start() +} + + +async function main_version5() { + const backend = createBackend({ + plugins: [ + catalogPlugin(), + ], + }) + + await backend.start() +} + + +async function main_version5b() { + const backend = createBackend({ + plugins: [ + catalogPlugin.modules.entitiesCatalog(), + catalogPlugin.modules.locationService(), + scaffolderPlugin, + ], + }) + + await backend.start() +} + + +async function main_version5c() { + const backend = createBackend({ + plugins: [ + scaffolderPlugin, + ], + modules: [ + catalogPlugin.modules.entitiesCatalog(), + catalogPlugin.modules.locationService(), + ] + }) + + await backend.start() +} + + +async function main_version6() { + const backend = createBackend({ + plugins: [ + catalogPlugin({ extensions }), + ], + }) + + await backend.start() +} + +async function main_version7() { + type CatalogExtension = ({ database, orchestrator, }: any) => () => Promise<{ router: Router }>; + + const extensions: CatalogExtension[] = [ + ({ database, orchestrator }) => async () => { + const router = Router(); + router.post('/stop-orchestrator', () => orchestrator.stop()) + + return { router }; + } + ]; + + // /extensions/stop-orch + + + const backend = createBackend({ + plugins: [ + catalogPlugin({ extensions }), + ], + }) + + await backend.start() +} + +async function main_version7b() { + type CatalogExtension = ({ container }: any) => () => Promise; + + const extensions: CatalogExtension[] = [ + (container) => async () => { + const pluginRouter = container.get('pluginRouter') + const orchestrator = container.get('orchestrator') + + const router = Router(); + router.post('/stop-orchestrator', () => orchestrator.stop()) + + pluginRouter.use(router) + } + ]; + + // /extensions/stop-orch + + + const backend = createBackend({ + plugins: [ + catalogPlugin({ extensions }), + ], + }) + + await backend.start() +} + + + + + + + + + + + + + +// Catalog Plugin implementation + +const myModule = createCatalogExtension({ + entityProviders: [MyProviderFactory], + entityProcessors: [], +}); + +class MyProviderFactory { + constructor(registry: ProviderRegistry /* from the catalog */, things: Thing[] /* from the adopter */) { + registry.add(...things.map(t => t.create(...))) + } +} + +class MyProviderFactory { + constructor(ctx: Context, registry: ProviderRegistry, things: Thing[]) { + registry.add(...things.map(thing => ctx.get('catalog-provider-api').withTag(thing))) + } +} + + +const myEntityProvider = createBackendModule({ + factory: (container) => { + const api = container.get('catalog-provider-api') + ///... + return // ??? + } +}) + +const myEntityProvider = createCatalogEntityProviderExtension({ + ..., +}); + +const catalogPlugin = createBackendPlugin({ + modules: [ + myModule + ] +}) + +// How do you install additional features into the catalog? + + +import { catalogPlugin } from '@backstage/plugin-catalog-backend'; +import { githubEntityProvider } from '@backstage/plugin-catalog-backend-module-github'; + +async function main_version10() { + const backend = createBackend({ + modules: [ + catalogPlugin.modules.entitiesCatalog({ + providers: [githubEntityProvider], + }), + catalogPlugin.modules.locationService(), + ] + }) + + await backend.start() +} + + +async function main_version10a() { + const backend = createBackend({ + modules: [ + catalogPlugin.modules.entitiesCatalog(), + catalogPlugin.modules.locationService(), + githubEntityProvider, + ] + }) + + await backend.start() +} + + +async function main_version10b() { + const backend = createBackend({ + modules: [ + catalogPlugin.modules.entitiesCatalog(), + catalogPlugin.modules.locationService(), + githubEntityProvider, + ] + }) + + await backend.start() +} + +async function main_version10c() { + const backend = createBackend({ + modules: [ + catalogPlugin(), + searchPlugin({ + collators: new CatalogCollator(), // :( + }), + ] + }) + + await backend.start() +} + + + +// possible DI way to do that @johan, nice maaan! +container.add(someCollator); +container.add(otherCOllator); +... +container.getAll(); + +// types are build time ;) :shakefist: +container.add(SearchCollator, someCollator); +container.add(SearchCollator, otherCOllator); +... +container.getAll(SearchCollator); From 7e48611ba6a84690cb9c0a661e0ac7e3b34c76a3 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 5 Jul 2022 15:14:21 +0200 Subject: [PATCH 34/59] =?UTF-8?q?chore:=20wiring=20up=20the=20catalog=20?= =?UTF-8?q?=F0=9F=93=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Co-authored-by: Johan Haals Co-authored-by: Patrik Oldsberg Signed-off-by: blam --- packages/backend-app-api/package.json | 2 + .../implementations/httpRouterService.ts | 44 +++++++++++++++++++ .../src/services/implementations/index.ts | 2 + packages/backend-plugin-api/package.json | 6 ++- .../definitions/httpRouterServiceRef.ts | 25 +++++++++-- .../src/services/definitions/index.ts | 2 +- packages/backend/src/next/index.ts | 18 ++++++-- 7 files changed, 90 insertions(+), 9 deletions(-) create mode 100644 packages/backend-app-api/src/services/implementations/httpRouterService.ts diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index b0bbb8cc8b..6ad48f86d5 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -38,6 +38,8 @@ "@backstage/backend-common": "^0.14.0", "@backstage/backend-tasks": "^0.3.2", "@backstage/plugin-permission-node": "^0.6.2", + "express": "^4.17.1", + "express-promise-router": "^4.1.0", "winston": "^3.2.1" }, "devDependencies": { diff --git a/packages/backend-app-api/src/services/implementations/httpRouterService.ts b/packages/backend-app-api/src/services/implementations/httpRouterService.ts new file mode 100644 index 0000000000..82dfb13218 --- /dev/null +++ b/packages/backend-app-api/src/services/implementations/httpRouterService.ts @@ -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 { + createServiceFactory, + httpRouterServiceRef, +} from '@backstage/backend-plugin-api'; +import Router from 'express-promise-router'; +import express, { Handler } from 'express'; + +export const httpRouterFactory = createServiceFactory({ + service: httpRouterServiceRef, + deps: {}, + factory: async () => { + const app = express(); + const rootRouter = Router(); + + app.use(rootRouter); + app.listen(8123); + + return async (pluginId?: string) => { + if (!pluginId) { + return rootRouter; + } + return { + use(handler: Handler) { + rootRouter.use(`/api/${pluginId}`, handler); + }, + }; + }; + }, +}); diff --git a/packages/backend-app-api/src/services/implementations/index.ts b/packages/backend-app-api/src/services/implementations/index.ts index f520b43cd4..e6b6604069 100644 --- a/packages/backend-app-api/src/services/implementations/index.ts +++ b/packages/backend-app-api/src/services/implementations/index.ts @@ -23,6 +23,7 @@ import { permissionsFactory } from './permissionsService'; import { schedulerFactory } from './schedulerService'; import { tokenManagerFactory } from './tokenManagerService'; import { urlReaderFactory } from './urlReaderService'; +import { httpRouterFactory } from './httpRouterService'; export const defaultServiceFactories = [ cacheFactory, @@ -34,4 +35,5 @@ export const defaultServiceFactories = [ schedulerFactory, tokenManagerFactory, urlReaderFactory, + httpRouterFactory, ]; diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index b5c724f764..dc52366c65 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -37,10 +37,12 @@ "@backstage/config": "^1.0.1", "@backstage/backend-common": "^0.14.0", "@backstage/plugin-permission-common": "^0.6.2", - "@backstage/backend-tasks": "^0.3.2" + "@backstage/backend-tasks": "^0.3.2", + "express": "^4.17.1" }, "devDependencies": { - "@backstage/cli": "^0.17.2-next.0" + "@backstage/cli": "^0.17.2-next.0", + "@types/express": "^4.17.6" }, "files": [ "dist", diff --git a/packages/backend-plugin-api/src/services/definitions/httpRouterServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/httpRouterServiceRef.ts index 9cf1089119..65a01fde3a 100644 --- a/packages/backend-plugin-api/src/services/definitions/httpRouterServiceRef.ts +++ b/packages/backend-plugin-api/src/services/definitions/httpRouterServiceRef.ts @@ -15,11 +15,30 @@ */ import { createServiceRef } from '../system/types'; +import { Handler } from 'express'; -export interface HttpRouterApi { - get(path: string): void; +// const apiRouter = Router(); +// apiRouter.use('/catalog', await catalog(catalogEnv)); +// const service = createServiceBuilder(module) +// .loadConfig(config) +// .addRouter('', await healthcheck(healthcheckEnv)) +// .addRouter('', metricsHandler()) +// .addRouter('/api', apiRouter) +// .addRouter('', await app(appEnv)); + +// interface BackstageRequest extends Request { +// identity?: BackstageIdentity; +// context?: Context; +// } + +// interface RequestIdentityService { +// getRequestIdentity(req: Request): BackstageIdentity | undefined; +// } + +export interface HttpRouterService { + use(handler: Handler): void; } -export const httpRouterServiceRef = createServiceRef({ +export const httpRouterServiceRef = createServiceRef({ id: 'core.httpRouter', }); diff --git a/packages/backend-plugin-api/src/services/definitions/index.ts b/packages/backend-plugin-api/src/services/definitions/index.ts index 30f2e009c5..556aa88c72 100644 --- a/packages/backend-plugin-api/src/services/definitions/index.ts +++ b/packages/backend-plugin-api/src/services/definitions/index.ts @@ -28,7 +28,7 @@ export { configServiceRef } from './configServiceRef'; export { httpRouterServiceRef } from './httpRouterServiceRef'; -export type { HttpRouterApi } from './httpRouterServiceRef'; +export type { HttpRouterService } from './httpRouterServiceRef'; export { loggerServiceRef } from './loggerServiceRef'; export type { Logger } from './loggerServiceRef'; export { urlReaderServiceRef } from './urlReaderServiceRef'; diff --git a/packages/backend/src/next/index.ts b/packages/backend/src/next/index.ts index 034ef5e5d2..de40592ea5 100644 --- a/packages/backend/src/next/index.ts +++ b/packages/backend/src/next/index.ts @@ -27,6 +27,7 @@ import { loggerServiceRef, permissionsServiceRef, urlReaderServiceRef, + httpRouterServiceRef, } from '@backstage/backend-plugin-api'; import { CatalogBuilder, @@ -72,8 +73,16 @@ export const catalogPlugin = createBackendPlugin({ reader: urlReaderServiceRef, permissions: permissionsServiceRef, database: databaseServiceRef, + httpRouter: httpRouterServiceRef, }, - async init({ logger, config, reader, database, permissions }) { + async init({ + logger, + config, + reader, + database, + permissions, + httpRouter, + }) { const winstonLogger = loggerToWinstonLogger(logger); const builder = await CatalogBuilder.create({ config, @@ -82,9 +91,12 @@ export const catalogPlugin = createBackendPlugin({ database, logger: winstonLogger, }); - builder.addProcessor(processingExtensions.processors); - const { processingEngine } = await builder.build(); + builder.addProcessor(...processingExtensions.processors); + const { processingEngine, router } = await builder.build(); + await processingEngine.start(); + + httpRouter.use(router); }, }); }, From 0d71831aae42f02c48cfc33ebe771c738f5862fe Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Wed, 6 Jul 2022 10:41:41 +0200 Subject: [PATCH 35/59] chore: delete experiements Signed-off-by: Johan Haals --- packages/backend/src/experiment1.ts | 350 ---------------------------- 1 file changed, 350 deletions(-) delete mode 100644 packages/backend/src/experiment1.ts diff --git a/packages/backend/src/experiment1.ts b/packages/backend/src/experiment1.ts deleted file mode 100644 index 10a752927f..0000000000 --- a/packages/backend/src/experiment1.ts +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright 2022 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import express, { NextFunction, Request, Response } from 'express'; -import Router from 'express-promise-router'; -/* -Things to consider: - - - Make the router accessible? Allow integrators to add their own middleware - - The backend entrypoint should make it clear what routes are available - - Modules should not be required to have a router - - Internal modules that extend the functionality of plugins? - - Exposed on under the plugin route, access to same resources? - -*/ - -const routes = { - '/': [/* something */], -} as const; - -interface BackendModule { - routes?: () => [string, (request: Request, response: Response, next: NextFunction) => void]; - start?: () => Promise; - stop?: () => Promise; -} - -const theBackend: BackendModule = { - const modules: Module[]; - async start() { - modules.forEach(it => it.start()) - } - routes() { - return modules.reduce((acc, it) => ({...acc, [it.name]: it.routes()}), {}) - } -} - -async function main_version1() { - const backend: BackendModule = createBackend({ - - }) - - // -> modules install routes and other stuff too? - backend.installModule(catalogPlugin.modules.entitiesCatalog({ startEngine: false })) - backend.installModule(catalogPlugin.modules.locationService({...config})) - - const app = express() - - // Probably problematic to have the installation be too deep - app.use('/catalog/entities', catalogPlugin.modules.entitiesCatalog({ startEngine: false })) - - app.use('/catalog', catalogPlugin.modules.entitiesCatalog({ startEngine: false })) - - const entitiesCatalogModule = catalogPlugin.modules.entitiesCatalog({ startEngine: false }) - for (const route of entitiesCatalogModule.routes) { - app.use(route.path, route.handler) - } - - const entitiesCatalogController = createController(catalogPlugin.modules.entitiesCatalog({ startEngine: false })) - app.use('/catalog/entities', entitiesCatalogController.entities) - - app.use('/catalog', createPluginRouter(entitiesCatalogModule.routes())); - // Get router from startup? - // Hiding creation of router might be bad - - Object.entries(backend.routes()).forEach(([module, routes]) => console.log(`Registering route ${route.join(', ')} for module ${module}`))) - - const { router } = await backend.start() - - // Or access the router directly? - const router = backend.getRouter(); - - - - - app.use(router); -} - - -async function main_version2() { - const backend = createBackend({ - modules: [ - catalogPlugin.modules.entitiesCatalog(), - catalogPlugin.modules.locationService(), - ], - }) - - await backend.start() -} - - -async function main_version3() { - const backend = createBackend({ - modules: { - '/catalog': [ - catalogPlugin.modules.entitiesCatalog(), - catalogPlugin.modules.locationService(), - ], - }, - }) - - await backend.start() -} - - -async function main_version4() { - const backend = createBackend({ - modules: { - '/catalog/entities': catalogPlugin.modules.entitiesCatalog(), - '/catalog/locations': catalogPlugin.modules.locationService(), - '/catalog/extensions': roadieCatalogPlugin.modules.catalogExtensions(), - }, - }) - - await backend.start() -} - - -async function main_version5() { - const backend = createBackend({ - plugins: [ - catalogPlugin(), - ], - }) - - await backend.start() -} - - -async function main_version5b() { - const backend = createBackend({ - plugins: [ - catalogPlugin.modules.entitiesCatalog(), - catalogPlugin.modules.locationService(), - scaffolderPlugin, - ], - }) - - await backend.start() -} - - -async function main_version5c() { - const backend = createBackend({ - plugins: [ - scaffolderPlugin, - ], - modules: [ - catalogPlugin.modules.entitiesCatalog(), - catalogPlugin.modules.locationService(), - ] - }) - - await backend.start() -} - - -async function main_version6() { - const backend = createBackend({ - plugins: [ - catalogPlugin({ extensions }), - ], - }) - - await backend.start() -} - -async function main_version7() { - type CatalogExtension = ({ database, orchestrator, }: any) => () => Promise<{ router: Router }>; - - const extensions: CatalogExtension[] = [ - ({ database, orchestrator }) => async () => { - const router = Router(); - router.post('/stop-orchestrator', () => orchestrator.stop()) - - return { router }; - } - ]; - - // /extensions/stop-orch - - - const backend = createBackend({ - plugins: [ - catalogPlugin({ extensions }), - ], - }) - - await backend.start() -} - -async function main_version7b() { - type CatalogExtension = ({ container }: any) => () => Promise; - - const extensions: CatalogExtension[] = [ - (container) => async () => { - const pluginRouter = container.get('pluginRouter') - const orchestrator = container.get('orchestrator') - - const router = Router(); - router.post('/stop-orchestrator', () => orchestrator.stop()) - - pluginRouter.use(router) - } - ]; - - // /extensions/stop-orch - - - const backend = createBackend({ - plugins: [ - catalogPlugin({ extensions }), - ], - }) - - await backend.start() -} - - - - - - - - - - - - - -// Catalog Plugin implementation - -const myModule = createCatalogExtension({ - entityProviders: [MyProviderFactory], - entityProcessors: [], -}); - -class MyProviderFactory { - constructor(registry: ProviderRegistry /* from the catalog */, things: Thing[] /* from the adopter */) { - registry.add(...things.map(t => t.create(...))) - } -} - -class MyProviderFactory { - constructor(ctx: Context, registry: ProviderRegistry, things: Thing[]) { - registry.add(...things.map(thing => ctx.get('catalog-provider-api').withTag(thing))) - } -} - - -const myEntityProvider = createBackendModule({ - factory: (container) => { - const api = container.get('catalog-provider-api') - ///... - return // ??? - } -}) - -const myEntityProvider = createCatalogEntityProviderExtension({ - ..., -}); - -const catalogPlugin = createBackendPlugin({ - modules: [ - myModule - ] -}) - -// How do you install additional features into the catalog? - - -import { catalogPlugin } from '@backstage/plugin-catalog-backend'; -import { githubEntityProvider } from '@backstage/plugin-catalog-backend-module-github'; - -async function main_version10() { - const backend = createBackend({ - modules: [ - catalogPlugin.modules.entitiesCatalog({ - providers: [githubEntityProvider], - }), - catalogPlugin.modules.locationService(), - ] - }) - - await backend.start() -} - - -async function main_version10a() { - const backend = createBackend({ - modules: [ - catalogPlugin.modules.entitiesCatalog(), - catalogPlugin.modules.locationService(), - githubEntityProvider, - ] - }) - - await backend.start() -} - - -async function main_version10b() { - const backend = createBackend({ - modules: [ - catalogPlugin.modules.entitiesCatalog(), - catalogPlugin.modules.locationService(), - githubEntityProvider, - ] - }) - - await backend.start() -} - -async function main_version10c() { - const backend = createBackend({ - modules: [ - catalogPlugin(), - searchPlugin({ - collators: new CatalogCollator(), // :( - }), - ] - }) - - await backend.start() -} - - - -// possible DI way to do that @johan, nice maaan! -container.add(someCollator); -container.add(otherCOllator); -... -container.getAll(); - -// types are build time ;) :shakefist: -container.add(SearchCollator, someCollator); -container.add(SearchCollator, otherCOllator); -... -container.getAll(SearchCollator); From 699881cdd9d661211a56990ce6a1bdec34f46f1d Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Wed, 6 Jul 2022 11:06:17 +0200 Subject: [PATCH 36/59] chore: Move catalogPlugin to catalog-backend Signed-off-by: Johan Haals --- packages/backend/src/next/index.ts | 88 +-------------- plugins/catalog-backend/api-report.md | 14 +++ plugins/catalog-backend/package.json | 2 + .../src/service/CatalogPlugin.ts | 105 ++++++++++++++++++ plugins/catalog-backend/src/service/index.ts | 3 + 5 files changed, 128 insertions(+), 84 deletions(-) create mode 100644 plugins/catalog-backend/src/service/CatalogPlugin.ts diff --git a/packages/backend/src/next/index.ts b/packages/backend/src/next/index.ts index de40592ea5..f0f246343d 100644 --- a/packages/backend/src/next/index.ts +++ b/packages/backend/src/next/index.ts @@ -14,94 +14,14 @@ * limitations under the License. */ +import { createBackend } from '@backstage/backend-app-api'; +import { createBackendModule } from '@backstage/backend-plugin-api'; import { - createBackend, - loggerToWinstonLogger, -} from '@backstage/backend-app-api'; -import { - configServiceRef, - createBackendModule, - createBackendPlugin, - createServiceRef, - databaseServiceRef, - loggerServiceRef, - permissionsServiceRef, - urlReaderServiceRef, - httpRouterServiceRef, -} from '@backstage/backend-plugin-api'; -import { - CatalogBuilder, - CatalogProcessor, + catalogPlugin, + catalogProcessingInitApiRef, } from '@backstage/plugin-catalog-backend'; import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend'; -interface CatalogProcessingInitApi { - addProcessor(processor: CatalogProcessor): void; -} - -export const catalogProcessingInitApiRef = - createServiceRef({ - id: 'catalog.processing', - }); - -class CatalogExtensionPointImpl implements CatalogProcessingInitApi { - #processors = new Array(); - - addProcessor(processor: CatalogProcessor): void { - this.#processors.push(processor); - } - - get processors() { - return this.#processors; - } -} - -export const catalogPlugin = createBackendPlugin({ - id: 'catalog', - register(env) { - const processingExtensions = new CatalogExtensionPointImpl(); - // plugins depending on this API will be initialized before this plugins init method is executed. - env.registerExtensionPoint( - catalogProcessingInitApiRef, - processingExtensions, - ); - - env.registerInit({ - deps: { - logger: loggerServiceRef, - config: configServiceRef, - reader: urlReaderServiceRef, - permissions: permissionsServiceRef, - database: databaseServiceRef, - httpRouter: httpRouterServiceRef, - }, - async init({ - logger, - config, - reader, - database, - permissions, - httpRouter, - }) { - const winstonLogger = loggerToWinstonLogger(logger); - const builder = await CatalogBuilder.create({ - config, - reader, - permissions, - database, - logger: winstonLogger, - }); - builder.addProcessor(...processingExtensions.processors); - const { processingEngine, router } = await builder.build(); - - await processingEngine.start(); - - httpRouter.use(router); - }, - }); - }, -}); - export const scaffolderCatalogExtension = createBackendModule({ moduleId: 'scaffolder.extention', pluginId: 'catalog', diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index 3bd9504bea..b7e63ae66d 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -5,6 +5,7 @@ ```ts /// +import { BackendRegistrable } from '@backstage/backend-plugin-api'; import { CatalogApi } from '@backstage/catalog-client'; import { CatalogEntityDocument } from '@backstage/plugin-catalog-common'; import { CatalogProcessor } from '@backstage/plugin-catalog-node'; @@ -46,6 +47,7 @@ import { Readable } from 'stream'; import { ResourcePermission } from '@backstage/plugin-permission-common'; import { Router } from 'express'; import { ScmIntegrationRegistry } from '@backstage/integration'; +import { ServiceRef } from '@backstage/backend-plugin-api'; import { TokenManager } from '@backstage/backend-common'; import { UrlReader } from '@backstage/backend-common'; import { Validators } from '@backstage/catalog-model'; @@ -215,6 +217,9 @@ export type CatalogEnvironment = { export type CatalogPermissionRule = PermissionRule; +// @alpha +export const catalogPlugin: (option: unknown) => BackendRegistrable; + // @public (undocumented) export interface CatalogProcessingEngine { // (undocumented) @@ -223,6 +228,15 @@ export interface CatalogProcessingEngine { stop(): Promise; } +// @alpha (undocumented) +export interface CatalogProcessingInitApi { + // (undocumented) + addProcessor(processor: CatalogProcessor): void; +} + +// @alpha (undocumented) +export const catalogProcessingInitApiRef: ServiceRef; + export { CatalogProcessor }; export { CatalogProcessorCache }; diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 3177782289..c36e28deb8 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -34,6 +34,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { + "@backstage/backend-app-api": "^0.0.0", + "@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", diff --git a/plugins/catalog-backend/src/service/CatalogPlugin.ts b/plugins/catalog-backend/src/service/CatalogPlugin.ts new file mode 100644 index 0000000000..6742757294 --- /dev/null +++ b/plugins/catalog-backend/src/service/CatalogPlugin.ts @@ -0,0 +1,105 @@ +/* + * 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 { loggerToWinstonLogger } from '@backstage/backend-app-api'; +import { + configServiceRef, + createBackendPlugin, + createServiceRef, + databaseServiceRef, + loggerServiceRef, + permissionsServiceRef, + urlReaderServiceRef, + httpRouterServiceRef, +} from '@backstage/backend-plugin-api'; +import { CatalogProcessor } from '../api/processor'; +import { CatalogBuilder } from './CatalogBuilder'; + +/** + * @alpha + */ +export interface CatalogProcessingInitApi { + addProcessor(processor: CatalogProcessor): void; +} + +/** + * @alpha + */ +export const catalogProcessingInitApiRef = + createServiceRef({ + id: 'catalog.processing', + }); + +class CatalogExtensionPointImpl implements CatalogProcessingInitApi { + #processors = new Array(); + + addProcessor(processor: CatalogProcessor): void { + this.#processors.push(processor); + } + + get processors() { + return this.#processors; + } +} + +/** + * Catalog plugin + * @alpha + */ +export const catalogPlugin = createBackendPlugin({ + id: 'catalog', + register(env) { + const processingExtensions = new CatalogExtensionPointImpl(); + // plugins depending on this API will be initialized before this plugins init method is executed. + env.registerExtensionPoint( + catalogProcessingInitApiRef, + processingExtensions, + ); + + env.registerInit({ + deps: { + logger: loggerServiceRef, + config: configServiceRef, + reader: urlReaderServiceRef, + permissions: permissionsServiceRef, + database: databaseServiceRef, + httpRouter: httpRouterServiceRef, + }, + async init({ + logger, + config, + reader, + database, + permissions, + httpRouter, + }) { + const winstonLogger = loggerToWinstonLogger(logger); + const builder = await CatalogBuilder.create({ + config, + reader, + permissions, + database, + logger: winstonLogger, + }); + builder.addProcessor(...processingExtensions.processors); + const { processingEngine, router } = await builder.build(); + + await processingEngine.start(); + + httpRouter.use(router); + }, + }); + }, +}); diff --git a/plugins/catalog-backend/src/service/index.ts b/plugins/catalog-backend/src/service/index.ts index b1e91e4382..ed24780c5a 100644 --- a/plugins/catalog-backend/src/service/index.ts +++ b/plugins/catalog-backend/src/service/index.ts @@ -16,3 +16,6 @@ export type { CatalogEnvironment } from './CatalogBuilder'; export { CatalogBuilder } from './CatalogBuilder'; + +export type { CatalogProcessingInitApi } from './CatalogPlugin'; +export { catalogPlugin, catalogProcessingInitApiRef } from './CatalogPlugin'; From 4ba38d1f27246b96b035479ba3378c02e8487160 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Wed, 6 Jul 2022 16:08:25 +0200 Subject: [PATCH 37/59] Move shared types into catalog-node package Signed-off-by: Johan Haals --- packages/backend-app-api/package.json | 8 +- packages/backend-plugin-api/package.json | 8 +- packages/backend/src/next/index.ts | 40 ++--- .../src/service/CatalogPlugin.ts | 26 +--- plugins/catalog-backend/src/service/index.ts | 4 +- plugins/catalog-node/api-report.md | 10 ++ plugins/catalog-node/package.json | 1 + plugins/catalog-node/src/extensions.ts | 32 ++++ plugins/catalog-node/src/index.ts | 2 + yarn.lock | 146 +----------------- 10 files changed, 82 insertions(+), 195 deletions(-) create mode 100644 plugins/catalog-node/src/extensions.ts diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index 6ad48f86d5..ae6f7eb03b 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -35,15 +35,15 @@ }, "dependencies": { "@backstage/backend-plugin-api": "^0.0.0", - "@backstage/backend-common": "^0.14.0", - "@backstage/backend-tasks": "^0.3.2", - "@backstage/plugin-permission-node": "^0.6.2", + "@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.17.2-next.0" + "@backstage/cli": "^0.18.0-next.2" }, "files": [ "dist", diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index dc52366c65..24d2012374 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -35,13 +35,13 @@ }, "dependencies": { "@backstage/config": "^1.0.1", - "@backstage/backend-common": "^0.14.0", - "@backstage/plugin-permission-common": "^0.6.2", - "@backstage/backend-tasks": "^0.3.2", + "@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", "express": "^4.17.1" }, "devDependencies": { - "@backstage/cli": "^0.17.2-next.0", + "@backstage/cli": "^0.18.0-next.2", "@types/express": "^4.17.6" }, "files": [ diff --git a/packages/backend/src/next/index.ts b/packages/backend/src/next/index.ts index f0f246343d..0a16160a23 100644 --- a/packages/backend/src/next/index.ts +++ b/packages/backend/src/next/index.ts @@ -15,34 +15,34 @@ */ import { createBackend } from '@backstage/backend-app-api'; -import { createBackendModule } from '@backstage/backend-plugin-api'; +// import { createBackendModule } from '@backstage/backend-plugin-api'; import { catalogPlugin, - catalogProcessingInitApiRef, + // catalogProcessingInitApiRef, } from '@backstage/plugin-catalog-backend'; -import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend'; +// import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend'; -export const scaffolderCatalogExtension = createBackendModule({ - moduleId: 'scaffolder.extention', - pluginId: 'catalog', - register(env) { - env.registerInit({ - deps: { - catalogProcessingInitApi: catalogProcessingInitApiRef, - }, - async init({ catalogProcessingInitApi }) { - catalogProcessingInitApi.addProcessor( - new ScaffolderEntitiesProcessor(), - ); - }, - }); - }, -}); +// export const scaffolderCatalogExtension = createBackendModule({ +// moduleId: 'scaffolder.extention', +// pluginId: 'catalog', +// register(env) { +// env.registerInit({ +// deps: { +// catalogProcessingInitApi: catalogProcessingInitApiRef, +// }, +// async init({ catalogProcessingInitApi }) { +// catalogProcessingInitApi.addProcessor( +// new ScaffolderEntitiesProcessor(), +// ); +// }, +// }); +// }, +// }); const backend = createBackend({ apis: [], }); backend.add(catalogPlugin({})); -backend.add(scaffolderCatalogExtension({})); +// backend.add(scaffolderCatalogExtension({})); backend.start(); diff --git a/plugins/catalog-backend/src/service/CatalogPlugin.ts b/plugins/catalog-backend/src/service/CatalogPlugin.ts index 6742757294..d6dc4d11da 100644 --- a/plugins/catalog-backend/src/service/CatalogPlugin.ts +++ b/plugins/catalog-backend/src/service/CatalogPlugin.ts @@ -17,32 +17,20 @@ import { loggerToWinstonLogger } from '@backstage/backend-app-api'; import { configServiceRef, createBackendPlugin, - createServiceRef, databaseServiceRef, loggerServiceRef, permissionsServiceRef, urlReaderServiceRef, httpRouterServiceRef, } from '@backstage/backend-plugin-api'; -import { CatalogProcessor } from '../api/processor'; +import { CatalogProcessor } from '@backstage/plugin-catalog-node'; import { CatalogBuilder } from './CatalogBuilder'; +import { + CatalogProcessingExtensionPoint, + catalogProcessingExtentionPoint, +} from '@backstage/plugin-catalog-node'; -/** - * @alpha - */ -export interface CatalogProcessingInitApi { - addProcessor(processor: CatalogProcessor): void; -} - -/** - * @alpha - */ -export const catalogProcessingInitApiRef = - createServiceRef({ - id: 'catalog.processing', - }); - -class CatalogExtensionPointImpl implements CatalogProcessingInitApi { +class CatalogExtensionPointImpl implements CatalogProcessingExtensionPoint { #processors = new Array(); addProcessor(processor: CatalogProcessor): void { @@ -64,7 +52,7 @@ export const catalogPlugin = createBackendPlugin({ const processingExtensions = new CatalogExtensionPointImpl(); // plugins depending on this API will be initialized before this plugins init method is executed. env.registerExtensionPoint( - catalogProcessingInitApiRef, + catalogProcessingExtentionPoint, processingExtensions, ); diff --git a/plugins/catalog-backend/src/service/index.ts b/plugins/catalog-backend/src/service/index.ts index ed24780c5a..7e0c6025c3 100644 --- a/plugins/catalog-backend/src/service/index.ts +++ b/plugins/catalog-backend/src/service/index.ts @@ -16,6 +16,4 @@ export type { CatalogEnvironment } from './CatalogBuilder'; export { CatalogBuilder } from './CatalogBuilder'; - -export type { CatalogProcessingInitApi } from './CatalogPlugin'; -export { catalogPlugin, catalogProcessingInitApiRef } from './CatalogPlugin'; +export { catalogPlugin } from './CatalogPlugin'; diff --git a/plugins/catalog-node/api-report.md b/plugins/catalog-node/api-report.md index d3460e4e27..cf81f494c5 100644 --- a/plugins/catalog-node/api-report.md +++ b/plugins/catalog-node/api-report.md @@ -8,6 +8,16 @@ import { CompoundEntityRef } from '@backstage/catalog-model'; import { Entity } from '@backstage/catalog-model'; import { JsonValue } from '@backstage/types'; +import { ServiceRef } from '@backstage/backend-plugin-api'; + +// @alpha (undocumented) +export interface CatalogProcessingExtensionPoint { + // (undocumented) + addProcessor(processor: CatalogProcessor): void; +} + +// @alpha (undocumented) +export const catalogProcessingExtentionPoint: ServiceRef; // @public (undocumented) export type CatalogProcessor = { diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index a1c96990a0..d6228c717f 100644 --- a/plugins/catalog-node/package.json +++ b/plugins/catalog-node/package.json @@ -25,6 +25,7 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { + "@backstage/backend-plugin-api": "^0.0.0", "@backstage/catalog-model": "^1.1.0-next.2", "@backstage/errors": "1.1.0-next.0", "@backstage/types": "^1.0.0" diff --git a/plugins/catalog-node/src/extensions.ts b/plugins/catalog-node/src/extensions.ts new file mode 100644 index 0000000000..61605d3b26 --- /dev/null +++ b/plugins/catalog-node/src/extensions.ts @@ -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 '@backstage/backend-plugin-api'; +import { CatalogProcessor } from './api/processor'; + +/** + * @alpha + */ +export interface CatalogProcessingExtensionPoint { + addProcessor(processor: CatalogProcessor): void; +} + +/** + * @alpha + */ +export const catalogProcessingExtentionPoint = + createServiceRef({ + id: 'catalog.processing', + }); diff --git a/plugins/catalog-node/src/index.ts b/plugins/catalog-node/src/index.ts index 6a1accfcbd..fc7a1b1b67 100644 --- a/plugins/catalog-node/src/index.ts +++ b/plugins/catalog-node/src/index.ts @@ -20,5 +20,7 @@ * @packageDocumentation */ +export type { CatalogProcessingExtensionPoint } from './extensions'; +export { catalogProcessingExtentionPoint } from './extensions'; export * from './api'; export * from './processing'; diff --git a/yarn.lock b/yarn.lock index fe5ff8cb76..e35aee85fb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1557,126 +1557,6 @@ lodash "^4.17.21" uuid "^8.0.0" -"@backstage/cli@^0.17.2-next.0": - version "0.17.2" - resolved "https://registry.npmjs.org/@backstage/cli/-/cli-0.17.2.tgz#2387b8d24d8af4828b84baaa62e6b444ec4330e6" - integrity sha512-stRJWmokD7SXnclZ1dsVfA1stUP4PQPkbi3GkwY1zM84y4M20dU+YHde7MrTILMPnhMY+16WdTdfbeqLfXOJrw== - dependencies: - "@backstage/cli-common" "^0.1.9" - "@backstage/config" "^1.0.1" - "@backstage/config-loader" "^1.1.2" - "@backstage/errors" "^1.0.0" - "@backstage/release-manifests" "^0.0.4" - "@backstage/types" "^1.0.0" - "@hot-loader/react-dom-v16" "npm:@hot-loader/react-dom@^16.0.2" - "@hot-loader/react-dom-v17" "npm:@hot-loader/react-dom@^17.0.2" - "@manypkg/get-packages" "^1.1.3" - "@octokit/request" "^5.4.12" - "@rollup/plugin-commonjs" "^22.0.0" - "@rollup/plugin-json" "^4.1.0" - "@rollup/plugin-node-resolve" "^13.0.0" - "@rollup/plugin-yaml" "^3.1.0" - "@spotify/eslint-config-base" "^13.0.0" - "@spotify/eslint-config-react" "^13.0.0" - "@spotify/eslint-config-typescript" "^13.0.0" - "@sucrase/jest-plugin" "^2.1.1" - "@sucrase/webpack-loader" "^2.0.0" - "@svgr/plugin-jsx" "6.2.x" - "@svgr/plugin-svgo" "6.2.x" - "@svgr/rollup" "6.2.x" - "@svgr/webpack" "6.2.x" - "@types/webpack-env" "^1.15.2" - "@typescript-eslint/eslint-plugin" "^5.9.0" - "@typescript-eslint/parser" "^5.9.0" - "@yarnpkg/lockfile" "^1.1.0" - "@yarnpkg/parsers" "^3.0.0-rc.4" - bfj "^7.0.2" - buffer "^6.0.3" - chalk "^4.0.0" - chokidar "^3.3.1" - commander "^9.1.0" - css-loader "^6.5.1" - diff "^5.0.0" - esbuild "^0.14.10" - esbuild-loader "^2.18.0" - eslint "^8.6.0" - eslint-config-prettier "^8.3.0" - eslint-formatter-friendly "^7.0.0" - eslint-plugin-deprecation "^1.3.2" - eslint-plugin-import "^2.25.4" - eslint-plugin-jest "^26.1.2" - eslint-plugin-jsx-a11y "^6.5.1" - eslint-plugin-monorepo "^0.3.2" - eslint-plugin-react "^7.28.0" - eslint-plugin-react-hooks "^4.3.0" - eslint-webpack-plugin "^3.1.1" - express "^4.17.1" - fork-ts-checker-webpack-plugin "^7.0.0-alpha.8" - fs-extra "10.1.0" - glob "^7.1.7" - global-agent "^3.0.0" - handlebars "^4.7.3" - html-webpack-plugin "^5.3.1" - inquirer "^8.2.0" - jest "^27.5.1" - jest-css-modules "^2.1.0" - jest-runtime "^27.5.1" - jest-transform-yaml "^1.0.0" - json-schema "^0.4.0" - lodash "^4.17.21" - mini-css-extract-plugin "^2.4.2" - minimatch "5.1.0" - node-fetch "^2.6.7" - node-libs-browser "^2.2.1" - npm-packlist "^5.0.0" - ora "^5.3.0" - postcss "^8.1.0" - process "^0.11.10" - react-dev-utils "^12.0.0-next.60" - react-hot-loader "^4.13.0" - recursive-readdir "^2.2.2" - replace-in-file "^6.0.0" - rollup "^2.60.2" - rollup-plugin-dts "^4.0.1" - rollup-plugin-esbuild "^4.7.2" - rollup-plugin-postcss "^4.0.0" - rollup-pluginutils "^2.8.2" - run-script-webpack-plugin "^0.0.14" - semver "^7.3.2" - style-loader "^3.3.1" - sucrase "^3.20.2" - tar "^6.1.2" - terser-webpack-plugin "^5.1.3" - util "^0.12.3" - webpack "^5.66.0" - webpack-dev-server "^4.7.3" - webpack-node-externals "^3.0.0" - yaml "^1.10.0" - yml-loader "^2.1.0" - yn "^4.0.0" - zod "^3.11.6" - -"@backstage/config-loader@^1.1.2": - version "1.1.2" - resolved "https://registry.npmjs.org/@backstage/config-loader/-/config-loader-1.1.2.tgz#72cb0d7b2647f5a646bb279360bc34732e06521f" - integrity sha512-c5ZO7xDJn609DBIsYAWGE5kgh+7SPYUmG2ADtVX9SbXaql3VCafGlhc2hAZQa/O12W04qi3GgwGg0bqSFmx5uw== - dependencies: - "@backstage/cli-common" "^0.1.9" - "@backstage/config" "^1.0.1" - "@backstage/errors" "^1.0.0" - "@backstage/types" "^1.0.0" - "@types/json-schema" "^7.0.6" - ajv "^8.10.0" - chokidar "^3.5.2" - fs-extra "10.1.0" - json-schema "^0.4.0" - json-schema-merge-allof "^0.8.1" - json-schema-traverse "^1.0.0" - node-fetch "^2.6.7" - typescript-json-schema "^0.53.0" - yaml "^1.9.2" - yup "^0.32.9" - "@backstage/core-components@^0.9.0", "@backstage/core-components@^0.9.5": version "0.9.5" resolved "https://registry.npmjs.org/@backstage/core-components/-/core-components-0.9.5.tgz#5a0b34867aaee0549bfa67b39a69c09588fa3c7a" @@ -5675,7 +5555,7 @@ dependencies: "@rollup/pluginutils" "^3.0.8" -"@rollup/plugin-node-resolve@^13.0.0", "@rollup/plugin-node-resolve@^13.0.6": +"@rollup/plugin-node-resolve@^13.0.6": version "13.3.0" resolved "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.3.0.tgz#da1c5c5ce8316cef96a2f823d111c1e4e498801c" integrity sha512-Lus8rbUo1eEcnS4yTFKLZrVumLPY+YayBdWXgFSHYhTT2iJbMhoaaBL3xl5NCdeRytErGr8tZ0L71BMRmnlwSw== @@ -20624,11 +20504,6 @@ path-case@^3.0.4: dot-case "^3.0.4" tslib "^2.0.3" -path-equal@1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/path-equal/-/path-equal-1.1.2.tgz#260e7c449c4c2022f68cc5fa6e617e892858250d" - integrity sha512-p5kxPPwCdbf5AdXzT1bUBJomhgBlEjRBavYNr1XUpMFIE4Hnf2roueCMXudZK5tnaAu1tTmp3GPzqwJK45IHEA== - path-equal@^1.1.2: version "1.2.2" resolved "https://registry.npmjs.org/path-equal/-/path-equal-1.2.2.tgz#fa2997f0a829de22ec8f5f86461ca5590d49b832" @@ -23153,11 +23028,6 @@ run-parallel@^1.1.9: resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== -run-script-webpack-plugin@^0.0.14: - version "0.0.14" - resolved "https://registry.npmjs.org/run-script-webpack-plugin/-/run-script-webpack-plugin-0.0.14.tgz#fe2362b32c1dab7a8af7a6f1246fc043690cedd7" - integrity sha512-DXe6lzzEVXjBr/74zd4m4yOfmz5P6GMjzhQxDDsViOmwG7cap8UCE6RgD5rT7zf4wM83a+ToHnpB3v4efUv5IA== - run-script-webpack-plugin@^0.1.0: version "0.1.1" resolved "https://registry.npmjs.org/run-script-webpack-plugin/-/run-script-webpack-plugin-0.1.1.tgz#dad3114be32eb864d2160306e4d9c52a2c1cfd59" @@ -25441,20 +25311,6 @@ typedarray@^0.0.6: resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript-json-schema@^0.53.0: - version "0.53.1" - resolved "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.53.1.tgz#9204547f3e145169b40928998366ff6d28b81d32" - integrity sha512-Hg+RnOKUd38MOzC0rDft03a8xvwO+gCcj1F77smw2tCoZYQpFoLtrXWBGdvCX+REliko5WYel2kux17HPFqjLQ== - dependencies: - "@types/json-schema" "^7.0.9" - "@types/node" "^16.9.2" - glob "^7.1.7" - path-equal "1.1.2" - safe-stable-stringify "^2.2.0" - ts-node "^10.2.1" - typescript "~4.6.0" - yargs "^17.1.1" - typescript-json-schema@^0.54.0: version "0.54.0" resolved "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.54.0.tgz#b3fc42ad90df6a0f6ab57571ebc8b4d41125df4f" From 9d9b7f77091f976ab79b8ec3d25d355af72773cf Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Wed, 6 Jul 2022 16:11:38 +0200 Subject: [PATCH 38/59] add missing docstrings Signed-off-by: Johan Haals --- .../services/definitions/cacheServiceRef.ts | 3 +++ .../services/definitions/configServiceRef.ts | 3 +++ .../definitions/databaseServiceRef.ts | 3 +++ .../definitions/discoveryServiceRef.ts | 3 +++ .../definitions/httpRouterServiceRef.ts | 24 +++++-------------- .../src/services/definitions/index.ts | 12 ---------- .../services/definitions/loggerServiceRef.ts | 6 +++++ .../definitions/permissionsServiceRef.ts | 3 +++ .../definitions/schedulerServiceRef.ts | 3 +++ .../definitions/scheldulerServiceRef.ts | 3 +++ .../definitions/tokenManagerServiceRef.ts | 3 +++ .../definitions/urlReaderServiceRef.ts | 3 +++ .../src/services/system/types.ts | 6 +++++ 13 files changed, 45 insertions(+), 30 deletions(-) diff --git a/packages/backend-plugin-api/src/services/definitions/cacheServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/cacheServiceRef.ts index 439a2b645d..0b572f1712 100644 --- a/packages/backend-plugin-api/src/services/definitions/cacheServiceRef.ts +++ b/packages/backend-plugin-api/src/services/definitions/cacheServiceRef.ts @@ -17,6 +17,9 @@ import { createServiceRef } from '../system/types'; import { PluginCacheManager } from '@backstage/backend-common'; +/** + * @public + */ export const cacheServiceRef = createServiceRef({ id: 'core.cache', }); diff --git a/packages/backend-plugin-api/src/services/definitions/configServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/configServiceRef.ts index 9a4199967d..ba5dcacdc8 100644 --- a/packages/backend-plugin-api/src/services/definitions/configServiceRef.ts +++ b/packages/backend-plugin-api/src/services/definitions/configServiceRef.ts @@ -17,6 +17,9 @@ import { Config } from '@backstage/config'; import { createServiceRef } from '../system/types'; +/** + * @public + */ export const configServiceRef = createServiceRef({ id: 'core.config', }); diff --git a/packages/backend-plugin-api/src/services/definitions/databaseServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/databaseServiceRef.ts index 62f7f8a157..b41159dc9e 100644 --- a/packages/backend-plugin-api/src/services/definitions/databaseServiceRef.ts +++ b/packages/backend-plugin-api/src/services/definitions/databaseServiceRef.ts @@ -17,6 +17,9 @@ import { PluginDatabaseManager } from '@backstage/backend-common'; import { createServiceRef } from '../system/types'; +/** + * @public + */ export const databaseServiceRef = createServiceRef({ id: 'core.database', }); diff --git a/packages/backend-plugin-api/src/services/definitions/discoveryServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/discoveryServiceRef.ts index 3dfd5fa62b..675ac206a2 100644 --- a/packages/backend-plugin-api/src/services/definitions/discoveryServiceRef.ts +++ b/packages/backend-plugin-api/src/services/definitions/discoveryServiceRef.ts @@ -17,6 +17,9 @@ import { createServiceRef } from '../system/types'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; +/** + * @public + */ export const discoveryServiceRef = createServiceRef({ id: 'core.discovery', }); diff --git a/packages/backend-plugin-api/src/services/definitions/httpRouterServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/httpRouterServiceRef.ts index 65a01fde3a..fbc5a27e87 100644 --- a/packages/backend-plugin-api/src/services/definitions/httpRouterServiceRef.ts +++ b/packages/backend-plugin-api/src/services/definitions/httpRouterServiceRef.ts @@ -17,28 +17,16 @@ import { createServiceRef } from '../system/types'; import { Handler } from 'express'; -// const apiRouter = Router(); -// apiRouter.use('/catalog', await catalog(catalogEnv)); -// const service = createServiceBuilder(module) -// .loadConfig(config) -// .addRouter('', await healthcheck(healthcheckEnv)) -// .addRouter('', metricsHandler()) -// .addRouter('/api', apiRouter) -// .addRouter('', await app(appEnv)); - -// interface BackstageRequest extends Request { -// identity?: BackstageIdentity; -// context?: Context; -// } - -// interface RequestIdentityService { -// getRequestIdentity(req: Request): BackstageIdentity | undefined; -// } - +/** + * @public + */ export interface HttpRouterService { use(handler: Handler): void; } +/** + * @public + */ export const httpRouterServiceRef = createServiceRef({ id: 'core.httpRouter', }); diff --git a/packages/backend-plugin-api/src/services/definitions/index.ts b/packages/backend-plugin-api/src/services/definitions/index.ts index 556aa88c72..797cfb5a76 100644 --- a/packages/backend-plugin-api/src/services/definitions/index.ts +++ b/packages/backend-plugin-api/src/services/definitions/index.ts @@ -14,18 +14,6 @@ * limitations under the License. */ -// export type PluginEnvironment = { -// logger: Logger; -// cache: PluginCacheManager; -// database: PluginDatabaseManager; -// config: Config; -// reader: UrlReader; -// discovery: PluginEndpointDiscovery; -// tokenManager: TokenManager; -// permissions: PermissionEvaluator | PermissionAuthorizer; -// scheduler: PluginTaskScheduler; -// }; - export { configServiceRef } from './configServiceRef'; export { httpRouterServiceRef } from './httpRouterServiceRef'; export type { HttpRouterService } from './httpRouterServiceRef'; diff --git a/packages/backend-plugin-api/src/services/definitions/loggerServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/loggerServiceRef.ts index 564ce15ded..e99bc4e7d4 100644 --- a/packages/backend-plugin-api/src/services/definitions/loggerServiceRef.ts +++ b/packages/backend-plugin-api/src/services/definitions/loggerServiceRef.ts @@ -16,11 +16,17 @@ import { createServiceRef } from '../system/types'; +/** + * @public + */ export interface Logger { info(message: string): void; child(fields: { [name: string]: string }): Logger; } +/** + * @public + */ export const loggerServiceRef = createServiceRef({ id: 'core.logger', }); diff --git a/packages/backend-plugin-api/src/services/definitions/permissionsServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/permissionsServiceRef.ts index 4355286611..b13ca9e240 100644 --- a/packages/backend-plugin-api/src/services/definitions/permissionsServiceRef.ts +++ b/packages/backend-plugin-api/src/services/definitions/permissionsServiceRef.ts @@ -20,6 +20,9 @@ import { PermissionEvaluator, } from '@backstage/plugin-permission-common'; +/** + * @public + */ export const permissionsServiceRef = createServiceRef< PermissionEvaluator | PermissionAuthorizer >({ diff --git a/packages/backend-plugin-api/src/services/definitions/schedulerServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/schedulerServiceRef.ts index 3a3abfcc10..ca442dd34d 100644 --- a/packages/backend-plugin-api/src/services/definitions/schedulerServiceRef.ts +++ b/packages/backend-plugin-api/src/services/definitions/schedulerServiceRef.ts @@ -17,6 +17,9 @@ import { createServiceRef } from '../system/types'; import { PluginTaskScheduler } from '@backstage/backend-tasks'; +/** + * @public + */ export const schedulerServiceRef = createServiceRef({ id: 'core.scheduler', }); diff --git a/packages/backend-plugin-api/src/services/definitions/scheldulerServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/scheldulerServiceRef.ts index 4355286611..b13ca9e240 100644 --- a/packages/backend-plugin-api/src/services/definitions/scheldulerServiceRef.ts +++ b/packages/backend-plugin-api/src/services/definitions/scheldulerServiceRef.ts @@ -20,6 +20,9 @@ import { PermissionEvaluator, } from '@backstage/plugin-permission-common'; +/** + * @public + */ export const permissionsServiceRef = createServiceRef< PermissionEvaluator | PermissionAuthorizer >({ diff --git a/packages/backend-plugin-api/src/services/definitions/tokenManagerServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/tokenManagerServiceRef.ts index c62d4bb634..6995033e81 100644 --- a/packages/backend-plugin-api/src/services/definitions/tokenManagerServiceRef.ts +++ b/packages/backend-plugin-api/src/services/definitions/tokenManagerServiceRef.ts @@ -17,6 +17,9 @@ import { createServiceRef } from '../system/types'; import { TokenManager } from '@backstage/backend-common'; +/** + * @public + */ export const tokenManagerServiceRef = createServiceRef({ id: 'core.tokenManager', }); diff --git a/packages/backend-plugin-api/src/services/definitions/urlReaderServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/urlReaderServiceRef.ts index 25a9666882..ebb32f1aed 100644 --- a/packages/backend-plugin-api/src/services/definitions/urlReaderServiceRef.ts +++ b/packages/backend-plugin-api/src/services/definitions/urlReaderServiceRef.ts @@ -17,6 +17,9 @@ import { createServiceRef } from '../system/types'; import { UrlReader } from '@backstage/backend-common'; +/** + * @public + */ export const urlReaderServiceRef = createServiceRef({ id: 'core.urlReader', }); diff --git a/packages/backend-plugin-api/src/services/system/types.ts b/packages/backend-plugin-api/src/services/system/types.ts index 2f59e65320..30d8d94c11 100644 --- a/packages/backend-plugin-api/src/services/system/types.ts +++ b/packages/backend-plugin-api/src/services/system/types.ts @@ -56,6 +56,9 @@ export type AnyServiceFactory = ServiceFactory< { [key in string]: unknown } >; +/** + * @public + */ export function createServiceRef(options: { id: string }): ServiceRef { return { id: options.id, @@ -69,6 +72,9 @@ export function createServiceRef(options: { id: string }): ServiceRef { }; } +/** + * @public + */ export function createServiceFactory< Api, Impl extends Api, From 5da7205bad3b2d70663b8d728e79b44258f4df87 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 5 Jul 2022 15:27:48 +0200 Subject: [PATCH 39/59] =?UTF-8?q?chore:=20wire=20up=20the=20service=20bygg?= =?UTF-8?q?are=20=F0=9F=93=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Co-authored-by: Johan Haals Co-authored-by: Patrik Oldsberg Signed-off-by: blam --- .../implementations/httpRouterService.ts | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/backend-app-api/src/services/implementations/httpRouterService.ts b/packages/backend-app-api/src/services/implementations/httpRouterService.ts index 82dfb13218..505906d13b 100644 --- a/packages/backend-app-api/src/services/implementations/httpRouterService.ts +++ b/packages/backend-app-api/src/services/implementations/httpRouterService.ts @@ -13,22 +13,27 @@ * 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 express, { Handler } from 'express'; +import { Handler } from 'express'; +import { createServiceBuilder } from '@backstage/backend-common'; export const httpRouterFactory = createServiceFactory({ service: httpRouterServiceRef, - deps: {}, - factory: async () => { - const app = express(); + deps: { + configFactory: configServiceRef, + }, + factory: async ({ configFactory }) => { const rootRouter = Router(); - - app.use(rootRouter); - app.listen(8123); + const service = createServiceBuilder(module) + .loadConfig(await configFactory('root')) + .addRouter('', rootRouter); + await service.start(); return async (pluginId?: string) => { if (!pluginId) { From f6404275c796b10bca90df145552d786dc1d8ec9 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 6 Jul 2022 16:41:49 +0200 Subject: [PATCH 40/59] chore: added in the router things: Co-authored-by: Johan Haals Signed-off-by: blam --- .../implementations/httpRouterService.ts | 8 +++---- .../src/services/system/types.ts | 2 +- packages/backend/src/next/index.ts | 24 +++++++++++++++++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/packages/backend-app-api/src/services/implementations/httpRouterService.ts b/packages/backend-app-api/src/services/implementations/httpRouterService.ts index 505906d13b..1f72378643 100644 --- a/packages/backend-app-api/src/services/implementations/httpRouterService.ts +++ b/packages/backend-app-api/src/services/implementations/httpRouterService.ts @@ -30,18 +30,18 @@ export const httpRouterFactory = createServiceFactory({ }, factory: async ({ configFactory }) => { const rootRouter = Router(); + const service = createServiceBuilder(module) .loadConfig(await configFactory('root')) .addRouter('', rootRouter); + await service.start(); return async (pluginId?: string) => { - if (!pluginId) { - return rootRouter; - } + const path = pluginId ? `/api/${pluginId}` : ''; return { use(handler: Handler) { - rootRouter.use(`/api/${pluginId}`, handler); + rootRouter.use(path, handler); }, }; }; diff --git a/packages/backend-plugin-api/src/services/system/types.ts b/packages/backend-plugin-api/src/services/system/types.ts index 30d8d94c11..40534fcbcb 100644 --- a/packages/backend-plugin-api/src/services/system/types.ts +++ b/packages/backend-plugin-api/src/services/system/types.ts @@ -79,6 +79,6 @@ export function createServiceFactory< Api, Impl extends Api, Deps extends { [name in string]: unknown }, ->(factory: ServiceFactory): ServiceFactory { +>(factory: ServiceFactory): ServiceFactory { return factory; } diff --git a/packages/backend/src/next/index.ts b/packages/backend/src/next/index.ts index 0a16160a23..96b36e3e03 100644 --- a/packages/backend/src/next/index.ts +++ b/packages/backend/src/next/index.ts @@ -39,6 +39,30 @@ import { // }, // }); +// export const appPlugin = createBackendPlugin({ +// id: 'app', +// register(env) { +// env.registerInit({ +// deps: { +// httpRouter: httpRouterServiceRef, +// database: databaseServiceRef, +// logger: loggerServiceRef, +// config: configServiceRef, +// }, +// async init({ httpRouter, config, logger, database }) { +// console.log('App plugin init'); + +// const appBackendRoute = await createAppBackendRouter({ +// appPackageName: 'example-app', +// config, +// logger: loggerToWinstonLogger(logger), +// database, +// }); +// }, +// }); +// }, +// }); + const backend = createBackend({ apis: [], }); From 634b191757cac7aef316f62ff1b33800fc996e2d Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 6 Jul 2022 16:45:22 +0200 Subject: [PATCH 41/59] chore: fix imports in the catalog plugin ja! Signed-off-by: blam Signed-off-by: Patrik Oldsberg --- plugins/catalog-backend/src/service/CatalogPlugin.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog-backend/src/service/CatalogPlugin.ts b/plugins/catalog-backend/src/service/CatalogPlugin.ts index d6dc4d11da..a2fcfe3f4b 100644 --- a/plugins/catalog-backend/src/service/CatalogPlugin.ts +++ b/plugins/catalog-backend/src/service/CatalogPlugin.ts @@ -23,9 +23,9 @@ import { urlReaderServiceRef, httpRouterServiceRef, } from '@backstage/backend-plugin-api'; -import { CatalogProcessor } from '@backstage/plugin-catalog-node'; import { CatalogBuilder } from './CatalogBuilder'; import { + CatalogProcessor, CatalogProcessingExtensionPoint, catalogProcessingExtentionPoint, } from '@backstage/plugin-catalog-node'; From 506ddb6ac883943c08c01c111b9bca639b46cfe6 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Thu, 7 Jul 2022 14:00:12 +0200 Subject: [PATCH 42/59] Rename catalog-node plugin, add scaffolder extension Signed-off-by: Johan Haals --- packages/backend/src/next/index.ts | 27 ++----------- plugins/scaffolder-backend/api-report.md | 6 +++ plugins/scaffolder-backend/package.json | 8 +++- .../extension/ScaffolderCatalogExtension.ts | 39 +++++++++++++++++++ .../scaffolder-backend/src/extension/index.ts | 16 ++++++++ plugins/scaffolder-backend/src/index.ts | 1 + 6 files changed, 71 insertions(+), 26 deletions(-) create mode 100644 plugins/scaffolder-backend/src/extension/ScaffolderCatalogExtension.ts create mode 100644 plugins/scaffolder-backend/src/extension/index.ts diff --git a/packages/backend/src/next/index.ts b/packages/backend/src/next/index.ts index 96b36e3e03..9deab2feeb 100644 --- a/packages/backend/src/next/index.ts +++ b/packages/backend/src/next/index.ts @@ -15,29 +15,8 @@ */ import { createBackend } from '@backstage/backend-app-api'; -// import { createBackendModule } from '@backstage/backend-plugin-api'; -import { - catalogPlugin, - // catalogProcessingInitApiRef, -} from '@backstage/plugin-catalog-backend'; -// import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend'; - -// export const scaffolderCatalogExtension = createBackendModule({ -// moduleId: 'scaffolder.extention', -// pluginId: 'catalog', -// register(env) { -// env.registerInit({ -// deps: { -// catalogProcessingInitApi: catalogProcessingInitApiRef, -// }, -// async init({ catalogProcessingInitApi }) { -// catalogProcessingInitApi.addProcessor( -// new ScaffolderEntitiesProcessor(), -// ); -// }, -// }); -// }, -// }); +import { catalogPlugin } from '@backstage/plugin-catalog-backend'; +import { scaffolderCatalogExtension } from '@backstage/plugin-scaffolder-backend'; // export const appPlugin = createBackendPlugin({ // id: 'app', @@ -68,5 +47,5 @@ const backend = createBackend({ }); backend.add(catalogPlugin({})); -// backend.add(scaffolderCatalogExtension({})); +backend.add(scaffolderCatalogExtension({})); backend.start(); diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 2053f01e39..672b853f3b 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -5,6 +5,7 @@ ```ts /// +import { BackendRegistrable } from '@backstage/backend-plugin-api'; import { CatalogApi } from '@backstage/catalog-client'; import { CatalogProcessor } from '@backstage/plugin-catalog-backend'; import { CatalogProcessorEmit } from '@backstage/plugin-catalog-backend'; @@ -543,6 +544,11 @@ export type RunCommandOptions = { logStream?: Writable; }; +// @alpha +export const scaffolderCatalogExtension: ( + option: unknown, +) => BackendRegistrable; + // @public (undocumented) export class ScaffolderEntitiesProcessor implements CatalogProcessor { // (undocumented) diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index a1bb552435..f2fabad69d 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -9,7 +9,8 @@ "publishConfig": { "access": "public", "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "types": "dist/index.d.ts", + "alphaTypes": "dist/index.alpha.d.ts" }, "backstage": { "role": "backend-plugin" @@ -25,7 +26,7 @@ ], "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build", + "build": "backstage-cli package build --experimental-type-build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -42,6 +43,8 @@ "@backstage/integration": "^1.2.2-next.2", "@backstage/plugin-catalog-backend": "^1.2.1-next.2", "@backstage/plugin-scaffolder-common": "^1.1.2-next.0", + "@backstage/backend-plugin-api": "^0.0.0", + "@backstage/plugin-catalog-node": "^0.0.0", "@backstage/types": "^1.0.0", "@gitbeaker/core": "^35.6.0", "@gitbeaker/node": "^35.1.0", @@ -93,6 +96,7 @@ "yaml": "^1.10.0" }, "files": [ + "alpha", "dist", "migrations", "config.d.ts", diff --git a/plugins/scaffolder-backend/src/extension/ScaffolderCatalogExtension.ts b/plugins/scaffolder-backend/src/extension/ScaffolderCatalogExtension.ts new file mode 100644 index 0000000000..9ca140a952 --- /dev/null +++ b/plugins/scaffolder-backend/src/extension/ScaffolderCatalogExtension.ts @@ -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 { createBackendModule } from '@backstage/backend-plugin-api'; +import { catalogProcessingExtentionPoint } from '@backstage/plugin-catalog-node'; +import { ScaffolderEntitiesProcessor } from '../processor'; + +/** + * @alpha + * Registers the ScaffolderEntitiesProcessor with the catalog processing extension point. + */ +export const scaffolderCatalogExtension = createBackendModule({ + moduleId: 'scaffolder.extention', + pluginId: 'catalog', + register(env) { + env.registerInit({ + deps: { + catalogProcessingExtensionPoint: catalogProcessingExtentionPoint, + }, + async init({ catalogProcessingExtensionPoint }) { + catalogProcessingExtensionPoint.addProcessor( + new ScaffolderEntitiesProcessor(), + ); + }, + }); + }, +}); diff --git a/plugins/scaffolder-backend/src/extension/index.ts b/plugins/scaffolder-backend/src/extension/index.ts new file mode 100644 index 0000000000..672e29e2ee --- /dev/null +++ b/plugins/scaffolder-backend/src/extension/index.ts @@ -0,0 +1,16 @@ +/* + * 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 { scaffolderCatalogExtension } from './ScaffolderCatalogExtension'; diff --git a/plugins/scaffolder-backend/src/index.ts b/plugins/scaffolder-backend/src/index.ts index 5978b6389b..a1032449d5 100644 --- a/plugins/scaffolder-backend/src/index.ts +++ b/plugins/scaffolder-backend/src/index.ts @@ -24,3 +24,4 @@ export * from './scaffolder'; export * from './service/router'; export * from './lib'; export * from './processor'; +export * from './extension'; From aedb038a8b3bfe19b91c33022db2fbe17f5dc784 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 8 Jul 2022 10:43:49 +0200 Subject: [PATCH 43/59] backend-plugin-api: use type instead of interface to work around api-extractor bug Signed-off-by: Patrik Oldsberg --- packages/backend-plugin-api/src/services/system/types.ts | 4 ++-- packages/backend-plugin-api/src/wiring/types.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/backend-plugin-api/src/services/system/types.ts b/packages/backend-plugin-api/src/services/system/types.ts index 40534fcbcb..66b3e89e3c 100644 --- a/packages/backend-plugin-api/src/services/system/types.ts +++ b/packages/backend-plugin-api/src/services/system/types.ts @@ -19,7 +19,7 @@ * * @public */ -export interface ServiceRef { +export type ServiceRef = { id: string; /** @@ -31,7 +31,7 @@ export interface ServiceRef { toString(): string; $$ref: 'service'; -} +}; type TypesToServiceRef = { [key in keyof T]: ServiceRef }; type DepsToDepFactories = { diff --git a/packages/backend-plugin-api/src/wiring/types.ts b/packages/backend-plugin-api/src/wiring/types.ts index 746d47b355..be4bf949e7 100644 --- a/packages/backend-plugin-api/src/wiring/types.ts +++ b/packages/backend-plugin-api/src/wiring/types.ts @@ -21,7 +21,7 @@ import { ServiceRef } from '../services/system/types'; * * @public */ -export interface ExtensionPoint { +export type ExtensionPoint = { id: string; /** @@ -34,7 +34,7 @@ export interface ExtensionPoint { toString(): string; $$ref: 'extension-point'; -} +}; export function createExtensionPoint(options: { id: string; From 922f53f5926702a53a1c18900151d40889fe770e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 8 Jul 2022 10:45:17 +0200 Subject: [PATCH 44/59] backend-plugin-api: add API report Signed-off-by: Patrik Oldsberg --- packages/backend-plugin-api/api-report.md | 206 ++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 packages/backend-plugin-api/api-report.md diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md new file mode 100644 index 0000000000..875f589d17 --- /dev/null +++ b/packages/backend-plugin-api/api-report.md @@ -0,0 +1,206 @@ +## 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 { 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 { UrlReader } from '@backstage/backend-common'; + +// Warning: (ae-missing-release-tag) "AnyServiceFactory" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type AnyServiceFactory = ServiceFactory< + unknown, + unknown, + { + [key in string]: unknown; + } +>; + +// Warning: (ae-missing-release-tag) "BackendInitRegistry" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface BackendInitRegistry { + // (undocumented) + registerExtensionPoint( + ref: ServiceRef, + impl: TExtensionPoint, + ): void; + // (undocumented) + registerInit< + Deps extends { + [name in string]: unknown; + }, + >(options: { + deps: { + [name in keyof Deps]: ServiceRef; + }; + init: (deps: Deps) => Promise; + }): void; +} + +// Warning: (ae-missing-release-tag) "BackendModuleConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface BackendModuleConfig { + // (undocumented) + moduleId: string; + // (undocumented) + pluginId: string; + // (undocumented) + register( + reg: Omit, + options: TOptions, + ): void; +} + +// Warning: (ae-missing-release-tag) "BackendPluginConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface BackendPluginConfig { + // (undocumented) + id: string; + // (undocumented) + register(reg: BackendInitRegistry, options: TOptions): void; +} + +// Warning: (ae-missing-release-tag) "BackendRegistrable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface BackendRegistrable { + // (undocumented) + id: string; + // (undocumented) + register(reg: BackendInitRegistry): void; +} + +// @public (undocumented) +export const cacheServiceRef: ServiceRef; + +// @public (undocumented) +export const configServiceRef: ServiceRef; + +// Warning: (ae-missing-release-tag) "createBackendModule" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function createBackendModule( + config: BackendModuleConfig, +): (option: TOptions) => BackendRegistrable; + +// Warning: (ae-missing-release-tag) "createBackendPlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function createBackendPlugin( + config: BackendPluginConfig, +): (option: TOptions) => BackendRegistrable; + +// Warning: (ae-missing-release-tag) "createExtensionPoint" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function createExtensionPoint(options: { + id: string; +}): ExtensionPoint; + +// @public (undocumented) +export function createServiceFactory< + Api, + Impl extends Api, + Deps extends { + [name in string]: unknown; + }, +>(factory: ServiceFactory): ServiceFactory; + +// @public (undocumented) +export function createServiceRef(options: { id: string }): ServiceRef; + +// @public (undocumented) +export const databaseServiceRef: ServiceRef; + +// @public (undocumented) +export const discoveryServiceRef: ServiceRef; + +// @public +export type ExtensionPoint = { + id: string; + T: T; + toString(): string; + $$ref: 'extension-point'; +}; + +// Warning: (ae-missing-release-tag) "FactoryFunc" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type FactoryFunc = (pluginId: string) => Promise; + +// @public (undocumented) +export interface HttpRouterService { + // (undocumented) + use(handler: Handler): void; +} + +// @public (undocumented) +export const httpRouterServiceRef: ServiceRef; + +// @public (undocumented) +export interface Logger { + // (undocumented) + child(fields: { [name: string]: string }): Logger; + // (undocumented) + info(message: string): void; +} + +// @public (undocumented) +export const loggerServiceRef: ServiceRef; + +// @public (undocumented) +export const permissionsServiceRef: ServiceRef< + PermissionAuthorizer | PermissionEvaluator +>; + +// @public (undocumented) +export const schedulerServiceRef: ServiceRef; + +// Warning: (ae-missing-release-tag) "ServiceFactory" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type ServiceFactory< + TApi, + TImpl extends TApi, + TDeps extends { + [name in string]: unknown; + }, +> = { + service: ServiceRef; + deps: TypesToServiceRef; + factory(deps: DepsToDepFactories): Promise>; +}; + +// @public +export type ServiceRef = { + id: string; + T: T; + toString(): string; + $$ref: 'service'; +}; + +// @public (undocumented) +export const tokenManagerServiceRef: ServiceRef; + +// @public (undocumented) +export const urlReaderServiceRef: ServiceRef; + +// Warnings were encountered during analysis: +// +// src/services/system/types.d.ts:27:5 - (ae-forgotten-export) The symbol "TypesToServiceRef" needs to be exported by the entry point index.d.ts +// src/services/system/types.d.ts:28:5 - (ae-forgotten-export) The symbol "DepsToDepFactories" needs to be exported by the entry point index.d.ts +// src/wiring/types.d.ts:10:67 - (tsdoc-code-span-missing-delimiter) The code span is missing its closing backtick +// src/wiring/types.d.ts:11:24 - (tsdoc-code-span-missing-delimiter) The code span is missing its closing backtick +``` From a3cdfcd07821025c38fa1695bf7334783d55bb7a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 8 Jul 2022 10:56:46 +0200 Subject: [PATCH 45/59] backend-plugin-api: fix API report warnings Signed-off-by: Patrik Oldsberg --- packages/backend-plugin-api/api-report.md | 37 +++++-------------- .../src/services/system/types.ts | 10 ++++- .../backend-plugin-api/src/wiring/types.ts | 12 ++++-- 3 files changed, 27 insertions(+), 32 deletions(-) diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md index 875f589d17..a4d45a2fb7 100644 --- a/packages/backend-plugin-api/api-report.md +++ b/packages/backend-plugin-api/api-report.md @@ -14,8 +14,6 @@ import { PluginTaskScheduler } from '@backstage/backend-tasks'; import { TokenManager } from '@backstage/backend-common'; import { UrlReader } from '@backstage/backend-common'; -// Warning: (ae-missing-release-tag) "AnyServiceFactory" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type AnyServiceFactory = ServiceFactory< unknown, @@ -25,8 +23,6 @@ export type AnyServiceFactory = ServiceFactory< } >; -// Warning: (ae-missing-release-tag) "BackendInitRegistry" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export interface BackendInitRegistry { // (undocumented) @@ -47,8 +43,6 @@ export interface BackendInitRegistry { }): void; } -// Warning: (ae-missing-release-tag) "BackendModuleConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export interface BackendModuleConfig { // (undocumented) @@ -62,8 +56,6 @@ export interface BackendModuleConfig { ): void; } -// Warning: (ae-missing-release-tag) "BackendPluginConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export interface BackendPluginConfig { // (undocumented) @@ -72,8 +64,6 @@ export interface BackendPluginConfig { register(reg: BackendInitRegistry, options: TOptions): void; } -// Warning: (ae-missing-release-tag) "BackendRegistrable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export interface BackendRegistrable { // (undocumented) @@ -88,22 +78,16 @@ export const cacheServiceRef: ServiceRef; // @public (undocumented) export const configServiceRef: ServiceRef; -// Warning: (ae-missing-release-tag) "createBackendModule" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function createBackendModule( config: BackendModuleConfig, ): (option: TOptions) => BackendRegistrable; -// Warning: (ae-missing-release-tag) "createBackendPlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function createBackendPlugin( config: BackendPluginConfig, ): (option: TOptions) => BackendRegistrable; -// Warning: (ae-missing-release-tag) "createExtensionPoint" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function createExtensionPoint(options: { id: string; @@ -124,6 +108,11 @@ export function createServiceRef(options: { id: string }): ServiceRef; // @public (undocumented) export const databaseServiceRef: ServiceRef; +// @public (undocumented) +export type DepsToDepFactories = { + [key in keyof T]: (pluginId: string) => Promise; +}; + // @public (undocumented) export const discoveryServiceRef: ServiceRef; @@ -135,8 +124,6 @@ export type ExtensionPoint = { $$ref: 'extension-point'; }; -// Warning: (ae-missing-release-tag) "FactoryFunc" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type FactoryFunc = (pluginId: string) => Promise; @@ -168,8 +155,6 @@ export const permissionsServiceRef: ServiceRef< // @public (undocumented) export const schedulerServiceRef: ServiceRef; -// Warning: (ae-missing-release-tag) "ServiceFactory" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type ServiceFactory< TApi, @@ -195,12 +180,10 @@ export type ServiceRef = { export const tokenManagerServiceRef: ServiceRef; // @public (undocumented) -export const urlReaderServiceRef: ServiceRef; +export type TypesToServiceRef = { + [key in keyof T]: ServiceRef; +}; -// Warnings were encountered during analysis: -// -// src/services/system/types.d.ts:27:5 - (ae-forgotten-export) The symbol "TypesToServiceRef" needs to be exported by the entry point index.d.ts -// src/services/system/types.d.ts:28:5 - (ae-forgotten-export) The symbol "DepsToDepFactories" needs to be exported by the entry point index.d.ts -// src/wiring/types.d.ts:10:67 - (tsdoc-code-span-missing-delimiter) The code span is missing its closing backtick -// src/wiring/types.d.ts:11:24 - (tsdoc-code-span-missing-delimiter) The code span is missing its closing backtick +// @public (undocumented) +export const urlReaderServiceRef: ServiceRef; ``` diff --git a/packages/backend-plugin-api/src/services/system/types.ts b/packages/backend-plugin-api/src/services/system/types.ts index 66b3e89e3c..d578434170 100644 --- a/packages/backend-plugin-api/src/services/system/types.ts +++ b/packages/backend-plugin-api/src/services/system/types.ts @@ -33,13 +33,18 @@ export type ServiceRef = { $$ref: 'service'; }; -type TypesToServiceRef = { [key in keyof T]: ServiceRef }; -type DepsToDepFactories = { +/** @public */ +export type TypesToServiceRef = { [key in keyof T]: ServiceRef }; + +/** @public */ +export type DepsToDepFactories = { [key in keyof T]: (pluginId: string) => Promise; }; +/** @public */ export type FactoryFunc = (pluginId: string) => Promise; +/** @public */ export type ServiceFactory< TApi, TImpl extends TApi, @@ -50,6 +55,7 @@ export type ServiceFactory< factory(deps: DepsToDepFactories): Promise>; }; +/** @public */ export type AnyServiceFactory = ServiceFactory< unknown, unknown, diff --git a/packages/backend-plugin-api/src/wiring/types.ts b/packages/backend-plugin-api/src/wiring/types.ts index be4bf949e7..2b4aacb40a 100644 --- a/packages/backend-plugin-api/src/wiring/types.ts +++ b/packages/backend-plugin-api/src/wiring/types.ts @@ -25,9 +25,8 @@ export type ExtensionPoint = { 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. + * 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; @@ -36,6 +35,7 @@ export type ExtensionPoint = { $$ref: 'extension-point'; }; +/** @public */ export function createExtensionPoint(options: { id: string; }): ExtensionPoint { @@ -51,6 +51,7 @@ export function createExtensionPoint(options: { }; } +/** @public */ export interface BackendInitRegistry { registerExtensionPoint( ref: ServiceRef, @@ -62,16 +63,19 @@ export interface BackendInitRegistry { }): void; } +/** @public */ export interface BackendRegistrable { id: string; register(reg: BackendInitRegistry): void; } +/** @public */ export interface BackendPluginConfig { id: string; register(reg: BackendInitRegistry, options: TOptions): void; } +/** @public */ export function createBackendPlugin( config: BackendPluginConfig, ): (option: TOptions) => BackendRegistrable { @@ -83,6 +87,7 @@ export function createBackendPlugin( }); } +/** @public */ export interface BackendModuleConfig { pluginId: string; moduleId: string; @@ -92,6 +97,7 @@ export interface BackendModuleConfig { ): void; } +/** @public */ export function createBackendModule( config: BackendModuleConfig, ): (option: TOptions) => BackendRegistrable { From e360c28f226e6beec820f0c96221ec5b615203a4 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Fri, 8 Jul 2022 11:18:50 +0200 Subject: [PATCH 46/59] Rename scaffolderCatalogModule Signed-off-by: Johan Haals --- packages/backend/src/next/index.ts | 4 +- .../extension/ScaffolderCatalogModule.test.ts | 42 +++++++++++++++++++ ...xtension.ts => ScaffolderCatalogModule.ts} | 4 +- .../scaffolder-backend/src/extension/index.ts | 2 +- 4 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 plugins/scaffolder-backend/src/extension/ScaffolderCatalogModule.test.ts rename plugins/scaffolder-backend/src/extension/{ScaffolderCatalogExtension.ts => ScaffolderCatalogModule.ts} (92%) diff --git a/packages/backend/src/next/index.ts b/packages/backend/src/next/index.ts index 9deab2feeb..cda7ae4007 100644 --- a/packages/backend/src/next/index.ts +++ b/packages/backend/src/next/index.ts @@ -16,7 +16,7 @@ import { createBackend } from '@backstage/backend-app-api'; import { catalogPlugin } from '@backstage/plugin-catalog-backend'; -import { scaffolderCatalogExtension } from '@backstage/plugin-scaffolder-backend'; +import { scaffolderCatalogModule } from '@backstage/plugin-scaffolder-backend'; // export const appPlugin = createBackendPlugin({ // id: 'app', @@ -47,5 +47,5 @@ const backend = createBackend({ }); backend.add(catalogPlugin({})); -backend.add(scaffolderCatalogExtension({})); +backend.add(scaffolderCatalogModule({})); backend.start(); diff --git a/plugins/scaffolder-backend/src/extension/ScaffolderCatalogModule.test.ts b/plugins/scaffolder-backend/src/extension/ScaffolderCatalogModule.test.ts new file mode 100644 index 0000000000..f07eb0f7ae --- /dev/null +++ b/plugins/scaffolder-backend/src/extension/ScaffolderCatalogModule.test.ts @@ -0,0 +1,42 @@ +/* + * 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 { BackendInitRegistry } from '@backstage/backend-plugin-api'; +import { ScaffolderEntitiesProcessor } from '../processor'; +import { scaffolderCatalogModule } from './ScaffolderCatalogModule'; + +describe('ScaffolderCatalogModule', () => { + it('should register the extension point', () => { + // TODO(jhaals): clean this up and add test helpers for backend system. + const ext = scaffolderCatalogModule({}); + expect(ext.id).toBe('catalog.scaffolder.module'); + const registry: jest.Mocked = { + registerInit: jest.fn(), + } as any; + ext.register(registry); + + const extensionPoint = { + addProcessor: jest.fn(), + }; + + registry.registerInit.mock.calls[0][0].init({ + catalogProcessingExtensionPoint: extensionPoint, + }); + expect(extensionPoint.addProcessor).toHaveBeenCalledWith( + new ScaffolderEntitiesProcessor(), + ); + }); +}); diff --git a/plugins/scaffolder-backend/src/extension/ScaffolderCatalogExtension.ts b/plugins/scaffolder-backend/src/extension/ScaffolderCatalogModule.ts similarity index 92% rename from plugins/scaffolder-backend/src/extension/ScaffolderCatalogExtension.ts rename to plugins/scaffolder-backend/src/extension/ScaffolderCatalogModule.ts index 9ca140a952..bdce46a31a 100644 --- a/plugins/scaffolder-backend/src/extension/ScaffolderCatalogExtension.ts +++ b/plugins/scaffolder-backend/src/extension/ScaffolderCatalogModule.ts @@ -21,8 +21,8 @@ import { ScaffolderEntitiesProcessor } from '../processor'; * @alpha * Registers the ScaffolderEntitiesProcessor with the catalog processing extension point. */ -export const scaffolderCatalogExtension = createBackendModule({ - moduleId: 'scaffolder.extention', +export const scaffolderCatalogModule = createBackendModule({ + moduleId: 'scaffolder.module', pluginId: 'catalog', register(env) { env.registerInit({ diff --git a/plugins/scaffolder-backend/src/extension/index.ts b/plugins/scaffolder-backend/src/extension/index.ts index 672e29e2ee..c827d9cafd 100644 --- a/plugins/scaffolder-backend/src/extension/index.ts +++ b/plugins/scaffolder-backend/src/extension/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { scaffolderCatalogExtension } from './ScaffolderCatalogExtension'; +export { scaffolderCatalogModule } from './ScaffolderCatalogModule'; From 9ce1bc564f07c4c48ec8d90a0ed172299889bec7 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Fri, 8 Jul 2022 11:19:21 +0200 Subject: [PATCH 47/59] Add addEntityProvider method to catalog extension Signed-off-by: Johan Haals --- plugins/catalog-backend/src/service/CatalogPlugin.ts | 11 +++++++++++ plugins/catalog-node/src/extensions.ts | 2 ++ 2 files changed, 13 insertions(+) diff --git a/plugins/catalog-backend/src/service/CatalogPlugin.ts b/plugins/catalog-backend/src/service/CatalogPlugin.ts index a2fcfe3f4b..fd3397612f 100644 --- a/plugins/catalog-backend/src/service/CatalogPlugin.ts +++ b/plugins/catalog-backend/src/service/CatalogPlugin.ts @@ -28,18 +28,28 @@ import { CatalogProcessor, CatalogProcessingExtensionPoint, catalogProcessingExtentionPoint, + EntityProvider, } from '@backstage/plugin-catalog-node'; class CatalogExtensionPointImpl implements CatalogProcessingExtensionPoint { #processors = new Array(); + #entityProviders = new Array(); addProcessor(processor: CatalogProcessor): void { this.#processors.push(processor); } + addEntityProvider(provider: EntityProvider): void { + this.#entityProviders.push(provider); + } + get processors() { return this.#processors; } + + get entityProviders() { + return this.#entityProviders; + } } /** @@ -82,6 +92,7 @@ export const catalogPlugin = createBackendPlugin({ logger: winstonLogger, }); builder.addProcessor(...processingExtensions.processors); + builder.addEntityProvider(...processingExtensions.entityProviders); const { processingEngine, router } = await builder.build(); await processingEngine.start(); diff --git a/plugins/catalog-node/src/extensions.ts b/plugins/catalog-node/src/extensions.ts index 61605d3b26..560d9d4db1 100644 --- a/plugins/catalog-node/src/extensions.ts +++ b/plugins/catalog-node/src/extensions.ts @@ -14,6 +14,7 @@ * limitations under the License. */ import { createServiceRef } from '@backstage/backend-plugin-api'; +import { EntityProvider } from './api'; import { CatalogProcessor } from './api/processor'; /** @@ -21,6 +22,7 @@ import { CatalogProcessor } from './api/processor'; */ export interface CatalogProcessingExtensionPoint { addProcessor(processor: CatalogProcessor): void; + addEntityProvider(provider: EntityProvider): void; } /** From 5f7c8c45f4d84d4763fbcda0516c79e1eab56a0a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 8 Jul 2022 14:15:15 +0200 Subject: [PATCH 48/59] backend: move additions to new backend-next package Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- packages/backend-next/.eslintrc.js | 1 + packages/backend-next/README.md | 5 +++ packages/backend-next/package.json | 38 +++++++++++++++++++ packages/backend-next/src/index.test.ts | 24 ++++++++++++ .../src/next => backend-next/src}/index.ts | 24 ------------ packages/backend/package.json | 2 - 6 files changed, 68 insertions(+), 26 deletions(-) create mode 100644 packages/backend-next/.eslintrc.js create mode 100644 packages/backend-next/README.md create mode 100644 packages/backend-next/package.json create mode 100644 packages/backend-next/src/index.test.ts rename packages/{backend/src/next => backend-next/src}/index.ts (58%) diff --git a/packages/backend-next/.eslintrc.js b/packages/backend-next/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/backend-next/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/backend-next/README.md b/packages/backend-next/README.md new file mode 100644 index 0000000000..94fc0767c4 --- /dev/null +++ b/packages/backend-next/README.md @@ -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. diff --git a/packages/backend-next/package.json b/packages/backend-next/package.json new file mode 100644 index 0000000000..6feaf5ad97 --- /dev/null +++ b/packages/backend-next/package.json @@ -0,0 +1,38 @@ +{ + "name": "example-backend-next", + "version": "0.2.73-next.2", + "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" + ] +} diff --git a/packages/backend-next/src/index.test.ts b/packages/backend-next/src/index.test.ts new file mode 100644 index 0000000000..8b41455b27 --- /dev/null +++ b/packages/backend-next/src/index.test.ts @@ -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. + */ + +import { PluginEnvironment } from './types'; + +describe('test', () => { + it('unbreaks the test runner', () => { + const unbreaker = {} as PluginEnvironment; + expect(unbreaker).toBeTruthy(); + }); +}); diff --git a/packages/backend/src/next/index.ts b/packages/backend-next/src/index.ts similarity index 58% rename from packages/backend/src/next/index.ts rename to packages/backend-next/src/index.ts index cda7ae4007..6463dc7ed5 100644 --- a/packages/backend/src/next/index.ts +++ b/packages/backend-next/src/index.ts @@ -18,30 +18,6 @@ import { createBackend } from '@backstage/backend-app-api'; import { catalogPlugin } from '@backstage/plugin-catalog-backend'; import { scaffolderCatalogModule } from '@backstage/plugin-scaffolder-backend'; -// export const appPlugin = createBackendPlugin({ -// id: 'app', -// register(env) { -// env.registerInit({ -// deps: { -// httpRouter: httpRouterServiceRef, -// database: databaseServiceRef, -// logger: loggerServiceRef, -// config: configServiceRef, -// }, -// async init({ httpRouter, config, logger, database }) { -// console.log('App plugin init'); - -// const appBackendRoute = await createAppBackendRouter({ -// appPackageName: 'example-app', -// config, -// logger: loggerToWinstonLogger(logger), -// database, -// }); -// }, -// }); -// }, -// }); - const backend = createBackend({ apis: [], }); diff --git a/packages/backend/package.json b/packages/backend/package.json index 7604f1e609..df6fe5ec3b 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -26,8 +26,6 @@ "build-image": "docker build ../.. -f Dockerfile --tag example-backend" }, "dependencies": { - "@backstage/backend-plugin-api": "^0.0.0", - "@backstage/backend-app-api": "^0.0.0", "@backstage/backend-common": "^0.14.1-next.2", "@backstage/backend-tasks": "^0.3.3-next.2", "@backstage/catalog-client": "^1.0.4-next.1", From f147543044b3008b6e990f2db8a16f99931f1661 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Fri, 8 Jul 2022 14:20:21 +0200 Subject: [PATCH 49/59] Update packages/backend-app-api/src/wiring/BackendInitializer.ts Co-authored-by: Phil Kuang Signed-off-by: Patrik Oldsberg --- packages/backend-app-api/src/wiring/BackendInitializer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.ts b/packages/backend-app-api/src/wiring/BackendInitializer.ts index 6338b60bfb..d33427d54d 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.ts @@ -69,7 +69,7 @@ export class BackendInitializer { extension.register({ registerExtensionPoint: (api, impl) => { if (registerInit) { - throw new Error('registerInitApi called after registerInit'); + throw new Error('registerExtensionPoint called after registerInit'); } if (this.#apis.has(api)) { throw new Error(`API ${api.id} already registered`); From 877e66267ade22422a4de78138e18fe628ac03b3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 8 Jul 2022 12:31:47 +0000 Subject: [PATCH 50/59] fix(deps): update dependency azure-devops-node-api to v11.2.0 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index fee2c11171..5aa94d402e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8568,9 +8568,9 @@ axobject-query@^2.2.0: integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== azure-devops-node-api@^11.0.1: - version "11.1.1" - resolved "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.1.1.tgz#dd1356031fa4e334e016732594e8fee0f68268c4" - integrity sha512-XDG91XzLZ15reP12s3jFkKS8oiagSICjnLwxEYieme4+4h3ZveFOFRA4iYIG40RyHXsiI0mefFYYMFIJbMpWcg== + version "11.2.0" + resolved "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.2.0.tgz#bf04edbef60313117a0507415eed4790a420ad6b" + integrity sha512-XdiGPhrpaT5J8wdERRKs5g8E0Zy1pvOYTli7z9E8nmOn3YGp4FhtjhrOyFmX/8veWCwdI69mCHKJw6l+4J/bHA== dependencies: tunnel "0.0.6" typed-rest-client "^1.8.4" From 7f5a1f9b04d42f3edd5a6240f2b58d959ef4e9a2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 8 Jul 2022 14:48:08 +0200 Subject: [PATCH 51/59] backend-plugin-api: loggerToWinstonLogger refactor Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- packages/backend-app-api/src/index.ts | 1 - .../services/implementations/configService.ts | 2 +- .../services/implementations/loggerService.ts | 28 ++++-------- .../implementations/tokenManagerService.ts | 2 +- .../implementations/urlReaderService.ts | 2 +- packages/backend-plugin-api/package.json | 4 +- packages/backend-plugin-api/src/index.ts | 3 +- .../src/services/helpers/index.ts} | 11 +---- .../services/helpers/loggerToWinstonLogger.ts | 43 +++++++++++++++++++ .../backend-plugin-api/src/services/index.ts | 19 ++++++++ .../src/services/system/index.ts | 25 +++++++++++ plugins/catalog-backend/package.json | 1 - .../src/service/CatalogPlugin.ts | 2 +- 13 files changed, 105 insertions(+), 38 deletions(-) rename packages/{backend-next/src/index.test.ts => backend-plugin-api/src/services/helpers/index.ts} (69%) create mode 100644 packages/backend-plugin-api/src/services/helpers/loggerToWinstonLogger.ts create mode 100644 packages/backend-plugin-api/src/services/index.ts create mode 100644 packages/backend-plugin-api/src/services/system/index.ts diff --git a/packages/backend-app-api/src/index.ts b/packages/backend-app-api/src/index.ts index d75f5c0941..33aca2b291 100644 --- a/packages/backend-app-api/src/index.ts +++ b/packages/backend-app-api/src/index.ts @@ -21,4 +21,3 @@ */ export { createBackend } from './wiring/types'; -export { loggerToWinstonLogger } from './services/implementations/loggerService'; diff --git a/packages/backend-app-api/src/services/implementations/configService.ts b/packages/backend-app-api/src/services/implementations/configService.ts index e9a81ae100..94a59baf34 100644 --- a/packages/backend-app-api/src/services/implementations/configService.ts +++ b/packages/backend-app-api/src/services/implementations/configService.ts @@ -18,9 +18,9 @@ import { loadBackendConfig } from '@backstage/backend-common'; import { configServiceRef, createServiceFactory, + loggerToWinstonLogger, loggerServiceRef, } from '@backstage/backend-plugin-api'; -import { loggerToWinstonLogger } from './loggerService'; export const configFactory = createServiceFactory({ service: configServiceRef, diff --git a/packages/backend-app-api/src/services/implementations/loggerService.ts b/packages/backend-app-api/src/services/implementations/loggerService.ts index ff6af4b643..fbeb4b9ade 100644 --- a/packages/backend-app-api/src/services/implementations/loggerService.ts +++ b/packages/backend-app-api/src/services/implementations/loggerService.ts @@ -23,38 +23,26 @@ import { import { Logger as WinstonLogger } from 'winston'; class BackstageLogger implements Logger { - constructor( - private readonly options: { - winston: WinstonLogger; - }, - ) {} + static fromWinston(logger: WinstonLogger): BackstageLogger { + return new BackstageLogger(logger); + } + + private constructor(private readonly winston: WinstonLogger) {} info(message: string, ...meta: any[]): void { - this.options.winston.info(message, ...meta); + this.winston.info(message, ...meta); } child(fields: { [name: string]: string }): Logger { - return new BackstageLogger({ - winston: this.options.winston.child(fields), - }); + return new BackstageLogger(this.winston.child(fields)); } - - toWinston() { - return this.options.winston; - } -} - -export function loggerToWinstonLogger(logger: Logger): WinstonLogger { - return (logger as BackstageLogger).toWinston(); } export const loggerFactory = createServiceFactory({ service: loggerServiceRef, deps: {}, factory: async () => { - const root = new BackstageLogger({ - winston: createRootLogger(), - }); + const root = BackstageLogger.fromWinston(createRootLogger()); return async (pluginId: string) => { return root.child({ pluginId }); }; diff --git a/packages/backend-app-api/src/services/implementations/tokenManagerService.ts b/packages/backend-app-api/src/services/implementations/tokenManagerService.ts index 7f0423e845..2e82fce9d9 100644 --- a/packages/backend-app-api/src/services/implementations/tokenManagerService.ts +++ b/packages/backend-app-api/src/services/implementations/tokenManagerService.ts @@ -19,9 +19,9 @@ import { loggerServiceRef, createServiceFactory, tokenManagerServiceRef, + loggerToWinstonLogger, } from '@backstage/backend-plugin-api'; import { ServerTokenManager } from '@backstage/backend-common'; -import { loggerToWinstonLogger } from './loggerService'; export const tokenManagerFactory = createServiceFactory({ service: tokenManagerServiceRef, diff --git a/packages/backend-app-api/src/services/implementations/urlReaderService.ts b/packages/backend-app-api/src/services/implementations/urlReaderService.ts index 7df6ca33a9..74431dfa0d 100644 --- a/packages/backend-app-api/src/services/implementations/urlReaderService.ts +++ b/packages/backend-app-api/src/services/implementations/urlReaderService.ts @@ -19,9 +19,9 @@ import { configServiceRef, createServiceFactory, loggerServiceRef, + loggerToWinstonLogger, urlReaderServiceRef, } from '@backstage/backend-plugin-api'; -import { loggerToWinstonLogger } from './loggerService'; export const urlReaderFactory = createServiceFactory({ service: urlReaderServiceRef, diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index 24d2012374..dcf37826df 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -38,7 +38,9 @@ "@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", - "express": "^4.17.1" + "express": "^4.17.1", + "winston": "^3.2.1", + "winston-transport": "^4.5.0" }, "devDependencies": { "@backstage/cli": "^0.18.0-next.2", diff --git a/packages/backend-plugin-api/src/index.ts b/packages/backend-plugin-api/src/index.ts index e82218ca69..452fa046f9 100644 --- a/packages/backend-plugin-api/src/index.ts +++ b/packages/backend-plugin-api/src/index.ts @@ -20,6 +20,5 @@ * @packageDocumentation */ +export * from './services'; export * from './wiring'; -export * from './services/system/types'; -export * from './services/definitions'; diff --git a/packages/backend-next/src/index.test.ts b/packages/backend-plugin-api/src/services/helpers/index.ts similarity index 69% rename from packages/backend-next/src/index.test.ts rename to packages/backend-plugin-api/src/services/helpers/index.ts index 8b41455b27..24336c1af2 100644 --- a/packages/backend-next/src/index.test.ts +++ b/packages/backend-plugin-api/src/services/helpers/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Backstage Authors + * 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. @@ -14,11 +14,4 @@ * limitations under the License. */ -import { PluginEnvironment } from './types'; - -describe('test', () => { - it('unbreaks the test runner', () => { - const unbreaker = {} as PluginEnvironment; - expect(unbreaker).toBeTruthy(); - }); -}); +export { loggerToWinstonLogger } from './loggerToWinstonLogger'; diff --git a/packages/backend-plugin-api/src/services/helpers/loggerToWinstonLogger.ts b/packages/backend-plugin-api/src/services/helpers/loggerToWinstonLogger.ts new file mode 100644 index 0000000000..65f97db745 --- /dev/null +++ b/packages/backend-plugin-api/src/services/helpers/loggerToWinstonLogger.ts @@ -0,0 +1,43 @@ +/* + * 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(); + } +} + +export function loggerToWinstonLogger( + logger: BackstageLogger, + opts?: TransportStreamOptions, +): WinstonLogger { + return createLogger({ + transports: [new BackstageLoggerTransport(logger, opts)], + }); +} diff --git a/packages/backend-plugin-api/src/services/index.ts b/packages/backend-plugin-api/src/services/index.ts new file mode 100644 index 0000000000..96bd3d320a --- /dev/null +++ b/packages/backend-plugin-api/src/services/index.ts @@ -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'; diff --git a/packages/backend-plugin-api/src/services/system/index.ts b/packages/backend-plugin-api/src/services/system/index.ts new file mode 100644 index 0000000000..eead2297a5 --- /dev/null +++ b/packages/backend-plugin-api/src/services/system/index.ts @@ -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'; diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index c36e28deb8..6ebcae936b 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -34,7 +34,6 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-app-api": "^0.0.0", "@backstage/backend-plugin-api": "^0.0.0", "@backstage/plugin-catalog-node": "^0.0.0", "@backstage/backend-common": "^0.14.1-next.2", diff --git a/plugins/catalog-backend/src/service/CatalogPlugin.ts b/plugins/catalog-backend/src/service/CatalogPlugin.ts index fd3397612f..b82797ec8b 100644 --- a/plugins/catalog-backend/src/service/CatalogPlugin.ts +++ b/plugins/catalog-backend/src/service/CatalogPlugin.ts @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { loggerToWinstonLogger } from '@backstage/backend-app-api'; import { configServiceRef, createBackendPlugin, databaseServiceRef, loggerServiceRef, + loggerToWinstonLogger, permissionsServiceRef, urlReaderServiceRef, httpRouterServiceRef, From 825d769650a2ccb3e6e1288c3571cac2c05bfed0 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 8 Jul 2022 15:25:38 +0200 Subject: [PATCH 52/59] update API report for backend system changes Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- packages/backend-plugin-api/api-report.md | 8 ++++++++ .../src/services/helpers/loggerToWinstonLogger.ts | 1 + plugins/catalog-backend/api-report.md | 10 ---------- plugins/catalog-node/api-report.md | 2 ++ plugins/scaffolder-backend/api-report.md | 4 +--- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md index a4d45a2fb7..df8474d670 100644 --- a/packages/backend-plugin-api/api-report.md +++ b/packages/backend-plugin-api/api-report.md @@ -5,6 +5,7 @@ ```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'; @@ -12,6 +13,7 @@ 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) @@ -147,6 +149,12 @@ export interface Logger { // @public (undocumented) export const loggerServiceRef: ServiceRef; +// @public (undocumented) +export function loggerToWinstonLogger( + logger: Logger, + opts?: TransportStreamOptions, +): Logger_2; + // @public (undocumented) export const permissionsServiceRef: ServiceRef< PermissionAuthorizer | PermissionEvaluator diff --git a/packages/backend-plugin-api/src/services/helpers/loggerToWinstonLogger.ts b/packages/backend-plugin-api/src/services/helpers/loggerToWinstonLogger.ts index 65f97db745..b9ccd70d3f 100644 --- a/packages/backend-plugin-api/src/services/helpers/loggerToWinstonLogger.ts +++ b/packages/backend-plugin-api/src/services/helpers/loggerToWinstonLogger.ts @@ -33,6 +33,7 @@ class BackstageLoggerTransport extends Transport { } } +/** @public */ export function loggerToWinstonLogger( logger: BackstageLogger, opts?: TransportStreamOptions, diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index b7e63ae66d..b5263172cb 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -47,7 +47,6 @@ import { Readable } from 'stream'; import { ResourcePermission } from '@backstage/plugin-permission-common'; import { Router } from 'express'; import { ScmIntegrationRegistry } from '@backstage/integration'; -import { ServiceRef } from '@backstage/backend-plugin-api'; import { TokenManager } from '@backstage/backend-common'; import { UrlReader } from '@backstage/backend-common'; import { Validators } from '@backstage/catalog-model'; @@ -228,15 +227,6 @@ export interface CatalogProcessingEngine { stop(): Promise; } -// @alpha (undocumented) -export interface CatalogProcessingInitApi { - // (undocumented) - addProcessor(processor: CatalogProcessor): void; -} - -// @alpha (undocumented) -export const catalogProcessingInitApiRef: ServiceRef; - export { CatalogProcessor }; export { CatalogProcessorCache }; diff --git a/plugins/catalog-node/api-report.md b/plugins/catalog-node/api-report.md index cf81f494c5..0449708bc3 100644 --- a/plugins/catalog-node/api-report.md +++ b/plugins/catalog-node/api-report.md @@ -12,6 +12,8 @@ import { ServiceRef } from '@backstage/backend-plugin-api'; // @alpha (undocumented) export interface CatalogProcessingExtensionPoint { + // (undocumented) + addEntityProvider(provider: EntityProvider): void; // (undocumented) addProcessor(processor: CatalogProcessor): void; } diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 672b853f3b..dfca5994fd 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -545,9 +545,7 @@ export type RunCommandOptions = { }; // @alpha -export const scaffolderCatalogExtension: ( - option: unknown, -) => BackendRegistrable; +export const scaffolderCatalogModule: (option: unknown) => BackendRegistrable; // @public (undocumented) export class ScaffolderEntitiesProcessor implements CatalogProcessor { From faf37e12a8d87859428bbf5418a77f0faf9c6943 Mon Sep 17 00:00:00 2001 From: Marc Rooding Date: Fri, 8 Jul 2022 15:33:35 +0200 Subject: [PATCH 53/59] Reworded the supported vendors Signed-off-by: Marc Rooding --- docs/integrations/ldap/org.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/integrations/ldap/org.md b/docs/integrations/ldap/org.md index 010f46832d..dbd3f4ff43 100644 --- a/docs/integrations/ldap/org.md +++ b/docs/integrations/ldap/org.md @@ -14,11 +14,7 @@ entities that mirror your org setup. ## Supported vendors -Currently, Backstage only supports the following LDAP vendors: - -1. OpenLDAP (default) -2. Active Directory -3. FreeIPA +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 From fcfea69d83bc3fca4f0169b2f4e412aef9f0e645 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 8 Jul 2022 15:33:26 +0200 Subject: [PATCH 54/59] backend-app-api: fixes, renames, cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Johan Haals Co-authored-by: Fredrik Adelöw Signed-off-by: Patrik Oldsberg --- packages/backend-app-api/README.md | 2 + packages/backend-app-api/api-report.md | 18 +++++-- packages/backend-app-api/src/index.ts | 2 +- .../src/wiring/BackendInitializer.ts | 54 +++++++++---------- .../src/wiring/BackstageBackend.ts | 8 +-- ...{CoreApiRegistry.ts => ServiceRegistry.ts} | 22 ++++---- packages/backend-app-api/src/wiring/index.ts | 18 +++++++ packages/backend-app-api/src/wiring/types.ts | 13 ++++- packages/backend-plugin-api/README.md | 2 + 9 files changed, 88 insertions(+), 51 deletions(-) rename packages/backend-app-api/src/wiring/{CoreApiRegistry.ts => ServiceRegistry.ts} (71%) create mode 100644 packages/backend-app-api/src/wiring/index.ts diff --git a/packages/backend-app-api/README.md b/packages/backend-app-api/README.md index 295a04c7a1..ee608ceb43 100644 --- a/packages/backend-app-api/README.md +++ b/packages/backend-app-api/README.md @@ -1,5 +1,7 @@ # @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 diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md index 8c64858310..a37ec6abc6 100644 --- a/packages/backend-app-api/api-report.md +++ b/packages/backend-app-api/api-report.md @@ -6,10 +6,20 @@ import { AnyServiceFactory } from '@backstage/backend-plugin-api'; import { BackendRegistrable } from '@backstage/backend-plugin-api'; -// Warning: (ae-forgotten-export) The symbol "CreateBackendOptions" needs to be exported by the entry point index.d.ts -// Warning: (ae-forgotten-export) The symbol "Backend" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "createBackend" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// +// @public (undocumented) +export interface Backend { + // (undocumented) + add(extension: BackendRegistrable): void; + // (undocumented) + start(): Promise; +} + // @public (undocumented) export function createBackend(options?: CreateBackendOptions): Backend; + +// @public (undocumented) +export interface CreateBackendOptions { + // (undocumented) + apis: AnyServiceFactory[]; +} ``` diff --git a/packages/backend-app-api/src/index.ts b/packages/backend-app-api/src/index.ts index 33aca2b291..c58379c3e4 100644 --- a/packages/backend-app-api/src/index.ts +++ b/packages/backend-app-api/src/index.ts @@ -20,4 +20,4 @@ * @packageDocumentation */ -export { createBackend } from './wiring/types'; +export * from './wiring'; diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.ts b/packages/backend-app-api/src/wiring/BackendInitializer.ts index d33427d54d..ab086f4144 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.ts @@ -14,31 +14,38 @@ * limitations under the License. */ -import { BackendRegistrable, ServiceRef } from '@backstage/backend-plugin-api'; -import { BackendRegisterInit, ApiHolder } from './types'; +import { + BackendRegistrable, + ExtensionPoint, + ServiceRef, +} from '@backstage/backend-plugin-api'; +import { BackendRegisterInit, ServiceHolder } from './types'; + +type ServiceOrExtensionPoint = ExtensionPoint | ServiceRef; export class BackendInitializer { #started = false; #extensions = new Map(); - // #stops = []; #registerInits = new Array(); - #apis = new Map, unknown>(); - #apiHolder: ApiHolder; + #extensionPoints = new Map(); + #serviceHolder: ServiceHolder; - constructor(apiHolder: ApiHolder) { - this.#apiHolder = apiHolder; + constructor(serviceHolder: ServiceHolder) { + this.#serviceHolder = serviceHolder; } async #getInitDeps( - deps: { [name: string]: ServiceRef }, + deps: { [name: string]: ServiceOrExtensionPoint }, pluginId: string, ) { return Object.fromEntries( await Promise.all( - Object.entries(deps).map(async ([name, apiRef]) => [ + Object.entries(deps).map(async ([name, ref]) => [ name, - this.#apis.get(apiRef) || - (await this.#apiHolder.get(apiRef)!(pluginId)), + this.#extensionPoints.get(ref) || + (await this.#serviceHolder.get(ref as ServiceRef)!( + pluginId, + )), ]), ), ); @@ -67,15 +74,15 @@ export class BackendInitializer { console.log('Registering', extension.id); extension.register({ - registerExtensionPoint: (api, impl) => { + registerExtensionPoint: (extensionPointRef, impl) => { if (registerInit) { throw new Error('registerExtensionPoint called after registerInit'); } - if (this.#apis.has(api)) { - throw new Error(`API ${api.id} already registered`); + if (this.#extensionPoints.has(extensionPointRef)) { + throw new Error(`API ${extensionPointRef.id} already registered`); } - this.#apis.set(api, impl); - provides.add(api); + this.#extensionPoints.set(extensionPointRef, impl); + provides.add(extensionPointRef); }, registerInit: registerOptions => { if (registerInit) { @@ -105,20 +112,11 @@ export class BackendInitializer { const orderedRegisterResults = this.#resolveInitOrder(this.#registerInits); for (const registerInit of orderedRegisterResults) { - // TODO: DI const deps = await this.#getInitDeps(registerInit.deps, registerInit.id); await registerInit.init(deps); - // Maybe return stop? or lifecycle API - // this.#stops.push(); } } - // async stop(): Promise { - // for (const stop of this.#stops) { - // await stop.stop(); - // } - // } - private validateSetup() {} #resolveInitOrder(registerInits: Array) { @@ -133,13 +131,13 @@ export class BackendInitializer { for (const registerInit of registerInitsToOrder) { const unInitializedDependents = []; - for (const api of registerInit.provides) { + for (const serviceRef of registerInit.provides) { if ( registerInitsToOrder.some( - init => init !== registerInit && init.consumes.has(api), + init => init !== registerInit && init.consumes.has(serviceRef), ) ) { - unInitializedDependents.push(api); + unInitializedDependents.push(serviceRef); } } diff --git a/packages/backend-app-api/src/wiring/BackstageBackend.ts b/packages/backend-app-api/src/wiring/BackstageBackend.ts index 69df1fdf82..104d2b6fc8 100644 --- a/packages/backend-app-api/src/wiring/BackstageBackend.ts +++ b/packages/backend-app-api/src/wiring/BackstageBackend.ts @@ -19,16 +19,16 @@ import { BackendRegistrable, } from '@backstage/backend-plugin-api'; import { BackendInitializer } from './BackendInitializer'; -import { CoreApiRegistry } from './CoreApiRegistry'; +import { ServiceRegistry } from './ServiceRegistry'; import { Backend } from './types'; export class BackstageBackend implements Backend { - #coreApis: CoreApiRegistry; + #services: ServiceRegistry; #initializer: BackendInitializer; constructor(apiFactories: AnyServiceFactory[]) { - this.#coreApis = new CoreApiRegistry(apiFactories); - this.#initializer = new BackendInitializer(this.#coreApis); + this.#services = new ServiceRegistry(apiFactories); + this.#initializer = new BackendInitializer(this.#services); } add(extension: BackendRegistrable): void { diff --git a/packages/backend-app-api/src/wiring/CoreApiRegistry.ts b/packages/backend-app-api/src/wiring/ServiceRegistry.ts similarity index 71% rename from packages/backend-app-api/src/wiring/CoreApiRegistry.ts rename to packages/backend-app-api/src/wiring/ServiceRegistry.ts index 4b1e0f5ce0..bdaecf30c6 100644 --- a/packages/backend-app-api/src/wiring/CoreApiRegistry.ts +++ b/packages/backend-app-api/src/wiring/ServiceRegistry.ts @@ -19,7 +19,7 @@ import { ServiceRef, } from '@backstage/backend-plugin-api'; -export class CoreApiRegistry { +export class ServiceRegistry { readonly #implementations: Map>; readonly #factories: Map; @@ -35,29 +35,27 @@ export class CoreApiRegistry { } return async (pluginId: string): Promise => { - if (this.#implementations.has(ref.id)) { - if (this.#implementations.get(ref.id)!.has(pluginId)) { - return this.#implementations.get(ref.id)!.get(pluginId) as T; + let implementations = this.#implementations.get(ref.id); + if (implementations) { + if (implementations.has(pluginId)) { + return implementations.get(pluginId) as T; } - this.#implementations.set(ref.id, new Map()); } else { - this.#implementations.set(ref.id, new Map()); + implementations = new Map(); + this.#implementations.set(ref.id, implementations); } const factoryDeps = Object.fromEntries( - Object.entries(factory.deps).map(([name, apiRef]) => [ + Object.entries(factory.deps).map(([name, serviceRef]) => [ name, - this.get(apiRef)!, // TODO: throw + this.get(serviceRef)!, // TODO: throw ]), ); const factoryFunc = await factory.factory(factoryDeps); const implementation = await factoryFunc(pluginId); - this.#implementations.set( - ref.id, - this.#implementations.get(ref.id)!.set(pluginId, implementation), - ); + implementations.set(pluginId, implementation); return implementation as T; }; diff --git a/packages/backend-app-api/src/wiring/index.ts b/packages/backend-app-api/src/wiring/index.ts new file mode 100644 index 0000000000..1dd91e30e1 --- /dev/null +++ b/packages/backend-app-api/src/wiring/index.ts @@ -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'; diff --git a/packages/backend-app-api/src/wiring/types.ts b/packages/backend-app-api/src/wiring/types.ts index c1c43a8ba8..112fe06b05 100644 --- a/packages/backend-app-api/src/wiring/types.ts +++ b/packages/backend-app-api/src/wiring/types.ts @@ -23,6 +23,9 @@ import { import { defaultServiceFactories } from '../services/implementations'; import { BackstageBackend } from './BackstageBackend'; +/** + * @public + */ export interface Backend { add(extension: BackendRegistrable): void; start(): Promise; @@ -36,14 +39,20 @@ export interface BackendRegisterInit { init: (deps: { [name: string]: unknown }) => Promise; } -interface CreateBackendOptions { +/** + * @public + */ +export interface CreateBackendOptions { apis: AnyServiceFactory[]; } -export type ApiHolder = { +export type ServiceHolder = { get(api: ServiceRef): FactoryFunc | undefined; }; +/** + * @public + */ export function createBackend(options?: CreateBackendOptions): Backend { // TODO: merge with provided APIs return new BackstageBackend([ diff --git a/packages/backend-plugin-api/README.md b/packages/backend-plugin-api/README.md index 9e28e220a1..364655dd60 100644 --- a/packages/backend-plugin-api/README.md +++ b/packages/backend-plugin-api/README.md @@ -1,5 +1,7 @@ # @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 From f710231475102bf8bdd18586cfd79c1b1622670d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 8 Jul 2022 15:41:18 +0200 Subject: [PATCH 55/59] backend-plugin-api: add TODOs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- packages/backend-plugin-api/src/wiring/types.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/backend-plugin-api/src/wiring/types.ts b/packages/backend-plugin-api/src/wiring/types.ts index 2b4aacb40a..2b0bef16f7 100644 --- a/packages/backend-plugin-api/src/wiring/types.ts +++ b/packages/backend-plugin-api/src/wiring/types.ts @@ -75,6 +75,7 @@ export interface BackendPluginConfig { register(reg: BackendInitRegistry, options: TOptions): void; } +// TODO: Make option optional in the returned factory if they are indeed optional /** @public */ export function createBackendPlugin( config: BackendPluginConfig, @@ -97,6 +98,7 @@ export interface BackendModuleConfig { ): void; } +// TODO: Make option optional in the returned factory if they are indeed optional /** @public */ export function createBackendModule( config: BackendModuleConfig, @@ -104,6 +106,7 @@ export function createBackendModule( return options => ({ id: `${config.pluginId}.${config.moduleId}`, register(register) { + // TODO: Hide registerExtensionPoint return config.register(register, options); }, }); From ca32d532354568e384fac6b1170a141bc17176dc Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 8 Jul 2022 15:42:43 +0200 Subject: [PATCH 56/59] backend-next: set version to 0.0.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Johan Haals Co-authored-by: Fredrik Adelöw Signed-off-by: Patrik Oldsberg --- packages/backend-next/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend-next/package.json b/packages/backend-next/package.json index 6feaf5ad97..673116790e 100644 --- a/packages/backend-next/package.json +++ b/packages/backend-next/package.json @@ -1,6 +1,6 @@ { "name": "example-backend-next", - "version": "0.2.73-next.2", + "version": "0.0.0", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", From b4e127d126bb76ec7aee19194f0bacb4fd462bfe Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 8 Jul 2022 15:43:15 +0200 Subject: [PATCH 57/59] backend-plugin-api: no schelduler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Co-authored-by: blam Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- .../definitions/scheldulerServiceRef.ts | 30 ------------------- 1 file changed, 30 deletions(-) delete mode 100644 packages/backend-plugin-api/src/services/definitions/scheldulerServiceRef.ts diff --git a/packages/backend-plugin-api/src/services/definitions/scheldulerServiceRef.ts b/packages/backend-plugin-api/src/services/definitions/scheldulerServiceRef.ts deleted file mode 100644 index b13ca9e240..0000000000 --- a/packages/backend-plugin-api/src/services/definitions/scheldulerServiceRef.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2022 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { createServiceRef } from '../system/types'; -import { - PermissionAuthorizer, - PermissionEvaluator, -} from '@backstage/plugin-permission-common'; - -/** - * @public - */ -export const permissionsServiceRef = createServiceRef< - PermissionEvaluator | PermissionAuthorizer ->({ - id: 'core.permissions', -}); From 91c1d12123b55f09c494f0c192b7f087d450b84d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 8 Jul 2022 15:46:16 +0200 Subject: [PATCH 58/59] changesets: added changesets for initial experimental backend system Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- .changeset/beige-kiwis-know.md | 6 ++++++ .changeset/lazy-steaks-tell.md | 5 +++++ .changeset/polite-moose-beam.md | 5 +++++ .changeset/short-wolves-applaud.md | 5 +++++ .changeset/swift-plants-fix.md | 7 +++++++ 5 files changed, 28 insertions(+) create mode 100644 .changeset/beige-kiwis-know.md create mode 100644 .changeset/lazy-steaks-tell.md create mode 100644 .changeset/polite-moose-beam.md create mode 100644 .changeset/short-wolves-applaud.md create mode 100644 .changeset/swift-plants-fix.md diff --git a/.changeset/beige-kiwis-know.md b/.changeset/beige-kiwis-know.md new file mode 100644 index 0000000000..696b9e81cb --- /dev/null +++ b/.changeset/beige-kiwis-know.md @@ -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. diff --git a/.changeset/lazy-steaks-tell.md b/.changeset/lazy-steaks-tell.md new file mode 100644 index 0000000000..5e63816ada --- /dev/null +++ b/.changeset/lazy-steaks-tell.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-node': minor +--- + +Added alpha exports for the new experimental backend system. diff --git a/.changeset/polite-moose-beam.md b/.changeset/polite-moose-beam.md new file mode 100644 index 0000000000..5e41018ae6 --- /dev/null +++ b/.changeset/polite-moose-beam.md @@ -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. diff --git a/.changeset/short-wolves-applaud.md b/.changeset/short-wolves-applaud.md new file mode 100644 index 0000000000..fa5cebffc3 --- /dev/null +++ b/.changeset/short-wolves-applaud.md @@ -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. diff --git a/.changeset/swift-plants-fix.md b/.changeset/swift-plants-fix.md new file mode 100644 index 0000000000..52873b7985 --- /dev/null +++ b/.changeset/swift-plants-fix.md @@ -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. From 79849709d5e4b91e79300f093a3dfd3b7c87c427 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 8 Jul 2022 16:01:51 +0200 Subject: [PATCH 59/59] backend-plugin-api: fix @types/express dep Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- packages/backend-plugin-api/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index dcf37826df..f9109ae680 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -38,13 +38,13 @@ "@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", - "@types/express": "^4.17.6" + "@backstage/cli": "^0.18.0-next.2" }, "files": [ "dist",