first commit

This commit is contained in:
2025-10-26 23:10:15 +08:00
commit 8f0345b7be
14961 changed files with 2356381 additions and 0 deletions

136
node_modules/@oclif/core/lib/config/config.d.ts generated vendored Normal file
View File

@@ -0,0 +1,136 @@
import { Command } from '../command';
import { Hook, Hooks, OclifConfiguration, PJSON, S3Templates, Topic, UserPJSON } from '../interfaces';
import { ArchTypes, Config as IConfig, LoadOptions, PlatformTypes, VersionDetails } from '../interfaces/config';
import { Plugin as IPlugin, Options } from '../interfaces/plugin';
import { Theme } from '../interfaces/theme';
export declare class Config implements IConfig {
options: Options;
arch: ArchTypes;
bin: string;
binAliases?: string[] | undefined;
binPath?: string | undefined;
cacheDir: string;
channel: string;
configDir: string;
dataDir: string;
dirname: string;
flexibleTaxonomy: boolean;
home: string;
isSingleCommandCLI: boolean;
name: string;
npmRegistry?: string | undefined;
nsisCustomization?: string | undefined;
pjson: PJSON;
platform: PlatformTypes;
plugins: Map<string, IPlugin>;
root: string;
shell: string;
theme?: Theme | undefined;
topicSeparator: ' ' | ':';
updateConfig: NonNullable<OclifConfiguration['update']>;
userAgent: string;
userPJSON?: UserPJSON | undefined;
valid: boolean;
version: string;
protected warned: boolean;
windows: boolean;
private _base;
private _commandIDs;
private _commands;
private _topics;
private commandPermutations;
private pluginLoader;
private rootPlugin;
private topicPermutations;
constructor(options: Options);
static load(opts?: LoadOptions): Promise<Config>;
get commandIDs(): string[];
get commands(): Command.Loadable[];
protected get isProd(): boolean;
static get rootPlugin(): IPlugin | undefined;
get topics(): Topic[];
get versionDetails(): VersionDetails;
protected _shell(): string;
protected dir(category: 'cache' | 'config' | 'data'): string;
findCommand(id: string, opts: {
must: true;
}): Command.Loadable;
findCommand(id: string, opts?: {
must: boolean;
}): Command.Loadable | undefined;
/**
* Find all command ids that include the provided command id.
*
* For example, if the command ids are:
* - foo:bar:baz
* - one:two:three
*
* `bar` would return `foo:bar:baz`
*
* @param partialCmdId string
* @param argv string[] process.argv containing the flags and arguments provided by the user
* @returns string[]
*/
findMatches(partialCmdId: string, argv: string[]): Command.Loadable[];
findTopic(id: string, opts: {
must: true;
}): Topic;
findTopic(id: string, opts?: {
must: boolean;
}): Topic | undefined;
/**
* Returns an array of all command ids. If flexible taxonomy is enabled then all permutations will be appended to the array.
* @returns string[]
*/
getAllCommandIDs(): string[];
/**
* Returns an array of all commands. If flexible taxonomy is enabled then all permutations will be appended to the array.
* @returns Command.Loadable[]
*/
getAllCommands(): Command.Loadable[];
getPluginsList(): IPlugin[];
load(): Promise<void>;
loadPluginsAndCommands(opts?: {
force: boolean;
}): Promise<void>;
loadTheme(): Promise<Theme | undefined>;
protected macosCacheDir(): string | undefined;
runCommand<T = unknown>(id: string, argv?: string[], cachedCommand?: Command.Loadable | null): Promise<T>;
runHook<T extends keyof Hooks, P extends Hooks = Hooks>(event: T, opts: P[T]['options'], timeout?: number, captureErrors?: boolean): Promise<Hook.Result<P[T]['return']>>;
s3Key(type: keyof S3Templates, ext?: '.tar.gz' | '.tar.xz' | IConfig.s3Key.Options, options?: IConfig.s3Key.Options): string;
s3Url(key: string): string;
scopedEnvVar(k: string): string | undefined;
/**
* this DOES NOT account for bin aliases, use scopedEnvVarKeys instead which will account for bin aliases
* @param k {string}, the unscoped key you want to get the value for
* @returns {string} returns the env var key
*/
scopedEnvVarKey(k: string): string;
/**
* gets the scoped env var keys for a given key, including bin aliases
* @param k {string}, the env key e.g. 'debug'
* @returns {string[]} e.g. ['SF_DEBUG', 'SFDX_DEBUG']
*/
scopedEnvVarKeys(k: string): string[];
scopedEnvVarTrue(k: string): boolean;
protected windowsHome(): string | undefined;
protected windowsHomedriveHome(): string | undefined;
protected windowsUserprofileHome(): string | undefined;
private buildS3Config;
private getCmdLookupId;
private getTopicLookupId;
/**
* Insert legacy plugins
*
* Replace invalid CLI plugins (cli-engine plugins, mostly Heroku) loaded via `this.loadPlugins`
* with oclif-compatible ones returned by @oclif/plugin-legacy init hook.
*
* @param plugins array of oclif-compatible plugins
*/
private insertLegacyPlugins;
private isJitPluginCommand;
private loadCommands;
private loadTopics;
private maybeAdjustDebugSetting;
private warn;
}

816
node_modules/@oclif/core/lib/config/config.js generated vendored Normal file
View File

