import fs from 'fs' ; import path from 'path' ; import { FileBasedPluginType , ServiceManagerConfigType } from '.' ; import { ServiceManager , AbstractPluginManager } from '../ServiceManager' ; import { Instantiable } from '../Core' ; import { createDebugLogger } from '../../debug' ; const debug = createDebugLogger ( 'pluginManager' ) ; export class AbstractFileBasedPluginManager extends AbstractPluginManager { constructor ( creationContext , locations , config ) { super ( creationContext , config ) ; if ( locations ) { this . loadFromLocations ( locations ) ; } } public static getPluginName ( plugin ) { if ( typeof plugin === 'string' ) { return plugin ; } return plugin . name ; } public loadFromLocations ( pluginDirectories ? ) { if ( pluginDirectories ) { pluginDirectories . forEach ( directory => this . loadDirectory ( directory ) ) ; } return this ; } public loadDirectory ( pluginDirectory ) { let stat ; try { stat = fs . statSync ( pluginDirectory ) ; } catch ( error ) { if ( error . code === 'ENOENT' ) { debug ( `Directory "${ pluginDirectory }" not found for plugin manager.` ) ; return ; } throw error ; } if ( ! stat . isDirectory ( ) ) { throw new Error ( 'Plugin location must be a directory.' ) ; } const plugins = fs . readdirSync ( pluginDirectory ) . filter ( ( fileName ) => ! ! fileName . match ( /^(?!.*index\.(js|ts)$).*(^.?|\.[^d]|[^.]d|[^.][^d])\.(js|ts)$/ ) ) . map ( ( fileName ) => fileName . replace ( /\.(js|ts)$/ , '' ) ) . map ( ( plugin ) => { const Plugin = require ( path . resolve ( pluginDirectory , plugin ) ) ; if ( typeof Plugin === 'function' ) { return Plugin ; } if ( typeof Plugin . default === 'function' ) { return Plugin . default ; } if ( typeof Plugin [ plugin ] === 'function' ) { return Plugin [ plugin ] ; } throw new TypeError ( `Unable to load plugin "${ plugin }" due to missing constructable export.` ) ; } ) ; this . registerPlugins ( plugins ) ; } public getPlugin ( plugin ) { return this . get ( plugin ) ; } protected registerPlugins ( plugins ) { plugins . forEach ( Plugin => this . registerPlugin ( Plugin ) ) ; return this ; } protected registerPlugin ( Plugin ) { this . registerInvokable ( Plugin , Plugin ) ; this . registerAlias ( Plugin . name , Plugin ) ; return this ; } }