Skip to content

Commit

Permalink
Merge branch 'main' into prerelease/v2
Browse files Browse the repository at this point in the history
  • Loading branch information
mdonnalley committed Jan 19, 2023
2 parents 648a3be + eabc9ec commit 257c81b
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 13 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,4 @@
"pretest": "yarn build --noEmit && tsc -p test --noEmit --skipLibCheck"
},
"types": "lib/index.d.ts"
}
}
56 changes: 45 additions & 11 deletions src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@ export class Config implements IConfig {
},
}

await this.loadPluginsAndCommands()

debug('config done')
}

async loadPluginsAndCommands(): Promise<void> {
await this.loadUserPlugins()
await this.loadDevPlugins()
await this.loadCorePlugins()
Expand All @@ -186,8 +192,6 @@ export class Config implements IConfig {
this.loadCommands(plugin)
this.loadTopics(plugin)
}

debug('config done')
}

public async loadCorePlugins(): Promise<void> {
Expand Down Expand Up @@ -302,23 +306,39 @@ export class Config implements IConfig {

public async runCommand<T = unknown>(id: string, argv: string[] = [], cachedCommand: Command.Loadable | null = null): Promise<T> {
debug('runCommand %s %o', id, argv)
const c = cachedCommand ?? this.findCommand(id)
let c = cachedCommand ?? this.findCommand(id)
if (!c) {
const matches = this.flexibleTaxonomy ? this.findMatches(id, argv) : []
const hookResult = this.flexibleTaxonomy && matches.length > 0 ?
await this.runHook('command_incomplete', {id, argv, matches}) :
await this.runHook('command_not_found', {id, argv})

if (hookResult.successes[0]) {
const cmdResult = hookResult.successes[0].result
return cmdResult as T
}
if (hookResult.successes[0]) return hookResult.successes[0].result as T
if (hookResult.failures[0]) throw hookResult.failures[0].error
throw new CLIError(`command ${id} not found`)
}

if (hookResult.failures[0]) {
throw hookResult.failures[0].error
if (this.isJitPluginCommand(c)) {
const pluginName = c.pluginName!
const pluginVersion = this.pjson.oclif.jitPlugins![pluginName]
const jitResult = await this.runHook('jit_plugin_not_installed', {
id,
argv,
command: c,
pluginName,
pluginVersion,
})
if (jitResult.failures[0]) throw jitResult.failures[0].error
if (jitResult.successes[0]) {
await this.loadPluginsAndCommands()
c = this.findCommand(id) ?? c
} else {
// this means that no jit_plugin_not_installed hook exists, so we should run the default behavior
const result = await this.runHook('command_not_found', {id, argv})
if (result.successes[0]) return result.successes[0].result as T
if (result.failures[0]) throw result.failures[0].error
throw new CLIError(`command ${id} not found`)
}

throw new CLIError(`command ${id} not found`)
}

const command = await c.load()
Expand Down Expand Up @@ -570,6 +590,10 @@ export class Config implements IConfig {
return isProd()
}

private isJitPluginCommand(c: Command.Loadable): boolean {
return Object.keys(this.pjson.oclif.jitPlugins ?? {}).includes(c.pluginName ?? '') && !this.plugins.find(p => p.name === c?.pluginName)
}

private getCmdLookupId(id: string): string {
if (this._commands.has(id)) return id
if (this.commandPermutations.hasValid(id)) return this.commandPermutations.getValid(id)!
Expand Down Expand Up @@ -684,6 +708,16 @@ export class Config implements IConfig {
return -1
}

// if a is a jit plugin and b is not sort b first
if (a.pluginType === 'jit' && b.pluginType !== 'jit') {
return 1
}

// if b is a jit plugin and a is not sort a first
if (b.pluginType === 'jit' && a.pluginType !== 'jit') {
return -1
}

// neither plugin is core, so do not change the order
return 0
})
Expand Down
7 changes: 6 additions & 1 deletion src/config/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,12 @@ export class Plugin implements IPlugin {
this.manifest = await this._manifest(Boolean(this.options.ignoreManifest), Boolean(this.options.errorOnManifestCreate))
this.commands = Object
.entries(this.manifest.commands)
.map(([id, c]) => ({...c, pluginAlias: this.alias, pluginType: this.type, load: async () => this.findCommand(id, {must: true})}))
.map(([id, c]) => ({
...c,
pluginAlias: this.alias,
pluginType: c.pluginType === 'jit' ? 'jit' : this.type,
load: async () => this.findCommand(id, {must: true}),
}))
.sort((a, b) => a.id.localeCompare(b.id))
}

Expand Down
5 changes: 5 additions & 0 deletions src/interfaces/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ export interface Hooks {
options: {id: string; argv: string[], matches: Command.Loadable[]};
return: unknown;
};
'jit_plugin_not_installed': {
options: {id: string; argv: string[]; command: Command.Loadable, pluginName: string; pluginVersion: string};
return: unknown;
};
'plugins:preinstall': {
options: {
plugin: { name: string; tag: string; type: 'npm' } | { url: string; type: 'repo' };
Expand All @@ -60,6 +64,7 @@ export namespace Hook {
export type Update = Hook<'update'>
export type CommandNotFound = Hook<'command_not_found'>
export type CommandIncomplete = Hook<'command_incomplete'>
export type JitPluginNotInstalled = Hook<'jit_plugin_not_installed'>

export interface Context {
config: Config;
Expand Down
2 changes: 2 additions & 0 deletions src/interfaces/pjson.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export namespace PJSON {
default?: string;
plugins?: string[];
devPlugins?: string[];
jitPlugins?: Record<string, string>;
helpClass?: string;
helpOptions?: HelpOptions;
aliases?: { [name: string]: string | null };
Expand Down Expand Up @@ -80,6 +81,7 @@ export namespace PJSON {
scope?: string;
dirname?: string;
flexibleTaxonomy?: boolean;
jitPlugins?: Record<string, string>;
};
}

Expand Down
1 change: 1 addition & 0 deletions src/interfaces/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export interface PluginOptions {

export interface Options extends PluginOptions {
devPlugins?: boolean;
jitPlugins?: boolean;
userPlugins?: boolean;
channel?: string;
version?: string;
Expand Down

0 comments on commit 257c81b

Please sign in to comment.