@@ -0,0 +1,816 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Config = void 0;
const ejs = __importStar(require("ejs"));
const is_wsl_1 = __importDefault(require("is-wsl"));
const node_os_1 = require("node:os");
const node_path_1 = require("node:path");
const node_url_1 = require("node:url");
const cache_1 = __importDefault(require("../cache"));
const errors_1 = require("../errors");
const util_1 = require("../help/util");
const logger_1 = require("../logger");
const module_loader_1 = require("../module-loader");
const performance_1 = require("../performance");
const settings_1 = require("../settings");
const determine_priority_1 = require("../util/determine-priority");
const fs_1 = require("../util/fs");
const ids_1 = require("../util/ids");
const os_1 = require("../util/os");
const util_2 = require("../util/util");
const ux_1 = require("../ux");
const theme_1 = require("../ux/theme");
const plugin_loader_1 = __importDefault(require("./plugin-loader"));
const ts_path_1 = require("./ts-path");
const util_3 = require("./util");
const debug = (0, util_3.makeDebug)();
const _pjson = cache_1.default.getInstance().get('@oclif/core');
const BASE = `${_pjson.name}@${_pjson.version}`;
const ROOT_ONLY_HOOKS = new Set(['preparse']);
function displayWarnings() {
if (process.listenerCount('warning') > 1)
return;
process.on('warning', (warning) => {
console.error(warning.stack);
if (warning.detail)
console.error(warning.detail);
});
}
function channelFromVersion(version) {
const m = version.match(/[^-]+(?:-([^.]+))?/);
return (m && m[1]) || 'stable';
}
function isConfig(o) {
return o && Boolean(o._base);
}
class Permutations extends Map {
validPermutations = new Map();
add(permutation, commandId) {
this.validPermutations.set(permutation, commandId);
for (const id of (0, util_3.collectUsableIds)([permutation])) {
if (this.has(id)) {
this.set(id, this.get(id).add(commandId));
}
else {
this.set(id, new Set([commandId]));
}
}
}
get(key) {
return super.get(key) ?? new Set();
}
getAllValid() {
return [...this.validPermutations.keys()];
}
getValid(key) {
return this.validPermutations.get(key);
}
hasValid(key) {
return this.validPermutations.has(key);
}
}
class Config {
options;
arch;
bin;
binAliases;
binPath;
cacheDir;
channel;
configDir;
dataDir;
dirname;
flexibleTaxonomy;
home;
isSingleCommandCLI = false;
name;
npmRegistry;
nsisCustomization;
pjson;
platform;
plugins = new Map();
root;
shell;
theme;
topicSeparator = ':';
updateConfig;
userAgent;
userPJSON;
valid;
version;
warned = false;
windows;
_base = BASE;
_commandIDs;
_commands = new Map();
_topics = new Map();
commandPermutations = new Permutations();
pluginLoader;
rootPlugin;
topicPermutations = new Permutations();
constructor(options) {
this.options = options;
}
static async load(opts = module.filename || __dirname) {
(0, logger_1.setLogger)(opts);
// Handle the case when a file URL string is passed in such as 'import.meta.url'; covert to file path.
if (typeof opts === 'string' && opts.startsWith('file://')) {
opts = (0, node_url_1.fileURLToPath)(opts);
}
if (typeof opts === 'string')
opts = { root: opts };
if (isConfig(opts)) {
/**
* Reload the Config based on the version required by the command.
* This is needed because the command is given the Config instantiated
* by the root plugin, which may be a different version than the one
* required by the command.
*
* Doing this ensures that the command can freely use any method on Config that
* exists in the version of Config required by the command but may not exist on the
* root's instance of Config.
*/
if (BASE !== opts._base) {
debug(`reloading config from ${opts._base} to ${BASE}`);
const config = new Config({ ...opts.options, plugins: opts.plugins });
await config.load();
return config;
}
return opts;
}
const config = new Config(opts);
await config.load();
return config;
}
get commandIDs() {
if (this._commandIDs)
return this._commandIDs;
this._commandIDs = this.commands.map((c) => c.id);
return this._commandIDs;
}
get commands() {
return [...this._commands.values()];
}
get isProd() {
return (0, util_2.isProd)();
}
static get rootPlugin() {
return this.rootPlugin;
}
get topics() {
return [...this._topics.values()];
}
get versionDetails() {
const [cliVersion, architecture, nodeVersion] = this.userAgent.split(' ');
return {
architecture,
cliVersion,
nodeVersion,
osVersion: `${(0, node_os_1.type)()} ${(0, node_os_1.release)()}`,
pluginVersions: Object.fromEntries([...this.plugins.values()].map((p) => [p.name, { root: p.root, type: p.type, version: p.version }])),
rootPath: this.root,
shell: this.shell,
};
}
_shell() {
let shellPath;
const { COMSPEC } = process.env;
const SHELL = process.env.SHELL ?? (0, node_os_1.userInfo)().shell?.split(node_path_1.sep)?.pop();
if (SHELL) {
shellPath = SHELL.split('/');
}
else if (this.windows && process.title.toLowerCase().includes('powershell')) {
shellPath = ['powershell'];
}
else if (this.windows && process.title.toLowerCase().includes('command prompt')) {
shellPath = ['cmd.exe'];
}
else if (this.windows && COMSPEC) {
shellPath = COMSPEC.split(/\\|\//);
}
else {
shellPath = ['unknown'];
}
return shellPath.at(-1) ?? 'unknown';
}
dir(category) {
const base = process.env[`XDG_${category.toUpperCase()}_HOME`] ||
(this.windows && process.env.LOCALAPPDATA) ||
(0, node_path_1.join)(this.home, category === 'data' ? '.local/share' : '.' + category);
return (0, node_path_1.join)(base, this.dirname);
}
findCommand(id, opts = {}) {
const lookupId = this.getCmdLookupId(id);
const command = this._commands.get(lookupId);
if (opts.must && !command)
(0, errors_1.error)(`command ${lookupId} not found`);
return command;
}
/**
* Find all command ids that include the provided command id.
*
* For example, if the command ids are:
* - foo:bar:baz
* - one:two:three
*
* `bar` would return `foo:bar:baz`
*
* @param partialCmdId string
* @param argv string[] process.argv containing the flags and arguments provided by the user
* @returns string[]
*/
findMatches(partialCmdId, argv) {
const flags = argv
.filter((arg) => !(0, util_1.getHelpFlagAdditions)(this).includes(arg) && arg.startsWith('-'))
.map((a) => a.replaceAll('-', ''));
const possibleMatches = [...this.commandPermutations.get(partialCmdId)].map((k) => this._commands.get(k));
const matches = possibleMatches.filter((command) => {
const cmdFlags = Object.entries(command.flags).flatMap(([flag, def]) => def.char ? [def.char, flag] : [flag]);
// A command is a match if the provided flags belong to the full command
return flags.every((f) => cmdFlags.includes(f));
});
return matches;
}
findTopic(name, opts = {}) {
const lookupId = this.getTopicLookupId(name);
const topic = this._topics.get(lookupId);
if (topic)
return topic;
if (opts.must)
throw new Error(`topic ${name} not found`);
}
/**
* Returns an array of all command ids. If flexible taxonomy is enabled then all permutations will be appended to the array.
* @returns string[]
*/
getAllCommandIDs() {
return this.getAllCommands().map((c) => c.id);
}
/**
* Returns an array of all commands. If flexible taxonomy is enabled then all permutations will be appended to the array.
* @returns Command.Loadable[]
*/
getAllCommands() {
const commands = [...this._commands.values()];
const validPermutations = [...this.commandPermutations.getAllValid()];
for (const permutation of validPermutations) {
if (!this._commands.has(permutation)) {
const cmd = this._commands.get(this.getCmdLookupId(permutation));
commands.push({ ...cmd, id: permutation });
}
}
return commands;
}
getPluginsList() {
return [...this.plugins.values()];
}
// eslint-disable-next-line complexity
async load() {
settings_1.settings.performanceEnabled =
(settings_1.settings.performanceEnabled === undefined ? this.options.enablePerf : settings_1.settings.performanceEnabled) ?? false;
if (settings_1.settings.debug)
displayWarnings();
(0, logger_1.setLogger)(this.options);
const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, 'config.load');
this.pluginLoader = new plugin_loader_1.default({ plugins: this.options.plugins, root: this.options.root });
this.rootPlugin = await this.pluginLoader.loadRoot({ pjson: this.options.pjson });
// Cache the root plugin so that we can reference it later when determining if
// we should skip ts-node registration for an ESM plugin.
const cache = cache_1.default.getInstance();
cache.set('rootPlugin', this.rootPlugin);
cache.set('exitCodes', this.rootPlugin.pjson.oclif.exitCodes ?? {});
this.root = this.rootPlugin.root;
this.pjson = this.rootPlugin.pjson;
this.plugins.set(this.rootPlugin.name, this.rootPlugin);
this.root = this.rootPlugin.root;
this.pjson = this.rootPlugin.pjson;
this.name = this.pjson.name;
this.version = this.options.version || this.pjson.version || '0.0.0';
this.channel = this.options.channel || channelFromVersion(this.version);
this.valid = this.rootPlugin.valid;
this.arch = (0, node_os_1.arch)() === 'ia32' ? 'x86' : (0, node_os_1.arch)();
this.platform = is_wsl_1.default ? 'wsl' : (0, os_1.getPlatform)();
this.windows = this.platform === 'win32';
this.bin = this.pjson.oclif.bin || this.name;
this.binAliases = this.pjson.oclif.binAliases;
this.nsisCustomization = this.pjson.oclif.nsisCustomization;
this.dirname = this.pjson.oclif.dirname || this.name;
this.flexibleTaxonomy = this.pjson.oclif.flexibleTaxonomy || false;
// currently, only colons or spaces are valid separators
if (this.pjson.oclif.topicSeparator && [' ', ':'].includes(this.pjson.oclif.topicSeparator))
this.topicSeparator = this.pjson.oclif.topicSeparator;
if (this.platform === 'win32')
this.dirname = this.dirname.replace('/', '\\');
this.userAgent = `${this.name}/${this.version} ${this.platform}-${this.arch} node-${process.version}`;
this.shell = this._shell();
this.home = process.env.HOME || (this.windows && this.windowsHome()) || (0, os_1.getHomeDir)() || (0, node_os_1.tmpdir)();
this.cacheDir = this.scopedEnvVar('CACHE_DIR') || this.macosCacheDir() || this.dir('cache');
this.configDir = this.scopedEnvVar('CONFIG_DIR') || this.dir('config');
this.dataDir = this.scopedEnvVar('DATA_DIR') || this.dir('data');
this.binPath = this.scopedEnvVar('BINPATH');
this.npmRegistry = this.scopedEnvVar('NPM_REGISTRY') || this.pjson.oclif.npmRegistry;
this.theme = await this.loadTheme();
this.updateConfig = {
...this.pjson.oclif.update,
node: this.pjson.oclif.update?.node ?? {},
s3: this.buildS3Config(),
};
this.isSingleCommandCLI = Boolean(typeof this.pjson.oclif.commands !== 'string' &&
this.pjson.oclif.commands?.strategy === 'single' &&
this.pjson.oclif.commands?.target);
this.maybeAdjustDebugSetting();
await this.loadPluginsAndCommands();
debug('config done');
marker?.addDetails({
commandPermutations: this.commands.length,
commands: [...this.plugins.values()].reduce((acc, p) => acc + p.commands.length, 0),
plugins: this.plugins.size,
topics: this.topics.length,
});
marker?.stop();
}
async loadPluginsAndCommands(opts) {
const pluginsMarker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, 'config.loadAllPlugins');
const { errors, plugins } = await this.pluginLoader.loadChildren({
dataDir: this.dataDir,
devPlugins: this.options.devPlugins,
force: opts?.force ?? false,
pluginAdditions: this.options.pluginAdditions,
rootPlugin: this.rootPlugin,
userPlugins: this.options.userPlugins,
});
this.plugins = plugins;
pluginsMarker?.stop();
const commandsMarker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, 'config.loadAllCommands');
for (const plugin of this.plugins.values()) {
this.loadCommands(plugin);
this.loadTopics(plugin);
}
commandsMarker?.stop();
for (const error of errors) {
this.warn(error);
}
}
async loadTheme() {
if (this.scopedEnvVarTrue('DISABLE_THEME'))
return;
const userThemeFile = (0, node_path_1.resolve)(this.configDir, 'theme.json');
const getDefaultTheme = async () => {
if (!this.pjson.oclif.theme)
return;
if (typeof this.pjson.oclif.theme === 'string') {
return (0, fs_1.safeReadJson)((0, node_path_1.resolve)(this.root, this.pjson.oclif.theme));
}
return this.pjson.oclif.theme;
};
const [defaultTheme, userTheme] = await Promise.all([
getDefaultTheme(),
(0, fs_1.safeReadJson)(userThemeFile),
]);
// Merge the default theme with the user theme, giving the user theme precedence.
const merged = { ...defaultTheme, ...userTheme };
return Object.keys(merged).length > 0 ? (0, theme_1.parseTheme)(merged) : undefined;
}
macosCacheDir() {
return (this.platform === 'darwin' && (0, node_path_1.join)(this.home, 'Library', 'Caches', this.dirname)) || undefined;
}
async runCommand(id, argv = [], cachedCommand = null) {
const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, `config.runCommand#${id}`);
debug('runCommand %s %o', id, argv);
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', { argv, id, matches })
: await this.runHook('command_not_found', { argv, id });
if (hookResult.successes[0])
return hookResult.successes[0].result;
if (hookResult.failures[0])
throw hookResult.failures[0].error;
throw new errors_1.CLIError(`command ${id} not found`);
}
if (this.isJitPluginCommand(c)) {
const pluginName = c.pluginName;
const pluginVersion = this.pjson.oclif.jitPlugins[pluginName];
const jitResult = await this.runHook('jit_plugin_not_installed', {
argv,
command: c,
id,
pluginName,
pluginVersion,
});
if (jitResult.failures[0])
throw jitResult.failures[0].error;
if (jitResult.successes[0]) {
await this.loadPluginsAndCommands({ force: true });
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', { argv, id });
if (result.successes[0])
return result.successes[0].result;
if (result.failures[0])
throw result.failures[0].error;
throw new errors_1.CLIError(`command ${id} not found`);
}
}
const command = await c.load();
await this.runHook('prerun', { argv, Command: command });
const result = (await command.run(argv, this));
// If plugins:uninstall was run, we need to remove all the uninstalled plugins
// from this.plugins so that the postrun hook doesn't attempt to run any
// hooks that might have existed in the uninstalled plugins.
if (c.id === 'plugins:uninstall') {
for (const arg of argv)
this.plugins.delete(arg);
}
await this.runHook('postrun', { argv, Command: command, result });
marker?.addDetails({ command: id, plugin: c.pluginName });
marker?.stop();
return result;
}
async runHook(event, opts, timeout, captureErrors) {
const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, `config.runHook#${event}`);
debug('start %s hook', event);
const search = (m) => {
if (typeof m === 'function')
return m;
if (m.default && typeof m.default === 'function')
return m.default;
return Object.values(m).find((m) => typeof m === 'function');
};
const withTimeout = async (ms, promise) => {
let id;
const timeout = new Promise((_, reject) => {
id = setTimeout(() => {
reject(new Error(`Timed out after ${ms} ms.`));
}, ms).unref();
});
return Promise.race([promise, timeout]).then((result) => {
clearTimeout(id);
return result;
});
};
const final = {
failures: [],
successes: [],
};
const plugins = ROOT_ONLY_HOOKS.has(event) ? [this.rootPlugin] : [...this.plugins.values()];
const promises = plugins.map(async (p) => {
const debug = (0, logger_1.makeDebug)([p.name, 'hooks', event].join(':'));
const context = {
config: this,
debug,
error(message, options = {}) {
(0, errors_1.error)(message, options);
},
exit(code = 0) {
(0, errors_1.exit)(code);
},
log(message, ...args) {
ux_1.ux.stdout(message, ...args);
},
warn(message) {
(0, errors_1.warn)(message);
},
};
const hooks = p.hooks[event] || [];
for (const hook of hooks) {
const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, `config.runHook#${p.name}(${hook.target})`);
try {
/* eslint-disable no-await-in-loop */
const { filePath, isESM, module } = await (0, module_loader_1.loadWithData)(p, await (0, ts_path_1.tsPath)(p.root, hook.target, p));
debug('start', isESM ? '(import)' : '(require)', filePath);
// If no hook is found using the identifier, then we should `search` for the hook but only if the hook identifier is 'default'
// A named identifier (e.g. MY_HOOK) that isn't found indicates that the hook isn't implemented in the plugin.
const hookFn = module[hook.identifier] ?? (hook.identifier === 'default' ? search(module) : undefined);
if (!hookFn) {
debug('No hook found for hook definition:', hook);
continue;
}
const result = timeout
? await withTimeout(timeout, hookFn.call(context, { ...opts, config: this, context }))
: await hookFn.call(context, { ...opts, config: this, context });
final.successes.push({ plugin: p, result });
if (p.name === '@oclif/plugin-legacy' && event === 'init') {
this.insertLegacyPlugins(result);
}
debug('done');
}
catch (error) {
final.failures.push({ error: error, plugin: p });
debug(error);
// Do not throw the error if
// captureErrors is set to true
// error.oclif.exit is undefined or 0
// error.code is MODULE_NOT_FOUND
if (!captureErrors &&
error.oclif?.exit !== undefined &&
error.oclif?.exit !== 0 &&
error.code !== 'MODULE_NOT_FOUND')
throw error;
}
marker?.addDetails({
event,
hook: hook.target,
plugin: p.name,
});
marker?.stop();
}
});
await Promise.all(promises);
debug('%s hook done', event);
marker?.stop();
return final;
}
s3Key(type, ext, options = {}) {
if (typeof ext === 'object')
options = ext;
else if (ext)
options.ext = ext;
const template = this.updateConfig.s3?.templates?.[options.platform ? 'target' : 'vanilla'][type] ?? '';
return ejs.render(template, { ...this, ...options });
}
s3Url(key) {
const { host } = this.updateConfig.s3 ?? { host: undefined };
if (!host)
throw new Error('no s3 host is set');
const url = new node_url_1.URL(host);
url.pathname = (0, node_path_1.join)(url.pathname, key);
return url.toString();
}
scopedEnvVar(k) {
return process.env[this.scopedEnvVarKeys(k).find((k) => process.env[k])];
}
/**
* this DOES NOT account for bin aliases, use scopedEnvVarKeys instead which will account for bin aliases
* @param k {string}, the unscoped key you want to get the value for
* @returns {string} returns the env var key
*/
scopedEnvVarKey(k) {
return [this.bin, k]
.map((p) => p.replaceAll('@', '').replaceAll(/[/-]/g, '_'))
.join('_')
.toUpperCase();
}
/**
* gets the scoped env var keys for a given key, including bin aliases
* @param k {string}, the env key e.g. 'debug'
* @returns {string[]} e.g. ['SF_DEBUG', 'SFDX_DEBUG']
*/
scopedEnvVarKeys(k) {
return [this.bin, ...(this.binAliases ?? [])]
.filter(Boolean)
.map((alias) => [alias.replaceAll('@', '').replaceAll(/[/-]/g, '_'), k].join('_').toUpperCase());
}
scopedEnvVarTrue(k) {
const v = this.scopedEnvVar(k);
return v === '1' || v === 'true';
}
windowsHome() {
return this.windowsHomedriveHome() || this.windowsUserprofileHome();
}
windowsHomedriveHome() {
return process.env.HOMEDRIVE && process.env.HOMEPATH && (0, node_path_1.join)(process.env.HOMEDRIVE, process.env.HOMEPATH);
}
windowsUserprofileHome() {
return process.env.USERPROFILE;
}
buildS3Config() {
const s3 = this.pjson.oclif.update?.s3;
const bucket = this.scopedEnvVar('S3_BUCKET') ?? s3?.bucket;
const host = s3?.host ?? (bucket && `https://${bucket}.s3.amazonaws.com`);
const templates = {
...s3?.templates,
target: {
baseDir: '<%- bin %>',
manifest: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %><%- platform %>-<%- arch %>",
unversioned: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %><%- bin %>-<%- platform %>-<%- arch %><%- ext %>",
versioned: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %><%- bin %>-v<%- version %>/<%- bin %>-v<%- version %>-<%- platform %>-<%- arch %><%- ext %>",
...(s3?.templates && s3?.templates.target),
},
vanilla: {
baseDir: '<%- bin %>',
manifest: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %>version",
unversioned: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %><%- bin %><%- ext %>",
versioned: "<%- channel === 'stable' ? '' : 'channels/' + channel + '/' %><%- bin %>-v<%- version %>/<%- bin %>-v<%- version %><%- ext %>",
...(s3?.templates && s3?.templates.vanilla),
},
};
return {
bucket,
host,
templates,
};
}
getCmdLookupId(id) {
if (this._commands.has(id))
return id;
if (this.commandPermutations.hasValid(id))
return this.commandPermutations.getValid(id);
return id;
}
getTopicLookupId(id) {
if (this._topics.has(id))
return id;
if (this.topicPermutations.hasValid(id))
return this.topicPermutations.getValid(id);
return id;
}
/**
* Insert legacy plugins
*
* Replace invalid CLI plugins (cli-engine plugins, mostly Heroku) loaded via `this.loadPlugins`
* with oclif-compatible ones returned by @oclif/plugin-legacy init hook.
*
* @param plugins array of oclif-compatible plugins
*/
insertLegacyPlugins(plugins) {
for (const plugin of plugins) {
this.plugins.set(plugin.name, plugin);
// Delete all commands from the legacy plugin so that we can re-add them.
// This is necessary because determinePriority will pick the initial
// command that was added, which won't have been converted by PluginLegacy yet.
for (const cmd of plugin.commands ?? []) {
this._commands.delete(cmd.id);
for (const alias of [...(cmd.aliases ?? []), ...(cmd.hiddenAliases ?? [])]) {
this._commands.delete(alias);
}
}
this.loadCommands(plugin);
}
}
isJitPluginCommand(c) {
// Return true if the command's plugin is listed under oclif.jitPlugins AND if the plugin hasn't been loaded to this.plugins
return (Object.keys(this.pjson.oclif.jitPlugins ?? {}).includes(c.pluginName ?? '') &&
Boolean(c?.pluginName && !this.plugins.has(c.pluginName)));
}
loadCommands(plugin) {
const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, `config.loadCommands#${plugin.name}`, { plugin: plugin.name });
for (const command of plugin.commands) {
// set canonical command id
if (this._commands.has(command.id)) {
const prioritizedCommand = (0, determine_priority_1.determinePriority)(this.pjson.oclif.plugins ?? [], [
this._commands.get(command.id),
command,
]);
this._commands.set(prioritizedCommand.id, prioritizedCommand);
}
else {
this._commands.set(command.id, command);
}
// v3 moved command id permutations to the manifest, but some plugins may not have
// the new manifest yet. For those, we need to calculate the permutations here.
const permutations = this.flexibleTaxonomy && command.permutations === undefined
? (0, util_3.getCommandIdPermutations)(command.id)
: (command.permutations ?? [command.id]);
// set every permutation
for (const permutation of permutations) {
this.commandPermutations.add(permutation, command.id);
}
const handleAlias = (alias, hidden = false) => {
const aliasWithDefaultTopicSeparator = (0, ids_1.toStandardizedId)(alias, this);
if (this._commands.has(aliasWithDefaultTopicSeparator)) {
const prioritizedCommand = (0, determine_priority_1.determinePriority)(this.pjson.oclif.plugins ?? [], [
this._commands.get(aliasWithDefaultTopicSeparator),
command,
]);
this._commands.set(aliasWithDefaultTopicSeparator, {
...prioritizedCommand,
id: aliasWithDefaultTopicSeparator,
});
}
else {
this._commands.set(aliasWithDefaultTopicSeparator, { ...command, hidden, id: aliasWithDefaultTopicSeparator });
}
// set every permutation of the aliases
// v3 moved command alias permutations to the manifest, but some plugins may not have
// the new manifest yet. For those, we need to calculate the permutations here.
const aliasPermutations = this.flexibleTaxonomy && command.aliasPermutations === undefined
? (0, util_3.getCommandIdPermutations)(aliasWithDefaultTopicSeparator)
: (command.permutations ?? [aliasWithDefaultTopicSeparator]);
// set every permutation
for (const permutation of aliasPermutations) {
this.commandPermutations.add(permutation, command.id);
}
};
// set command aliases
for (const alias of command.aliases ?? []) {
handleAlias(alias);
}
// set hidden command aliases
for (const alias of command.hiddenAliases ?? []) {
handleAlias(alias, true);
}
}
marker?.addDetails({ commandCount: plugin.commands.length });
marker?.stop();
}
loadTopics(plugin) {
const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, `config.loadTopics#${plugin.name}`, { plugin: plugin.name });
for (const topic of (0, util_2.compact)(plugin.topics)) {
const existing = this._topics.get(topic.name);
if (existing) {
existing.description = topic.description || existing.description;
existing.hidden = existing.hidden || topic.hidden;
}
else {
this._topics.set(topic.name, topic);
}
const permutations = this.flexibleTaxonomy ? (0, util_3.getCommandIdPermutations)(topic.name) : [topic.name];
for (const permutation of permutations) {
this.topicPermutations.add(permutation, topic.name);
}
}
// Add missing topics for displaying help when partial commands are entered.
for (const c of plugin.commands.filter((c) => !c.hidden)) {
const parts = c.id.split(':');
while (parts.length > 0) {
const name = parts.join(':');
if (name && !this._topics.has(name)) {
this._topics.set(name, { description: c.summary || c.description, name });
}
parts.pop();
}
}
marker?.stop();
}
maybeAdjustDebugSetting() {
if (this.scopedEnvVarTrue('DEBUG')) {
settings_1.settings.debug = true;
displayWarnings();
}
}
warn(err, scope) {
if (this.warned)
return;
if (typeof err === 'string') {
process.emitWarning(err);
return;
}
if (err instanceof Error) {
const modifiedErr = err;
modifiedErr.name = `${err.name} Plugin: ${this.name}`;
modifiedErr.detail = (0, util_2.compact)([
err.detail,
`module: ${this._base}`,
scope && `task: ${scope}`,
`plugin: ${this.name}`,
`root: ${this.root}`,
'See more details with DEBUG=*',
]).join('\n');
process.emitWarning(err);
return;
}
// err is an object
process.emitWarning('Config.warn expected either a string or Error, but instead received an object');
err.name = `${err.name} Plugin: ${this.name}`;
err.detail = (0, util_2.compact)([
err.detail,
`module: ${this._base}`,
scope && `task: ${scope}`,
`plugin: ${this.name}`,
`root: ${this.root}`,
'See more details with DEBUG=*',
]).join('\n');
process.emitWarning(JSON.stringify(err));
}
}
exports.Config = Config;

