@alcyone-labs/arg-parser 2.12.2 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1588,6 +1588,9 @@ const zodFlagSchema = z.object({
1588
1588
  ),
1589
1589
  setWorkingDirectory: z.boolean().optional().describe(
1590
1590
  "If true, this flag's value becomes the effective working directory for file operations."
1591
+ ),
1592
+ positional: z.number().int().positive("Positional index must be a positive integer (1, 2, 3...)").optional().describe(
1593
+ "If set, this flag captures the Nth trailing positional argument (1-indexed). Multiple flags can have different positional values to capture multiple trailing args in order."
1591
1594
  )
1592
1595
  }).transform((obj) => {
1593
1596
  const newObj = { ...obj };
@@ -4430,7 +4433,11 @@ class ArgParserBase {
4430
4433
  const autoDiscoveredEnvFile = this.#configurationManager.discoverEnvFile(basePath);
4431
4434
  if (autoDiscoveredEnvFile) {
4432
4435
  console.warn(`Auto-discovered env file: ${autoDiscoveredEnvFile}`);
4433
- dotenv.config({ path: autoDiscoveredEnvFile, quiet: true });
4436
+ dotenv.config({
4437
+ path: autoDiscoveredEnvFile,
4438
+ quiet: true,
4439
+ override: true
4440
+ });
4434
4441
  try {
4435
4442
  const { finalParser: envFinalParser, parserChain: envParserChain } = this.#_identifyCommandChainAndParsers(
4436
4443
  processArgs,
@@ -5175,6 +5182,31 @@ class ArgParserBase {
5175
5182
  }
5176
5183
  }
5177
5184
  }
5185
+ const trailingArgs = [];
5186
+ for (let i = 0; i < args.length; i++) {
5187
+ if (!consumedIndices.has(i)) {
5188
+ const arg = args[i];
5189
+ if (!arg.startsWith("-")) {
5190
+ trailingArgs.push({ index: i, value: arg });
5191
+ }
5192
+ }
5193
+ }
5194
+ const positionalFlags = flags.filter(
5195
+ (f) => typeof f["positional"] === "number" && f["positional"] > 0
5196
+ ).sort(
5197
+ (a, b) => a["positional"] - b["positional"]
5198
+ );
5199
+ for (const posFlag of positionalFlags) {
5200
+ const posIndex = posFlag["positional"] - 1;
5201
+ const existingValue = output[posFlag["name"]];
5202
+ const hasExistingValue = posFlag["allowMultiple"] ? Array.isArray(existingValue) && existingValue.length > 0 : existingValue !== void 0;
5203
+ if (hasExistingValue) continue;
5204
+ if (posIndex < trailingArgs.length) {
5205
+ const trailing = trailingArgs[posIndex];
5206
+ await this._addToOutput(posFlag, trailing.value, output, options);
5207
+ consumedIndices.add(trailing.index);
5208
+ }
5209
+ }
5178
5210
  let firstUnconsumedIndex = args.length;
5179
5211
  for (let i = 0; i < args.length; i++) {
5180
5212
  if (!consumedIndices.has(i)) {
@@ -5208,6 +5240,22 @@ class ArgParserBase {
5208
5240
  `;
5209
5241
  }
5210
5242
  const indent = (level = 1) => " ".repeat(level);
5243
+ const positionalFlagsForUsage = this.#flagManager.flags.filter(
5244
+ (f) => typeof f["positional"] === "number" && f["positional"] > 0
5245
+ ).sort(
5246
+ (a, b) => a["positional"] - b["positional"]
5247
+ );
5248
+ if (positionalFlagsForUsage.length > 0) {
5249
+ const commandName = this.#subCommandName || this.#appCommandName || this.#appName;
5250
+ const posArgs = positionalFlagsForUsage.map((f) => {
5251
+ const isMandatory = typeof f["mandatory"] === "function" ? true : f["mandatory"];
5252
+ const argName = f["valueHint"] || f["name"].toUpperCase();
5253
+ return isMandatory ? `<${argName}>` : `[${argName}]`;
5254
+ }).join(" ");
5255
+ help += `${cyan("Usage:")} ${commandName} [OPTIONS] ${posArgs}
5256
+
5257
+ `;
5258
+ }
5211
5259
  if (this.#subCommands.size > 0) {
5212
5260
  help += `${cyan("Available sub-commands:")}
5213
5261
  `;
@@ -5216,7 +5264,12 @@ class ArgParserBase {
5216
5264
  if (!(actualSubParserInstance instanceof ArgParserBase)) {
5217
5265
  return `${indent()}${green(name.padEnd(20))} [Error: Subcommand '${name}' has an invalid parser configuration]`;
5218
5266
  }
5219
- let subHelp = `${indent()}${green(name.padEnd(20))} ${white(actualSubParserInstance.#description || "")}`;
5267
+ let subHelp = `${indent()}${green(name)}`;
5268
+ const subDescription = actualSubParserInstance.#description;
5269
+ if (subDescription) {
5270
+ subHelp += `
5271
+ ${indent(2)}${white(subDescription)}`;
5272
+ }
5220
5273
  const flagsFromSubManager = actualSubParserInstance && actualSubParserInstance.#flagManager ? actualSubParserInstance.#flagManager.flags : void 0;
5221
5274
  const subFlags = (flagsFromSubManager || []).filter(
5222
5275
  (f) => f["name"] !== "help"
@@ -5339,6 +5392,9 @@ ${cyan("Flags:")}
5339
5392
  `Allowed values: ${flag["enum"].map((v) => `'${v}'`).join(", ")}`
5340
5393
  );
5341
5394
  }
5395
+ if (typeof flag["positional"] === "number" && flag["positional"] > 0) {
5396
+ metaLines.push(`Positional argument #${flag["positional"]}`);
5397
+ }
5342
5398
  const maxOptionLength = Math.max(
5343
5399
  ...localFlags.map(
5344
5400
  (f) => f["options"].join(", ").length