Merge pull request #21764 from davidfestal/meet-api-design-style-guidelines
Refactor the `backend-plugin-manager`to meet Backstage API design style guidelines
This commit is contained in:
@@ -65,6 +65,44 @@ export interface BaseDynamicPlugin {
|
||||
// @public (undocumented)
|
||||
export type DynamicPlugin = FrontendDynamicPlugin | BackendDynamicPlugin;
|
||||
|
||||
// @public (undocumented)
|
||||
export class DynamicPluginManager implements DynamicPluginProvider {
|
||||
// (undocumented)
|
||||
addBackendPlugin(plugin: BackendDynamicPlugin): void;
|
||||
// (undocumented)
|
||||
get availablePackages(): ScannedPluginPackage[];
|
||||
// (undocumented)
|
||||
backendPlugins(): BackendDynamicPlugin[];
|
||||
// (undocumented)
|
||||
static create(
|
||||
options: DynamicPluginManagerOptions,
|
||||
): Promise<DynamicPluginManager>;
|
||||
// (undocumented)
|
||||
frontendPlugins(): FrontendDynamicPlugin[];
|
||||
// (undocumented)
|
||||
plugins(): DynamicPlugin[];
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface DynamicPluginManagerOptions {
|
||||
// (undocumented)
|
||||
config: Config;
|
||||
// (undocumented)
|
||||
logger: LoggerService;
|
||||
// (undocumented)
|
||||
moduleLoader?: ModuleLoader;
|
||||
// (undocumented)
|
||||
preferAlpha?: boolean;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface DynamicPluginProvider
|
||||
extends FrontendPluginProvider,
|
||||
BackendPluginProvider {
|
||||
// (undocumented)
|
||||
plugins(): DynamicPlugin[];
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface DynamicPluginsFactoryOptions {
|
||||
// (undocumented)
|
||||
@@ -80,11 +118,11 @@ export const dynamicPluginsFeatureDiscoveryServiceFactory: () => ServiceFactory<
|
||||
// @public (undocumented)
|
||||
export const dynamicPluginsServiceFactory: (
|
||||
options?: DynamicPluginsFactoryOptions | undefined,
|
||||
) => ServiceFactory<BackendPluginProvider, 'root'>;
|
||||
) => ServiceFactory<DynamicPluginProvider, 'root'>;
|
||||
|
||||
// @public (undocumented)
|
||||
export const dynamicPluginsServiceRef: ServiceRef<
|
||||
BackendPluginProvider,
|
||||
DynamicPluginProvider,
|
||||
'root'
|
||||
>;
|
||||
|
||||
@@ -94,6 +132,12 @@ export interface FrontendDynamicPlugin extends BaseDynamicPlugin {
|
||||
platform: 'web';
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface FrontendPluginProvider {
|
||||
// (undocumented)
|
||||
frontendPlugins(): FrontendDynamicPlugin[];
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export function isBackendDynamicPluginInstaller(
|
||||
obj: any,
|
||||
@@ -161,25 +205,6 @@ export interface NewBackendPluginInstaller {
|
||||
kind: 'new';
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export class PluginManager implements BackendPluginProvider {
|
||||
// (undocumented)
|
||||
addBackendPlugin(plugin: BackendDynamicPlugin): void;
|
||||
// (undocumented)
|
||||
get availablePackages(): ScannedPluginPackage[];
|
||||
// (undocumented)
|
||||
backendPlugins(): BackendDynamicPlugin[];
|
||||
// (undocumented)
|
||||
static fromConfig(
|
||||
config: Config,
|
||||
logger: LoggerService,
|
||||
preferAlpha?: boolean,
|
||||
moduleLoader?: ModuleLoader,
|
||||
): Promise<PluginManager>;
|
||||
// (undocumented)
|
||||
readonly plugins: DynamicPlugin[];
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export type ScannedPluginManifest = BackstagePackageJson &
|
||||
Required<Pick<BackstagePackageJson, 'main'>> &
|
||||
|
||||
@@ -25,14 +25,19 @@ export type {
|
||||
NewBackendPluginInstaller,
|
||||
LegacyBackendPluginInstaller,
|
||||
LegacyPluginEnvironment,
|
||||
DynamicPluginProvider,
|
||||
FrontendPluginProvider,
|
||||
BackendPluginProvider,
|
||||
} from './types';
|
||||
|
||||
export {
|
||||
PluginManager,
|
||||
DynamicPluginManager,
|
||||
dynamicPluginsFeatureDiscoveryServiceFactory,
|
||||
dynamicPluginsServiceFactory,
|
||||
dynamicPluginsServiceRef,
|
||||
} from './plugin-manager';
|
||||
|
||||
export type { DynamicPluginsFactoryOptions } from './plugin-manager';
|
||||
export type {
|
||||
DynamicPluginManagerOptions,
|
||||
DynamicPluginsFactoryOptions,
|
||||
} from './plugin-manager';
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { PluginManager, dynamicPluginsServiceFactory } from './plugin-manager';
|
||||
import {
|
||||
DynamicPluginManager,
|
||||
dynamicPluginsServiceFactory,
|
||||
} from './plugin-manager';
|
||||
import {
|
||||
BackendFeature,
|
||||
coreServices,
|
||||
@@ -462,12 +465,16 @@ describe('backend-plugin-manager', () => {
|
||||
mockDir.setContent(mockedFiles);
|
||||
|
||||
const logger = new MockedLogger();
|
||||
const pluginManager = new (PluginManager as any)(logger, [plugin], {
|
||||
const pluginManager = new (DynamicPluginManager as any)(
|
||||
logger,
|
||||
async bootstrap(_: string, __: string[]): Promise<void> {},
|
||||
load: async (packagePath: string) =>
|
||||
await require(/* webpackIgnore: true */ packagePath),
|
||||
});
|
||||
[plugin],
|
||||
{
|
||||
logger,
|
||||
async bootstrap(_: string, __: string[]): Promise<void> {},
|
||||
load: async (packagePath: string) =>
|
||||
await require(/* webpackIgnore: true */ packagePath),
|
||||
},
|
||||
);
|
||||
|
||||
const loadedPlugins: DynamicPlugin[] = await pluginManager.loadPlugins();
|
||||
|
||||
@@ -483,7 +490,10 @@ describe('backend-plugin-manager', () => {
|
||||
describe('backendPlugins', () => {
|
||||
it('should return only backend plugins and modules', async () => {
|
||||
const logger = new MockedLogger();
|
||||
const pluginManager = new (PluginManager as any)(logger, '', []);
|
||||
const pluginManager = new (DynamicPluginManager as any)(
|
||||
logger,
|
||||
[],
|
||||
) as DynamicPluginManager;
|
||||
const plugins: BaseDynamicPlugin[] = [
|
||||
{
|
||||
name: 'a-frontend-plugin',
|
||||
@@ -504,7 +514,7 @@ describe('backend-plugin-manager', () => {
|
||||
version: '0.0.0',
|
||||
},
|
||||
];
|
||||
pluginManager.plugins = plugins;
|
||||
(pluginManager as any)._plugins = plugins;
|
||||
expect(pluginManager.backendPlugins()).toEqual([
|
||||
{
|
||||
name: 'a-backend-plugin',
|
||||
@@ -522,6 +532,57 @@ describe('backend-plugin-manager', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('frontendPlugins', () => {
|
||||
it('should return only frontend plugins', async () => {
|
||||
const logger = new MockedLogger();
|
||||
const pluginManager = new (DynamicPluginManager as any)(
|
||||
logger,
|
||||
[],
|
||||
) as DynamicPluginManager;
|
||||
const plugins: BaseDynamicPlugin[] = [
|
||||
{
|
||||
name: 'a-frontend-plugin',
|
||||
platform: 'web',
|
||||
role: 'frontend-plugin',
|
||||
version: '0.0.0',
|
||||
},
|
||||
{
|
||||
name: 'a-frontend-module',
|
||||
platform: 'web',
|
||||
role: 'frontend-plugin-module',
|
||||
version: '0.0.0',
|
||||
},
|
||||
{
|
||||
name: 'a-backend-plugin',
|
||||
platform: 'node',
|
||||
role: 'backend-plugin',
|
||||
version: '0.0.0',
|
||||
},
|
||||
{
|
||||
name: 'a-backend-module',
|
||||
platform: 'node',
|
||||
role: 'backend-plugin-module',
|
||||
version: '0.0.0',
|
||||
},
|
||||
];
|
||||
(pluginManager as any)._plugins = plugins;
|
||||
expect(pluginManager.frontendPlugins()).toEqual([
|
||||
{
|
||||
name: 'a-frontend-plugin',
|
||||
platform: 'web',
|
||||
role: 'frontend-plugin',
|
||||
version: '0.0.0',
|
||||
},
|
||||
{
|
||||
name: 'a-frontend-module',
|
||||
platform: 'web',
|
||||
role: 'frontend-plugin-module',
|
||||
version: '0.0.0',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('dynamicPluginsServiceFactory', () => {
|
||||
const otherMockDir = createMockDirectory();
|
||||
|
||||
@@ -547,27 +608,29 @@ describe('backend-plugin-manager', () => {
|
||||
'a-dynamic-plugin': {},
|
||||
});
|
||||
|
||||
const fromConfigSpier = jest.spyOn(PluginManager, 'fromConfig');
|
||||
const fromConfigSpier = jest.spyOn(DynamicPluginManager, 'create');
|
||||
const applyConfigSpier = jest
|
||||
.spyOn(PluginScanner.prototype as any, 'applyConfig')
|
||||
.mockImplementation(() => {});
|
||||
const scanRootSpier = jest
|
||||
.spyOn(PluginScanner.prototype, 'scanRoot')
|
||||
.mockImplementation(async () => [
|
||||
{
|
||||
location: url.pathToFileURL(
|
||||
mockDir.resolve('dynamic-plugins-root/a-dynamic-plugin'),
|
||||
),
|
||||
manifest: {
|
||||
name: 'test',
|
||||
version: '0.0.0',
|
||||
main: 'dist/index.cjs.js',
|
||||
backstage: {
|
||||
role: 'backend-plugin',
|
||||
.mockImplementation(async () => ({
|
||||
packages: [
|
||||
{
|
||||
location: url.pathToFileURL(
|
||||
mockDir.resolve('dynamic-plugins-root/a-dynamic-plugin'),
|
||||
),
|
||||
manifest: {
|
||||
name: 'test',
|
||||
version: '0.0.0',
|
||||
main: 'dist/index.cjs.js',
|
||||
backstage: {
|
||||
role: 'backend-plugin',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
],
|
||||
}));
|
||||
const mockedModuleLoader = {
|
||||
logger,
|
||||
bootstrap: jest.fn(),
|
||||
|
||||
@@ -15,10 +15,11 @@
|
||||
*/
|
||||
import { Config } from '@backstage/config';
|
||||
import {
|
||||
BackendPluginProvider,
|
||||
DynamicPluginProvider,
|
||||
BackendDynamicPlugin,
|
||||
isBackendDynamicPluginInstaller,
|
||||
DynamicPlugin,
|
||||
FrontendDynamicPlugin,
|
||||
} from './types';
|
||||
import { ScannedPluginPackage } from '../scanner';
|
||||
import { PluginScanner } from '../scanner/plugin-scanner';
|
||||
@@ -44,24 +45,37 @@ import {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export class PluginManager implements BackendPluginProvider {
|
||||
static async fromConfig(
|
||||
config: Config,
|
||||
logger: LoggerService,
|
||||
preferAlpha: boolean = false,
|
||||
moduleLoader: ModuleLoader = new CommonJSModuleLoader(logger),
|
||||
): Promise<PluginManager> {
|
||||
export interface DynamicPluginManagerOptions {
|
||||
config: Config;
|
||||
logger: LoggerService;
|
||||
preferAlpha?: boolean;
|
||||
moduleLoader?: ModuleLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export class DynamicPluginManager implements DynamicPluginProvider {
|
||||
static async create(
|
||||
options: DynamicPluginManagerOptions,
|
||||
): Promise<DynamicPluginManager> {
|
||||
/* eslint-disable-next-line no-restricted-syntax */
|
||||
const backstageRoot = findPaths(__dirname).targetRoot;
|
||||
const scanner = new PluginScanner(
|
||||
config,
|
||||
logger,
|
||||
const scanner = PluginScanner.create({
|
||||
config: options.config,
|
||||
logger: options.logger,
|
||||
backstageRoot,
|
||||
preferAlpha,
|
||||
);
|
||||
const scannedPlugins = await scanner.scanRoot();
|
||||
preferAlpha: options.preferAlpha,
|
||||
});
|
||||
const scannedPlugins = (await scanner.scanRoot()).packages;
|
||||
scanner.trackChanges();
|
||||
const manager = new PluginManager(logger, scannedPlugins, moduleLoader);
|
||||
const moduleLoader =
|
||||
options.moduleLoader || new CommonJSModuleLoader(options.logger);
|
||||
const manager = new DynamicPluginManager(
|
||||
options.logger,
|
||||
scannedPlugins,
|
||||
moduleLoader,
|
||||
);
|
||||
|
||||
const dynamicPluginsPaths = scannedPlugins.map(p =>
|
||||
fs.realpathSync(
|
||||
@@ -76,15 +90,15 @@ export class PluginManager implements BackendPluginProvider {
|
||||
moduleLoader.bootstrap(backstageRoot, dynamicPluginsPaths);
|
||||
|
||||
scanner.subscribeToRootDirectoryChange(async () => {
|
||||
manager._availablePackages = await scanner.scanRoot();
|
||||
manager._availablePackages = (await scanner.scanRoot()).packages;
|
||||
// TODO: do not store _scannedPlugins again, but instead store a diff of the changes
|
||||
});
|
||||
manager.plugins.push(...(await manager.loadPlugins()));
|
||||
manager._plugins.push(...(await manager.loadPlugins()));
|
||||
|
||||
return manager;
|
||||
}
|
||||
|
||||
readonly plugins: DynamicPlugin[];
|
||||
private readonly _plugins: DynamicPlugin[];
|
||||
private _availablePackages: ScannedPluginPackage[];
|
||||
|
||||
private constructor(
|
||||
@@ -92,7 +106,7 @@ export class PluginManager implements BackendPluginProvider {
|
||||
private packages: ScannedPluginPackage[],
|
||||
private readonly moduleLoader: ModuleLoader,
|
||||
) {
|
||||
this.plugins = [];
|
||||
this._plugins = [];
|
||||
this._availablePackages = packages;
|
||||
}
|
||||
|
||||
@@ -101,7 +115,7 @@ export class PluginManager implements BackendPluginProvider {
|
||||
}
|
||||
|
||||
addBackendPlugin(plugin: BackendDynamicPlugin): void {
|
||||
this.plugins.push(plugin);
|
||||
this._plugins.push(plugin);
|
||||
}
|
||||
|
||||
private async loadPlugins(): Promise<DynamicPlugin[]> {
|
||||
@@ -182,16 +196,26 @@ export class PluginManager implements BackendPluginProvider {
|
||||
}
|
||||
|
||||
backendPlugins(): BackendDynamicPlugin[] {
|
||||
return this.plugins.filter(
|
||||
return this._plugins.filter(
|
||||
(p): p is BackendDynamicPlugin => p.platform === 'node',
|
||||
);
|
||||
}
|
||||
|
||||
frontendPlugins(): FrontendDynamicPlugin[] {
|
||||
return this._plugins.filter(
|
||||
(p): p is FrontendDynamicPlugin => p.platform === 'web',
|
||||
);
|
||||
}
|
||||
|
||||
plugins(): DynamicPlugin[] {
|
||||
return this._plugins;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const dynamicPluginsServiceRef = createServiceRef<BackendPluginProvider>(
|
||||
export const dynamicPluginsServiceRef = createServiceRef<DynamicPluginProvider>(
|
||||
{
|
||||
id: 'core.dynamicplugins',
|
||||
scope: 'root',
|
||||
@@ -216,15 +240,12 @@ export const dynamicPluginsServiceFactory = createServiceFactory(
|
||||
logger: coreServices.rootLogger,
|
||||
},
|
||||
async factory({ config, logger }) {
|
||||
if (options?.moduleLoader) {
|
||||
return await PluginManager.fromConfig(
|
||||
config,
|
||||
logger,
|
||||
true,
|
||||
options.moduleLoader(logger),
|
||||
);
|
||||
}
|
||||
return await PluginManager.fromConfig(config, logger, true);
|
||||
return await DynamicPluginManager.create({
|
||||
config,
|
||||
logger,
|
||||
preferAlpha: true,
|
||||
moduleLoader: options?.moduleLoader?.(logger),
|
||||
});
|
||||
},
|
||||
}),
|
||||
);
|
||||
@@ -233,7 +254,7 @@ class DynamicPluginsEnabledFeatureDiscoveryService
|
||||
implements FeatureDiscoveryService
|
||||
{
|
||||
constructor(
|
||||
private readonly dynamicPlugins: BackendPluginProvider,
|
||||
private readonly dynamicPlugins: DynamicPluginProvider,
|
||||
private readonly featureDiscoveryService?: FeatureDiscoveryService,
|
||||
) {}
|
||||
|
||||
|
||||
@@ -67,6 +67,15 @@ export type LegacyPluginEnvironment = {
|
||||
pluginProvider: BackendPluginProvider;
|
||||
};
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface DynamicPluginProvider
|
||||
extends FrontendPluginProvider,
|
||||
BackendPluginProvider {
|
||||
plugins(): DynamicPlugin[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
@@ -74,6 +83,13 @@ export interface BackendPluginProvider {
|
||||
backendPlugins(): BackendDynamicPlugin[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface FrontendPluginProvider {
|
||||
frontendPlugins(): FrontendDynamicPlugin[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
|
||||
@@ -64,22 +64,23 @@ describe('plugin-scanner', () => {
|
||||
unsubscribe: configUnsubscribe,
|
||||
};
|
||||
};
|
||||
const pluginScanner = new PluginScanner(
|
||||
const pluginScanner = PluginScanner.create({
|
||||
config,
|
||||
logger,
|
||||
backstageRootDirectory,
|
||||
false,
|
||||
);
|
||||
backstageRoot: backstageRootDirectory,
|
||||
preferAlpha: false,
|
||||
});
|
||||
await pluginScanner.trackChanges();
|
||||
|
||||
expect(onConfigChange).toBeDefined();
|
||||
|
||||
let scannedPlugins: ScannedPluginPackage[] =
|
||||
await pluginScanner.scanRoot();
|
||||
let scannedPlugins: ScannedPluginPackage[] = (
|
||||
await pluginScanner.scanRoot()
|
||||
).packages;
|
||||
expect(scannedPlugins).toEqual([]);
|
||||
|
||||
const rootDirectorySubscriber = jest.fn(async () => {
|
||||
scannedPlugins = await pluginScanner.scanRoot();
|
||||
scannedPlugins = (await pluginScanner.scanRoot()).packages;
|
||||
});
|
||||
pluginScanner.subscribeToRootDirectoryChange(rootDirectorySubscriber);
|
||||
|
||||
|
||||
@@ -206,11 +206,11 @@ Please add '${mockDir.resolve(
|
||||
const logger = new MockedLogger();
|
||||
const backstageRoot = tc.backstageRoot ? tc.backstageRoot : '';
|
||||
function toTest(): PluginScanner {
|
||||
return new PluginScanner(
|
||||
new ConfigReader(tc.config),
|
||||
return PluginScanner.create({
|
||||
config: new ConfigReader(tc.config),
|
||||
logger,
|
||||
backstageRoot,
|
||||
);
|
||||
});
|
||||
}
|
||||
if (tc.fileSystem) {
|
||||
mockDir.setContent(tc.fileSystem);
|
||||
@@ -609,8 +609,8 @@ Please add '${mockDir.resolve(
|
||||
const logger = new MockedLogger();
|
||||
const backstageRoot = mockDir.resolve('backstageRoot');
|
||||
async function toTest(): Promise<ScannedPluginPackage[]> {
|
||||
const pluginScanner = new PluginScanner(
|
||||
new ConfigReader(
|
||||
const pluginScanner = PluginScanner.create({
|
||||
config: new ConfigReader(
|
||||
tc.fileSystem
|
||||
? {
|
||||
dynamicPlugins: {
|
||||
@@ -621,9 +621,9 @@ Please add '${mockDir.resolve(
|
||||
),
|
||||
logger,
|
||||
backstageRoot,
|
||||
tc.preferAlpha === undefined ? false : tc.preferAlpha,
|
||||
);
|
||||
return await pluginScanner.scanRoot();
|
||||
preferAlpha: tc.preferAlpha,
|
||||
});
|
||||
return (await pluginScanner.scanRoot()).packages;
|
||||
}
|
||||
if (tc.fileSystem) {
|
||||
mockDir.setContent(tc.fileSystem);
|
||||
|
||||
@@ -24,28 +24,39 @@ import debounce from 'lodash/debounce';
|
||||
import { PackagePlatform, PackageRoles } from '@backstage/cli-node';
|
||||
import { LoggerService } from '@backstage/backend-plugin-api';
|
||||
|
||||
export interface DynamicPluginScannerOptions {
|
||||
config: Config;
|
||||
backstageRoot: string;
|
||||
logger: LoggerService;
|
||||
preferAlpha?: boolean;
|
||||
}
|
||||
|
||||
export interface ScanRootResponse {
|
||||
packages: ScannedPluginPackage[];
|
||||
}
|
||||
|
||||
export class PluginScanner {
|
||||
private readonly logger: LoggerService;
|
||||
private backstageRoot: string;
|
||||
readonly #config: Config;
|
||||
private _rootDirectory?: string;
|
||||
private readonly preferAlpha: boolean;
|
||||
private configUnsubscribe?: () => void;
|
||||
private rootDirectoryWatcher?: chokidar.FSWatcher;
|
||||
private subscribers: (() => void)[] = [];
|
||||
|
||||
constructor(
|
||||
config: Config,
|
||||
logger: LoggerService,
|
||||
backstageRoot: string,
|
||||
preferAlpha: boolean = false,
|
||||
) {
|
||||
this.backstageRoot = backstageRoot;
|
||||
this.logger = logger;
|
||||
this.preferAlpha = preferAlpha;
|
||||
this.#config = config;
|
||||
private constructor(
|
||||
private readonly config: Config,
|
||||
private readonly logger: LoggerService,
|
||||
private readonly backstageRoot: string,
|
||||
private readonly preferAlpha: boolean,
|
||||
) {}
|
||||
|
||||
this.applyConfig();
|
||||
static create(options: DynamicPluginScannerOptions): PluginScanner {
|
||||
const scanner = new PluginScanner(
|
||||
options.config,
|
||||
options.logger,
|
||||
options.backstageRoot,
|
||||
options.preferAlpha || false,
|
||||
);
|
||||
scanner.applyConfig();
|
||||
return scanner;
|
||||
}
|
||||
|
||||
subscribeToRootDirectoryChange(subscriber: () => void) {
|
||||
@@ -57,7 +68,7 @@ export class PluginScanner {
|
||||
}
|
||||
|
||||
private applyConfig(): void | never {
|
||||
const dynamicPlugins = this.#config.getOptional('dynamicPlugins');
|
||||
const dynamicPlugins = this.config.getOptional('dynamicPlugins');
|
||||
if (!dynamicPlugins) {
|
||||
this.logger.info("'dynamicPlugins' config entry not found.");
|
||||
this._rootDirectory = undefined;
|
||||
@@ -114,9 +125,9 @@ export class PluginScanner {
|
||||
this._rootDirectory = dynamicPluginsRootPath;
|
||||
}
|
||||
|
||||
async scanRoot(): Promise<ScannedPluginPackage[]> {
|
||||
async scanRoot(): Promise<ScanRootResponse> {
|
||||
if (!this._rootDirectory) {
|
||||
return [];
|
||||
return { packages: [] };
|
||||
}
|
||||
|
||||
const dynamicPluginsLocation = this._rootDirectory;
|
||||
@@ -189,7 +200,7 @@ export class PluginScanner {
|
||||
|
||||
scannedPlugins.push(scannedPlugin);
|
||||
}
|
||||
return scannedPlugins;
|
||||
return { packages: scannedPlugins };
|
||||
}
|
||||
|
||||
private async scanDir(pluginHome: string): Promise<ScannedPluginPackage> {
|
||||
@@ -263,30 +274,28 @@ export class PluginScanner {
|
||||
};
|
||||
|
||||
await setupRootDirectoryWatcher();
|
||||
if (this.#config.subscribe) {
|
||||
const { unsubscribe } = this.#config.subscribe(
|
||||
async (): Promise<void> => {
|
||||
const oldRootDirectory = this._rootDirectory;
|
||||
try {
|
||||
this.applyConfig();
|
||||
} catch (e) {
|
||||
this.logger.error(
|
||||
'failed to apply new config for dynamic plugins',
|
||||
e,
|
||||
);
|
||||
if (this.config.subscribe) {
|
||||
const { unsubscribe } = this.config.subscribe(async (): Promise<void> => {
|
||||
const oldRootDirectory = this._rootDirectory;
|
||||
try {
|
||||
this.applyConfig();
|
||||
} catch (e) {
|
||||
this.logger.error(
|
||||
'failed to apply new config for dynamic plugins',
|
||||
e,
|
||||
);
|
||||
}
|
||||
if (oldRootDirectory !== this._rootDirectory) {
|
||||
this.logger.info(
|
||||
`rootDirectory changed in Config from '${oldRootDirectory}' to '${this._rootDirectory}'`,
|
||||
);
|
||||
this.subscribers.forEach(s => s());
|
||||
if (this.rootDirectoryWatcher) {
|
||||
await this.rootDirectoryWatcher.close();
|
||||
}
|
||||
if (oldRootDirectory !== this._rootDirectory) {
|
||||
this.logger.info(
|
||||
`rootDirectory changed in Config from '${oldRootDirectory}' to '${this._rootDirectory}'`,
|
||||
);
|
||||
this.subscribers.forEach(s => s());
|
||||
if (this.rootDirectoryWatcher) {
|
||||
await this.rootDirectoryWatcher.close();
|
||||
}
|
||||
await setupRootDirectoryWatcher();
|
||||
}
|
||||
},
|
||||
);
|
||||
await setupRootDirectoryWatcher();
|
||||
}
|
||||
});
|
||||
this.configUnsubscribe = unsubscribe;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user