3
node_modules/@oclif/core/lib/config/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,3 @@
export { Config } from './config';
export { Plugin } from './plugin';
export { tsPath } from './ts-path';

9
node_modules/@oclif/core/lib/config/index.js generated vendored Normal file
View File

@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.tsPath = exports.Plugin = exports.Config = void 0;
var config_1 = require("./config");
Object.defineProperty(exports, "Config", { enumerable: true, get: function () { return config_1.Config; } });
var plugin_1 = require("./plugin");
Object.defineProperty(exports, "Plugin", { enumerable: true, get: function () { return plugin_1.Plugin; } });
var ts_path_1 = require("./ts-path");
Object.defineProperty(exports, "tsPath", { enumerable: true, get: function () { return ts_path_1.tsPath; } });

38
node_modules/@oclif/core/lib/config/plugin-loader.d.ts generated vendored Normal file
View File

@@ -0,0 +1,38 @@
import { PJSON } from '../interfaces';
import { Plugin as IPlugin } from '../interfaces/plugin';
type PluginLoaderOptions = {
plugins?: IPlugin[] | PluginsMap | undefined;
root: string;
};
type LoadOpts = {
dataDir: string;
devPlugins?: boolean | undefined;
force?: boolean | undefined;
rootPlugin: IPlugin;
userPlugins?: boolean | undefined;
pluginAdditions?: {
core?: string[];
dev?: string[];
path?: string;
} | undefined;
};
type PluginsMap = Map<string, IPlugin>;
export default class PluginLoader {
options: PluginLoaderOptions;
errors: (Error | string)[];
plugins: PluginsMap;
private pluginsProvided;
constructor(options: PluginLoaderOptions);
loadChildren(opts: LoadOpts): Promise<{
errors: (Error | string)[];
plugins: PluginsMap;
}>;
loadRoot({ pjson }: {
pjson?: PJSON | undefined;
}): Promise<IPlugin>;
private loadCorePlugins;
private loadDevPlugins;
private loadPlugins;
private loadUserPlugins;
}
export {};

