-
Notifications
You must be signed in to change notification settings - Fork 26
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: use oclif/core v4 #1614
feat: use oclif/core v4 #1614
Changes from 21 commits
b09d551
5c7bf95
a80d695
bbff4db
d8e3de5
5173421
371552b
4c1b9f8
37467a5
29074e3
c469b6f
d3b8efa
5f6e3e5
1850fc7
ff45487
24d0778
ddce8c1
c9aaabd
82cc750
31330d3
3469f7c
40a5afd
719d3dd
ac7f720
87bf106
3810943
7a4c0ab
1351026
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,11 @@ | ||
#!/usr/bin/env ts-node | ||
|
||
async function main() { | ||
const oclif = await import('@oclif/core'); | ||
oclif.settings.performanceEnabled = true; | ||
await oclif.execute({ development: true, dir: import.meta.url }); | ||
const { settings } = await import('@oclif/core/settings'); | ||
const { execute } = await import('@oclif/core/execute'); | ||
|
||
settings.performanceEnabled = true; | ||
await execute({ development: true, dir: import.meta.url }); | ||
} | ||
|
||
await main(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,30 +3,13 @@ | |
// Pre-process/prune flags before creating or running the actual CLI | ||
(await import('../dist/flags.js')).preprocessCliFlags(process); | ||
|
||
const oclif = await import('@oclif/core'); | ||
const { createRequire } = await import('module'); | ||
const pjson = createRequire(import.meta.url)('../package.json'); | ||
// Since the CLI is a single process, we can have a larger amount of max listeners since | ||
// the process gets shut down. Don't set it to 0 (no limit) since we should still be aware | ||
// of rouge event listeners | ||
process.setMaxListeners(parseInt(process.env.SF_MAX_EVENT_LISTENERS, 10) || 1000); | ||
|
||
const cli = await import('../dist/cli.js'); | ||
|
||
async function main() { | ||
// Since the CLI is a single process, we can have a larger amount of max listeners since | ||
// the process gets shut down. Don't set it to 0 (no limit) since we should still be aware | ||
// of rouge event listeners | ||
process.setMaxListeners(parseInt(process.env.SF_MAX_EVENT_LISTENERS, 10) || 1000); | ||
|
||
// Don't let other plugins override the CLI specified max listener count | ||
process.setMaxListeners = () => {}; | ||
// Don't let other plugins override the CLI specified max listener count | ||
process.setMaxListeners = () => {}; | ||
|
||
cli | ||
.create({ version: pjson.version, bin: pjson.oclif.bin, channel: 'stable' }) | ||
.run() | ||
.then(async () => { | ||
await oclif.flush(); | ||
}) | ||
.catch(async (err) => { | ||
await oclif.handle(err); | ||
}); | ||
} | ||
|
||
await main(); | ||
const cli = await import('../dist/cli.js'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is it faster to |
||
await cli.run(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -139,7 +139,7 @@ | |
}, | ||
"dependencies": { | ||
"@inquirer/select": "^1.3.1", | ||
"@oclif/core": "3.26.9", | ||
"@oclif/core": "4.0.0", | ||
"@oclif/plugin-autocomplete": "3.1.2", | ||
"@oclif/plugin-commands": "4.0.2", | ||
"@oclif/plugin-help": "6.1.0", | ||
|
@@ -169,12 +169,12 @@ | |
"@salesforce/plugin-templates": "56.2.9", | ||
"@salesforce/plugin-trust": "3.7.4", | ||
"@salesforce/plugin-user": "3.5.11", | ||
"@salesforce/sf-plugins-core": "9.1.1", | ||
"chalk": "^5.3.0", | ||
"debug": "^4.3.4", | ||
"strip-ansi": "^7.1.0" | ||
"@salesforce/sf-plugins-core": "10.0.0", | ||
"ansis": "^3.2.0", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it shipped, you can bump |
||
"debug": "^4.3.4" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. debug-js/debug#926 you might want the latest of |
||
}, | ||
"pinnedDependencies": [ | ||
"@oclif/core", | ||
"@oclif/plugin-autocomplete", | ||
"@oclif/plugin-commands", | ||
"@oclif/plugin-help", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,12 +8,11 @@ | |
import { platform, arch, release } from 'node:os'; | ||
import { resolve } from 'node:path'; | ||
import { fileURLToPath } from 'node:url'; | ||
import { Config, Interfaces, run as oclifRun, settings } from '@oclif/core'; | ||
import { set } from '@salesforce/kit'; | ||
import Debug from 'debug'; | ||
import { default as nodeEnv, Env } from './util/env.js'; | ||
|
||
const debug = Debug('sf'); | ||
import { execute } from '@oclif/core/execute'; | ||
import { Config } from '@oclif/core/config'; | ||
import Interfaces from '@oclif/core/interfaces'; | ||
import NodeEnv, { Env } from './util/env.js'; | ||
import { logger } from './logger.js'; | ||
|
||
const envVars = [ | ||
...new Set([ | ||
|
@@ -41,14 +40,6 @@ export const UPDATE_DISABLED_DEMO = | |
'Manual and automatic CLI updates have been disabled in DEMO mode. ' + | ||
'To check for a new version, unset the environment variable SF_ENV.'; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if nothing else is using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and maybe the static prop on that class? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. checking my understanding: the CLI itself doesn't need to know about this, so the plugins that do need it (ex: plugin trust) can get it when they do? |
||
export function configureUpdateSites(config: Interfaces.Config, env = nodeEnv): void { | ||
const npmRegistry = env.getNpmRegistryOverride(); | ||
if (npmRegistry) { | ||
// Override config value if set via envar | ||
set(config, 'pjson.oclif.warn-if-update-available.registry', npmRegistry); | ||
} | ||
} | ||
|
||
export function configureAutoUpdate(envars: Env): void { | ||
if (envars.isDemoMode()) { | ||
// Disable autoupdates in demo mode | ||
|
@@ -76,11 +67,12 @@ export function configureAutoUpdate(envars: Env): void { | |
} | ||
} | ||
|
||
function debugCliInfo(version: string, channel: string, env: Env, config: Interfaces.Config): void { | ||
function debugCliInfo(env: Env, config: Interfaces.Config): void { | ||
mshanemc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
function debugSection(section: string, items: Array<[string, string]>): void { | ||
const pad = 25; | ||
debug('%s:', section.padStart(pad)); | ||
items.forEach(([name, value]) => debug('%s: %s', name.padStart(pad), value)); | ||
const header = `### ${section} ###`; | ||
logger.debug('%s', header.padStart(pad)); | ||
items.forEach(([name, value]) => logger.debug('%s: %s', name.padStart(pad), value)); | ||
} | ||
|
||
debugSection('OS', [ | ||
|
@@ -93,8 +85,8 @@ function debugCliInfo(version: string, channel: string, env: Env, config: Interf | |
debugSection('NODE', [['version', process.versions.node]]); | ||
|
||
debugSection('CLI', [ | ||
['version', version], | ||
['channel', channel], | ||
['version', config.version], | ||
['channel', config.channel], | ||
['bin', config.bin], | ||
['data', config.dataDir], | ||
['cache', config.cacheDir], | ||
|
@@ -112,33 +104,15 @@ function debugCliInfo(version: string, channel: string, env: Env, config: Interf | |
); | ||
} | ||
|
||
type CreateOptions = { | ||
version: string; | ||
bin: string | undefined; | ||
channel: string; | ||
run?: typeof oclifRun; | ||
env?: typeof nodeEnv; | ||
}; | ||
|
||
export function create({ version, bin, channel, run, env }: CreateOptions): { run: () => Promise<unknown> } { | ||
settings.performanceEnabled = true; | ||
const root = resolve(fileURLToPath(import.meta.url), '..'); | ||
const args = process.argv.slice(2); | ||
const environment = env ?? nodeEnv; | ||
return { | ||
async run(): Promise<unknown> { | ||
const config = new Config({ | ||
name: bin, | ||
root, | ||
version, | ||
channel, | ||
}); | ||
await config.load(); | ||
configureUpdateSites(config, environment); | ||
configureAutoUpdate(environment); | ||
debugCliInfo(version, channel, environment, config); | ||
// Example of how run is used in a test https://github.com/salesforcecli/cli/pull/171/files#diff-1deee0a575599b2df117c280da319f7938aaf6fdb0c04bcdbde769dbf464be69R46 | ||
return run ? run(args, config) : oclifRun(args, config); | ||
}, | ||
}; | ||
export async function run(): Promise<unknown> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is the part I don't understand (why we were doing it the other way before, what changed to make this the better option). It looks much cleaner, though! |
||
configureAutoUpdate(NodeEnv); | ||
const config = await Config.load({ | ||
root: resolve(fileURLToPath(import.meta.url), '..'), | ||
logger, | ||
enablePerf: true, | ||
}); | ||
debugCliInfo(NodeEnv, config); | ||
return execute({ | ||
loadOptions: config, | ||
}); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,8 +5,12 @@ | |
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause | ||
*/ | ||
|
||
import * as os from 'node:os'; | ||
import { Command, Hook, toConfiguredId, toStandardizedId, Interfaces, loadHelpClass } from '@oclif/core'; | ||
import os from 'node:os'; | ||
import { Command } from '@oclif/core/command'; | ||
import { type Hook } from '@oclif/core/hooks'; | ||
import { toConfiguredId, toStandardizedId } from '@oclif/core/util/ids'; | ||
import Interfaces from '@oclif/core/interfaces'; | ||
import { loadHelpClass } from '@oclif/core/help'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the |
||
|
||
function buildChoices( | ||
matches: Command.Loadable[], | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,8 @@ | |
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause | ||
*/ | ||
|
||
import { Hook, Errors } from '@oclif/core'; | ||
import { type Hook } from '@oclif/core/hooks'; | ||
import { handle } from '@oclif/core/handle'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe also only load this if needed inside the conditional instead of when the hook is instantiated? |
||
|
||
const hook: Hook.PluginsPreinstall = async function (options) { | ||
const verifySignHookResult = await this.config.runHook('plugins:preinstall:verify:signature', options); | ||
|
@@ -14,7 +15,7 @@ const hook: Hook.PluginsPreinstall = async function (options) { | |
); | ||
|
||
if (pluginTrustFailure !== undefined) { | ||
await Errors.handle(pluginTrustFailure.error); | ||
await handle(pluginTrustFailure.error); | ||
} | ||
}; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,8 @@ | |
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause | ||
*/ | ||
|
||
import { Hook, ux } from '@oclif/core'; | ||
import { type Hook } from '@oclif/core/hooks'; | ||
import ux from '@oclif/core/ux'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also maybe worth deferring to the conditional |
||
|
||
// eslint-disable-next-line @typescript-eslint/require-await | ||
const hook: Hook.Prerun = async function ({ Command, config }) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* | ||
* Copyright (c) 2023, salesforce.com, inc. | ||
* All rights reserved. | ||
* Licensed under the BSD 3-Clause license. | ||
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause | ||
*/ | ||
import { format } from 'node:util'; | ||
import Interfaces from '@oclif/core/interfaces'; | ||
import { Logger } from '@salesforce/core'; | ||
|
||
mshanemc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
export const customLogger = (namespace: string): Interfaces.Logger => { | ||
const sfLogger = new Logger(namespace); | ||
return { | ||
child: (ns: string, delimiter?: string) => customLogger(`${namespace}${delimiter ?? ':'}${ns}`), | ||
debug: (formatter: unknown, ...args: unknown[]) => sfLogger.debug(format(formatter, ...args)), | ||
mshanemc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
error: (formatter: unknown, ...args: unknown[]) => sfLogger.error(format(formatter, ...args)), | ||
info: (formatter: unknown, ...args: unknown[]) => sfLogger.info(format(formatter, ...args)), | ||
trace: (formatter: unknown, ...args: unknown[]) => sfLogger.trace(format(formatter, ...args)), | ||
warn: (formatter: unknown, ...args: unknown[]) => sfLogger.warn(format(formatter, ...args)), | ||
namespace, | ||
}; | ||
}; | ||
|
||
export const logger = customLogger('sf'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.