Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: export ModuleLoader #842

Merged
merged 1 commit into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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') {
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
10 changes: 9 additions & 1 deletion src/interfaces/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -55,7 +63,7 @@ export interface Hooks {

export type Hook<T extends keyof P, P extends Hooks = Hooks> = (
this: Hook.Context,
options: P[T]['options'] & {config: Config},
options: P[T]['options'] & {config: Config; context: Context},
) => Promise<P[T]['return']>

export namespace Hook {
Expand Down
12 changes: 6 additions & 6 deletions src/module-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ const isPlugin = (config: IConfig | IPlugin): config is IPlugin => (<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<any> {
export async function load<T = any>(config: IConfig | IPlugin, modulePath: string): Promise<T> {
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}`)
Expand All @@ -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<T = any>(
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 {
Expand Down Expand Up @@ -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<T = any>(
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`)
Expand Down
Loading