188
node_modules/@oclif/core/lib/config/plugin-loader.js generated vendored Normal file
View File

@@ -0,0 +1,188 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const minimatch_1 = require("minimatch");
const node_path_1 = require("node:path");
const performance_1 = require("../performance");
const fs_1 = require("../util/fs");
const util_1 = require("../util/util");
const plugin_1 = require("./plugin");
const util_2 = require("./util");
const debug = (0, util_2.makeDebug)();
function findMatchingDependencies(dependencies, patterns) {
return Object.keys(dependencies).filter((p) => patterns.some((w) => (0, minimatch_1.minimatch)(p, w)));
}
class PluginLoader {
options;
errors = [];
plugins = new Map();
pluginsProvided = false;
constructor(options) {
this.options = options;
if (options.plugins) {
this.pluginsProvided = true;
this.plugins = Array.isArray(options.plugins) ? new Map(options.plugins.map((p) => [p.name, p])) : options.plugins;
}
}
async loadChildren(opts) {
if (!this.pluginsProvided || opts.force) {
await this.loadUserPlugins(opts);
await this.loadDevPlugins(opts);
await this.loadCorePlugins(opts);
}
return { errors: this.errors, plugins: this.plugins };
}
async loadRoot({ pjson }) {
let rootPlugin;
if (this.pluginsProvided) {
const plugins = [...this.plugins.values()];
rootPlugin = plugins.find((p) => p.root === this.options.root) ?? plugins[0];
}
else {
const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, 'plugin.load#root');
rootPlugin = new plugin_1.Plugin({ isRoot: true, pjson, root: this.options.root });
await rootPlugin.load();
marker?.addDetails({
commandCount: rootPlugin.commands.length,
hasManifest: rootPlugin.hasManifest ?? false,
name: rootPlugin.name,
topicCount: rootPlugin.topics.length,
type: rootPlugin.type,
usesMain: Boolean(rootPlugin.pjson.main),
});
marker?.stop();
}
this.plugins.set(rootPlugin.name, rootPlugin);
return rootPlugin;
}
async loadCorePlugins(opts) {
const { plugins: corePlugins } = opts.rootPlugin.pjson.oclif;
if (corePlugins) {
const plugins = findMatchingDependencies(opts.rootPlugin.pjson.dependencies ?? {}, corePlugins);
await this.loadPlugins(opts.rootPlugin.root, 'core', plugins);
}
const { core: pluginAdditionsCore, path } = opts.pluginAdditions ?? { core: [] };
if (pluginAdditionsCore) {
if (path) {
// If path is provided, load plugins from the path
const pjson = await (0, fs_1.readJson)((0, node_path_1.join)(path, 'package.json'));
const plugins = findMatchingDependencies(pjson.dependencies ?? {}, pluginAdditionsCore);
await this.loadPlugins(path, 'core', plugins);
}
else {
const plugins = findMatchingDependencies(opts.rootPlugin.pjson.dependencies ?? {}, pluginAdditionsCore);
await this.loadPlugins(opts.rootPlugin.root, 'core', plugins);
}
}
}
async loadDevPlugins(opts) {
if (opts.devPlugins !== false) {
// do not load oclif.devPlugins in production
if ((0, util_1.isProd)())
return;
try {
const { devPlugins } = opts.rootPlugin.pjson.oclif;
if (devPlugins) {
const allDeps = { ...opts.rootPlugin.pjson.dependencies, ...opts.rootPlugin.pjson.devDependencies };
const plugins = findMatchingDependencies(allDeps ?? {}, devPlugins);
await this.loadPlugins(opts.rootPlugin.root, 'dev', plugins);
}
const { dev: pluginAdditionsDev, path } = opts.pluginAdditions ?? { core: [] };
if (pluginAdditionsDev) {
if (path) {
// If path is provided, load plugins from the path
const pjson = await (0, fs_1.readJson)((0, node_path_1.join)(path, 'package.json'));
const allDeps = { ...pjson.dependencies, ...pjson.devDependencies };
const plugins = findMatchingDependencies(allDeps ?? {}, pluginAdditionsDev);
await this.loadPlugins(path, 'dev', plugins);
}
else {
const allDeps = { ...opts.rootPlugin.pjson.dependencies, ...opts.rootPlugin.pjson.devDependencies };
const plugins = findMatchingDependencies(allDeps ?? {}, pluginAdditionsDev);
await this.loadPlugins(opts.rootPlugin.root, 'dev', plugins);
}
}
}
catch (error) {
process.emitWarning(error);
}
}
}
async loadPlugins(root, type, plugins, parent) {
if (!plugins || plugins.length === 0)
return;
const mark = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, `config.loadPlugins#${type}`);
debug('loading plugins', plugins);
await Promise.all((plugins || []).map(async (plugin) => {
try {
const name = typeof plugin === 'string' ? plugin : plugin.name;
const opts = {
name,
root,
type,
};
if (typeof plugin !== 'string') {
opts.tag = plugin.tag || opts.tag;
opts.root = plugin.root || opts.root;
opts.url = plugin.url;
}
if (parent) {
opts.parent = parent;
}
if (this.plugins.has(name))
return;
const pluginMarker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, `plugin.load#${name}`);
const instance = new plugin_1.Plugin(opts);
await instance.load();
pluginMarker?.addDetails({
commandCount: instance.commands.length,
hasManifest: instance.hasManifest,
name: instance.name,
topicCount: instance.topics.length,
type: instance.type,
usesMain: Boolean(instance.pjson.main),
});
pluginMarker?.stop();
this.plugins.set(instance.name, instance);
if (parent) {
instance.parent = parent;
if (!parent.children)
parent.children = [];
parent.children.push(instance);
}
if (instance.pjson.oclif.plugins) {
const allDeps = type === 'dev'
? { ...instance.pjson.dependencies, ...instance.pjson.devDependencies }
: instance.pjson.dependencies;
const plugins = findMatchingDependencies(allDeps ?? {}, instance.pjson.oclif.plugins);
await this.loadPlugins(instance.root, type, plugins, instance);
}
}
catch (error) {
this.errors.push(error);
}
}));
mark?.addDetails({ pluginCount: plugins.length });
mark?.stop();
}
async loadUserPlugins(opts) {
if (opts.userPlugins !== false) {
try {
const userPJSONPath = (0, node_path_1.join)(opts.dataDir, 'package.json');
debug('reading user plugins pjson %s', userPJSONPath);
// ignore cache because the file might have changed within the same process (e.g. during a JIT plugin install)
const pjson = await (0, fs_1.readJson)(userPJSONPath, false);
if (!pjson.oclif)
pjson.oclif = { schema: 1 };
if (!pjson.oclif.plugins)
pjson.oclif.plugins = [];
await this.loadPlugins(userPJSONPath, 'user', pjson.oclif.plugins.filter((p) => p.type === 'user'));
await this.loadPlugins(userPJSONPath, 'link', pjson.oclif.plugins.filter((p) => p.type === 'link'));
}
catch (error) {
if (error.code !== 'ENOENT')
process.emitWarning(error);
}
}
}
}
exports.default = PluginLoader;

