UNPKG

@hashgraph/solo

Version:

An opinionated CLI tool to deploy and manage private Hedera Networks.

102 lines 4.6 kB
// SPDX-License-Identifier: Apache-2.0 import { Flags as flags } from './flags.js'; import { ArgumentProcessor } from '../argument-processor.js'; import { container } from 'tsyringe-neo'; import { InjectTokens } from '../core/dependency-injection/inject-tokens.js'; /** * Helper function to convert a flag object to CLI option string * @param flag - The command flag * @returns CLI option string (e.g., '--deployment') */ export function optionFromFlag(flag) { return `--${flag.name}`; } /** * Helper function to create base argv array for command execution * @returns Base argv array */ export function newArgv() { return ['${PATH}/node', '${SOLO_ROOT}/solo.ts']; } /** * Helper function to append global flags to argv * @param argv - The argument array to append to * @param cacheDirectory - Optional cache directory path * @returns Updated argv array */ export function argvPushGlobalFlags(argv, cacheDirectory = '') { // Only propagate flags if they are explicitly set to true in the parent command const configManager = container.resolve(InjectTokens.ConfigManager); const developmentMode = configManager.getFlag(flags.devMode); if (typeof developmentMode === 'boolean' && developmentMode) { argv.push(optionFromFlag(flags.devMode)); } const quiet = configManager.getFlag(flags.quiet); if (typeof quiet === 'boolean' && quiet) { argv.push(optionFromFlag(flags.quiet)); } if (typeof cacheDirectory === 'string' && cacheDirectory.length > 0) { argv.push(optionFromFlag(flags.cacheDir), cacheDirectory); } return argv; } /** * Helper function to invoke a Solo command with proper task integration * @param title - Task title to display * @param commandName - Command name for task tracking * @param callback - Function that returns the argv array * @param taskList - TaskList instance for managing parent-child task relationships * @param skipCallback - Optional function to determine if task should be skipped * @returns Task object for Listr */ export function invokeSoloCommand(title, commandName, callback, taskList, skipCallback) { return { title, skip: skipCallback || (() => false), task: async (_context, taskListWrapper) => { return taskListWrapper.newListr([ { title, task: async (_isolatedContext, isolatedTaskWrapper) => { return subTaskSoloCommand(commandName, isolatedTaskWrapper, callback, taskList); }, }, ], { ctx: {}, }); }, }; } /** * Helper function to execute a Solo command and return child tasks * @param commandName - Command name for task tracking * @param taskListWrapper - Task list wrapper from Listr * @param callback - Function that returns the argv array * @param taskList - TaskList instance for managing parent-child task relationships * @returns Child tasks from command execution */ export async function subTaskSoloCommand(commandName, taskListWrapper, callback, taskList) { // one-shot can launch the same subcommand name in parallel (for example in // nested/parallel Listr branches). A single map slot per command name caused // last-writer-wins behavior, where one invocation overwrote another and task // output got attached to the wrong parent. Queueing preserves 1:1 pairing. const taskNode = { taskListWrapper }; const pendingTaskNodes = taskList.parentTaskListMap.get(commandName) ?? []; pendingTaskNodes.push(taskNode); taskList.parentTaskListMap.set(commandName, pendingTaskNodes); const newArgv = await callback(); const configManager = container.resolve(InjectTokens.ConfigManager); const scopedConfig = configManager.cloneActiveConfig(); // Subcommands run in parallel during one-shot flows. values-file is component-specific // and must come from each subcommand argv, not inherited from sibling command state. delete scopedConfig.flags[flags.valuesFile.name]; // ArgumentProcessor/command handlers read and write config flags deeply via // ConfigManager and Flags helpers. Running under a scoped copy keeps each // subcommand immutable from the perspective of siblings and removes shared // global-state races while still preserving existing call signatures. await configManager.runWithScopedConfig(scopedConfig, async () => { await ArgumentProcessor.process(newArgv); }); return taskNode.children; } //# sourceMappingURL=command-helpers.js.map