@backstage/backend-dynamic-feature-service 0.2.10-next.2 → 0.2.11-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +47 -0
- package/dist/index.cjs.js +16 -34
- package/dist/index.cjs.js.map +1 -1
- package/package.json +16 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,52 @@
|
|
|
1
1
|
# @backstage/backend-dynamic-feature-service
|
|
2
2
|
|
|
3
|
+
## 0.2.11-next.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
- @backstage/backend-app-api@0.7.6-next.0
|
|
9
|
+
- @backstage/cli-node@0.2.6-next.0
|
|
10
|
+
- @backstage/backend-tasks@0.5.24-next.0
|
|
11
|
+
- @backstage/backend-common@0.22.1-next.0
|
|
12
|
+
- @backstage/plugin-catalog-backend@1.23.0-next.0
|
|
13
|
+
- @backstage/plugin-search-backend-node@1.2.24-next.0
|
|
14
|
+
- @backstage/plugin-events-node@0.3.5-next.0
|
|
15
|
+
- @backstage/backend-plugin-api@0.6.19-next.0
|
|
16
|
+
- @backstage/plugin-auth-node@0.4.14-next.0
|
|
17
|
+
- @backstage/plugin-events-backend@0.3.6-next.0
|
|
18
|
+
- @backstage/plugin-permission-node@0.7.30-next.0
|
|
19
|
+
- @backstage/plugin-scaffolder-node@0.4.5-next.0
|
|
20
|
+
- @backstage/plugin-app-node@0.1.19-next.0
|
|
21
|
+
- @backstage/config-loader@1.8.0
|
|
22
|
+
- @backstage/cli-common@0.1.13
|
|
23
|
+
- @backstage/config@1.2.0
|
|
24
|
+
- @backstage/errors@1.2.4
|
|
25
|
+
- @backstage/types@1.1.1
|
|
26
|
+
- @backstage/plugin-permission-common@0.7.13
|
|
27
|
+
- @backstage/plugin-search-common@1.2.11
|
|
28
|
+
|
|
29
|
+
## 0.2.10
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
- b192752: Updated `README.md` to point to `packages/backend` instead of `packages/backend-next`.
|
|
34
|
+
- d229dc4: Move path utilities from `backend-common` to the `backend-plugin-api` package.
|
|
35
|
+
- b611fd0: Updates the `scanRoot` method in the `PluginScanner` class to specifically ignore the `lost+found` directory, which is a system-generated directory used for file recovery on Unix-like systems. Skipping this directory avoids unnecessary errors.
|
|
36
|
+
- Updated dependencies
|
|
37
|
+
- @backstage/plugin-catalog-backend@1.22.0
|
|
38
|
+
- @backstage/backend-app-api@0.7.3
|
|
39
|
+
- @backstage/backend-common@0.22.0
|
|
40
|
+
- @backstage/backend-plugin-api@0.6.18
|
|
41
|
+
- @backstage/plugin-scaffolder-node@0.4.4
|
|
42
|
+
- @backstage/backend-tasks@0.5.23
|
|
43
|
+
- @backstage/plugin-search-backend-node@1.2.22
|
|
44
|
+
- @backstage/plugin-events-node@0.3.4
|
|
45
|
+
- @backstage/plugin-auth-node@0.4.13
|
|
46
|
+
- @backstage/plugin-app-node@0.1.18
|
|
47
|
+
- @backstage/plugin-events-backend@0.3.5
|
|
48
|
+
- @backstage/plugin-permission-node@0.7.29
|
|
49
|
+
|
|
3
50
|
## 0.2.10-next.2
|
|
4
51
|
|
|
5
52
|
### Patch Changes
|
package/dist/index.cjs.js
CHANGED
|
@@ -14,7 +14,6 @@ var fs$2 = require('fs-extra');
|
|
|
14
14
|
var lodash = require('lodash');
|
|
15
15
|
var configLoader = require('@backstage/config-loader');
|
|
16
16
|
var pluginAppNode = require('@backstage/plugin-app-node');
|
|
17
|
-
var backendCommon = require('@backstage/backend-common');
|
|
18
17
|
var backendAppApi = require('@backstage/backend-app-api');
|
|
19
18
|
var winston = require('winston');
|
|
20
19
|
var getPackages = require('@manypkg/get-packages');
|
|
@@ -51,23 +50,17 @@ function isBackendDynamicPluginInstaller(obj) {
|
|
|
51
50
|
return obj !== void 0 && "kind" in obj && (obj.kind === "new" || obj.kind === "legacy");
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
var __defProp$1 = Object.defineProperty;
|
|
55
|
-
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
56
|
-
var __publicField$1 = (obj, key, value) => {
|
|
57
|
-
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
58
|
-
return value;
|
|
59
|
-
};
|
|
60
53
|
class PluginScanner {
|
|
61
54
|
constructor(config, logger, backstageRoot, preferAlpha) {
|
|
62
55
|
this.config = config;
|
|
63
56
|
this.logger = logger;
|
|
64
57
|
this.backstageRoot = backstageRoot;
|
|
65
58
|
this.preferAlpha = preferAlpha;
|
|
66
|
-
__publicField$1(this, "_rootDirectory");
|
|
67
|
-
__publicField$1(this, "configUnsubscribe");
|
|
68
|
-
__publicField$1(this, "rootDirectoryWatcher");
|
|
69
|
-
__publicField$1(this, "subscribers", []);
|
|
70
59
|
}
|
|
60
|
+
_rootDirectory;
|
|
61
|
+
configUnsubscribe;
|
|
62
|
+
rootDirectoryWatcher;
|
|
63
|
+
subscribers = [];
|
|
71
64
|
static create(options) {
|
|
72
65
|
const scanner = new PluginScanner(
|
|
73
66
|
options.config,
|
|
@@ -130,7 +123,6 @@ Please add '${backstageNodeModules}' to the 'NODE_PATH' when running the backsta
|
|
|
130
123
|
this._rootDirectory = dynamicPluginsRootPath;
|
|
131
124
|
}
|
|
132
125
|
async scanRoot() {
|
|
133
|
-
var _a;
|
|
134
126
|
if (!this._rootDirectory) {
|
|
135
127
|
return { packages: [] };
|
|
136
128
|
}
|
|
@@ -167,7 +159,7 @@ Please add '${backstageNodeModules}' to the 'NODE_PATH' when running the backsta
|
|
|
167
159
|
if (!scannedPlugin.manifest.main) {
|
|
168
160
|
throw new Error("field 'main' not found in 'package.json'");
|
|
169
161
|
}
|
|
170
|
-
if (
|
|
162
|
+
if (scannedPlugin.manifest.backstage?.role) {
|
|
171
163
|
platform = cliNode.PackageRoles.getRoleInfo(
|
|
172
164
|
scannedPlugin.manifest.backstage.role
|
|
173
165
|
).platform;
|
|
@@ -334,19 +326,11 @@ class CommonJSModuleLoader {
|
|
|
334
326
|
}
|
|
335
327
|
}
|
|
336
328
|
|
|
337
|
-
var __defProp = Object.defineProperty;
|
|
338
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
339
|
-
var __publicField = (obj, key, value) => {
|
|
340
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
341
|
-
return value;
|
|
342
|
-
};
|
|
343
329
|
class DynamicPluginManager {
|
|
344
330
|
constructor(logger, packages, moduleLoader) {
|
|
345
331
|
this.logger = logger;
|
|
346
332
|
this.packages = packages;
|
|
347
333
|
this.moduleLoader = moduleLoader;
|
|
348
|
-
__publicField(this, "_plugins");
|
|
349
|
-
__publicField(this, "_availablePackages");
|
|
350
334
|
this._plugins = [];
|
|
351
335
|
this._availablePackages = packages;
|
|
352
336
|
}
|
|
@@ -382,6 +366,8 @@ class DynamicPluginManager {
|
|
|
382
366
|
manager._plugins.push(...await manager.loadPlugins());
|
|
383
367
|
return manager;
|
|
384
368
|
}
|
|
369
|
+
_plugins;
|
|
370
|
+
_availablePackages;
|
|
385
371
|
get availablePackages() {
|
|
386
372
|
return this._availablePackages;
|
|
387
373
|
}
|
|
@@ -449,7 +435,7 @@ class DynamicPluginManager {
|
|
|
449
435
|
};
|
|
450
436
|
} catch (error) {
|
|
451
437
|
this.logger.error(
|
|
452
|
-
`an error
|
|
438
|
+
`an error occurred while loading dynamic backend plugin '${plugin.manifest.name}' from '${plugin.location}'`,
|
|
453
439
|
error
|
|
454
440
|
);
|
|
455
441
|
return void 0;
|
|
@@ -483,12 +469,11 @@ const dynamicPluginsServiceFactory = backendPluginApi.createServiceFactory(
|
|
|
483
469
|
logger: backendPluginApi.coreServices.rootLogger
|
|
484
470
|
},
|
|
485
471
|
async factory({ config, logger }) {
|
|
486
|
-
var _a;
|
|
487
472
|
return await DynamicPluginManager.create({
|
|
488
473
|
config,
|
|
489
474
|
logger,
|
|
490
475
|
preferAlpha: true,
|
|
491
|
-
moduleLoader:
|
|
476
|
+
moduleLoader: options?.moduleLoader?.(logger)
|
|
492
477
|
});
|
|
493
478
|
}
|
|
494
479
|
})
|
|
@@ -499,8 +484,7 @@ class DynamicPluginsEnabledFeatureDiscoveryService {
|
|
|
499
484
|
this.featureDiscoveryService = featureDiscoveryService;
|
|
500
485
|
}
|
|
501
486
|
async getBackendFeatures() {
|
|
502
|
-
|
|
503
|
-
const staticFeatures = (_c = (_b = await ((_a = this.featureDiscoveryService) == null ? void 0 : _a.getBackendFeatures())) == null ? void 0 : _b.features) != null ? _c : [];
|
|
487
|
+
const staticFeatures = (await this.featureDiscoveryService?.getBackendFeatures())?.features ?? [];
|
|
504
488
|
return {
|
|
505
489
|
features: [
|
|
506
490
|
...this.dynamicPlugins.backendPlugins().flatMap((plugin) => {
|
|
@@ -567,11 +551,11 @@ const dynamicPluginsSchemasServiceFactory = backendPluginApi.createServiceFactor
|
|
|
567
551
|
additionalSchemas = await gatherDynamicPluginsSchemas(
|
|
568
552
|
packages,
|
|
569
553
|
logger,
|
|
570
|
-
options
|
|
554
|
+
options?.schemaLocator
|
|
571
555
|
);
|
|
572
556
|
}
|
|
573
557
|
const serialized = configSchema.serialize();
|
|
574
|
-
if (
|
|
558
|
+
if (serialized?.backstageConfigSchemaVersion !== 1) {
|
|
575
559
|
throw new Error(
|
|
576
560
|
"Serialized configuration schema is invalid or has an invalid version number"
|
|
577
561
|
);
|
|
@@ -617,7 +601,7 @@ async function gatherDynamicPluginsSchemas(packages, logger, schemaLocator = ()
|
|
|
617
601
|
if (lodash.isEmpty(serialized)) {
|
|
618
602
|
continue;
|
|
619
603
|
}
|
|
620
|
-
if (!
|
|
604
|
+
if (!serialized?.$schema || serialized?.type !== "object") {
|
|
621
605
|
logger.error(
|
|
622
606
|
`Serialized configuration schema is invalid for plugin ${pluginPackage.manifest.name}`
|
|
623
607
|
);
|
|
@@ -639,9 +623,8 @@ const dynamicPluginsFrontendSchemas = backendPluginApi.createBackendModule({
|
|
|
639
623
|
configSchemaExtension: pluginAppNode.configSchemaExtensionPoint
|
|
640
624
|
},
|
|
641
625
|
async init({ config, schemas, configSchemaExtension }) {
|
|
642
|
-
|
|
643
|
-
const
|
|
644
|
-
const appDistDir = backendCommon.resolvePackagePath(appPackageName, "dist");
|
|
626
|
+
const appPackageName = config.getOptionalString("app.packageName") ?? "app";
|
|
627
|
+
const appDistDir = backendPluginApi.resolvePackagePath(appPackageName, "dist");
|
|
645
628
|
const compiledConfigSchema = await pluginAppNode.loadCompiledConfigSchema(appDistDir);
|
|
646
629
|
if (compiledConfigSchema) {
|
|
647
630
|
configSchemaExtension.setConfigSchema(
|
|
@@ -660,7 +643,6 @@ const dynamicPluginsRootLoggerServiceFactory = backendPluginApi.createServiceFac
|
|
|
660
643
|
schemas: dynamicPluginsSchemasServiceRef
|
|
661
644
|
},
|
|
662
645
|
async factory({ config, schemas }) {
|
|
663
|
-
var _a;
|
|
664
646
|
const logger = backendAppApi.WinstonLogger.create({
|
|
665
647
|
meta: {
|
|
666
648
|
service: "backstage"
|
|
@@ -677,7 +659,7 @@ const dynamicPluginsRootLoggerServiceFactory = backendPluginApi.createServiceFac
|
|
|
677
659
|
schema: (await schemas.addDynamicPluginsSchemas(configSchema)).schema
|
|
678
660
|
});
|
|
679
661
|
logger.addRedactions(secretEnumerator(config));
|
|
680
|
-
|
|
662
|
+
config.subscribe?.(() => logger.addRedactions(secretEnumerator(config)));
|
|
681
663
|
return logger;
|
|
682
664
|
}
|
|
683
665
|
});
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/manager/types.ts","../src/scanner/plugin-scanner.ts","../src/loader/CommonJSModuleLoader.ts","../src/manager/plugin-manager.ts","../src/schemas/schemas.ts","../src/schemas/appBackendModule.ts","../src/schemas/rootLoggerServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from 'winston';\nimport { Config } from '@backstage/config';\nimport {\n PluginCacheManager,\n PluginDatabaseManager,\n PluginEndpointDiscovery,\n TokenManager,\n UrlReader,\n} from '@backstage/backend-common';\nimport { Router } from 'express';\nimport { PluginTaskScheduler, TaskRunner } from '@backstage/backend-tasks';\nimport { IdentityApi } from '@backstage/plugin-auth-node';\nimport { PermissionEvaluator } from '@backstage/plugin-permission-common';\nimport {\n EventBroker,\n EventsService,\n HttpPostIngressOptions,\n} from '@backstage/plugin-events-node';\n\nimport { BackendFeature } from '@backstage/backend-plugin-api';\nimport { PackagePlatform, PackageRole } from '@backstage/cli-node';\nimport { CatalogBuilder } from '@backstage/plugin-catalog-backend';\nimport { TemplateAction } from '@backstage/plugin-scaffolder-node';\nimport { IndexBuilder } from '@backstage/plugin-search-backend-node';\nimport { EventsBackend } from '@backstage/plugin-events-backend';\nimport { PermissionPolicy } from '@backstage/plugin-permission-node';\n\n/**\n * @public\n *\n * @deprecated\n *\n * Support for the legacy backend system will be removed in the future.\n *\n * When adding a legacy plugin installer entrypoint in your plugin,\n * you should always take the opportunity to also implement support\n * for the new backend system if not already done.\n *\n */\nexport type LegacyPluginEnvironment = {\n logger: Logger;\n cache: PluginCacheManager;\n database: PluginDatabaseManager;\n config: Config;\n reader: UrlReader;\n discovery: PluginEndpointDiscovery;\n tokenManager: TokenManager;\n permissions: PermissionEvaluator;\n scheduler: PluginTaskScheduler;\n identity: IdentityApi;\n eventBroker: EventBroker;\n events: EventsService;\n pluginProvider: BackendPluginProvider;\n};\n\n/**\n * @public\n */\nexport interface DynamicPluginProvider\n extends FrontendPluginProvider,\n BackendPluginProvider {\n plugins(): DynamicPlugin[];\n}\n\n/**\n * @public\n */\nexport interface BackendPluginProvider {\n backendPlugins(): BackendDynamicPlugin[];\n}\n\n/**\n * @public\n */\nexport interface FrontendPluginProvider {\n frontendPlugins(): FrontendDynamicPlugin[];\n}\n\n/**\n * @public\n */\nexport interface BaseDynamicPlugin {\n name: string;\n version: string;\n role: PackageRole;\n platform: PackagePlatform;\n}\n\n/**\n * @public\n */\nexport type DynamicPlugin = FrontendDynamicPlugin | BackendDynamicPlugin;\n\n/**\n * @public\n */\nexport interface FrontendDynamicPlugin extends BaseDynamicPlugin {\n platform: 'web';\n}\n\n/**\n * @public\n */\nexport interface BackendDynamicPlugin extends BaseDynamicPlugin {\n platform: 'node';\n installer: BackendDynamicPluginInstaller;\n}\n\n/**\n * @public\n */\nexport type BackendDynamicPluginInstaller =\n | LegacyBackendPluginInstaller\n | NewBackendPluginInstaller;\n\n/**\n * @public\n */\nexport interface NewBackendPluginInstaller {\n kind: 'new';\n\n install(): BackendFeature | BackendFeature[];\n}\n\n/**\n * @public\n * @deprecated\n *\n * Support for the legacy backend system will be removed in the future.\n *\n * When adding a legacy plugin installer entrypoint in your plugin,\n * you should always take the opportunity to also implement support\n * for the new backend system if not already done.\n *\n */\nexport interface LegacyBackendPluginInstaller {\n kind: 'legacy';\n\n router?: {\n pluginID: string;\n createPlugin(env: LegacyPluginEnvironment): Promise<Router>;\n };\n\n catalog?(builder: CatalogBuilder, env: LegacyPluginEnvironment): void;\n scaffolder?(env: LegacyPluginEnvironment): TemplateAction<any>[];\n search?(\n indexBuilder: IndexBuilder,\n schedule: TaskRunner,\n env: LegacyPluginEnvironment,\n ): void;\n events?(\n eventsBackend: EventsBackend,\n env: LegacyPluginEnvironment,\n ): HttpPostIngressOptions[];\n permissions?: {\n policy?: PermissionPolicy;\n };\n}\n\n/**\n * @public\n */\nexport function isBackendDynamicPluginInstaller(\n obj: any,\n): obj is BackendDynamicPluginInstaller {\n return (\n obj !== undefined &&\n 'kind' in obj &&\n (obj.kind === 'new' || obj.kind === 'legacy')\n );\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Config } from '@backstage/config';\nimport { ScannedPluginPackage, ScannedPluginManifest } from './types';\nimport * as fs from 'fs/promises';\nimport { Stats, lstatSync, existsSync } from 'fs';\nimport * as chokidar from 'chokidar';\nimport * as path from 'path';\nimport * as url from 'url';\nimport debounce from 'lodash/debounce';\nimport { PackagePlatform, PackageRoles } from '@backstage/cli-node';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nexport interface DynamicPluginScannerOptions {\n config: Config;\n backstageRoot: string;\n logger: LoggerService;\n preferAlpha?: boolean;\n}\n\nexport interface ScanRootResponse {\n packages: ScannedPluginPackage[];\n}\n\nexport class PluginScanner {\n private _rootDirectory?: string;\n private configUnsubscribe?: () => void;\n private rootDirectoryWatcher?: chokidar.FSWatcher;\n private subscribers: (() => void)[] = [];\n\n private constructor(\n private readonly config: Config,\n private readonly logger: LoggerService,\n private readonly backstageRoot: string,\n private readonly preferAlpha: boolean,\n ) {}\n\n static create(options: DynamicPluginScannerOptions): PluginScanner {\n const scanner = new PluginScanner(\n options.config,\n options.logger,\n options.backstageRoot,\n options.preferAlpha || false,\n );\n scanner.applyConfig();\n return scanner;\n }\n\n subscribeToRootDirectoryChange(subscriber: () => void) {\n this.subscribers.push(subscriber);\n }\n\n get rootDirectory(): string | undefined {\n return this._rootDirectory;\n }\n\n private applyConfig(): void | never {\n const dynamicPlugins = this.config.getOptional('dynamicPlugins');\n if (!dynamicPlugins) {\n this.logger.info(\"'dynamicPlugins' config entry not found.\");\n this._rootDirectory = undefined;\n return;\n }\n if (typeof dynamicPlugins !== 'object') {\n this.logger.warn(\"'dynamicPlugins' config entry should be an object.\");\n this._rootDirectory = undefined;\n return;\n }\n if (!('rootDirectory' in dynamicPlugins)) {\n this.logger.warn(\n \"'dynamicPlugins' config entry does not contain the 'rootDirectory' field.\",\n );\n this._rootDirectory = undefined;\n return;\n }\n if (typeof dynamicPlugins.rootDirectory !== 'string') {\n this.logger.warn(\n \"'dynamicPlugins.rootDirectory' config entry should be a string.\",\n );\n this._rootDirectory = undefined;\n return;\n }\n\n const dynamicPluginsRootPath = path.isAbsolute(dynamicPlugins.rootDirectory)\n ? path.resolve(dynamicPlugins.rootDirectory)\n : path.resolve(this.backstageRoot, dynamicPlugins.rootDirectory);\n\n if (\n !path\n .dirname(dynamicPluginsRootPath)\n .startsWith(path.resolve(this.backstageRoot))\n ) {\n const nodePath = process.env.NODE_PATH;\n const backstageNodeModules = path.resolve(\n this.backstageRoot,\n 'node_modules',\n );\n if (\n !nodePath ||\n !nodePath.split(path.delimiter).includes(backstageNodeModules)\n ) {\n throw new Error(\n `Dynamic plugins under '${dynamicPluginsRootPath}' cannot access backstage modules in '${backstageNodeModules}'.\\n` +\n `Please add '${backstageNodeModules}' to the 'NODE_PATH' when running the backstage backend.`,\n );\n }\n }\n if (!lstatSync(dynamicPluginsRootPath).isDirectory()) {\n throw new Error('Not a directory');\n }\n\n this._rootDirectory = dynamicPluginsRootPath;\n }\n\n async scanRoot(): Promise<ScanRootResponse> {\n if (!this._rootDirectory) {\n return { packages: [] };\n }\n\n const dynamicPluginsLocation = this._rootDirectory;\n const scannedPlugins: ScannedPluginPackage[] = [];\n for (const dirEnt of await fs.readdir(dynamicPluginsLocation, {\n withFileTypes: true,\n })) {\n const pluginDir = dirEnt;\n\n if (pluginDir.name === 'lost+found') {\n this.logger.debug(`skipping '${pluginDir.name}' system directory`);\n continue;\n }\n const pluginHome = path.normalize(\n path.resolve(dynamicPluginsLocation, pluginDir.name),\n );\n if (dirEnt.isSymbolicLink()) {\n if (!(await fs.lstat(await fs.readlink(pluginHome))).isDirectory()) {\n this.logger.info(\n `skipping '${pluginHome}' since it is not a directory`,\n );\n continue;\n }\n } else if (!dirEnt.isDirectory()) {\n this.logger.info(\n `skipping '${pluginHome}' since it is not a directory`,\n );\n continue;\n }\n\n let scannedPlugin: ScannedPluginPackage;\n let platform: PackagePlatform;\n try {\n scannedPlugin = await this.scanDir(pluginHome);\n if (!scannedPlugin.manifest.main) {\n throw new Error(\"field 'main' not found in 'package.json'\");\n }\n if (scannedPlugin.manifest.backstage?.role) {\n platform = PackageRoles.getRoleInfo(\n scannedPlugin.manifest.backstage.role,\n ).platform;\n } else {\n throw new Error(\"field 'backstage.role' not found in 'package.json'\");\n }\n } catch (e) {\n this.logger.error(\n `failed to load dynamic plugin manifest from '${pluginHome}'`,\n e,\n );\n continue;\n }\n\n if (platform === 'node') {\n if (this.preferAlpha) {\n const pluginHomeAlpha = path.resolve(pluginHome, 'alpha');\n if (existsSync(pluginHomeAlpha)) {\n if ((await fs.lstat(pluginHomeAlpha)).isDirectory()) {\n const backstage = scannedPlugin.manifest.backstage;\n try {\n scannedPlugin = await this.scanDir(pluginHomeAlpha);\n } catch (e) {\n this.logger.error(\n `failed to load dynamic plugin manifest from '${pluginHomeAlpha}'`,\n e,\n );\n continue;\n }\n scannedPlugin.manifest.backstage = backstage;\n } else {\n this.logger.warn(\n `skipping '${pluginHomeAlpha}' since it is not a directory`,\n );\n }\n }\n }\n }\n\n scannedPlugins.push(scannedPlugin);\n }\n return { packages: scannedPlugins };\n }\n\n private async scanDir(pluginHome: string): Promise<ScannedPluginPackage> {\n const manifestFile = path.resolve(pluginHome, 'package.json');\n const content = await fs.readFile(manifestFile);\n const manifest: ScannedPluginManifest = JSON.parse(content.toString());\n return {\n location: url.pathToFileURL(pluginHome),\n manifest: manifest,\n };\n }\n\n async trackChanges(): Promise<void> {\n const setupRootDirectoryWatcher = async (): Promise<void> => {\n return new Promise((resolve, reject) => {\n if (!this._rootDirectory) {\n resolve();\n return;\n }\n const callSubscribers = debounce(() => {\n this.subscribers.forEach(s => s());\n }, 500);\n let ready = false;\n this.rootDirectoryWatcher = chokidar\n .watch(this._rootDirectory, {\n ignoreInitial: true,\n followSymlinks: true,\n depth: 1,\n disableGlobbing: true,\n })\n .on(\n 'all',\n (\n event: 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir',\n eventPath: string,\n _: Stats | undefined,\n ): void => {\n if (\n (['addDir', 'unlinkDir'].includes(event) &&\n path.dirname(eventPath) === this._rootDirectory) ||\n (['add', 'unlink', 'change'].includes(event) &&\n path.dirname(path.dirname(eventPath)) ===\n this._rootDirectory &&\n path.basename(eventPath) === 'package.json')\n ) {\n this.logger.info(\n `rootDirectory changed (${event} - ${eventPath}): scanning plugins again`,\n );\n callSubscribers();\n } else {\n this.logger.debug(\n `rootDirectory changed (${event} - ${eventPath}): no need to scan plugins again`,\n );\n }\n },\n )\n .on('error', (error: Error) => {\n this.logger.error(\n `error while watching '${this.rootDirectory}'`,\n error,\n );\n if (!ready) {\n reject(error);\n }\n })\n .on('ready', () => {\n ready = true;\n resolve();\n });\n });\n };\n\n await setupRootDirectoryWatcher();\n if (this.config.subscribe) {\n const { unsubscribe } = this.config.subscribe(async (): Promise<void> => {\n const oldRootDirectory = this._rootDirectory;\n try {\n this.applyConfig();\n } catch (e) {\n this.logger.error(\n 'failed to apply new config for dynamic plugins',\n e,\n );\n }\n if (oldRootDirectory !== this._rootDirectory) {\n this.logger.info(\n `rootDirectory changed in Config from '${oldRootDirectory}' to '${this._rootDirectory}'`,\n );\n this.subscribers.forEach(s => s());\n if (this.rootDirectoryWatcher) {\n await this.rootDirectoryWatcher.close();\n }\n await setupRootDirectoryWatcher();\n }\n });\n this.configUnsubscribe = unsubscribe;\n }\n }\n\n async untrackChanges() {\n if (this.rootDirectoryWatcher) {\n this.rootDirectoryWatcher.close();\n }\n if (this.configUnsubscribe) {\n this.configUnsubscribe();\n }\n }\n\n destructor() {\n this.untrackChanges();\n }\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ModuleLoader } from './types';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport path from 'path';\n\nexport class CommonJSModuleLoader implements ModuleLoader {\n constructor(public readonly logger: LoggerService) {}\n\n async bootstrap(\n backstageRoot: string,\n dynamicPluginsPaths: string[],\n ): Promise<void> {\n const backstageRootNodeModulesPath = `${backstageRoot}/node_modules`;\n const dynamicNodeModulesPaths = [\n ...dynamicPluginsPaths.map(p => path.resolve(p, 'node_modules')),\n ];\n const Module = require('module');\n const oldNodeModulePaths = Module._nodeModulePaths;\n Module._nodeModulePaths = (from: string): string[] => {\n const result: string[] = oldNodeModulePaths(from);\n if (!dynamicPluginsPaths.some(p => from.startsWith(p))) {\n return result;\n }\n const filtered = result.filter(nodeModulePath => {\n return (\n nodeModulePath === backstageRootNodeModulesPath ||\n dynamicNodeModulesPaths.some(p => nodeModulePath.startsWith(p))\n );\n });\n this.logger.debug(\n `Overriding node_modules search path for dynamic plugin ${from} to: ${filtered}`,\n );\n return filtered;\n };\n }\n\n async load(packagePath: string): Promise<any> {\n return await require(/* webpackIgnore: true */ packagePath);\n }\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Config } from '@backstage/config';\nimport {\n DynamicPluginProvider,\n BackendDynamicPlugin,\n isBackendDynamicPluginInstaller,\n DynamicPlugin,\n FrontendDynamicPlugin,\n} from './types';\nimport { ScannedPluginPackage } from '../scanner';\nimport { PluginScanner } from '../scanner/plugin-scanner';\nimport { ModuleLoader } from '../loader';\nimport { CommonJSModuleLoader } from '../loader/CommonJSModuleLoader';\nimport * as url from 'url';\nimport {\n BackendFeature,\n LoggerService,\n coreServices,\n createServiceFactory,\n createServiceRef,\n} from '@backstage/backend-plugin-api';\nimport { PackageRoles } from '@backstage/cli-node';\nimport { findPaths } from '@backstage/cli-common';\nimport path from 'path';\nimport * as fs from 'fs';\nimport {\n FeatureDiscoveryService,\n featureDiscoveryServiceRef,\n} from '@backstage/backend-plugin-api/alpha';\n\n/**\n * @public\n */\nexport interface DynamicPluginManagerOptions {\n config: Config;\n logger: LoggerService;\n preferAlpha?: boolean;\n moduleLoader?: ModuleLoader;\n}\n\n/**\n * @public\n */\nexport class DynamicPluginManager implements DynamicPluginProvider {\n static async create(\n options: DynamicPluginManagerOptions,\n ): Promise<DynamicPluginManager> {\n /* eslint-disable-next-line no-restricted-syntax */\n const backstageRoot = findPaths(__dirname).targetRoot;\n const scanner = PluginScanner.create({\n config: options.config,\n logger: options.logger,\n backstageRoot,\n preferAlpha: options.preferAlpha,\n });\n const scannedPlugins = (await scanner.scanRoot()).packages;\n scanner.trackChanges();\n const moduleLoader =\n options.moduleLoader || new CommonJSModuleLoader(options.logger);\n const manager = new DynamicPluginManager(\n options.logger,\n scannedPlugins,\n moduleLoader,\n );\n\n const dynamicPluginsPaths = scannedPlugins.map(p =>\n fs.realpathSync(\n path.dirname(\n path.dirname(\n path.resolve(url.fileURLToPath(p.location), p.manifest.main),\n ),\n ),\n ),\n );\n\n moduleLoader.bootstrap(backstageRoot, dynamicPluginsPaths);\n\n scanner.subscribeToRootDirectoryChange(async () => {\n manager._availablePackages = (await scanner.scanRoot()).packages;\n // TODO: do not store _scannedPlugins again, but instead store a diff of the changes\n });\n manager._plugins.push(...(await manager.loadPlugins()));\n\n return manager;\n }\n\n private readonly _plugins: DynamicPlugin[];\n private _availablePackages: ScannedPluginPackage[];\n\n private constructor(\n private readonly logger: LoggerService,\n private packages: ScannedPluginPackage[],\n private readonly moduleLoader: ModuleLoader,\n ) {\n this._plugins = [];\n this._availablePackages = packages;\n }\n\n get availablePackages(): ScannedPluginPackage[] {\n return this._availablePackages;\n }\n\n addBackendPlugin(plugin: BackendDynamicPlugin): void {\n this._plugins.push(plugin);\n }\n\n private async loadPlugins(): Promise<DynamicPlugin[]> {\n const loadedPlugins: DynamicPlugin[] = [];\n\n for (const scannedPlugin of this.packages) {\n const platform = PackageRoles.getRoleInfo(\n scannedPlugin.manifest.backstage.role,\n ).platform;\n\n if (\n platform === 'node' &&\n scannedPlugin.manifest.backstage.role.includes('-plugin')\n ) {\n const plugin = await this.loadBackendPlugin(scannedPlugin);\n if (plugin !== undefined) {\n loadedPlugins.push(plugin);\n }\n } else {\n loadedPlugins.push({\n name: scannedPlugin.manifest.name,\n version: scannedPlugin.manifest.version,\n role: scannedPlugin.manifest.backstage.role,\n platform: 'web',\n // TODO(davidfestal): add required front-end plugin information here.\n });\n }\n }\n return loadedPlugins;\n }\n\n private async loadBackendPlugin(\n plugin: ScannedPluginPackage,\n ): Promise<BackendDynamicPlugin | undefined> {\n const packagePath = url.fileURLToPath(\n `${plugin.location}/${plugin.manifest.main}`,\n );\n try {\n const pluginModule = await this.moduleLoader.load(packagePath);\n\n let dynamicPluginInstaller;\n if (isBackendFeature(pluginModule.default)) {\n dynamicPluginInstaller = {\n kind: 'new',\n install: () => pluginModule.default,\n };\n } else if (isBackendFeatureFactory(pluginModule.default)) {\n dynamicPluginInstaller = {\n kind: 'new',\n install: pluginModule.default,\n };\n } else {\n dynamicPluginInstaller = pluginModule.dynamicPluginInstaller;\n }\n if (!isBackendDynamicPluginInstaller(dynamicPluginInstaller)) {\n this.logger.error(\n `dynamic backend plugin '${plugin.manifest.name}' could not be loaded from '${plugin.location}': the module should either export a 'BackendFeature' or 'BackendFeatureFactory' as default export, or export a 'const dynamicPluginInstaller: BackendDynamicPluginInstaller' field as dynamic loading entrypoint.`,\n );\n return undefined;\n }\n this.logger.info(\n `loaded dynamic backend plugin '${plugin.manifest.name}' from '${plugin.location}'`,\n );\n return {\n name: plugin.manifest.name,\n version: plugin.manifest.version,\n platform: 'node',\n role: plugin.manifest.backstage.role,\n installer: dynamicPluginInstaller,\n };\n } catch (error) {\n this.logger.error(\n `an error occured while loading dynamic backend plugin '${plugin.manifest.name}' from '${plugin.location}'`,\n error,\n );\n return undefined;\n }\n }\n\n backendPlugins(): BackendDynamicPlugin[] {\n return this._plugins.filter(\n (p): p is BackendDynamicPlugin => p.platform === 'node',\n );\n }\n\n frontendPlugins(): FrontendDynamicPlugin[] {\n return this._plugins.filter(\n (p): p is FrontendDynamicPlugin => p.platform === 'web',\n );\n }\n\n plugins(): DynamicPlugin[] {\n return this._plugins;\n }\n}\n\n/**\n * @public\n */\nexport const dynamicPluginsServiceRef = createServiceRef<DynamicPluginProvider>(\n {\n id: 'core.dynamicplugins',\n scope: 'root',\n },\n);\n\n/**\n * @public\n */\nexport interface DynamicPluginsFactoryOptions {\n moduleLoader?(logger: LoggerService): ModuleLoader;\n}\n\n/**\n * @public\n */\nexport const dynamicPluginsServiceFactory = createServiceFactory(\n (options?: DynamicPluginsFactoryOptions) => ({\n service: dynamicPluginsServiceRef,\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.rootLogger,\n },\n async factory({ config, logger }) {\n return await DynamicPluginManager.create({\n config,\n logger,\n preferAlpha: true,\n moduleLoader: options?.moduleLoader?.(logger),\n });\n },\n }),\n);\n\nclass DynamicPluginsEnabledFeatureDiscoveryService\n implements FeatureDiscoveryService\n{\n constructor(\n private readonly dynamicPlugins: DynamicPluginProvider,\n private readonly featureDiscoveryService?: FeatureDiscoveryService,\n ) {}\n\n async getBackendFeatures(): Promise<{ features: Array<BackendFeature> }> {\n const staticFeatures =\n (await this.featureDiscoveryService?.getBackendFeatures())?.features ??\n [];\n\n return {\n features: [\n ...this.dynamicPlugins\n .backendPlugins()\n .flatMap((plugin): BackendFeature[] => {\n if (plugin.installer.kind === 'new') {\n const installed = plugin.installer.install();\n if (Array.isArray(installed)) {\n return installed;\n }\n return [installed];\n }\n return [];\n }),\n ...staticFeatures,\n ],\n };\n }\n}\n\n/**\n * @public\n */\nexport const dynamicPluginsFeatureDiscoveryServiceFactory =\n createServiceFactory({\n service: featureDiscoveryServiceRef,\n deps: {\n config: coreServices.rootConfig,\n dynamicPlugins: dynamicPluginsServiceRef,\n },\n factory({ dynamicPlugins }) {\n return new DynamicPluginsEnabledFeatureDiscoveryService(dynamicPlugins);\n },\n });\n\nfunction isBackendFeature(value: unknown): value is BackendFeature {\n return (\n !!value &&\n typeof value === 'object' &&\n (value as BackendFeature).$$type === '@backstage/BackendFeature'\n );\n}\n\nfunction isBackendFeatureFactory(\n value: unknown,\n): value is () => BackendFeature {\n return (\n !!value &&\n typeof value === 'function' &&\n (value as any).$$type === '@backstage/BackendFeatureFactory'\n );\n}\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ScannedPluginPackage } from '../scanner/types';\nimport {\n coreServices,\n createServiceFactory,\n createServiceRef,\n} from '@backstage/backend-plugin-api';\nimport { findPaths } from '@backstage/cli-common';\n\nimport fs from 'fs-extra';\nimport * as path from 'path';\nimport * as url from 'url';\nimport { isEmpty } from 'lodash';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { JsonObject } from '@backstage/types';\nimport { PluginScanner } from '../scanner/plugin-scanner';\nimport { ConfigSchema, loadConfigSchema } from '@backstage/config-loader';\n\n/**\n *\n * @public\n * */\nexport interface DynamicPluginsSchemasService {\n addDynamicPluginsSchemas(configSchema: ConfigSchema): Promise<{\n schema: ConfigSchema;\n }>;\n}\n\n/**\n * A service that provides the config schemas of scanned dynamic plugins.\n *\n * @public\n */\nexport const dynamicPluginsSchemasServiceRef =\n createServiceRef<DynamicPluginsSchemasService>({\n id: 'core.dynamicplugins.schemas',\n scope: 'root',\n });\n\n/**\n * @public\n */\nexport interface DynamicPluginsSchemasOptions {\n /**\n * Function that returns the path to the Json schema file for a given scanned plugin package.\n * The path is either absolute, or relative to the plugin package root directory.\n *\n * Default behavior is to look for the `dist/configSchema.json` relative path.\n *\n * @param pluginPackage - The scanned plugin package.\n * @returns the absolute or plugin-relative path to the Json schema file.\n */\n schemaLocator?: (pluginPackage: ScannedPluginPackage) => string;\n}\n\n/**\n * @public\n */\nexport const dynamicPluginsSchemasServiceFactory = createServiceFactory(\n (options?: DynamicPluginsSchemasOptions) => ({\n service: dynamicPluginsSchemasServiceRef,\n deps: {\n config: coreServices.rootConfig,\n },\n factory({ config }) {\n let additionalSchemas: { [context: string]: JsonObject } | undefined;\n\n return {\n async addDynamicPluginsSchemas(configSchema: ConfigSchema): Promise<{\n schema: ConfigSchema;\n }> {\n if (!additionalSchemas) {\n const logger = {\n ...console,\n child() {\n return this;\n },\n };\n\n const scanner = PluginScanner.create({\n config,\n logger,\n // eslint-disable-next-line no-restricted-syntax\n backstageRoot: findPaths(__dirname).targetRoot,\n preferAlpha: true,\n });\n\n const { packages } = await scanner.scanRoot();\n\n additionalSchemas = await gatherDynamicPluginsSchemas(\n packages,\n logger,\n options?.schemaLocator,\n );\n }\n\n const serialized = configSchema.serialize();\n if (serialized?.backstageConfigSchemaVersion !== 1) {\n throw new Error(\n 'Serialized configuration schema is invalid or has an invalid version number',\n );\n }\n const schemas = serialized.schemas as {\n value: JsonObject;\n path: string;\n }[];\n\n schemas.push(\n ...Object.keys(additionalSchemas).map(context => {\n return {\n path: context,\n value: additionalSchemas![context],\n };\n }),\n );\n serialized.schemas = schemas;\n return {\n schema: await loadConfigSchema({\n serialized,\n }),\n };\n },\n };\n },\n }),\n);\n\n/** @internal */\nasync function gatherDynamicPluginsSchemas(\n packages: ScannedPluginPackage[],\n logger: LoggerService,\n schemaLocator: (pluginPackage: ScannedPluginPackage) => string = () =>\n path.join('dist', 'configSchema.json'),\n): Promise<{ [context: string]: JsonObject }> {\n const allSchemas: { [context: string]: JsonObject } = {};\n\n for (const pluginPackage of packages) {\n let schemaLocation = schemaLocator(pluginPackage);\n\n if (!path.isAbsolute(schemaLocation)) {\n let pluginLocation = url.fileURLToPath(pluginPackage.location);\n if (path.basename(pluginLocation) === 'alpha') {\n pluginLocation = path.dirname(pluginLocation);\n }\n schemaLocation = path.resolve(pluginLocation, schemaLocation);\n }\n\n if (!(await fs.pathExists(schemaLocation))) {\n continue;\n }\n\n const serialized = await fs.readJson(schemaLocation);\n if (!serialized) {\n continue;\n }\n\n if (isEmpty(serialized)) {\n continue;\n }\n\n if (!serialized?.$schema || serialized?.type !== 'object') {\n logger.error(\n `Serialized configuration schema is invalid for plugin ${pluginPackage.manifest.name}`,\n );\n continue;\n }\n\n allSchemas[schemaLocation] = serialized;\n }\n\n return allSchemas;\n}\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createBackendModule,\n} from '@backstage/backend-plugin-api';\nimport { dynamicPluginsSchemasServiceRef } from './schemas';\nimport {\n configSchemaExtensionPoint,\n loadCompiledConfigSchema,\n} from '@backstage/plugin-app-node';\nimport { resolvePackagePath } from '@backstage/backend-common';\n\n/** @public */\nexport const dynamicPluginsFrontendSchemas = createBackendModule({\n pluginId: 'app',\n moduleId: 'core.dynamicplugins.frontendSchemas',\n register(reg) {\n reg.registerInit({\n deps: {\n config: coreServices.rootConfig,\n schemas: dynamicPluginsSchemasServiceRef,\n configSchemaExtension: configSchemaExtensionPoint,\n },\n async init({ config, schemas, configSchemaExtension }) {\n const appPackageName =\n config.getOptionalString('app.packageName') ?? 'app';\n const appDistDir = resolvePackagePath(appPackageName, 'dist');\n const compiledConfigSchema = await loadCompiledConfigSchema(appDistDir);\n if (compiledConfigSchema) {\n configSchemaExtension.setConfigSchema(\n (await schemas.addDynamicPluginsSchemas(compiledConfigSchema))\n .schema,\n );\n }\n },\n });\n },\n});\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createServiceFactory,\n coreServices,\n} from '@backstage/backend-plugin-api';\nimport { WinstonLogger } from '@backstage/backend-app-api';\nimport { transports, format } from 'winston';\nimport { createConfigSecretEnumerator } from '@backstage/backend-app-api';\nimport { loadConfigSchema } from '@backstage/config-loader';\nimport { getPackages } from '@manypkg/get-packages';\nimport { dynamicPluginsSchemasServiceRef } from './schemas';\n\n/** @public */\nexport const dynamicPluginsRootLoggerServiceFactory = createServiceFactory({\n service: coreServices.rootLogger,\n deps: {\n config: coreServices.rootConfig,\n schemas: dynamicPluginsSchemasServiceRef,\n },\n async factory({ config, schemas }) {\n const logger = WinstonLogger.create({\n meta: {\n service: 'backstage',\n },\n level: process.env.LOG_LEVEL || 'info',\n format:\n process.env.NODE_ENV === 'production'\n ? format.json()\n : WinstonLogger.colorFormat(),\n transports: [new transports.Console()],\n });\n\n const configSchema = await loadConfigSchema({\n dependencies: (\n await getPackages(process.cwd())\n ).packages.map(p => p.packageJson.name),\n });\n\n const secretEnumerator = await createConfigSecretEnumerator({\n logger,\n schema: (await schemas.addDynamicPluginsSchemas(configSchema)).schema,\n });\n logger.addRedactions(secretEnumerator(config));\n config.subscribe?.(() => logger.addRedactions(secretEnumerator(config)));\n\n return logger;\n },\n});\n"],"names":["__publicField","path","lstatSync","fs","PackageRoles","existsSync","url","debounce","chokidar","findPaths","createServiceRef","createServiceFactory","coreServices","featureDiscoveryServiceRef","loadConfigSchema","isEmpty","createBackendModule","configSchemaExtensionPoint","resolvePackagePath","loadCompiledConfigSchema","WinstonLogger","format","transports","getPackages","createConfigSecretEnumerator"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/manager/types.ts","../src/scanner/plugin-scanner.ts","../src/loader/CommonJSModuleLoader.ts","../src/manager/plugin-manager.ts","../src/schemas/schemas.ts","../src/schemas/appBackendModule.ts","../src/schemas/rootLoggerServiceFactory.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from 'winston';\nimport { Config } from '@backstage/config';\nimport {\n PluginCacheManager,\n PluginDatabaseManager,\n PluginEndpointDiscovery,\n TokenManager,\n UrlReader,\n} from '@backstage/backend-common';\nimport { Router } from 'express';\nimport { PluginTaskScheduler, TaskRunner } from '@backstage/backend-tasks';\nimport { IdentityApi } from '@backstage/plugin-auth-node';\nimport { PermissionEvaluator } from '@backstage/plugin-permission-common';\nimport {\n EventBroker,\n EventsService,\n HttpPostIngressOptions,\n} from '@backstage/plugin-events-node';\n\nimport { BackendFeature } from '@backstage/backend-plugin-api';\nimport { PackagePlatform, PackageRole } from '@backstage/cli-node';\nimport { CatalogBuilder } from '@backstage/plugin-catalog-backend';\nimport { TemplateAction } from '@backstage/plugin-scaffolder-node';\nimport { IndexBuilder } from '@backstage/plugin-search-backend-node';\nimport { EventsBackend } from '@backstage/plugin-events-backend';\nimport { PermissionPolicy } from '@backstage/plugin-permission-node';\n\n/**\n * @public\n *\n * @deprecated\n *\n * Support for the legacy backend system will be removed in the future.\n *\n * When adding a legacy plugin installer entrypoint in your plugin,\n * you should always take the opportunity to also implement support\n * for the new backend system if not already done.\n *\n */\nexport type LegacyPluginEnvironment = {\n logger: Logger;\n cache: PluginCacheManager;\n database: PluginDatabaseManager;\n config: Config;\n reader: UrlReader;\n discovery: PluginEndpointDiscovery;\n tokenManager: TokenManager;\n permissions: PermissionEvaluator;\n scheduler: PluginTaskScheduler;\n identity: IdentityApi;\n eventBroker: EventBroker;\n events: EventsService;\n pluginProvider: BackendPluginProvider;\n};\n\n/**\n * @public\n */\nexport interface DynamicPluginProvider\n extends FrontendPluginProvider,\n BackendPluginProvider {\n plugins(): DynamicPlugin[];\n}\n\n/**\n * @public\n */\nexport interface BackendPluginProvider {\n backendPlugins(): BackendDynamicPlugin[];\n}\n\n/**\n * @public\n */\nexport interface FrontendPluginProvider {\n frontendPlugins(): FrontendDynamicPlugin[];\n}\n\n/**\n * @public\n */\nexport interface BaseDynamicPlugin {\n name: string;\n version: string;\n role: PackageRole;\n platform: PackagePlatform;\n}\n\n/**\n * @public\n */\nexport type DynamicPlugin = FrontendDynamicPlugin | BackendDynamicPlugin;\n\n/**\n * @public\n */\nexport interface FrontendDynamicPlugin extends BaseDynamicPlugin {\n platform: 'web';\n}\n\n/**\n * @public\n */\nexport interface BackendDynamicPlugin extends BaseDynamicPlugin {\n platform: 'node';\n installer: BackendDynamicPluginInstaller;\n}\n\n/**\n * @public\n */\nexport type BackendDynamicPluginInstaller =\n | LegacyBackendPluginInstaller\n | NewBackendPluginInstaller;\n\n/**\n * @public\n */\nexport interface NewBackendPluginInstaller {\n kind: 'new';\n\n install(): BackendFeature | BackendFeature[];\n}\n\n/**\n * @public\n * @deprecated\n *\n * Support for the legacy backend system will be removed in the future.\n *\n * When adding a legacy plugin installer entrypoint in your plugin,\n * you should always take the opportunity to also implement support\n * for the new backend system if not already done.\n *\n */\nexport interface LegacyBackendPluginInstaller {\n kind: 'legacy';\n\n router?: {\n pluginID: string;\n createPlugin(env: LegacyPluginEnvironment): Promise<Router>;\n };\n\n catalog?(builder: CatalogBuilder, env: LegacyPluginEnvironment): void;\n scaffolder?(env: LegacyPluginEnvironment): TemplateAction<any>[];\n search?(\n indexBuilder: IndexBuilder,\n schedule: TaskRunner,\n env: LegacyPluginEnvironment,\n ): void;\n events?(\n eventsBackend: EventsBackend,\n env: LegacyPluginEnvironment,\n ): HttpPostIngressOptions[];\n permissions?: {\n policy?: PermissionPolicy;\n };\n}\n\n/**\n * @public\n */\nexport function isBackendDynamicPluginInstaller(\n obj: any,\n): obj is BackendDynamicPluginInstaller {\n return (\n obj !== undefined &&\n 'kind' in obj &&\n (obj.kind === 'new' || obj.kind === 'legacy')\n );\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Config } from '@backstage/config';\nimport { ScannedPluginPackage, ScannedPluginManifest } from './types';\nimport * as fs from 'fs/promises';\nimport { Stats, lstatSync, existsSync } from 'fs';\nimport * as chokidar from 'chokidar';\nimport * as path from 'path';\nimport * as url from 'url';\nimport debounce from 'lodash/debounce';\nimport { PackagePlatform, PackageRoles } from '@backstage/cli-node';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nexport interface DynamicPluginScannerOptions {\n config: Config;\n backstageRoot: string;\n logger: LoggerService;\n preferAlpha?: boolean;\n}\n\nexport interface ScanRootResponse {\n packages: ScannedPluginPackage[];\n}\n\nexport class PluginScanner {\n private _rootDirectory?: string;\n private configUnsubscribe?: () => void;\n private rootDirectoryWatcher?: chokidar.FSWatcher;\n private subscribers: (() => void)[] = [];\n\n private constructor(\n private readonly config: Config,\n private readonly logger: LoggerService,\n private readonly backstageRoot: string,\n private readonly preferAlpha: boolean,\n ) {}\n\n static create(options: DynamicPluginScannerOptions): PluginScanner {\n const scanner = new PluginScanner(\n options.config,\n options.logger,\n options.backstageRoot,\n options.preferAlpha || false,\n );\n scanner.applyConfig();\n return scanner;\n }\n\n subscribeToRootDirectoryChange(subscriber: () => void) {\n this.subscribers.push(subscriber);\n }\n\n get rootDirectory(): string | undefined {\n return this._rootDirectory;\n }\n\n private applyConfig(): void | never {\n const dynamicPlugins = this.config.getOptional('dynamicPlugins');\n if (!dynamicPlugins) {\n this.logger.info(\"'dynamicPlugins' config entry not found.\");\n this._rootDirectory = undefined;\n return;\n }\n if (typeof dynamicPlugins !== 'object') {\n this.logger.warn(\"'dynamicPlugins' config entry should be an object.\");\n this._rootDirectory = undefined;\n return;\n }\n if (!('rootDirectory' in dynamicPlugins)) {\n this.logger.warn(\n \"'dynamicPlugins' config entry does not contain the 'rootDirectory' field.\",\n );\n this._rootDirectory = undefined;\n return;\n }\n if (typeof dynamicPlugins.rootDirectory !== 'string') {\n this.logger.warn(\n \"'dynamicPlugins.rootDirectory' config entry should be a string.\",\n );\n this._rootDirectory = undefined;\n return;\n }\n\n const dynamicPluginsRootPath = path.isAbsolute(dynamicPlugins.rootDirectory)\n ? path.resolve(dynamicPlugins.rootDirectory)\n : path.resolve(this.backstageRoot, dynamicPlugins.rootDirectory);\n\n if (\n !path\n .dirname(dynamicPluginsRootPath)\n .startsWith(path.resolve(this.backstageRoot))\n ) {\n const nodePath = process.env.NODE_PATH;\n const backstageNodeModules = path.resolve(\n this.backstageRoot,\n 'node_modules',\n );\n if (\n !nodePath ||\n !nodePath.split(path.delimiter).includes(backstageNodeModules)\n ) {\n throw new Error(\n `Dynamic plugins under '${dynamicPluginsRootPath}' cannot access backstage modules in '${backstageNodeModules}'.\\n` +\n `Please add '${backstageNodeModules}' to the 'NODE_PATH' when running the backstage backend.`,\n );\n }\n }\n if (!lstatSync(dynamicPluginsRootPath).isDirectory()) {\n throw new Error('Not a directory');\n }\n\n this._rootDirectory = dynamicPluginsRootPath;\n }\n\n async scanRoot(): Promise<ScanRootResponse> {\n if (!this._rootDirectory) {\n return { packages: [] };\n }\n\n const dynamicPluginsLocation = this._rootDirectory;\n const scannedPlugins: ScannedPluginPackage[] = [];\n for (const dirEnt of await fs.readdir(dynamicPluginsLocation, {\n withFileTypes: true,\n })) {\n const pluginDir = dirEnt;\n\n if (pluginDir.name === 'lost+found') {\n this.logger.debug(`skipping '${pluginDir.name}' system directory`);\n continue;\n }\n const pluginHome = path.normalize(\n path.resolve(dynamicPluginsLocation, pluginDir.name),\n );\n if (dirEnt.isSymbolicLink()) {\n if (!(await fs.lstat(await fs.readlink(pluginHome))).isDirectory()) {\n this.logger.info(\n `skipping '${pluginHome}' since it is not a directory`,\n );\n continue;\n }\n } else if (!dirEnt.isDirectory()) {\n this.logger.info(\n `skipping '${pluginHome}' since it is not a directory`,\n );\n continue;\n }\n\n let scannedPlugin: ScannedPluginPackage;\n let platform: PackagePlatform;\n try {\n scannedPlugin = await this.scanDir(pluginHome);\n if (!scannedPlugin.manifest.main) {\n throw new Error(\"field 'main' not found in 'package.json'\");\n }\n if (scannedPlugin.manifest.backstage?.role) {\n platform = PackageRoles.getRoleInfo(\n scannedPlugin.manifest.backstage.role,\n ).platform;\n } else {\n throw new Error(\"field 'backstage.role' not found in 'package.json'\");\n }\n } catch (e) {\n this.logger.error(\n `failed to load dynamic plugin manifest from '${pluginHome}'`,\n e,\n );\n continue;\n }\n\n if (platform === 'node') {\n if (this.preferAlpha) {\n const pluginHomeAlpha = path.resolve(pluginHome, 'alpha');\n if (existsSync(pluginHomeAlpha)) {\n if ((await fs.lstat(pluginHomeAlpha)).isDirectory()) {\n const backstage = scannedPlugin.manifest.backstage;\n try {\n scannedPlugin = await this.scanDir(pluginHomeAlpha);\n } catch (e) {\n this.logger.error(\n `failed to load dynamic plugin manifest from '${pluginHomeAlpha}'`,\n e,\n );\n continue;\n }\n scannedPlugin.manifest.backstage = backstage;\n } else {\n this.logger.warn(\n `skipping '${pluginHomeAlpha}' since it is not a directory`,\n );\n }\n }\n }\n }\n\n scannedPlugins.push(scannedPlugin);\n }\n return { packages: scannedPlugins };\n }\n\n private async scanDir(pluginHome: string): Promise<ScannedPluginPackage> {\n const manifestFile = path.resolve(pluginHome, 'package.json');\n const content = await fs.readFile(manifestFile);\n const manifest: ScannedPluginManifest = JSON.parse(content.toString());\n return {\n location: url.pathToFileURL(pluginHome),\n manifest: manifest,\n };\n }\n\n async trackChanges(): Promise<void> {\n const setupRootDirectoryWatcher = async (): Promise<void> => {\n return new Promise((resolve, reject) => {\n if (!this._rootDirectory) {\n resolve();\n return;\n }\n const callSubscribers = debounce(() => {\n this.subscribers.forEach(s => s());\n }, 500);\n let ready = false;\n this.rootDirectoryWatcher = chokidar\n .watch(this._rootDirectory, {\n ignoreInitial: true,\n followSymlinks: true,\n depth: 1,\n disableGlobbing: true,\n })\n .on(\n 'all',\n (\n event: 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir',\n eventPath: string,\n _: Stats | undefined,\n ): void => {\n if (\n (['addDir', 'unlinkDir'].includes(event) &&\n path.dirname(eventPath) === this._rootDirectory) ||\n (['add', 'unlink', 'change'].includes(event) &&\n path.dirname(path.dirname(eventPath)) ===\n this._rootDirectory &&\n path.basename(eventPath) === 'package.json')\n ) {\n this.logger.info(\n `rootDirectory changed (${event} - ${eventPath}): scanning plugins again`,\n );\n callSubscribers();\n } else {\n this.logger.debug(\n `rootDirectory changed (${event} - ${eventPath}): no need to scan plugins again`,\n );\n }\n },\n )\n .on('error', (error: Error) => {\n this.logger.error(\n `error while watching '${this.rootDirectory}'`,\n error,\n );\n if (!ready) {\n reject(error);\n }\n })\n .on('ready', () => {\n ready = true;\n resolve();\n });\n });\n };\n\n await setupRootDirectoryWatcher();\n if (this.config.subscribe) {\n const { unsubscribe } = this.config.subscribe(async (): Promise<void> => {\n const oldRootDirectory = this._rootDirectory;\n try {\n this.applyConfig();\n } catch (e) {\n this.logger.error(\n 'failed to apply new config for dynamic plugins',\n e,\n );\n }\n if (oldRootDirectory !== this._rootDirectory) {\n this.logger.info(\n `rootDirectory changed in Config from '${oldRootDirectory}' to '${this._rootDirectory}'`,\n );\n this.subscribers.forEach(s => s());\n if (this.rootDirectoryWatcher) {\n await this.rootDirectoryWatcher.close();\n }\n await setupRootDirectoryWatcher();\n }\n });\n this.configUnsubscribe = unsubscribe;\n }\n }\n\n async untrackChanges() {\n if (this.rootDirectoryWatcher) {\n this.rootDirectoryWatcher.close();\n }\n if (this.configUnsubscribe) {\n this.configUnsubscribe();\n }\n }\n\n destructor() {\n this.untrackChanges();\n }\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ModuleLoader } from './types';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport path from 'path';\n\nexport class CommonJSModuleLoader implements ModuleLoader {\n constructor(public readonly logger: LoggerService) {}\n\n async bootstrap(\n backstageRoot: string,\n dynamicPluginsPaths: string[],\n ): Promise<void> {\n const backstageRootNodeModulesPath = `${backstageRoot}/node_modules`;\n const dynamicNodeModulesPaths = [\n ...dynamicPluginsPaths.map(p => path.resolve(p, 'node_modules')),\n ];\n const Module = require('module');\n const oldNodeModulePaths = Module._nodeModulePaths;\n Module._nodeModulePaths = (from: string): string[] => {\n const result: string[] = oldNodeModulePaths(from);\n if (!dynamicPluginsPaths.some(p => from.startsWith(p))) {\n return result;\n }\n const filtered = result.filter(nodeModulePath => {\n return (\n nodeModulePath === backstageRootNodeModulesPath ||\n dynamicNodeModulesPaths.some(p => nodeModulePath.startsWith(p))\n );\n });\n this.logger.debug(\n `Overriding node_modules search path for dynamic plugin ${from} to: ${filtered}`,\n );\n return filtered;\n };\n }\n\n async load(packagePath: string): Promise<any> {\n return await require(/* webpackIgnore: true */ packagePath);\n }\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Config } from '@backstage/config';\nimport {\n DynamicPluginProvider,\n BackendDynamicPlugin,\n isBackendDynamicPluginInstaller,\n DynamicPlugin,\n FrontendDynamicPlugin,\n} from './types';\nimport { ScannedPluginPackage } from '../scanner';\nimport { PluginScanner } from '../scanner/plugin-scanner';\nimport { ModuleLoader } from '../loader';\nimport { CommonJSModuleLoader } from '../loader/CommonJSModuleLoader';\nimport * as url from 'url';\nimport {\n BackendFeature,\n LoggerService,\n coreServices,\n createServiceFactory,\n createServiceRef,\n} from '@backstage/backend-plugin-api';\nimport { PackageRoles } from '@backstage/cli-node';\nimport { findPaths } from '@backstage/cli-common';\nimport path from 'path';\nimport * as fs from 'fs';\nimport {\n FeatureDiscoveryService,\n featureDiscoveryServiceRef,\n} from '@backstage/backend-plugin-api/alpha';\n\n/**\n * @public\n */\nexport interface DynamicPluginManagerOptions {\n config: Config;\n logger: LoggerService;\n preferAlpha?: boolean;\n moduleLoader?: ModuleLoader;\n}\n\n/**\n * @public\n */\nexport class DynamicPluginManager implements DynamicPluginProvider {\n static async create(\n options: DynamicPluginManagerOptions,\n ): Promise<DynamicPluginManager> {\n /* eslint-disable-next-line no-restricted-syntax */\n const backstageRoot = findPaths(__dirname).targetRoot;\n const scanner = PluginScanner.create({\n config: options.config,\n logger: options.logger,\n backstageRoot,\n preferAlpha: options.preferAlpha,\n });\n const scannedPlugins = (await scanner.scanRoot()).packages;\n scanner.trackChanges();\n const moduleLoader =\n options.moduleLoader || new CommonJSModuleLoader(options.logger);\n const manager = new DynamicPluginManager(\n options.logger,\n scannedPlugins,\n moduleLoader,\n );\n\n const dynamicPluginsPaths = scannedPlugins.map(p =>\n fs.realpathSync(\n path.dirname(\n path.dirname(\n path.resolve(url.fileURLToPath(p.location), p.manifest.main),\n ),\n ),\n ),\n );\n\n moduleLoader.bootstrap(backstageRoot, dynamicPluginsPaths);\n\n scanner.subscribeToRootDirectoryChange(async () => {\n manager._availablePackages = (await scanner.scanRoot()).packages;\n // TODO: do not store _scannedPlugins again, but instead store a diff of the changes\n });\n manager._plugins.push(...(await manager.loadPlugins()));\n\n return manager;\n }\n\n private readonly _plugins: DynamicPlugin[];\n private _availablePackages: ScannedPluginPackage[];\n\n private constructor(\n private readonly logger: LoggerService,\n private packages: ScannedPluginPackage[],\n private readonly moduleLoader: ModuleLoader,\n ) {\n this._plugins = [];\n this._availablePackages = packages;\n }\n\n get availablePackages(): ScannedPluginPackage[] {\n return this._availablePackages;\n }\n\n addBackendPlugin(plugin: BackendDynamicPlugin): void {\n this._plugins.push(plugin);\n }\n\n private async loadPlugins(): Promise<DynamicPlugin[]> {\n const loadedPlugins: DynamicPlugin[] = [];\n\n for (const scannedPlugin of this.packages) {\n const platform = PackageRoles.getRoleInfo(\n scannedPlugin.manifest.backstage.role,\n ).platform;\n\n if (\n platform === 'node' &&\n scannedPlugin.manifest.backstage.role.includes('-plugin')\n ) {\n const plugin = await this.loadBackendPlugin(scannedPlugin);\n if (plugin !== undefined) {\n loadedPlugins.push(plugin);\n }\n } else {\n loadedPlugins.push({\n name: scannedPlugin.manifest.name,\n version: scannedPlugin.manifest.version,\n role: scannedPlugin.manifest.backstage.role,\n platform: 'web',\n // TODO(davidfestal): add required front-end plugin information here.\n });\n }\n }\n return loadedPlugins;\n }\n\n private async loadBackendPlugin(\n plugin: ScannedPluginPackage,\n ): Promise<BackendDynamicPlugin | undefined> {\n const packagePath = url.fileURLToPath(\n `${plugin.location}/${plugin.manifest.main}`,\n );\n try {\n const pluginModule = await this.moduleLoader.load(packagePath);\n\n let dynamicPluginInstaller;\n if (isBackendFeature(pluginModule.default)) {\n dynamicPluginInstaller = {\n kind: 'new',\n install: () => pluginModule.default,\n };\n } else if (isBackendFeatureFactory(pluginModule.default)) {\n dynamicPluginInstaller = {\n kind: 'new',\n install: pluginModule.default,\n };\n } else {\n dynamicPluginInstaller = pluginModule.dynamicPluginInstaller;\n }\n if (!isBackendDynamicPluginInstaller(dynamicPluginInstaller)) {\n this.logger.error(\n `dynamic backend plugin '${plugin.manifest.name}' could not be loaded from '${plugin.location}': the module should either export a 'BackendFeature' or 'BackendFeatureFactory' as default export, or export a 'const dynamicPluginInstaller: BackendDynamicPluginInstaller' field as dynamic loading entrypoint.`,\n );\n return undefined;\n }\n this.logger.info(\n `loaded dynamic backend plugin '${plugin.manifest.name}' from '${plugin.location}'`,\n );\n return {\n name: plugin.manifest.name,\n version: plugin.manifest.version,\n platform: 'node',\n role: plugin.manifest.backstage.role,\n installer: dynamicPluginInstaller,\n };\n } catch (error) {\n this.logger.error(\n `an error occurred while loading dynamic backend plugin '${plugin.manifest.name}' from '${plugin.location}'`,\n error,\n );\n return undefined;\n }\n }\n\n backendPlugins(): BackendDynamicPlugin[] {\n return this._plugins.filter(\n (p): p is BackendDynamicPlugin => p.platform === 'node',\n );\n }\n\n frontendPlugins(): FrontendDynamicPlugin[] {\n return this._plugins.filter(\n (p): p is FrontendDynamicPlugin => p.platform === 'web',\n );\n }\n\n plugins(): DynamicPlugin[] {\n return this._plugins;\n }\n}\n\n/**\n * @public\n */\nexport const dynamicPluginsServiceRef = createServiceRef<DynamicPluginProvider>(\n {\n id: 'core.dynamicplugins',\n scope: 'root',\n },\n);\n\n/**\n * @public\n */\nexport interface DynamicPluginsFactoryOptions {\n moduleLoader?(logger: LoggerService): ModuleLoader;\n}\n\n/**\n * @public\n */\nexport const dynamicPluginsServiceFactory = createServiceFactory(\n (options?: DynamicPluginsFactoryOptions) => ({\n service: dynamicPluginsServiceRef,\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.rootLogger,\n },\n async factory({ config, logger }) {\n return await DynamicPluginManager.create({\n config,\n logger,\n preferAlpha: true,\n moduleLoader: options?.moduleLoader?.(logger),\n });\n },\n }),\n);\n\nclass DynamicPluginsEnabledFeatureDiscoveryService\n implements FeatureDiscoveryService\n{\n constructor(\n private readonly dynamicPlugins: DynamicPluginProvider,\n private readonly featureDiscoveryService?: FeatureDiscoveryService,\n ) {}\n\n async getBackendFeatures(): Promise<{ features: Array<BackendFeature> }> {\n const staticFeatures =\n (await this.featureDiscoveryService?.getBackendFeatures())?.features ??\n [];\n\n return {\n features: [\n ...this.dynamicPlugins\n .backendPlugins()\n .flatMap((plugin): BackendFeature[] => {\n if (plugin.installer.kind === 'new') {\n const installed = plugin.installer.install();\n if (Array.isArray(installed)) {\n return installed;\n }\n return [installed];\n }\n return [];\n }),\n ...staticFeatures,\n ],\n };\n }\n}\n\n/**\n * @public\n */\nexport const dynamicPluginsFeatureDiscoveryServiceFactory =\n createServiceFactory({\n service: featureDiscoveryServiceRef,\n deps: {\n config: coreServices.rootConfig,\n dynamicPlugins: dynamicPluginsServiceRef,\n },\n factory({ dynamicPlugins }) {\n return new DynamicPluginsEnabledFeatureDiscoveryService(dynamicPlugins);\n },\n });\n\nfunction isBackendFeature(value: unknown): value is BackendFeature {\n return (\n !!value &&\n typeof value === 'object' &&\n (value as BackendFeature).$$type === '@backstage/BackendFeature'\n );\n}\n\nfunction isBackendFeatureFactory(\n value: unknown,\n): value is () => BackendFeature {\n return (\n !!value &&\n typeof value === 'function' &&\n (value as any).$$type === '@backstage/BackendFeatureFactory'\n );\n}\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ScannedPluginPackage } from '../scanner/types';\nimport {\n coreServices,\n createServiceFactory,\n createServiceRef,\n} from '@backstage/backend-plugin-api';\nimport { findPaths } from '@backstage/cli-common';\n\nimport fs from 'fs-extra';\nimport * as path from 'path';\nimport * as url from 'url';\nimport { isEmpty } from 'lodash';\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { JsonObject } from '@backstage/types';\nimport { PluginScanner } from '../scanner/plugin-scanner';\nimport { ConfigSchema, loadConfigSchema } from '@backstage/config-loader';\n\n/**\n *\n * @public\n * */\nexport interface DynamicPluginsSchemasService {\n addDynamicPluginsSchemas(configSchema: ConfigSchema): Promise<{\n schema: ConfigSchema;\n }>;\n}\n\n/**\n * A service that provides the config schemas of scanned dynamic plugins.\n *\n * @public\n */\nexport const dynamicPluginsSchemasServiceRef =\n createServiceRef<DynamicPluginsSchemasService>({\n id: 'core.dynamicplugins.schemas',\n scope: 'root',\n });\n\n/**\n * @public\n */\nexport interface DynamicPluginsSchemasOptions {\n /**\n * Function that returns the path to the Json schema file for a given scanned plugin package.\n * The path is either absolute, or relative to the plugin package root directory.\n *\n * Default behavior is to look for the `dist/configSchema.json` relative path.\n *\n * @param pluginPackage - The scanned plugin package.\n * @returns the absolute or plugin-relative path to the Json schema file.\n */\n schemaLocator?: (pluginPackage: ScannedPluginPackage) => string;\n}\n\n/**\n * @public\n */\nexport const dynamicPluginsSchemasServiceFactory = createServiceFactory(\n (options?: DynamicPluginsSchemasOptions) => ({\n service: dynamicPluginsSchemasServiceRef,\n deps: {\n config: coreServices.rootConfig,\n },\n factory({ config }) {\n let additionalSchemas: { [context: string]: JsonObject } | undefined;\n\n return {\n async addDynamicPluginsSchemas(configSchema: ConfigSchema): Promise<{\n schema: ConfigSchema;\n }> {\n if (!additionalSchemas) {\n const logger = {\n ...console,\n child() {\n return this;\n },\n };\n\n const scanner = PluginScanner.create({\n config,\n logger,\n // eslint-disable-next-line no-restricted-syntax\n backstageRoot: findPaths(__dirname).targetRoot,\n preferAlpha: true,\n });\n\n const { packages } = await scanner.scanRoot();\n\n additionalSchemas = await gatherDynamicPluginsSchemas(\n packages,\n logger,\n options?.schemaLocator,\n );\n }\n\n const serialized = configSchema.serialize();\n if (serialized?.backstageConfigSchemaVersion !== 1) {\n throw new Error(\n 'Serialized configuration schema is invalid or has an invalid version number',\n );\n }\n const schemas = serialized.schemas as {\n value: JsonObject;\n path: string;\n }[];\n\n schemas.push(\n ...Object.keys(additionalSchemas).map(context => {\n return {\n path: context,\n value: additionalSchemas![context],\n };\n }),\n );\n serialized.schemas = schemas;\n return {\n schema: await loadConfigSchema({\n serialized,\n }),\n };\n },\n };\n },\n }),\n);\n\n/** @internal */\nasync function gatherDynamicPluginsSchemas(\n packages: ScannedPluginPackage[],\n logger: LoggerService,\n schemaLocator: (pluginPackage: ScannedPluginPackage) => string = () =>\n path.join('dist', 'configSchema.json'),\n): Promise<{ [context: string]: JsonObject }> {\n const allSchemas: { [context: string]: JsonObject } = {};\n\n for (const pluginPackage of packages) {\n let schemaLocation = schemaLocator(pluginPackage);\n\n if (!path.isAbsolute(schemaLocation)) {\n let pluginLocation = url.fileURLToPath(pluginPackage.location);\n if (path.basename(pluginLocation) === 'alpha') {\n pluginLocation = path.dirname(pluginLocation);\n }\n schemaLocation = path.resolve(pluginLocation, schemaLocation);\n }\n\n if (!(await fs.pathExists(schemaLocation))) {\n continue;\n }\n\n const serialized = await fs.readJson(schemaLocation);\n if (!serialized) {\n continue;\n }\n\n if (isEmpty(serialized)) {\n continue;\n }\n\n if (!serialized?.$schema || serialized?.type !== 'object') {\n logger.error(\n `Serialized configuration schema is invalid for plugin ${pluginPackage.manifest.name}`,\n );\n continue;\n }\n\n allSchemas[schemaLocation] = serialized;\n }\n\n return allSchemas;\n}\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createBackendModule,\n resolvePackagePath,\n} from '@backstage/backend-plugin-api';\nimport { dynamicPluginsSchemasServiceRef } from './schemas';\nimport {\n configSchemaExtensionPoint,\n loadCompiledConfigSchema,\n} from '@backstage/plugin-app-node';\n\n/** @public */\nexport const dynamicPluginsFrontendSchemas = createBackendModule({\n pluginId: 'app',\n moduleId: 'core.dynamicplugins.frontendSchemas',\n register(reg) {\n reg.registerInit({\n deps: {\n config: coreServices.rootConfig,\n schemas: dynamicPluginsSchemasServiceRef,\n configSchemaExtension: configSchemaExtensionPoint,\n },\n async init({ config, schemas, configSchemaExtension }) {\n const appPackageName =\n config.getOptionalString('app.packageName') ?? 'app';\n const appDistDir = resolvePackagePath(appPackageName, 'dist');\n const compiledConfigSchema = await loadCompiledConfigSchema(appDistDir);\n if (compiledConfigSchema) {\n configSchemaExtension.setConfigSchema(\n (await schemas.addDynamicPluginsSchemas(compiledConfigSchema))\n .schema,\n );\n }\n },\n });\n },\n});\n","/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createServiceFactory,\n coreServices,\n} from '@backstage/backend-plugin-api';\nimport { WinstonLogger } from '@backstage/backend-app-api';\nimport { transports, format } from 'winston';\nimport { createConfigSecretEnumerator } from '@backstage/backend-app-api';\nimport { loadConfigSchema } from '@backstage/config-loader';\nimport { getPackages } from '@manypkg/get-packages';\nimport { dynamicPluginsSchemasServiceRef } from './schemas';\n\n/** @public */\nexport const dynamicPluginsRootLoggerServiceFactory = createServiceFactory({\n service: coreServices.rootLogger,\n deps: {\n config: coreServices.rootConfig,\n schemas: dynamicPluginsSchemasServiceRef,\n },\n async factory({ config, schemas }) {\n const logger = WinstonLogger.create({\n meta: {\n service: 'backstage',\n },\n level: process.env.LOG_LEVEL || 'info',\n format:\n process.env.NODE_ENV === 'production'\n ? format.json()\n : WinstonLogger.colorFormat(),\n transports: [new transports.Console()],\n });\n\n const configSchema = await loadConfigSchema({\n dependencies: (\n await getPackages(process.cwd())\n ).packages.map(p => p.packageJson.name),\n });\n\n const secretEnumerator = await createConfigSecretEnumerator({\n logger,\n schema: (await schemas.addDynamicPluginsSchemas(configSchema)).schema,\n });\n logger.addRedactions(secretEnumerator(config));\n config.subscribe?.(() => logger.addRedactions(secretEnumerator(config)));\n\n return logger;\n },\n});\n"],"names":["path","lstatSync","fs","PackageRoles","existsSync","url","debounce","chokidar","findPaths","createServiceRef","createServiceFactory","coreServices","featureDiscoveryServiceRef","loadConfigSchema","isEmpty","createBackendModule","configSchemaExtensionPoint","resolvePackagePath","loadCompiledConfigSchema","WinstonLogger","format","transports","getPackages","createConfigSecretEnumerator"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/backend-dynamic-feature-service",
|
|
3
3
|
"description": "Backstage dynamic feature service",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.11-next.0",
|
|
5
5
|
"main": "./dist/index.cjs.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"publishConfig": {
|
|
@@ -38,24 +38,24 @@
|
|
|
38
38
|
"start": "backstage-cli package start"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@backstage/backend-app-api": "^0.7.
|
|
42
|
-
"@backstage/backend-common": "^0.22.
|
|
43
|
-
"@backstage/backend-plugin-api": "^0.6.
|
|
44
|
-
"@backstage/backend-tasks": "^0.5.
|
|
41
|
+
"@backstage/backend-app-api": "^0.7.6-next.0",
|
|
42
|
+
"@backstage/backend-common": "^0.22.1-next.0",
|
|
43
|
+
"@backstage/backend-plugin-api": "^0.6.19-next.0",
|
|
44
|
+
"@backstage/backend-tasks": "^0.5.24-next.0",
|
|
45
45
|
"@backstage/cli-common": "^0.1.13",
|
|
46
|
-
"@backstage/cli-node": "^0.2.
|
|
46
|
+
"@backstage/cli-node": "^0.2.6-next.0",
|
|
47
47
|
"@backstage/config": "^1.2.0",
|
|
48
48
|
"@backstage/config-loader": "^1.8.0",
|
|
49
49
|
"@backstage/errors": "^1.2.4",
|
|
50
|
-
"@backstage/plugin-app-node": "^0.1.
|
|
51
|
-
"@backstage/plugin-auth-node": "^0.4.
|
|
52
|
-
"@backstage/plugin-catalog-backend": "^1.
|
|
53
|
-
"@backstage/plugin-events-backend": "^0.3.
|
|
54
|
-
"@backstage/plugin-events-node": "^0.3.
|
|
50
|
+
"@backstage/plugin-app-node": "^0.1.19-next.0",
|
|
51
|
+
"@backstage/plugin-auth-node": "^0.4.14-next.0",
|
|
52
|
+
"@backstage/plugin-catalog-backend": "^1.23.0-next.0",
|
|
53
|
+
"@backstage/plugin-events-backend": "^0.3.6-next.0",
|
|
54
|
+
"@backstage/plugin-events-node": "^0.3.5-next.0",
|
|
55
55
|
"@backstage/plugin-permission-common": "^0.7.13",
|
|
56
|
-
"@backstage/plugin-permission-node": "^0.7.
|
|
57
|
-
"@backstage/plugin-scaffolder-node": "^0.4.
|
|
58
|
-
"@backstage/plugin-search-backend-node": "^1.2.
|
|
56
|
+
"@backstage/plugin-permission-node": "^0.7.30-next.0",
|
|
57
|
+
"@backstage/plugin-scaffolder-node": "^0.4.5-next.0",
|
|
58
|
+
"@backstage/plugin-search-backend-node": "^1.2.24-next.0",
|
|
59
59
|
"@backstage/plugin-search-common": "^1.2.11",
|
|
60
60
|
"@backstage/types": "^1.1.1",
|
|
61
61
|
"@manypkg/get-packages": "^1.1.3",
|
|
@@ -67,8 +67,8 @@
|
|
|
67
67
|
"winston": "^3.2.1"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
|
-
"@backstage/backend-test-utils": "^0.3.
|
|
71
|
-
"@backstage/cli": "^0.26.
|
|
70
|
+
"@backstage/backend-test-utils": "^0.3.9-next.0",
|
|
71
|
+
"@backstage/cli": "^0.26.6-next.0",
|
|
72
72
|
"wait-for-expect": "^3.0.2"
|
|
73
73
|
},
|
|
74
74
|
"files": [
|