51
node_modules/@oclif/core/lib/config/plugin.d.ts generated vendored Normal file
View File

@@ -0,0 +1,51 @@
import { Command } from '../command';
import { Manifest } from '../interfaces/manifest';
import { HookOptions, PJSON } from '../interfaces/pjson';
import { Plugin as IPlugin, PluginOptions } from '../interfaces/plugin';
import { Topic } from '../interfaces/topic';
export declare class Plugin implements IPlugin {
options: PluginOptions;
_base: string;
protected _debug: (..._: any) => void;
alias: string;
alreadyLoaded: boolean;
children: Plugin[];
commandIDs: string[];
commands: Command.Loadable[];
commandsDir: string | undefined;
hasManifest: boolean;
hooks: {
[key: string]: HookOptions[];
};
isRoot: boolean;
manifest: Manifest;
moduleType: 'commonjs' | 'module';
name: string;
parent?: Plugin | undefined;
pjson: PJSON;
root: string;
tag?: string | undefined;
type: string;
valid: boolean;
version: string;
private commandCache;
private commandDiscoveryOpts;
private flexibleTaxonomy;
constructor(options: PluginOptions);
get topics(): Topic[];
findCommand(id: string, opts: {
must: true;
}): Promise<Command.Class>;
findCommand(id: string, opts?: {
must: boolean;
}): Promise<Command.Class | undefined>;
load(): Promise<void>;
private _manifest;
private addErrorScope;
private getCommandIDs;
private getCommandIdsFromPattern;
private getCommandIdsFromTarget;
private getCommandsDir;
private loadCommandsFromTarget;
private warn;
}

374
node_modules/@oclif/core/lib/config/plugin.js generated vendored Normal file
View File

