import * as path from 'path' ; import * as resolve from 'resolve' ; import { IApiDocumenterPluginManifest , IFeatureDefinition } from './IApiDocumenterPluginManifest' ; import { MarkdownDocumenterFeature , MarkdownDocumenterFeatureContext } from './MarkdownDocumenterFeature' ; import { PluginFeatureInitialization } from './PluginFeature' ; import { DocumenterConfig } from '../documenters/DocumenterConfig' ; interface ILoadedPlugin { packageName : string ; manifest : IApiDocumenterPluginManifest ; } export class PluginLoader { public markdownDocumenterFeature : MarkdownDocumenterFeature | undefined ; public load ( documenterConfig , createContext ) { const configFileFolder = path . dirname ( documenterConfig . configFilePath ) ; for ( const configPlugin of documenterConfig . configFile . plugins || [ ] ) { try { const resolvedEntryPointPath = resolve . sync ( configPlugin . packageName , { basedir : configFileFolder } ) ; const entryPoint = require ( resolvedEntryPointPath ) ; if ( ! entryPoint ) { throw new Error ( 'Invalid entry point' ) ; } if ( ! entryPoint . apiDocumenterPluginManifest ) { throw new Error ( `The package is not an API documenter plugin;` + ` the "apiDocumenterPluginManifest" export was not found` ) ; } const manifest = entryPoint . apiDocumenterPluginManifest ; if ( manifest . manifestVersion !== 1000 ) { throw new Error ( `The plugin is not compatible with this version of API Documenter;` + ` unsupported manifestVersion` ) ; } const loadedPlugin = { packageName : configPlugin . packageName , manifest } ; const featureDefinitionsByName = new Map < string , IFeatureDefinition > ( ) ; for ( const featureDefinition of manifest . features ) { featureDefinitionsByName . set ( featureDefinition . featureName , featureDefinition ) ; } for ( const featureName of configPlugin . enabledFeatureNames ) { const featureDefinition = featureDefinitionsByName . get ( featureName ) ; if ( ! featureDefinition ) { throw new Error ( `The plugin ${ loadedPlugin . packageName } does not have a feature with name "${ featureName }"` ) ; } if ( featureDefinition . kind === 'MarkdownDocumenterFeature' ) { if ( this . markdownDocumenterFeature ) { throw new Error ( 'A MarkdownDocumenterFeature is already loaded' ) ; } const initialization = new PluginFeatureInitialization ( ) ; initialization . _context = createContext ( ) ; let markdownDocumenterFeature = undefined ; try { markdownDocumenterFeature = new featureDefinition . subclass ( initialization ) ; } catch ( e ) { throw new Error ( `Failed to construct feature subclass:\n` + ( e as Error ) . toString ( ) ) ; } if ( ! ( markdownDocumenterFeature instanceof MarkdownDocumenterFeature ) ) { throw new Error ( 'The constructed subclass was not an instance of MarkdownDocumenterFeature' ) ; } try { markdownDocumenterFeature . onInitialized ( ) ; } catch ( e ) { throw new Error ( 'Error occurred during the onInitialized() event: ' + ( e as Error ) . toString ( ) ) ; } this . markdownDocumenterFeature = markdownDocumenterFeature ; } else { throw new Error ( `Unknown feature definition kind: "${ featureDefinition . kind }"` ) ; } } } catch ( e ) { throw new Error ( `Error loading plugin ${ configPlugin . packageName }: ` + ( e as Error ) . message ) ; } } } }