(commandInstance, args, commandPath = [])
| 227 | // Unified command execution for both top-level commands and subcommands |
| 228 | // Supports n-depth subcommands, workspaces, and definitions |
| 229 | async execCommandClass (commandInstance, args, commandPath = []) { |
| 230 | const Command = commandInstance.constructor |
| 231 | const commandName = commandPath.join(':') |
| 232 | |
| 233 | // Handle subcommands if present |
| 234 | if (Command.subcommands) { |
| 235 | const subcommandName = args[0] |
| 236 | |
| 237 | // If help is requested without a subcommand, show main command help |
| 238 | if (this.config.get('usage') && !subcommandName) { |
| 239 | return output.standard(commandInstance.usage) |
| 240 | } |
| 241 | |
| 242 | // If no subcommand provided, show usage error |
| 243 | if (!subcommandName) { |
| 244 | throw commandInstance.usageError() |
| 245 | } |
| 246 | |
| 247 | // Check if the subcommand exists |
| 248 | const SubCommand = Command.subcommands[subcommandName] |
| 249 | if (!SubCommand) { |
| 250 | throw commandInstance.usageError(`Unknown subcommand: ${subcommandName}`) |
| 251 | } |
| 252 | |
| 253 | // Check if help is requested for the subcommand |
| 254 | if (this.config.get('usage')) { |
| 255 | const parentName = commandPath.join(' ') |
| 256 | return output.standard(SubCommand.getUsage(parentName)) |
| 257 | } |
| 258 | |
| 259 | // Create subcommand instance and recurse |
| 260 | const subcommandInstance = new SubCommand(this) |
| 261 | subcommandInstance.parentName = commandPath.join(' ') |
| 262 | const subcommandArgs = args.slice(1) // Remove subcommand name from args |
| 263 | const subcommandPath = [...commandPath, subcommandName] |
| 264 | |
| 265 | return time.start(`command:${subcommandPath.join(':')}`, () => |
| 266 | this.execCommandClass(subcommandInstance, subcommandArgs, subcommandPath)) |
| 267 | } |
| 268 | |
| 269 | // No subcommands - execute this command |
| 270 | if (this.config.get('usage')) { |
| 271 | return output.standard(commandInstance.usage) |
| 272 | } |
| 273 | |
| 274 | let execWorkspaces = false |
| 275 | const hasWsConfig = this.config.get('workspaces') || this.config.get('workspace').length |
| 276 | // if cwd is a workspace, the default is set to [that workspace] |
| 277 | const implicitWs = this.config.get('workspace', 'default').length |
| 278 | // (-ws || -w foo) && (cwd is not a workspace || command is not ignoring implicit workspaces) |
| 279 | if (hasWsConfig && (!implicitWs || !Command.ignoreImplicitWorkspace)) { |
| 280 | if (this.global) { |
| 281 | throw new Error('Workspaces not supported for global packages') |
| 282 | } |
| 283 | if (!Command.workspaces) { |
| 284 | throw Object.assign(new Error('This command does not support workspaces.'), { |
| 285 | code: 'ENOWORKSPACES', |
| 286 | }) |
no test coverage detected