@@ -0,0 +1,374 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Plugin = void 0;
const node_path_1 = require("node:path");
const node_util_1 = require("node:util");
const tinyglobby_1 = require("tinyglobby");
const cache_1 = __importDefault(require("../cache"));
const errors_1 = require("../errors");
const module_loader_1 = require("../module-loader");
const performance_1 = require("../performance");
const symbols_1 = require("../symbols");
const cache_command_1 = require("../util/cache-command");
const find_root_1 = require("../util/find-root");
const fs_1 = require("../util/fs");
const read_pjson_1 = require("../util/read-pjson");
const util_1 = require("../util/util");
const ts_path_1 = require("./ts-path");
const util_2 = require("./util");
const _pjson = cache_1.default.getInstance().get('@oclif/core');
function topicsToArray(input, base) {
if (!input)
return [];
base = base ? `${base}:` : '';
if (Array.isArray(input)) {
return [...input, input.flatMap((t) => topicsToArray(t.subtopics, `${base}${t.name}`))];
}
return Object.keys(input).flatMap((k) => {
input[k].name = k;
return [{ ...input[k], name: `${base}${k}` }, ...topicsToArray(input[k].subtopics, `${base}${input[k].name}`)];
});
}
const cachedCommandCanBeUsed = (manifest, id) => Boolean(manifest?.commands[id] && 'isESM' in manifest.commands[id] && 'relativePath' in manifest.commands[id]);
const searchForCommandClass = (cmd) => {
if (typeof cmd.run === 'function')
return cmd;
if (cmd.default && cmd.default.run)
return cmd.default;
return Object.values(cmd).find((cmd) => typeof cmd.run === 'function');
};
const ensureCommandClass = (cmd) => {
if (cmd && typeof cmd.run === 'function')
return cmd;
};
const GLOB_PATTERNS = [
'**/*.+(js|cjs|mjs|ts|tsx|mts|cts)',
'!**/*.+(d.ts|test.ts|test.js|spec.ts|spec.js|d.mts|d.cts)?(x)',
];
function processCommandIds(files) {
return files.map((file) => {
const p = (0, node_path_1.parse)(file);
const topics = p.dir.split('/');
const command = p.name !== 'index' && p.name;
const id = [...topics, command].filter(Boolean).join(':');
return id === '' ? symbols_1.SINGLE_COMMAND_CLI_SYMBOL : id;
});
}
function determineCommandDiscoveryOptions(commandDiscovery) {
if (!commandDiscovery)
return;
if (typeof commandDiscovery === 'string') {
return { globPatterns: GLOB_PATTERNS, strategy: 'pattern', target: commandDiscovery };
}
if (!commandDiscovery.target)
throw new errors_1.CLIError('`oclif.commandDiscovery.target` is required.');
if (!commandDiscovery.strategy)
throw new errors_1.CLIError('`oclif.commandDiscovery.strategy` is required.');
if (commandDiscovery.strategy === 'explicit' && !commandDiscovery.identifier) {
commandDiscovery.identifier = 'default';
}
return commandDiscovery;
}
function determineHookOptions(hook) {
if (typeof hook === 'string')
return { identifier: 'default', target: hook };
if (!hook.identifier)
return { ...hook, identifier: 'default' };
return hook;
}
class Plugin {
options;
_base = `${_pjson.name}@${_pjson.version}`;
_debug = (0, util_2.makeDebug)();
alias;
alreadyLoaded = false;
children = [];
commandIDs = [];
// This will be initialized in the _manifest() method, which gets called in the load() method.
commands;
commandsDir;
hasManifest = false;
hooks;
isRoot = false;
manifest;
moduleType;
name;
parent;
pjson;
root;
tag;
type;
valid = false;
version;
commandCache;
commandDiscoveryOpts;
flexibleTaxonomy;
constructor(options) {
this.options = options;
}
get topics() {
return topicsToArray(this.pjson.oclif.topics || {});
}
async findCommand(id, opts = {}) {
const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, `plugin.findCommand#${this.name}.${id}`, {
id,
plugin: this.name,
});
const fetch = async () => {
if (this.commandDiscoveryOpts?.strategy === 'pattern') {
const commandsDir = await this.getCommandsDir();
if (!commandsDir)
return;
let module;
let isESM;
let filePath;
try {
;
({ filePath, isESM, module } = cachedCommandCanBeUsed(this.manifest, id)
? await (0, module_loader_1.loadWithDataFromManifest)(this.manifest.commands[id], this.root)
: await (0, module_loader_1.loadWithData)(this, (0, node_path_1.join)(commandsDir ?? this.pjson.oclif.commands, ...id.split(':'))));
this._debug(isESM ? '(import)' : '(require)', filePath);
}
catch (error) {
if (!opts.must && error.code === 'MODULE_NOT_FOUND')
return;
throw error;
}
const cmd = searchForCommandClass(module);
if (!cmd)
return;
cmd.id = id;
cmd.plugin = this;
cmd.isESM = isESM;
cmd.relativePath = (0, node_path_1.relative)(this.root, filePath || '').split(node_path_1.sep);
return cmd;
}
if (this.commandDiscoveryOpts?.strategy === 'single' || this.commandDiscoveryOpts?.strategy === 'explicit') {
const commandCache = await this.loadCommandsFromTarget();
const cmd = ensureCommandClass(commandCache?.[id]);
if (!cmd)
return;
cmd.id = id;
cmd.plugin = this;
return cmd;
}
};
const cmd = await fetch();
if (!cmd && opts.must)
(0, errors_1.error)(`command ${id} not found`);
marker?.stop();
return cmd;
}
// eslint-disable-next-line complexity
async load() {
this.type = this.options.type ?? 'core';
this.tag = this.options.tag;
this.isRoot = this.options.isRoot ?? false;
if (this.options.parent)
this.parent = this.options.parent;
// Linked plugins already have a root so there's no need to search for it.
// However there could be child plugins nested inside the linked plugin, in which
// case we still need to search for the child plugin's root.
const root = this.options.pjson && this.options.isRoot
? this.options.root
: this.type === 'link' && !this.parent
? this.options.root
: await (0, find_root_1.findRoot)(this.options.name, this.options.root);
if (!root)
throw new errors_1.CLIError(`could not find package.json with ${(0, node_util_1.inspect)(this.options)}`);
this.root = root;
this._debug(`loading ${this.type} plugin from ${root}`);
this.pjson = this.options.pjson ?? (await (0, read_pjson_1.readPjson)(root));
this.flexibleTaxonomy = this.options?.flexibleTaxonomy || this.pjson.oclif?.flexibleTaxonomy || false;
this.moduleType = this.pjson.type === 'module' ? 'module' : 'commonjs';
this.name = this.pjson.name;
this.alias = this.options.name ?? this.pjson.name;
if (!this.name)
throw new errors_1.CLIError(`no name in package.json (${root})`);
this._debug = (0, util_2.makeDebug)(this.name);
this.version = this.pjson.version;
if (this.pjson.oclif) {
this.valid = true;
}
else {
this.pjson.oclif = this.pjson['cli-engine'] || {};
}
this.hooks = Object.fromEntries(Object.entries(this.pjson.oclif.hooks ?? {}).map(([k, v]) => [
k,
(0, util_1.castArray)(v).map((v) => determineHookOptions(v)),
]));
this.commandDiscoveryOpts = determineCommandDiscoveryOptions(this.pjson.oclif?.commands);
this._debug('command discovery options', this.commandDiscoveryOpts);
this.manifest = await this._manifest();
this.commands = Object.entries(this.manifest.commands)
.map(([id, c]) => ({
...c,
load: async () => this.findCommand(id, { must: true }),
pluginAlias: this.alias,
pluginType: c.pluginType === 'jit' ? 'jit' : this.type,
}))
.sort((a, b) => a.id.localeCompare(b.id));
}
async _manifest() {
const ignoreManifest = Boolean(this.options.ignoreManifest);
const errorOnManifestCreate = Boolean(this.options.errorOnManifestCreate);
const respectNoCacheDefault = Boolean(this.options.respectNoCacheDefault);
const readManifest = async (dotfile = false) => {
try {
const p = (0, node_path_1.join)(this.root, `${dotfile ? '.' : ''}oclif.manifest.json`);
const manifest = await (0, fs_1.readJson)(p);
if (!process.env.OCLIF_NEXT_VERSION && manifest.version.split('-')[0] !== this.version.split('-')[0]) {
process.emitWarning(`Mismatched version in ${this.name} plugin manifest. Expected: ${this.version} Received: ${manifest.version}\nThis usually means you have an oclif.manifest.json file that should be deleted in development. This file should be automatically generated when publishing.`);
}
else {
this._debug('using manifest from', p);
this.hasManifest = true;
return manifest;
}
}
catch (error) {
if (error.code === 'ENOENT') {
if (!dotfile)
return readManifest(true);
}
else {
this.warn(error, 'readManifest');
}
}
};
const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, `plugin.manifest#${this.name}`, { plugin: this.name });
if (!ignoreManifest) {
const manifest = await readManifest();
if (manifest) {
marker?.addDetails({ commandCount: Object.keys(manifest.commands).length, fromCache: true });
marker?.stop();
this.commandIDs = Object.keys(manifest.commands);
return manifest;
}
}
this.commandIDs = await this.getCommandIDs();
const manifest = {
commands: (await Promise.all(this.commandIDs.map(async (id) => {
try {
const found = await this.findCommand(id, { must: true });
const cached = await (0, cache_command_1.cacheCommand)(found, this, respectNoCacheDefault);
// Ensure that id is set to the id being processed
// This is necessary because the id is set by findCommand but if there
// are multiple instances of a Command, then the id will be set to the
// last one found.
cached.id = id;
if (this.flexibleTaxonomy) {
const permutations = (0, util_2.getCommandIdPermutations)(id);
const aliasPermutations = cached.aliases.flatMap((a) => (0, util_2.getCommandIdPermutations)(a));
return [id, { ...cached, aliasPermutations, permutations }];
}
return [id, cached];
}
catch (error) {
const scope = `findCommand (${id})`;
if (Boolean(errorOnManifestCreate) === false)
this.warn(error, scope);
else
throw this.addErrorScope(error, scope);
}
})))
// eslint-disable-next-line unicorn/prefer-native-coercion-functions
.filter((f) => Boolean(f))
.reduce((commands, [id, c]) => {
commands[id] = c;
return commands;
}, {}),
version: this.version,
};
marker?.addDetails({ commandCount: Object.keys(manifest.commands).length, fromCache: false });
marker?.stop();
return manifest;
}
addErrorScope(err, scope) {
err.name = err.name ?? (0, node_util_1.inspect)(err).trim();
err.detail = (0, util_1.compact)([
err.detail,
`module: ${this._base}`,
scope && `task: ${scope}`,
`plugin: ${this.name}`,
`root: ${this.root}`,
...(err.code ? [`code: ${err.code}`] : []),
...(err.message ? [`message: ${err.message}`] : []),
'See more details with DEBUG=*',
]).join('\n');
return err;
}
async getCommandIDs() {
const marker = performance_1.Performance.mark(performance_1.OCLIF_MARKER_OWNER, `plugin.getCommandIDs#${this.name}`, { plugin: this.name });
let ids;
switch (this.commandDiscoveryOpts?.strategy) {
case 'explicit': {
ids = (await this.getCommandIdsFromTarget()) ?? [];
break;
}
case 'pattern': {
ids = await this.getCommandIdsFromPattern();
break;
}
case 'single': {
ids = (await this.getCommandIdsFromTarget()) ?? [];
break;
}
default: {
ids = [];
}
}
this._debug('found commands', ids);
marker?.addDetails({ count: ids.length });
marker?.stop();
return ids;
}
async getCommandIdsFromPattern() {
const commandsDir = await this.getCommandsDir();
if (!commandsDir)
return [];
this._debug(`loading IDs from ${commandsDir}`);
const files = await (0, tinyglobby_1.glob)(this.commandDiscoveryOpts?.globPatterns ?? GLOB_PATTERNS, { cwd: commandsDir });
return processCommandIds(files);
}
async getCommandIdsFromTarget() {
const commandsFromExport = await this.loadCommandsFromTarget();
if (commandsFromExport) {
return Object.entries((await this.loadCommandsFromTarget()) ?? [])
.filter(([, cmd]) => ensureCommandClass(cmd))
.map(([id]) => id);
}
}
async getCommandsDir() {
if (this.commandsDir)
return this.commandsDir;
this.commandsDir = await (0, ts_path_1.tsPath)(this.root, this.commandDiscoveryOpts?.target, this);
return this.commandsDir;
}
async loadCommandsFromTarget() {
if (this.commandCache)
return this.commandCache;
if (this.commandDiscoveryOpts?.strategy === 'explicit' && this.commandDiscoveryOpts.target) {
const filePath = await (0, ts_path_1.tsPath)(this.root, this.commandDiscoveryOpts.target, this);
const module = await (0, module_loader_1.load)(this, filePath);
this.commandCache = module[this.commandDiscoveryOpts?.identifier ?? 'default'] ?? {};
return this.commandCache;
}
if (this.commandDiscoveryOpts?.strategy === 'single' && this.commandDiscoveryOpts.target) {
const filePath = await (0, ts_path_1.tsPath)(this.root, this.commandDiscoveryOpts?.target ?? this.root, this);
const module = await (0, module_loader_1.load)(this, filePath);
this.commandCache = { [symbols_1.SINGLE_COMMAND_CLI_SYMBOL]: searchForCommandClass(module) };
return this.commandCache;
}
}
warn(err, scope) {
if (typeof err === 'string')
err = new Error(err);
const warning = this.addErrorScope(err, scope);
process.emitWarning(warning.name, warning);
}
}
exports.Plugin = Plugin;

