(depth = 1)
| 279 | } |
| 280 | |
| 281 | flags (depth = 1) { |
| 282 | const commandDefinitions = this.constructor.definitions || [] |
| 283 | |
| 284 | // Build types, shorthands, and defaults from definitions |
| 285 | const types = {} |
| 286 | const defaults = {} |
| 287 | const cmdShorthands = {} |
| 288 | const aliasMap = {} // Track which aliases map to which main keys |
| 289 | |
| 290 | for (const def of commandDefinitions) { |
| 291 | defaults[def.key] = def.default |
| 292 | types[def.key] = def.type |
| 293 | |
| 294 | // Handle aliases defined in the definition |
| 295 | if (def.alias && Array.isArray(def.alias)) { |
| 296 | for (const aliasKey of def.alias) { |
| 297 | types[aliasKey] = def.type // Needed for nopt to parse aliases |
| 298 | if (!aliasMap[def.key]) { |
| 299 | aliasMap[def.key] = [] |
| 300 | } |
| 301 | aliasMap[def.key].push(aliasKey) |
| 302 | } |
| 303 | } |
| 304 | |
| 305 | // Handle short options |
| 306 | if (def.short) { |
| 307 | const shorts = Array.isArray(def.short) ? def.short : [def.short] |
| 308 | for (const short of shorts) { |
| 309 | cmdShorthands[short] = [`--${def.key}`] |
| 310 | } |
| 311 | } |
| 312 | } |
| 313 | |
| 314 | // Parse args |
| 315 | let parsed = {} |
| 316 | let remains = [] |
| 317 | const argv = this.config.argv |
| 318 | if (argv && argv.length > 0) { |
| 319 | // config.argv contains the full command line including node, npm, and command names |
| 320 | // Format: ['node', 'npm', 'command', 'subcommand', 'positional', '--flags'] |
| 321 | // depth tells us how many command names to skip (1 for top-level, 2 for subcommand, etc.) |
| 322 | const offset = 2 + depth // Skip 'node', 'npm', and all command/subcommand names |
| 323 | parsed = nopt(types, cmdShorthands, argv, offset) |
| 324 | remains = parsed.argv.remain |
| 325 | delete parsed.argv |
| 326 | } |
| 327 | |
| 328 | // Validate flags - only if command has definitions (new system) |
| 329 | if (this.constructor.definitions && this.constructor.definitions.length > 0) { |
| 330 | this.#validateFlags(parsed, commandDefinitions, remains) |
| 331 | } |
| 332 | |
| 333 | // Check for conflicts between main flags and their aliases |
| 334 | // Also map aliases back to their main keys |
| 335 | for (const [mainKey, aliases] of Object.entries(aliasMap)) { |
| 336 | const providedKeys = [] |
| 337 | if (mainKey in parsed) { |
| 338 | providedKeys.push(mainKey) |
no test coverage detected