diff --git a/src/config/config.ts b/src/config/config.ts index 708c61456..d9dc83479 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -515,8 +515,8 @@ export class Config implements IConfig { debug('start', isESM ? '(import)' : '(require)', filePath) const result = timeout - ? await withTimeout(timeout, search(module).call(context, {...(opts as any), config: this})) - : await search(module).call(context, {...(opts as any), config: this}) + ? await withTimeout(timeout, search(module).call(context, {...(opts as any), config: this, context})) + : await search(module).call(context, {...(opts as any), config: this, context}) final.successes.push({plugin: p, result}) if (p.name === '@oclif/plugin-legacy' && event === 'init') { diff --git a/src/index.ts b/src/index.ts index d6c0c6982..03787eb00 100644 --- a/src/index.ts +++ b/src/index.ts @@ -29,6 +29,7 @@ export {toConfiguredId, toStandardizedId} from './help/util' export * as Interfaces from './interfaces' export {Hook} from './interfaces/hooks' export {run} from './main' +export * as ModuleLoader from './module-loader' export * as Parser from './parser' export {Performance} from './performance' export {Settings, settings} from './settings' diff --git a/src/interfaces/hooks.ts b/src/interfaces/hooks.ts index d5290d469..4e21e145c 100644 --- a/src/interfaces/hooks.ts +++ b/src/interfaces/hooks.ts @@ -7,6 +7,14 @@ interface HookMeta { return: any } +type Context = { + debug(...args: any[]): void + error(message: Error | string, options?: {code?: string; exit?: number}): void + exit(code?: number): void + log(message?: any, ...args: any[]): void + warn(message: string): void +} + export interface Hooks { [event: string]: HookMeta command_incomplete: { @@ -55,7 +63,7 @@ export interface Hooks { export type Hook = ( this: Hook.Context, - options: P[T]['options'] & {config: Config}, + options: P[T]['options'] & {config: Config; context: Context}, ) => Promise export namespace Hook { diff --git a/src/module-loader.ts b/src/module-loader.ts index 553f6dfcc..588a4d915 100644 --- a/src/module-loader.ts +++ b/src/module-loader.ts @@ -34,12 +34,12 @@ const isPlugin = (config: IConfig | IPlugin): config is IPlugin => (con * * @returns {Promise<*>} The entire ESM module from dynamic import or CJS module by require. */ -export async function load(config: IConfig | IPlugin, modulePath: string): Promise { +export async function load(config: IConfig | IPlugin, modulePath: string): Promise { let filePath: string | undefined let isESM: boolean | undefined try { ;({filePath, isESM} = resolvePath(config, modulePath)) - return isESM ? await import(pathToFileURL(filePath).href) : require(filePath) + return (isESM ? await import(pathToFileURL(filePath).href) : require(filePath)) as T } catch (error: any) { if (error.code === 'MODULE_NOT_FOUND' || error.code === 'ERR_MODULE_NOT_FOUND') { throw new ModuleLoadError(`${isESM ? 'import()' : 'require'} failed to load ${filePath || modulePath}`) @@ -66,10 +66,10 @@ export async function load(config: IConfig | IPlugin, modulePath: string): Promi * @returns {Promise<{isESM: boolean, module: *, filePath: string}>} An object with the loaded module & data including * file path and whether the module is ESM. */ -export async function loadWithData( +export async function loadWithData( config: IConfig | IPlugin, modulePath: string, -): Promise<{filePath: string; isESM: boolean; module: any}> { +): Promise<{filePath: string; isESM: boolean; module: T}> { let filePath: string | undefined let isESM: boolean | undefined try { @@ -102,10 +102,10 @@ export async function loadWithData( * @returns {Promise<{isESM: boolean, module: *, filePath: string}>} An object with the loaded module & data including * file path and whether the module is ESM. */ -export async function loadWithDataFromManifest( +export async function loadWithDataFromManifest( cached: Command.Cached, modulePath: string, -): Promise<{filePath: string; isESM: boolean; module: any}> { +): Promise<{filePath: string; isESM: boolean; module: T}> { const {id, isESM, relativePath} = cached if (!relativePath) { throw new ModuleLoadError(`Cached command ${id} does not have a relative path`)