9
node_modules/@oclif/core/lib/config/ts-path.d.ts generated vendored Normal file
View File

@@ -0,0 +1,9 @@
import { Plugin, TSConfig } from '../interfaces';
export declare const TS_CONFIGS: Record<string, TSConfig | undefined>;
/**
* Convert a path from the compiled ./lib files to the ./src typescript source
* this is for developing typescript plugins/CLIs
* if there is a tsconfig and the original sources exist, it attempts to require ts-node
*/
export declare function tsPath(root: string, orig: string, plugin: Plugin): Promise<string>;
export declare function tsPath(root: string, orig: string | undefined, plugin?: Plugin | undefined): Promise<string | undefined>;

293
node_modules/@oclif/core/lib/config/ts-path.js generated vendored Normal file
View File

@@ -0,0 +1,293 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TS_CONFIGS = void 0;
exports.tsPath = tsPath;
const promises_1 = require("node:fs/promises");
const node_path_1 = require("node:path");
const node_url_1 = require("node:url");
const cache_1 = __importDefault(require("../cache"));
const warn_1 = require("../errors/warn");
const settings_1 = require("../settings");
const fs_1 = require("../util/fs");
const read_tsconfig_1 = require("../util/read-tsconfig");
const util_1 = require("../util/util");
const util_2 = require("./util");
const debug = (0, util_2.makeDebug)('ts-path');
exports.TS_CONFIGS = {};
const REGISTERED = new Set();
function determineRuntime() {
/**
* Examples:
* #!/usr/bin/env bun
* bun bin/run.js
* bun bin/dev.js
*/
if (process.execPath.split(node_path_1.sep).includes('bun'))
return 'bun';
/**
* Examples:
* #!/usr/bin/env node
* #!/usr/bin/env node --loader ts-node/esm --experimental-specifier-resolution=node --no-warnings
* node bin/run.js
* node bin/dev.js
*/
if (process.execArgv.length === 0)
return 'node';
/**
* Examples:
* #!/usr/bin/env ts-node
* #!/usr/bin/env node_modules/.bin/ts-node
* ts-node bin/run.js
* ts-node bin/dev.js
*/
if (process.execArgv[0] === '--require' && process.execArgv[1].split(node_path_1.sep).includes('ts-node'))
return 'ts-node';
if (process.execArgv[0].split(node_path_1.sep).includes('ts-node'))
return 'ts-node';
/**
* Examples:
* #!/usr/bin/env tsx
* #!/usr/bin/env node_modules/.bin/tsx
* tsx bin/run.js
* tsx bin/dev.js
*/
if (process.execArgv[0] === '--require' && process.execArgv[1].split(node_path_1.sep).includes('tsx'))
return 'tsx';
return 'node';
}
const RUN_TIME = determineRuntime();
function isErrno(error) {
return 'code' in error && error.code === 'ENOENT';
}
async function loadTSConfig(root) {
try {
if (exports.TS_CONFIGS[root])
return exports.TS_CONFIGS[root];
const tsconfig = await (0, read_tsconfig_1.readTSConfig)(root);
if (!tsconfig)
return;
debug('tsconfig: %O', tsconfig);
exports.TS_CONFIGS[root] = tsconfig;
return exports.TS_CONFIGS[root];
}
catch (error) {
if (isErrno(error))
return;
debug(`Could not parse tsconfig.json. Skipping typescript path lookup for ${root}.`);
(0, warn_1.memoizedWarn)(`Could not parse tsconfig.json for ${root}. Falling back to compiled source.`);
}
}
async function registerTsx(root, moduleType) {
if (REGISTERED.has(root))
return;
try {
const apiPath = moduleType === 'module' ? 'tsx/esm/api' : 'tsx/cjs/api';
const tsxPath = require.resolve(apiPath, { paths: [root] });
if (!tsxPath)
return;
debug('registering tsx at', root);
debug('tsx path:', tsxPath);
const { href } = (0, node_url_1.pathToFileURL)(tsxPath);
debug('tsx href:', href);
const { register } = await import(href);
debug('Successfully imported tsx');
register();
REGISTERED.add(root);
}
catch (error) {
debug(`Could not find tsx. Skipping tsx registration for ${root}.`);
debug(error);
}
}
async function registerTSNode(root, tsconfig) {
if (REGISTERED.has(root))
return;
debug('registering ts-node at', root);
const tsNodePath = require.resolve('ts-node', { paths: [root, __dirname] });
debug('ts-node path:', tsNodePath);
let tsNode;
try {
tsNode = require(tsNodePath);
debug('Successfully required ts-node');
}
catch (error) {
debug(`Could not find ts-node at ${tsNodePath}. Skipping ts-node registration for ${root}.`);
debug(error);
(0, warn_1.memoizedWarn)(`Could not find ts-node at ${tsNodePath}. Please ensure that ts-node is a devDependency. Falling back to compiled source.`);
return;
}
const typeRoots = [(0, node_path_1.join)(root, 'node_modules', '@types')];
const rootDirs = [];
if (tsconfig.compilerOptions.rootDirs) {
for (const r of tsconfig.compilerOptions.rootDirs) {
rootDirs.push((0, node_path_1.join)(root, r));
}
}
else if (tsconfig.compilerOptions.rootDir) {
rootDirs.push((0, node_path_1.join)(root, tsconfig.compilerOptions.rootDir));
}
else if (tsconfig.compilerOptions.baseUrl) {
rootDirs.push((0, node_path_1.join)(root, tsconfig.compilerOptions.baseUrl));
}
else {
rootDirs.push((0, node_path_1.join)(root, 'src'));
}
// Because we need to provide a modified `rootDirs` to ts-node, we need to
// remove `baseUrl` and `rootDir` from `compilerOptions` so that they
// don't conflict.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { baseUrl, rootDir, ...rest } = tsconfig.compilerOptions;
const conf = {
compilerOptions: {
...rest,
rootDirs,
typeRoots,
},
...tsconfig['ts-node'],
cwd: root,
esm: tsconfig['ts-node']?.esm ?? true,
experimentalSpecifierResolution: tsconfig['ts-node']?.experimentalSpecifierResolution ?? 'explicit',
scope: true,
scopeDir: root,
skipProject: true,
transpileOnly: true,
};
debug('ts-node options: %O', conf);
tsNode.register(conf);
REGISTERED.add(root);
}
/**
* Skip ts-node registration for ESM plugins in production.
* The node/ts-node ecosystem is not mature enough to support auto-transpiling ESM modules at this time.
* See the following:
* - https://github.com/TypeStrong/ts-node/issues/1791#issuecomment-1149754228
* - https://github.com/nodejs/node/issues/49432
* - https://github.com/nodejs/node/pull/49407
* - https://github.com/nodejs/node/issues/34049
*
* We still register tsx/ts-node for ESM plugins when NODE_ENV is "test" or "development" and root plugin is also ESM
* since that allows plugins to be auto-transpiled when developing locally using `bin/dev.js`.
*/
function cannotTranspileEsm(rootPlugin, plugin, isProduction) {
return ((isProduction || rootPlugin?.moduleType === 'commonjs') &&
plugin?.moduleType === 'module' &&
!plugin?.pjson.devDependencies?.tsx);
}
/**
* If the dev script is run with ts-node for an ESM plugin, skip ts-node registration
* and fall back on compiled source since ts-node executable cannot transpile ESM in Node 20+
*
* See the following:
* https://nodejs.org/en/blog/announcements/v20-release-announce#custom-esm-loader-hooks-nearing-stable
* https://github.com/oclif/core/issues/817
* https://github.com/TypeStrong/ts-node/issues/1997
*/
function cannotUseTsNode(root, plugin, isProduction) {
if (plugin?.moduleType !== 'module' || isProduction)
return false;
const nodeMajor = Number.parseInt(process.version.replace('v', '').split('.')[0], 10);
return RUN_TIME === 'ts-node' && nodeMajor >= 20;
}
/**
* Determine the path to the source file from the compiled ./lib files
*/
async function determinePath(root, orig, plugin) {
const tsconfig = await loadTSConfig(root);
if (!tsconfig)
return orig;
debug(`Determining path for ${orig}`);
if (RUN_TIME === 'bun') {
debug(`Skipping ts-node registration for ${root} because the runtime is: ${RUN_TIME}`);
}
else {
// attempt to register tsx first. If it fails to register, we will fall back to ts-node
await registerTsx(root, plugin?.moduleType);
// if tsx registration succeeded, then this will exit early since the path will be in REGISTERED already
await registerTSNode(root, tsconfig);
}
const { baseUrl, outDir, rootDir, rootDirs } = tsconfig.compilerOptions;
const rootDirPath = rootDir ?? (rootDirs ?? [])[0] ?? baseUrl;
if (!rootDirPath) {
debug(`no rootDir, rootDirs, or baseUrl specified in tsconfig.json. Returning default path ${orig}`);
return orig;
}
if (!outDir) {
debug(`no outDir specified in tsconfig.json. Returning default path ${orig}`);
return orig;
}
// rewrite path from ./lib/foo to ./src/foo
const lib = (0, node_path_1.join)(root, outDir); // ./lib
const src = (0, node_path_1.join)(root, rootDirPath); // ./src
const relative = (0, node_path_1.relative)(lib, orig); // ./commands
// For hooks, it might point to a js file, not a module. Something like "./hooks/myhook.js" which doesn't need the js.
const out = (0, node_path_1.join)(src, relative).replace(/\.js$/, ''); // ./src/commands
// this can be a directory of commands or point to a hook file
// if it's a directory, we check if the path exists. If so, return the path to the directory.
// For hooks, it might point to a module, not a file. Something like "./hooks/myhook"
// That file doesn't exist, and the real file is "./hooks/myhook.ts"
// In that case we attempt to resolve to the filename. If it fails it will revert back to the lib path
debug(`lib dir: ${lib}`);
debug(`src dir: ${src}`);
debug(`src directory to find: ${out}`);
if ((0, fs_1.existsSync)(out)) {
debug(`Found source directory for ${orig} at ${out}`);
return out;
}
const sourceFiles = await Promise.all([
(0, promises_1.access)(`${out}.ts`)
.then(() => `${out}.ts`)
.catch(() => false),
(0, promises_1.access)(`${out}.tsx`)
.then(() => `${out}.tsx`)
.catch(() => false),
]);
if (sourceFiles.some(Boolean)) {
debug(`Found source file for ${orig} at ${out}`);
return out;
}
debug(`No source file found. Returning default path ${orig}`);
if (!(0, util_1.isProd)())
(0, warn_1.memoizedWarn)(`Could not find source for ${orig} based on tsconfig. Defaulting to compiled source.`);
return orig;
}
async function tsPath(root, orig, plugin) {
const rootPlugin = plugin?.options.isRoot ? plugin : cache_1.default.getInstance().get('rootPlugin');
if (!orig)
return orig;
orig = orig.startsWith(root) ? orig : (0, node_path_1.join)(root, orig);
// NOTE: The order of these checks matter!
const enableAutoTranspile = settings_1.settings.enableAutoTranspile ?? settings_1.settings.tsnodeEnabled;
if (enableAutoTranspile === false) {
debug(`Skipping typescript path lookup for ${root} because enableAutoTranspile is explicitly set to false`);
return orig;
}
const isProduction = (0, util_1.isProd)();
// Do not skip ts-node registration if the plugin is linked
if (enableAutoTranspile === undefined && isProduction && plugin?.type !== 'link') {
debug(`Skipping typescript path lookup for ${root} because NODE_ENV is NOT "test" or "development"`);
return orig;
}
if (cannotTranspileEsm(rootPlugin, plugin, isProduction)) {
debug(`Skipping typescript path lookup for ${root} because it's an ESM module (NODE_ENV: ${process.env.NODE_ENV}, root plugin module type: ${rootPlugin?.moduleType})`);
const warningIsDisabled = process.env.OCLIF_DISABLE_LINKED_ESM_WARNING && (0, util_1.isTruthy)(process.env.OCLIF_DISABLE_LINKED_ESM_WARNING);
// Only warn if the plugin is linked AND the warning is not disabled
if (plugin?.type === 'link' && !warningIsDisabled)
(0, warn_1.memoizedWarn)(`${plugin?.name} is a linked ESM module and cannot be auto-transpiled. Existing compiled source will be used instead.`);
return orig;
}
if (cannotUseTsNode(root, plugin, isProduction)) {
debug(`Skipping typescript path lookup for ${root} because ts-node is run in node version ${process.version}"`);
(0, warn_1.memoizedWarn)(`ts-node executable cannot transpile ESM in Node 20. Existing compiled source will be used instead. See https://github.com/oclif/core/issues/817.`);
return orig;
}
try {
return await determinePath(root, orig, plugin);
}
catch (error) {
debug(error);
return orig;
}
}

