politty 0.4.3 → 0.4.6
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/{arg-registry-BUUhZ7JR.d.ts → arg-registry-2m40k1Et.d.ts} +1 -1
- package/dist/{arg-registry-BUUhZ7JR.d.ts.map → arg-registry-2m40k1Et.d.ts.map} +1 -1
- package/dist/augment.d.ts +1 -1
- package/dist/completion/index.cjs +16 -168
- package/dist/completion/index.d.cts +2 -77
- package/dist/completion/index.d.ts +2 -77
- package/dist/completion/index.js +3 -154
- package/dist/{zsh-CASZWn0o.cjs → completion-Df0eZ70u.cjs} +326 -37
- package/dist/completion-Df0eZ70u.cjs.map +1 -0
- package/dist/{zsh-hjvdI8uZ.js → completion-_AnQsWh9.js} +298 -27
- package/dist/completion-_AnQsWh9.js.map +1 -0
- package/dist/docs/index.cjs +276 -29
- package/dist/docs/index.cjs.map +1 -1
- package/dist/docs/index.d.cts +62 -7
- package/dist/docs/index.d.cts.map +1 -1
- package/dist/docs/index.d.ts +62 -7
- package/dist/docs/index.d.ts.map +1 -1
- package/dist/docs/index.js +271 -30
- package/dist/docs/index.js.map +1 -1
- package/dist/{value-completion-resolver-BQgHsX7b.d.cts → index-BZalbMeu.d.ts} +83 -4
- package/dist/index-BZalbMeu.d.ts.map +1 -0
- package/dist/{value-completion-resolver-C9LTGr0O.d.ts → index-C5-0RXiH.d.cts} +83 -4
- package/dist/index-C5-0RXiH.d.cts.map +1 -0
- package/dist/index.cjs +8 -7
- package/dist/index.d.cts +67 -13
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +68 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -5
- package/dist/{lazy-BEDnSR0m.cjs → lazy-DHlvJiQQ.cjs} +44 -8
- package/dist/lazy-DHlvJiQQ.cjs.map +1 -0
- package/dist/{lazy-BrEg8SgI.js → lazy-DSyfzR-F.js} +38 -8
- package/dist/lazy-DSyfzR-F.js.map +1 -0
- package/dist/{runner-C4fSHJMe.cjs → runner-C1Aah5c5.cjs} +365 -23
- package/dist/runner-C1Aah5c5.cjs.map +1 -0
- package/dist/{runner-D6k4BgB4.js → runner-DjG0uBxQ.js} +365 -23
- package/dist/runner-DjG0uBxQ.js.map +1 -0
- package/dist/{schema-extractor-n9288WJ6.d.ts → schema-extractor-C9APqeSL.d.ts} +30 -3
- package/dist/schema-extractor-C9APqeSL.d.ts.map +1 -0
- package/dist/{schema-extractor-DFaAZzaY.d.cts → schema-extractor-CVf0J4An.d.cts} +29 -2
- package/dist/schema-extractor-CVf0J4An.d.cts.map +1 -0
- package/dist/{subcommand-router-CAzBsLSI.js → subcommand-router-CKuy6D2b.js} +2 -2
- package/dist/{subcommand-router-CAzBsLSI.js.map → subcommand-router-CKuy6D2b.js.map} +1 -1
- package/dist/{subcommand-router-ZjNjFaUL.cjs → subcommand-router-sZHhUP7b.cjs} +2 -2
- package/dist/{subcommand-router-ZjNjFaUL.cjs.map → subcommand-router-sZHhUP7b.cjs.map} +1 -1
- package/package.json +9 -9
- package/dist/completion/index.cjs.map +0 -1
- package/dist/completion/index.d.cts.map +0 -1
- package/dist/completion/index.d.ts.map +0 -1
- package/dist/completion/index.js.map +0 -1
- package/dist/lazy-BEDnSR0m.cjs.map +0 -1
- package/dist/lazy-BrEg8SgI.js.map +0 -1
- package/dist/runner-C4fSHJMe.cjs.map +0 -1
- package/dist/runner-D6k4BgB4.js.map +0 -1
- package/dist/schema-extractor-DFaAZzaY.d.cts.map +0 -1
- package/dist/schema-extractor-n9288WJ6.d.ts.map +0 -1
- package/dist/value-completion-resolver-BQgHsX7b.d.cts.map +0 -1
- package/dist/value-completion-resolver-C9LTGr0O.d.ts.map +0 -1
- package/dist/zsh-CASZWn0o.cjs.map +0 -1
- package/dist/zsh-hjvdI8uZ.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const require_subcommand_router = require('./subcommand-router-
|
|
2
|
-
const require_lazy = require('./lazy-
|
|
1
|
+
const require_subcommand_router = require('./subcommand-router-sZHhUP7b.cjs');
|
|
2
|
+
const require_lazy = require('./lazy-DHlvJiQQ.cjs');
|
|
3
3
|
let zod = require("zod");
|
|
4
4
|
let node_util = require("node:util");
|
|
5
5
|
let string_width = require("string-width");
|
|
@@ -539,6 +539,7 @@ function renderUsageLine(command, context) {
|
|
|
539
539
|
const parts = [];
|
|
540
540
|
const name = buildUsageCommandName(command, context);
|
|
541
541
|
parts.push(styles.commandName(name));
|
|
542
|
+
if (context?.globalExtracted?.fields.length) parts.push(styles.placeholder("[global options]"));
|
|
542
543
|
const extracted = require_lazy.getExtractedFields(command);
|
|
543
544
|
if (extracted) {
|
|
544
545
|
const positionals = extracted.fields.filter((a) => a.positional);
|
|
@@ -724,6 +725,24 @@ function formatOption(flags, description, indent = 0, extraDescPadding = 0) {
|
|
|
724
725
|
return `${indentStr} ${padEndVisual(flags, effectiveFlagWidth)}${description}`;
|
|
725
726
|
}
|
|
726
727
|
/**
|
|
728
|
+
* Format a single option field as a help line
|
|
729
|
+
*/
|
|
730
|
+
function formatFieldLine(opt, indent = 0, extraDescPadding = 0) {
|
|
731
|
+
const flags = formatFlags(opt);
|
|
732
|
+
let desc = opt.description ?? "";
|
|
733
|
+
if (opt.defaultValue !== void 0) desc += ` ${styles.defaultValue(`(default: ${JSON.stringify(opt.defaultValue)})`)}`;
|
|
734
|
+
if (opt.required) desc += ` ${styles.required("(required)")}`;
|
|
735
|
+
const envInfo = formatEnvInfo(opt.env);
|
|
736
|
+
if (envInfo) desc += ` ${envInfo}`;
|
|
737
|
+
return formatOption(flags, desc, indent, extraDescPadding);
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* Render global options section
|
|
741
|
+
*/
|
|
742
|
+
function renderGlobalOptions(globalExtracted) {
|
|
743
|
+
return globalExtracted.fields.filter((a) => !a.positional).map((opt) => formatFieldLine(opt)).join("\n");
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
727
746
|
* Render options for a subcommand (used by showSubcommandOptions)
|
|
728
747
|
*/
|
|
729
748
|
function renderSubcommandOptionsCompact(command, indent) {
|
|
@@ -786,6 +805,7 @@ function generateHelp(command, options) {
|
|
|
786
805
|
sections.push(`${styles.sectionHeader("Usage:")} ${renderUsageLine(command, context)}`);
|
|
787
806
|
const optionsText = renderOptions(command, options.descriptions, context);
|
|
788
807
|
if (optionsText) sections.push(`${styles.sectionHeader("Options:")}\n${optionsText}`);
|
|
808
|
+
if (context?.globalExtracted?.fields.length) sections.push(`${styles.sectionHeader("Global Options:")}\n${renderGlobalOptions(context.globalExtracted)}`);
|
|
789
809
|
if (options.showSubcommands !== false && command.subCommands && getVisibleSubcommandEntries(command.subCommands).length > 0) {
|
|
790
810
|
const currentPath = context?.commandPath?.join(" ") ?? "";
|
|
791
811
|
const visibleSubCommands = Object.fromEntries(getVisibleSubcommandEntries(command.subCommands));
|
|
@@ -1098,13 +1118,20 @@ function formatCommandValidationErrors(errors) {
|
|
|
1098
1118
|
* - Combined short options: -abc (treated as -a -b -c if all are boolean)
|
|
1099
1119
|
* - Positional arguments
|
|
1100
1120
|
* - -- to stop parsing options
|
|
1121
|
+
* - Boolean negation: --no-flag, --noFlag (requires `booleanFlags`)
|
|
1122
|
+
*
|
|
1123
|
+
* **Note:** When using negation detection (`--noFlag` / `--no-flag`),
|
|
1124
|
+
* supply `definedNames` so that options whose names happen to start with
|
|
1125
|
+
* "no" (e.g. `noDryRun`) are not mistaken for negation of another flag.
|
|
1126
|
+
* Without `definedNames`, all `--noX` forms matching a boolean flag will
|
|
1127
|
+
* be treated as negation.
|
|
1101
1128
|
*
|
|
1102
1129
|
* @param argv - Command line arguments
|
|
1103
1130
|
* @param options - Parser options
|
|
1104
1131
|
* @returns Parsed arguments
|
|
1105
1132
|
*/
|
|
1106
1133
|
function parseArgv(argv, options = {}) {
|
|
1107
|
-
const { aliasMap = /* @__PURE__ */ new Map(), booleanFlags = /* @__PURE__ */ new Set(), arrayFlags = /* @__PURE__ */ new Set() } = options;
|
|
1134
|
+
const { aliasMap = /* @__PURE__ */ new Map(), booleanFlags = /* @__PURE__ */ new Set(), arrayFlags = /* @__PURE__ */ new Set(), definedNames = /* @__PURE__ */ new Set() } = options;
|
|
1108
1135
|
const result = {
|
|
1109
1136
|
options: {},
|
|
1110
1137
|
positionals: [],
|
|
@@ -1137,11 +1164,28 @@ function parseArgv(argv, options = {}) {
|
|
|
1137
1164
|
const withoutDashes = arg.slice(2);
|
|
1138
1165
|
if (withoutDashes.startsWith("no-")) {
|
|
1139
1166
|
const flagName = withoutDashes.slice(3);
|
|
1140
|
-
|
|
1167
|
+
if (flagName === flagName.toLowerCase()) {
|
|
1168
|
+
const resolvedName = aliasMap.get(flagName) ?? flagName;
|
|
1169
|
+
if (booleanFlags.has(resolvedName)) {
|
|
1170
|
+
const asIsResolved = aliasMap.get(withoutDashes) ?? withoutDashes;
|
|
1171
|
+
if (!definedNames.has(asIsResolved)) {
|
|
1172
|
+
setOption(flagName, false);
|
|
1173
|
+
i++;
|
|
1174
|
+
continue;
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
if (withoutDashes.length > 2 && withoutDashes.startsWith("no") && /[A-Z]/.test(withoutDashes[2])) {
|
|
1180
|
+
const camelFlagName = withoutDashes[2].toLowerCase() + withoutDashes.slice(3);
|
|
1181
|
+
const resolvedName = aliasMap.get(camelFlagName) ?? camelFlagName;
|
|
1141
1182
|
if (booleanFlags.has(resolvedName)) {
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1183
|
+
const asIsResolved = aliasMap.get(withoutDashes) ?? withoutDashes;
|
|
1184
|
+
if (!definedNames.has(asIsResolved)) {
|
|
1185
|
+
setOption(camelFlagName, false);
|
|
1186
|
+
i++;
|
|
1187
|
+
continue;
|
|
1188
|
+
}
|
|
1145
1189
|
}
|
|
1146
1190
|
}
|
|
1147
1191
|
const eqIndex = withoutDashes.indexOf("=");
|
|
@@ -1207,16 +1251,21 @@ function buildParserOptions(extracted) {
|
|
|
1207
1251
|
const aliasMap = /* @__PURE__ */ new Map();
|
|
1208
1252
|
const booleanFlags = /* @__PURE__ */ new Set();
|
|
1209
1253
|
const arrayFlags = /* @__PURE__ */ new Set();
|
|
1254
|
+
const definedNames = /* @__PURE__ */ new Set();
|
|
1255
|
+
for (const field of extracted.fields) definedNames.add(field.name);
|
|
1210
1256
|
for (const field of extracted.fields) {
|
|
1211
1257
|
if (field.cliName !== field.name) aliasMap.set(field.cliName, field.name);
|
|
1212
1258
|
if (field.alias) aliasMap.set(field.alias, field.name);
|
|
1259
|
+
const camelVariant = require_lazy.toCamelCase(field.name);
|
|
1260
|
+
if (camelVariant !== field.name && !definedNames.has(camelVariant) && !aliasMap.has(camelVariant)) aliasMap.set(camelVariant, field.name);
|
|
1213
1261
|
if (field.type === "boolean") booleanFlags.add(field.name);
|
|
1214
1262
|
if (field.type === "array") arrayFlags.add(field.name);
|
|
1215
1263
|
}
|
|
1216
1264
|
return {
|
|
1217
1265
|
aliasMap,
|
|
1218
1266
|
booleanFlags,
|
|
1219
|
-
arrayFlags
|
|
1267
|
+
arrayFlags,
|
|
1268
|
+
definedNames
|
|
1220
1269
|
};
|
|
1221
1270
|
}
|
|
1222
1271
|
/**
|
|
@@ -1240,6 +1289,151 @@ function mergeWithPositionals(parsed, extracted) {
|
|
|
1240
1289
|
return result;
|
|
1241
1290
|
}
|
|
1242
1291
|
|
|
1292
|
+
//#endregion
|
|
1293
|
+
//#region src/parser/subcommand-scanner.ts
|
|
1294
|
+
/**
|
|
1295
|
+
* Build lookup tables from extracted global schema fields.
|
|
1296
|
+
* Shared by scanForSubcommand, separateGlobalArgs, and findFirstPositional.
|
|
1297
|
+
*/
|
|
1298
|
+
function buildGlobalFlagLookup(globalExtracted) {
|
|
1299
|
+
const { aliasMap = /* @__PURE__ */ new Map(), booleanFlags = /* @__PURE__ */ new Set() } = buildParserOptions(globalExtracted);
|
|
1300
|
+
return {
|
|
1301
|
+
aliasMap,
|
|
1302
|
+
booleanFlags,
|
|
1303
|
+
flagNames: new Set(globalExtracted.fields.map((f) => f.name)),
|
|
1304
|
+
cliNames: new Set(globalExtracted.fields.map((f) => f.cliName)),
|
|
1305
|
+
aliases: new Set(globalExtracted.fields.filter((f) => f.alias).map((f) => f.alias))
|
|
1306
|
+
};
|
|
1307
|
+
}
|
|
1308
|
+
/**
|
|
1309
|
+
* Resolve a long option (--flag, --flag=value, --no-flag) against global flag lookup.
|
|
1310
|
+
* Returns the resolved camelCase name and whether it is a known global flag.
|
|
1311
|
+
*/
|
|
1312
|
+
function resolveGlobalLongOption(arg, lookup) {
|
|
1313
|
+
const withoutDashes = arg.includes("=") ? arg.slice(2, arg.indexOf("=")) : arg.slice(2);
|
|
1314
|
+
const isNegated = withoutDashes.startsWith("no-");
|
|
1315
|
+
const flagName = isNegated ? withoutDashes.slice(3) : withoutDashes;
|
|
1316
|
+
const resolvedName = lookup.aliasMap.get(flagName) ?? flagName;
|
|
1317
|
+
return {
|
|
1318
|
+
resolvedName,
|
|
1319
|
+
withoutDashes,
|
|
1320
|
+
isNegated,
|
|
1321
|
+
isGlobal: lookup.flagNames.has(resolvedName) || lookup.cliNames.has(withoutDashes) || lookup.cliNames.has(flagName)
|
|
1322
|
+
};
|
|
1323
|
+
}
|
|
1324
|
+
/**
|
|
1325
|
+
* Check whether a non-boolean flag should consume the next argv token as its value.
|
|
1326
|
+
* Returns true when the next token exists, is not a flag, and the current flag
|
|
1327
|
+
* is not boolean / negated / using = syntax.
|
|
1328
|
+
*/
|
|
1329
|
+
function shouldConsumeValue(arg, resolvedName, isNegated, nextArg, booleanFlags) {
|
|
1330
|
+
return !arg.includes("=") && !booleanFlags.has(resolvedName) && !isNegated && nextArg !== void 0 && !nextArg.startsWith("-");
|
|
1331
|
+
}
|
|
1332
|
+
/**
|
|
1333
|
+
* Collect a recognized global flag (and its value if applicable) into `dest`,
|
|
1334
|
+
* returning how many argv positions were consumed (1 or 2).
|
|
1335
|
+
*/
|
|
1336
|
+
function collectGlobalFlag(argv, i, resolvedName, isNegated, booleanFlags, dest) {
|
|
1337
|
+
const arg = argv[i];
|
|
1338
|
+
dest.push(arg);
|
|
1339
|
+
if (shouldConsumeValue(arg, resolvedName, isNegated, argv[i + 1], booleanFlags)) {
|
|
1340
|
+
dest.push(argv[i + 1]);
|
|
1341
|
+
return 2;
|
|
1342
|
+
}
|
|
1343
|
+
return 1;
|
|
1344
|
+
}
|
|
1345
|
+
/**
|
|
1346
|
+
* Scan argv to find the subcommand position, skipping over global flags.
|
|
1347
|
+
*
|
|
1348
|
+
* Walks argv and recognizes global flags (long, short, --no-*) so that
|
|
1349
|
+
* `my-cli --verbose build --output dist` correctly identifies `build` as
|
|
1350
|
+
* the subcommand (index 1) rather than treating `--verbose` as the subcommand.
|
|
1351
|
+
*
|
|
1352
|
+
* Limitation: flags appearing before the subcommand name are matched only
|
|
1353
|
+
* against the global schema. If a flag is defined in both global and a
|
|
1354
|
+
* subcommand's local schema, the pre-subcommand occurrence is always treated
|
|
1355
|
+
* as global because the local schema is not available until the subcommand is
|
|
1356
|
+
* identified (lazy-loaded commands make eager checking infeasible). Place
|
|
1357
|
+
* colliding flags after the subcommand name so that `separateGlobalArgs` can
|
|
1358
|
+
* apply local-precedence logic.
|
|
1359
|
+
*
|
|
1360
|
+
* @param argv - Command line arguments
|
|
1361
|
+
* @param subCommandNames - Valid subcommand names
|
|
1362
|
+
* @param globalExtracted - Extracted fields from global args schema
|
|
1363
|
+
* @returns Scan result with subcommand position and token separation
|
|
1364
|
+
*/
|
|
1365
|
+
function scanForSubcommand(argv, subCommandNames, globalExtracted) {
|
|
1366
|
+
const lookup = buildGlobalFlagLookup(globalExtracted);
|
|
1367
|
+
const subCommandNameSet = new Set(subCommandNames);
|
|
1368
|
+
const globalTokensBefore = [];
|
|
1369
|
+
let i = 0;
|
|
1370
|
+
while (i < argv.length) {
|
|
1371
|
+
const arg = argv[i];
|
|
1372
|
+
if (arg === "--" || BUILTIN_FLAGS.has(arg)) break;
|
|
1373
|
+
if (!arg.startsWith("-") && subCommandNameSet.has(arg)) return {
|
|
1374
|
+
subCommandIndex: i,
|
|
1375
|
+
globalTokensBefore,
|
|
1376
|
+
tokensAfterSubcommand: argv.slice(i + 1)
|
|
1377
|
+
};
|
|
1378
|
+
if (arg.startsWith("--")) {
|
|
1379
|
+
const { resolvedName, isNegated, isGlobal } = resolveGlobalLongOption(arg, lookup);
|
|
1380
|
+
if (isGlobal) {
|
|
1381
|
+
i += collectGlobalFlag(argv, i, resolvedName, isNegated, lookup.booleanFlags, globalTokensBefore);
|
|
1382
|
+
continue;
|
|
1383
|
+
}
|
|
1384
|
+
break;
|
|
1385
|
+
}
|
|
1386
|
+
if (arg.startsWith("-") && arg.length > 1) {
|
|
1387
|
+
const withoutDash = arg.includes("=") ? arg.slice(1, arg.indexOf("=")) : arg.slice(1);
|
|
1388
|
+
if (withoutDash.length === 1) {
|
|
1389
|
+
const resolvedName = lookup.aliasMap.get(withoutDash) ?? withoutDash;
|
|
1390
|
+
if (lookup.aliases.has(withoutDash) || lookup.flagNames.has(resolvedName)) {
|
|
1391
|
+
i += collectGlobalFlag(argv, i, resolvedName, false, lookup.booleanFlags, globalTokensBefore);
|
|
1392
|
+
continue;
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
break;
|
|
1396
|
+
}
|
|
1397
|
+
break;
|
|
1398
|
+
}
|
|
1399
|
+
return {
|
|
1400
|
+
subCommandIndex: -1,
|
|
1401
|
+
globalTokensBefore,
|
|
1402
|
+
tokensAfterSubcommand: []
|
|
1403
|
+
};
|
|
1404
|
+
}
|
|
1405
|
+
const BUILTIN_FLAGS = new Set([
|
|
1406
|
+
"--help",
|
|
1407
|
+
"-h",
|
|
1408
|
+
"--help-all",
|
|
1409
|
+
"-H",
|
|
1410
|
+
"--version"
|
|
1411
|
+
]);
|
|
1412
|
+
/**
|
|
1413
|
+
* Find the first positional argument in argv, properly skipping global flag values.
|
|
1414
|
+
* Without globalExtracted, falls back to the first non-flag token.
|
|
1415
|
+
*/
|
|
1416
|
+
function findFirstPositional(argv, globalExtracted) {
|
|
1417
|
+
if (!globalExtracted) return argv.find((arg) => !arg.startsWith("-"));
|
|
1418
|
+
const lookup = buildGlobalFlagLookup(globalExtracted);
|
|
1419
|
+
for (let i = 0; i < argv.length; i++) {
|
|
1420
|
+
const arg = argv[i];
|
|
1421
|
+
if (!arg.startsWith("-")) return arg;
|
|
1422
|
+
if (arg === "--") return void 0;
|
|
1423
|
+
if (arg.startsWith("--")) {
|
|
1424
|
+
const { resolvedName, isNegated, isGlobal } = resolveGlobalLongOption(arg, lookup);
|
|
1425
|
+
if (isGlobal && shouldConsumeValue(arg, resolvedName, isNegated, argv[i + 1], lookup.booleanFlags)) i++;
|
|
1426
|
+
continue;
|
|
1427
|
+
}
|
|
1428
|
+
if (arg.length === 2) {
|
|
1429
|
+
const ch = arg[1];
|
|
1430
|
+
if (lookup.aliases.has(ch)) {
|
|
1431
|
+
if (shouldConsumeValue(arg, lookup.aliasMap.get(ch) ?? ch, false, argv[i + 1], lookup.booleanFlags)) i++;
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1243
1437
|
//#endregion
|
|
1244
1438
|
//#region src/parser/arg-parser.ts
|
|
1245
1439
|
/**
|
|
@@ -1253,7 +1447,23 @@ function mergeWithPositionals(parsed, extracted) {
|
|
|
1253
1447
|
function parseArgs(argv, command, options = {}) {
|
|
1254
1448
|
const subCommandNames = command.subCommands ? Object.keys(command.subCommands) : [];
|
|
1255
1449
|
const hasSubCommands = subCommandNames.length > 0;
|
|
1256
|
-
if (hasSubCommands && argv.length > 0) {
|
|
1450
|
+
if (hasSubCommands && argv.length > 0) if (options.globalExtracted) {
|
|
1451
|
+
const scanResult = scanForSubcommand(argv, subCommandNames, options.globalExtracted);
|
|
1452
|
+
if (scanResult.subCommandIndex >= 0) {
|
|
1453
|
+
const rawGlobalArgs = parseGlobalArgs(scanResult.globalTokensBefore, options.globalExtracted);
|
|
1454
|
+
return {
|
|
1455
|
+
helpRequested: false,
|
|
1456
|
+
helpAllRequested: false,
|
|
1457
|
+
versionRequested: false,
|
|
1458
|
+
subCommand: argv[scanResult.subCommandIndex],
|
|
1459
|
+
remainingArgs: scanResult.tokensAfterSubcommand,
|
|
1460
|
+
rawArgs: {},
|
|
1461
|
+
positionals: [],
|
|
1462
|
+
unknownFlags: [],
|
|
1463
|
+
rawGlobalArgs
|
|
1464
|
+
};
|
|
1465
|
+
}
|
|
1466
|
+
} else {
|
|
1257
1467
|
const firstArg = argv[0];
|
|
1258
1468
|
if (firstArg && !firstArg.startsWith("-") && subCommandNames.includes(firstArg)) return {
|
|
1259
1469
|
helpRequested: false,
|
|
@@ -1291,6 +1501,13 @@ function parseArgs(argv, command, options = {}) {
|
|
|
1291
1501
|
positionals: [],
|
|
1292
1502
|
unknownFlags: []
|
|
1293
1503
|
};
|
|
1504
|
+
let commandArgv = argv;
|
|
1505
|
+
let rawGlobalArgs;
|
|
1506
|
+
if (options.globalExtracted) {
|
|
1507
|
+
const { separated, globalParsed } = separateGlobalArgs(argv, options.globalExtracted, extracted);
|
|
1508
|
+
commandArgv = separated;
|
|
1509
|
+
rawGlobalArgs = globalParsed;
|
|
1510
|
+
}
|
|
1294
1511
|
if (!extracted) return {
|
|
1295
1512
|
helpRequested: false,
|
|
1296
1513
|
helpAllRequested: false,
|
|
@@ -1299,9 +1516,11 @@ function parseArgs(argv, command, options = {}) {
|
|
|
1299
1516
|
remainingArgs: [],
|
|
1300
1517
|
rawArgs: {},
|
|
1301
1518
|
positionals: [],
|
|
1302
|
-
unknownFlags: []
|
|
1519
|
+
unknownFlags: [],
|
|
1520
|
+
rawGlobalArgs
|
|
1303
1521
|
};
|
|
1304
|
-
const
|
|
1522
|
+
const parserOptions = buildParserOptions(extracted);
|
|
1523
|
+
const parsed = parseArgv(commandArgv, parserOptions);
|
|
1305
1524
|
const rawArgs = mergeWithPositionals(parsed, extracted);
|
|
1306
1525
|
for (const field of extracted.fields) if (field.env && rawArgs[field.name] === void 0) {
|
|
1307
1526
|
const envNames = Array.isArray(field.env) ? field.env : [field.env];
|
|
@@ -1316,6 +1535,11 @@ function parseArgs(argv, command, options = {}) {
|
|
|
1316
1535
|
const knownFlags = new Set(extracted.fields.map((f) => f.name));
|
|
1317
1536
|
const knownCliNames = new Set(extracted.fields.map((f) => f.cliName));
|
|
1318
1537
|
const knownAliases = new Set(extracted.fields.filter((f) => f.alias).map((f) => f.alias));
|
|
1538
|
+
if (options.globalExtracted) for (const f of options.globalExtracted.fields) {
|
|
1539
|
+
knownFlags.add(f.name);
|
|
1540
|
+
knownCliNames.add(f.cliName);
|
|
1541
|
+
if (f.alias) knownAliases.add(f.alias);
|
|
1542
|
+
}
|
|
1319
1543
|
const unknownFlags = [];
|
|
1320
1544
|
for (const key of Object.keys(parsed.options)) if (!knownFlags.has(key) && !knownCliNames.has(key) && !knownAliases.has(key)) unknownFlags.push(key);
|
|
1321
1545
|
return {
|
|
@@ -1327,7 +1551,64 @@ function parseArgs(argv, command, options = {}) {
|
|
|
1327
1551
|
rawArgs,
|
|
1328
1552
|
positionals: parsed.positionals,
|
|
1329
1553
|
unknownFlags,
|
|
1330
|
-
extractedFields: extracted
|
|
1554
|
+
extractedFields: extracted,
|
|
1555
|
+
rawGlobalArgs
|
|
1556
|
+
};
|
|
1557
|
+
}
|
|
1558
|
+
/**
|
|
1559
|
+
* Parse global args from a list of tokens (e.g., tokens before the subcommand).
|
|
1560
|
+
* Env fallbacks are applied later in the runner on the accumulated global args.
|
|
1561
|
+
*/
|
|
1562
|
+
function parseGlobalArgs(tokens, globalExtracted) {
|
|
1563
|
+
if (tokens.length === 0) return {};
|
|
1564
|
+
return mergeWithPositionals(parseArgv(tokens, buildParserOptions(globalExtracted)), globalExtracted);
|
|
1565
|
+
}
|
|
1566
|
+
/**
|
|
1567
|
+
* Separate global flags from command-local args in argv.
|
|
1568
|
+
* Global flags mixed with command args (e.g., `build --verbose --output dist`)
|
|
1569
|
+
* are extracted and returned separately.
|
|
1570
|
+
* When a flag is defined in both global and local schemas, the local definition
|
|
1571
|
+
* takes precedence (the flag stays in the command tokens).
|
|
1572
|
+
*
|
|
1573
|
+
* Note: Combined short flags (e.g., `-vq`) are not decomposed here; only
|
|
1574
|
+
* single-character short options are recognized as global. The underlying
|
|
1575
|
+
* `parseArgv` handles combined shorts for command-local parsing.
|
|
1576
|
+
*/
|
|
1577
|
+
function separateGlobalArgs(argv, globalExtracted, localExtracted) {
|
|
1578
|
+
const lookup = buildGlobalFlagLookup(globalExtracted);
|
|
1579
|
+
const localCliNames = new Set(localExtracted?.fields.map((f) => f.cliName) ?? []);
|
|
1580
|
+
const localAliases = new Set(localExtracted?.fields.filter((f) => f.alias).map((f) => f.alias) ?? []);
|
|
1581
|
+
const globalTokens = [];
|
|
1582
|
+
const commandTokens = [];
|
|
1583
|
+
for (let i = 0; i < argv.length; i++) {
|
|
1584
|
+
const arg = argv[i];
|
|
1585
|
+
if (arg === "--") {
|
|
1586
|
+
commandTokens.push(...argv.slice(i));
|
|
1587
|
+
break;
|
|
1588
|
+
}
|
|
1589
|
+
if (arg.startsWith("--")) {
|
|
1590
|
+
const { resolvedName, withoutDashes, isNegated, isGlobal } = resolveGlobalLongOption(arg, lookup);
|
|
1591
|
+
const flagName = isNegated ? withoutDashes.slice(3) : withoutDashes;
|
|
1592
|
+
const isLocalCollision = localCliNames.has(withoutDashes) || localCliNames.has(flagName);
|
|
1593
|
+
if (isGlobal && !isLocalCollision) {
|
|
1594
|
+
i += collectGlobalFlag(argv, i, resolvedName, isNegated, lookup.booleanFlags, globalTokens) - 1;
|
|
1595
|
+
continue;
|
|
1596
|
+
}
|
|
1597
|
+
} else if (arg.startsWith("-") && arg.length > 1) {
|
|
1598
|
+
const withoutDash = arg.includes("=") ? arg.slice(1, arg.indexOf("=")) : arg.slice(1);
|
|
1599
|
+
if (withoutDash.length === 1) {
|
|
1600
|
+
const resolvedName = lookup.aliasMap.get(withoutDash) ?? withoutDash;
|
|
1601
|
+
if ((lookup.aliases.has(withoutDash) || lookup.flagNames.has(resolvedName)) && !localAliases.has(withoutDash)) {
|
|
1602
|
+
i += collectGlobalFlag(argv, i, resolvedName, false, lookup.booleanFlags, globalTokens) - 1;
|
|
1603
|
+
continue;
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
commandTokens.push(arg);
|
|
1608
|
+
}
|
|
1609
|
+
return {
|
|
1610
|
+
separated: commandTokens,
|
|
1611
|
+
globalParsed: parseGlobalArgs(globalTokens, globalExtracted)
|
|
1331
1612
|
};
|
|
1332
1613
|
}
|
|
1333
1614
|
|
|
@@ -1510,11 +1791,11 @@ const defaultLogger = {
|
|
|
1510
1791
|
* ```
|
|
1511
1792
|
*/
|
|
1512
1793
|
async function runCommand(command, argv, options = {}) {
|
|
1794
|
+
const globalExtracted = extractAndValidateGlobal(options);
|
|
1513
1795
|
return runCommandInternal(command, argv, {
|
|
1514
1796
|
...options,
|
|
1515
1797
|
handleSignals: false,
|
|
1516
|
-
|
|
1517
|
-
logger: options.logger
|
|
1798
|
+
_globalExtracted: globalExtracted
|
|
1518
1799
|
});
|
|
1519
1800
|
}
|
|
1520
1801
|
/**
|
|
@@ -1541,16 +1822,20 @@ async function runCommand(command, argv, options = {}) {
|
|
|
1541
1822
|
* ```
|
|
1542
1823
|
*/
|
|
1543
1824
|
async function runMain(command, options = {}) {
|
|
1825
|
+
const globalExtracted = extractAndValidateGlobal(options);
|
|
1544
1826
|
const result = await runCommandInternal(command, process.argv.slice(2), {
|
|
1545
1827
|
debug: options.debug,
|
|
1546
1828
|
captureLogs: options.captureLogs,
|
|
1547
1829
|
skipValidation: options.skipValidation,
|
|
1548
1830
|
handleSignals: true,
|
|
1549
1831
|
logger: options.logger,
|
|
1832
|
+
globalArgs: options.globalArgs,
|
|
1833
|
+
_globalExtracted: globalExtracted,
|
|
1550
1834
|
_context: {
|
|
1551
1835
|
commandPath: [],
|
|
1552
1836
|
rootName: command.name,
|
|
1553
|
-
rootVersion: options.version
|
|
1837
|
+
rootVersion: options.version,
|
|
1838
|
+
globalExtracted
|
|
1554
1839
|
}
|
|
1555
1840
|
});
|
|
1556
1841
|
if (process.stdout.writableLength > 0) await new Promise((resolve) => process.stdout.once("drain", resolve));
|
|
@@ -1563,7 +1848,8 @@ async function runCommandInternal(command, argv, options = {}) {
|
|
|
1563
1848
|
const logger = options.logger ?? defaultLogger;
|
|
1564
1849
|
const context = options._context ?? {
|
|
1565
1850
|
commandPath: [],
|
|
1566
|
-
rootName: command.name
|
|
1851
|
+
rootName: command.name,
|
|
1852
|
+
globalExtracted: options._globalExtracted
|
|
1567
1853
|
};
|
|
1568
1854
|
const collector = options.captureLogs ?? false ? require_subcommand_router.createLogCollector() : null;
|
|
1569
1855
|
collector?.start();
|
|
@@ -1571,12 +1857,19 @@ async function runCommandInternal(command, argv, options = {}) {
|
|
|
1571
1857
|
return require_subcommand_router.mergeLogs(options._existingLogs ?? require_subcommand_router.emptyLogs(), collector?.getLogs() ?? require_subcommand_router.emptyLogs());
|
|
1572
1858
|
};
|
|
1573
1859
|
try {
|
|
1574
|
-
const parseResult = parseArgs(argv, command, {
|
|
1860
|
+
const parseResult = parseArgs(argv, command, {
|
|
1861
|
+
skipValidation: options.skipValidation,
|
|
1862
|
+
globalExtracted: options._globalExtracted
|
|
1863
|
+
});
|
|
1864
|
+
const accumulatedGlobalArgs = {
|
|
1865
|
+
...options._parsedGlobalArgs,
|
|
1866
|
+
...parseResult.rawGlobalArgs
|
|
1867
|
+
};
|
|
1575
1868
|
if (parseResult.helpRequested || parseResult.helpAllRequested) {
|
|
1576
1869
|
let hasUnknownSubcommand = false;
|
|
1577
1870
|
const subCmdNames = require_subcommand_router.listSubCommands(command);
|
|
1578
1871
|
if (subCmdNames.length > 0) {
|
|
1579
|
-
const potentialSubCmd = argv
|
|
1872
|
+
const potentialSubCmd = findFirstPositional(argv, context.globalExtracted);
|
|
1580
1873
|
if (potentialSubCmd && !subCmdNames.includes(potentialSubCmd)) {
|
|
1581
1874
|
logger.error(formatUnknownSubcommand(potentialSubCmd, subCmdNames));
|
|
1582
1875
|
logger.error("");
|
|
@@ -1620,13 +1913,15 @@ async function runCommandInternal(command, argv, options = {}) {
|
|
|
1620
1913
|
const subContext = {
|
|
1621
1914
|
commandPath: [...context.commandPath ?? [], parseResult.subCommand],
|
|
1622
1915
|
rootName: context.rootName,
|
|
1623
|
-
rootVersion: context.rootVersion
|
|
1916
|
+
rootVersion: context.rootVersion,
|
|
1917
|
+
globalExtracted: context.globalExtracted
|
|
1624
1918
|
};
|
|
1625
1919
|
collector?.stop();
|
|
1626
1920
|
return runCommandInternal(subCmd, parseResult.remainingArgs, {
|
|
1627
1921
|
...options,
|
|
1628
1922
|
_context: subContext,
|
|
1629
|
-
_existingLogs: getCurrentLogs()
|
|
1923
|
+
_existingLogs: getCurrentLogs(),
|
|
1924
|
+
_parsedGlobalArgs: accumulatedGlobalArgs
|
|
1630
1925
|
});
|
|
1631
1926
|
}
|
|
1632
1927
|
}
|
|
@@ -1658,9 +1953,35 @@ async function runCommandInternal(command, argv, options = {}) {
|
|
|
1658
1953
|
};
|
|
1659
1954
|
} else if (unknownKeysMode === "strip") for (const flag of parseResult.unknownFlags) logger.error(formatUnknownFlagWarning(flag, knownFlags));
|
|
1660
1955
|
}
|
|
1956
|
+
let validatedGlobalArgs = {};
|
|
1957
|
+
if (options.globalArgs && options._globalExtracted) {
|
|
1958
|
+
for (const field of options._globalExtracted.fields) if (field.env && accumulatedGlobalArgs[field.name] === void 0) {
|
|
1959
|
+
const envNames = Array.isArray(field.env) ? field.env : [field.env];
|
|
1960
|
+
for (const envName of envNames) {
|
|
1961
|
+
const envValue = process.env[envName];
|
|
1962
|
+
if (envValue !== void 0) {
|
|
1963
|
+
accumulatedGlobalArgs[field.name] = envValue;
|
|
1964
|
+
break;
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
const globalValidation = validateArgs(accumulatedGlobalArgs, options.globalArgs);
|
|
1969
|
+
if (!globalValidation.success) {
|
|
1970
|
+
const errorMessage = formatValidationErrors$1(globalValidation.errors);
|
|
1971
|
+
logger.error(errorMessage);
|
|
1972
|
+
collector?.stop();
|
|
1973
|
+
return {
|
|
1974
|
+
success: false,
|
|
1975
|
+
error: new Error(errorMessage),
|
|
1976
|
+
exitCode: 1,
|
|
1977
|
+
logs: getCurrentLogs()
|
|
1978
|
+
};
|
|
1979
|
+
}
|
|
1980
|
+
validatedGlobalArgs = globalValidation.data;
|
|
1981
|
+
}
|
|
1661
1982
|
if (!command.args) {
|
|
1662
1983
|
collector?.stop();
|
|
1663
|
-
return await executeLifecycle(command,
|
|
1984
|
+
return await executeLifecycle(command, validatedGlobalArgs, {
|
|
1664
1985
|
handleSignals: options.handleSignals,
|
|
1665
1986
|
captureLogs: options.captureLogs,
|
|
1666
1987
|
existingLogs: getCurrentLogs()
|
|
@@ -1677,8 +1998,12 @@ async function runCommandInternal(command, argv, options = {}) {
|
|
|
1677
1998
|
logs: getCurrentLogs()
|
|
1678
1999
|
};
|
|
1679
2000
|
}
|
|
2001
|
+
const mergedArgs = {
|
|
2002
|
+
...validatedGlobalArgs,
|
|
2003
|
+
...validationResult.data
|
|
2004
|
+
};
|
|
1680
2005
|
collector?.stop();
|
|
1681
|
-
return await executeLifecycle(command,
|
|
2006
|
+
return await executeLifecycle(command, mergedArgs, {
|
|
1682
2007
|
handleSignals: options.handleSignals,
|
|
1683
2008
|
captureLogs: options.captureLogs,
|
|
1684
2009
|
existingLogs: getCurrentLogs()
|
|
@@ -1695,6 +2020,23 @@ async function runCommandInternal(command, argv, options = {}) {
|
|
|
1695
2020
|
};
|
|
1696
2021
|
}
|
|
1697
2022
|
}
|
|
2023
|
+
/**
|
|
2024
|
+
* Extract global fields from options.globalArgs and validate the schema upfront.
|
|
2025
|
+
* Rejects positional fields since global options must be flags.
|
|
2026
|
+
* Returns undefined when no globalArgs is provided.
|
|
2027
|
+
*/
|
|
2028
|
+
function extractAndValidateGlobal(options) {
|
|
2029
|
+
if (!options.globalArgs) return void 0;
|
|
2030
|
+
const extracted = require_lazy.extractFields(options.globalArgs);
|
|
2031
|
+
if (!options.skipValidation) {
|
|
2032
|
+
validateDuplicateFields(extracted);
|
|
2033
|
+
validateDuplicateAliases(extracted);
|
|
2034
|
+
validateReservedAliases(extracted, true);
|
|
2035
|
+
const positionalNames = extracted.fields.filter((f) => f.positional).map((f) => f.name);
|
|
2036
|
+
if (positionalNames.length > 0) throw new Error(`Global options schema must not contain positional arguments. Found: ${positionalNames.join(", ")}`);
|
|
2037
|
+
}
|
|
2038
|
+
return extracted;
|
|
2039
|
+
}
|
|
1698
2040
|
|
|
1699
2041
|
//#endregion
|
|
1700
2042
|
Object.defineProperty(exports, 'DuplicateAliasError', {
|
|
@@ -1835,4 +2177,4 @@ Object.defineProperty(exports, 'validateReservedAliases', {
|
|
|
1835
2177
|
return validateReservedAliases;
|
|
1836
2178
|
}
|
|
1837
2179
|
});
|
|
1838
|
-
//# sourceMappingURL=runner-
|
|
2180
|
+
//# sourceMappingURL=runner-C1Aah5c5.cjs.map
|