23
node_modules/@oclif/core/lib/config/util.d.ts generated vendored Normal file
View File

@@ -0,0 +1,23 @@
export declare function makeDebug(...scope: string[]): (..._: any) => void;
export declare function getPermutations(arr: string[]): Array<string[]>;
export declare function getCommandIdPermutations(commandId: string): string[];
/**
* Return an array of ids that represent all the usable combinations that a user could enter.
*
* For example, if the command ids are:
* - foo:bar:baz
* - one:two:three
* Then the usable ids would be:
* - foo
* - foo:bar
* - foo:bar:baz
* - one
* - one:two
* - one:two:three
*
* This allows us to determine which parts of the argv array belong to the command id whenever the topicSeparator is a space.
*
* @param commandIds string[]
* @returns string[]
*/
export declare const collectUsableIds: (commandIds: string[]) => Set<string>;

54
node_modules/@oclif/core/lib/config/util.js generated vendored Normal file
View File

@@ -0,0 +1,54 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.collectUsableIds = void 0;
exports.makeDebug = makeDebug;
exports.getPermutations = getPermutations;
exports.getCommandIdPermutations = getCommandIdPermutations;
const logger_1 = require("../logger");
function makeDebug(...scope) {
return (formatter, ...args) => (0, logger_1.getLogger)(['config', ...scope].join(':')).debug(formatter, ...args);
}
// Adapted from https://github.com/angus-c/just/blob/master/packages/array-permutations/index.js
function getPermutations(arr) {
if (arr.length === 0)
return [];
if (arr.length === 1)
return [arr];
const output = [];
const partialPermutations = getPermutations(arr.slice(1));
const first = arr[0];
for (let i = 0, len = partialPermutations.length; i < len; i++) {
const partial = partialPermutations[i];
for (let j = 0, len2 = partial.length; j <= len2; j++) {
const start = partial.slice(0, j);
const end = partial.slice(j);
const merged = [...start, first, ...end];
output.push(merged);
}
}
return output;
}
function getCommandIdPermutations(commandId) {
return getPermutations(commandId.split(':')).flatMap((c) => c.join(':'));
}
/**
* Return an array of ids that represent all the usable combinations that a user could enter.
*
* For example, if the command ids are:
* - foo:bar:baz
* - one:two:three
* Then the usable ids would be:
* - foo
* - foo:bar
* - foo:bar:baz
* - one
* - one:two
* - one:two:three
*
* This allows us to determine which parts of the argv array belong to the command id whenever the topicSeparator is a space.
*
* @param commandIds string[]
* @returns string[]
*/
const collectUsableIds = (commandIds) => new Set(commandIds.flatMap((id) => id.split(':').map((_, i, a) => a.slice(0, i + 1).join(':'))));
exports.collectUsableIds = collectUsableIds;