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
|
-
import { a as getExtractedFields, i as extractFields, r as resolveSubCommandMeta } from "./lazy-
|
|
2
|
-
import { a as emptyLogs, i as createLogCollector, n as resolveLazyCommand, o as mergeLogs, r as resolveSubcommand, t as listSubCommands } from "./subcommand-router-
|
|
1
|
+
import { a as getExtractedFields, i as extractFields, r as resolveSubCommandMeta, s as toCamelCase } from "./lazy-DSyfzR-F.js";
|
|
2
|
+
import { a as emptyLogs, i as createLogCollector, n as resolveLazyCommand, o as mergeLogs, r as resolveSubcommand, t as listSubCommands } from "./subcommand-router-CKuy6D2b.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { styleText } from "node:util";
|
|
5
5
|
import stringWidth from "string-width";
|
|
@@ -555,6 +555,7 @@ function renderUsageLine(command, context) {
|
|
|
555
555
|
const parts = [];
|
|
556
556
|
const name = buildUsageCommandName(command, context);
|
|
557
557
|
parts.push(styles.commandName(name));
|
|
558
|
+
if (context?.globalExtracted?.fields.length) parts.push(styles.placeholder("[global options]"));
|
|
558
559
|
const extracted = getExtractedFields(command);
|
|
559
560
|
if (extracted) {
|
|
560
561
|
const positionals = extracted.fields.filter((a) => a.positional);
|
|
@@ -740,6 +741,24 @@ function formatOption(flags, description, indent = 0, extraDescPadding = 0) {
|
|
|
740
741
|
return `${indentStr} ${padEndVisual(flags, effectiveFlagWidth)}${description}`;
|
|
741
742
|
}
|
|
742
743
|
/**
|
|
744
|
+
* Format a single option field as a help line
|
|
745
|
+
*/
|
|
746
|
+
function formatFieldLine(opt, indent = 0, extraDescPadding = 0) {
|
|
747
|
+
const flags = formatFlags(opt);
|
|
748
|
+
let desc = opt.description ?? "";
|
|
749
|
+
if (opt.defaultValue !== void 0) desc += ` ${styles.defaultValue(`(default: ${JSON.stringify(opt.defaultValue)})`)}`;
|
|
750
|
+
if (opt.required) desc += ` ${styles.required("(required)")}`;
|
|
751
|
+
const envInfo = formatEnvInfo(opt.env);
|
|
752
|
+
if (envInfo) desc += ` ${envInfo}`;
|
|
753
|
+
return formatOption(flags, desc, indent, extraDescPadding);
|
|
754
|
+
}
|
|
755
|
+
/**
|
|
756
|
+
* Render global options section
|
|
757
|
+
*/
|
|
758
|
+
function renderGlobalOptions(globalExtracted) {
|
|
759
|
+
return globalExtracted.fields.filter((a) => !a.positional).map((opt) => formatFieldLine(opt)).join("\n");
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
743
762
|
* Render options for a subcommand (used by showSubcommandOptions)
|
|
744
763
|
*/
|
|
745
764
|
function renderSubcommandOptionsCompact(command, indent) {
|
|
@@ -802,6 +821,7 @@ function generateHelp(command, options) {
|
|
|
802
821
|
sections.push(`${styles.sectionHeader("Usage:")} ${renderUsageLine(command, context)}`);
|
|
803
822
|
const optionsText = renderOptions(command, options.descriptions, context);
|
|
804
823
|
if (optionsText) sections.push(`${styles.sectionHeader("Options:")}\n${optionsText}`);
|
|
824
|
+
if (context?.globalExtracted?.fields.length) sections.push(`${styles.sectionHeader("Global Options:")}\n${renderGlobalOptions(context.globalExtracted)}`);
|
|
805
825
|
if (options.showSubcommands !== false && command.subCommands && getVisibleSubcommandEntries(command.subCommands).length > 0) {
|
|
806
826
|
const currentPath = context?.commandPath?.join(" ") ?? "";
|
|
807
827
|
const visibleSubCommands = Object.fromEntries(getVisibleSubcommandEntries(command.subCommands));
|
|
@@ -1114,13 +1134,20 @@ function formatCommandValidationErrors(errors) {
|
|
|
1114
1134
|
* - Combined short options: -abc (treated as -a -b -c if all are boolean)
|
|
1115
1135
|
* - Positional arguments
|
|
1116
1136
|
* - -- to stop parsing options
|
|
1137
|
+
* - Boolean negation: --no-flag, --noFlag (requires `booleanFlags`)
|
|
1138
|
+
*
|
|
1139
|
+
* **Note:** When using negation detection (`--noFlag` / `--no-flag`),
|
|
1140
|
+
* supply `definedNames` so that options whose names happen to start with
|
|
1141
|
+
* "no" (e.g. `noDryRun`) are not mistaken for negation of another flag.
|
|
1142
|
+
* Without `definedNames`, all `--noX` forms matching a boolean flag will
|
|
1143
|
+
* be treated as negation.
|
|
1117
1144
|
*
|
|
1118
1145
|
* @param argv - Command line arguments
|
|
1119
1146
|
* @param options - Parser options
|
|
1120
1147
|
* @returns Parsed arguments
|
|
1121
1148
|
*/
|
|
1122
1149
|
function parseArgv(argv, options = {}) {
|
|
1123
|
-
const { aliasMap = /* @__PURE__ */ new Map(), booleanFlags = /* @__PURE__ */ new Set(), arrayFlags = /* @__PURE__ */ new Set() } = options;
|
|
1150
|
+
const { aliasMap = /* @__PURE__ */ new Map(), booleanFlags = /* @__PURE__ */ new Set(), arrayFlags = /* @__PURE__ */ new Set(), definedNames = /* @__PURE__ */ new Set() } = options;
|
|
1124
1151
|
const result = {
|
|
1125
1152
|
options: {},
|
|
1126
1153
|
positionals: [],
|
|
@@ -1153,11 +1180,28 @@ function parseArgv(argv, options = {}) {
|
|
|
1153
1180
|
const withoutDashes = arg.slice(2);
|
|
1154
1181
|
if (withoutDashes.startsWith("no-")) {
|
|
1155
1182
|
const flagName = withoutDashes.slice(3);
|
|
1156
|
-
|
|
1183
|
+
if (flagName === flagName.toLowerCase()) {
|
|
1184
|
+
const resolvedName = aliasMap.get(flagName) ?? flagName;
|
|
1185
|
+
if (booleanFlags.has(resolvedName)) {
|
|
1186
|
+
const asIsResolved = aliasMap.get(withoutDashes) ?? withoutDashes;
|
|
1187
|
+
if (!definedNames.has(asIsResolved)) {
|
|
1188
|
+
setOption(flagName, false);
|
|
1189
|
+
i++;
|
|
1190
|
+
continue;
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
if (withoutDashes.length > 2 && withoutDashes.startsWith("no") && /[A-Z]/.test(withoutDashes[2])) {
|
|
1196
|
+
const camelFlagName = withoutDashes[2].toLowerCase() + withoutDashes.slice(3);
|
|
1197
|
+
const resolvedName = aliasMap.get(camelFlagName) ?? camelFlagName;
|
|
1157
1198
|
if (booleanFlags.has(resolvedName)) {
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1199
|
+
const asIsResolved = aliasMap.get(withoutDashes) ?? withoutDashes;
|
|
1200
|
+
if (!definedNames.has(asIsResolved)) {
|
|
1201
|
+
setOption(camelFlagName, false);
|
|
1202
|
+
i++;
|
|
1203
|
+
continue;
|
|
1204
|
+
}
|
|
1161
1205
|
}
|
|
1162
1206
|
}
|
|
1163
1207
|
const eqIndex = withoutDashes.indexOf("=");
|
|
@@ -1223,16 +1267,21 @@ function buildParserOptions(extracted) {
|
|
|
1223
1267
|
const aliasMap = /* @__PURE__ */ new Map();
|
|
1224
1268
|
const booleanFlags = /* @__PURE__ */ new Set();
|
|
1225
1269
|
const arrayFlags = /* @__PURE__ */ new Set();
|
|
1270
|
+
const definedNames = /* @__PURE__ */ new Set();
|
|
1271
|
+
for (const field of extracted.fields) definedNames.add(field.name);
|
|
1226
1272
|
for (const field of extracted.fields) {
|
|
1227
1273
|
if (field.cliName !== field.name) aliasMap.set(field.cliName, field.name);
|
|
1228
1274
|
if (field.alias) aliasMap.set(field.alias, field.name);
|
|
1275
|
+
const camelVariant = toCamelCase(field.name);
|
|
1276
|
+
if (camelVariant !== field.name && !definedNames.has(camelVariant) && !aliasMap.has(camelVariant)) aliasMap.set(camelVariant, field.name);
|
|
1229
1277
|
if (field.type === "boolean") booleanFlags.add(field.name);
|
|
1230
1278
|
if (field.type === "array") arrayFlags.add(field.name);
|
|
1231
1279
|
}
|
|
1232
1280
|
return {
|
|
1233
1281
|
aliasMap,
|
|
1234
1282
|
booleanFlags,
|
|
1235
|
-
arrayFlags
|
|
1283
|
+
arrayFlags,
|
|
1284
|
+
definedNames
|
|
1236
1285
|
};
|
|
1237
1286
|
}
|
|
1238
1287
|
/**
|
|
@@ -1256,6 +1305,151 @@ function mergeWithPositionals(parsed, extracted) {
|
|
|
1256
1305
|
return result;
|
|
1257
1306
|
}
|
|
1258
1307
|
|
|
1308
|
+
//#endregion
|
|
1309
|
+
//#region src/parser/subcommand-scanner.ts
|
|
1310
|
+
/**
|
|
1311
|
+
* Build lookup tables from extracted global schema fields.
|
|
1312
|
+
* Shared by scanForSubcommand, separateGlobalArgs, and findFirstPositional.
|
|
1313
|
+
*/
|
|
1314
|
+
function buildGlobalFlagLookup(globalExtracted) {
|
|
1315
|
+
const { aliasMap = /* @__PURE__ */ new Map(), booleanFlags = /* @__PURE__ */ new Set() } = buildParserOptions(globalExtracted);
|
|
1316
|
+
return {
|
|
1317
|
+
aliasMap,
|
|
1318
|
+
booleanFlags,
|
|
1319
|
+
flagNames: new Set(globalExtracted.fields.map((f) => f.name)),
|
|
1320
|
+
cliNames: new Set(globalExtracted.fields.map((f) => f.cliName)),
|
|
1321
|
+
aliases: new Set(globalExtracted.fields.filter((f) => f.alias).map((f) => f.alias))
|
|
1322
|
+
};
|
|
1323
|
+
}
|
|
1324
|
+
/**
|
|
1325
|
+
* Resolve a long option (--flag, --flag=value, --no-flag) against global flag lookup.
|
|
1326
|
+
* Returns the resolved camelCase name and whether it is a known global flag.
|
|
1327
|
+
*/
|
|
1328
|
+
function resolveGlobalLongOption(arg, lookup) {
|
|
1329
|
+
const withoutDashes = arg.includes("=") ? arg.slice(2, arg.indexOf("=")) : arg.slice(2);
|
|
1330
|
+
const isNegated = withoutDashes.startsWith("no-");
|
|
1331
|
+
const flagName = isNegated ? withoutDashes.slice(3) : withoutDashes;
|
|
1332
|
+
const resolvedName = lookup.aliasMap.get(flagName) ?? flagName;
|
|
1333
|
+
return {
|
|
1334
|
+
resolvedName,
|
|
1335
|
+
withoutDashes,
|
|
1336
|
+
isNegated,
|
|
1337
|
+
isGlobal: lookup.flagNames.has(resolvedName) || lookup.cliNames.has(withoutDashes) || lookup.cliNames.has(flagName)
|
|
1338
|
+
};
|
|
1339
|
+
}
|
|
1340
|
+
/**
|
|
1341
|
+
* Check whether a non-boolean flag should consume the next argv token as its value.
|
|
1342
|
+
* Returns true when the next token exists, is not a flag, and the current flag
|
|
1343
|
+
* is not boolean / negated / using = syntax.
|
|
1344
|
+
*/
|
|
1345
|
+
function shouldConsumeValue(arg, resolvedName, isNegated, nextArg, booleanFlags) {
|
|
1346
|
+
return !arg.includes("=") && !booleanFlags.has(resolvedName) && !isNegated && nextArg !== void 0 && !nextArg.startsWith("-");
|
|
1347
|
+
}
|
|
1348
|
+
/**
|
|
1349
|
+
* Collect a recognized global flag (and its value if applicable) into `dest`,
|
|
1350
|
+
* returning how many argv positions were consumed (1 or 2).
|
|
1351
|
+
*/
|
|
1352
|
+
function collectGlobalFlag(argv, i, resolvedName, isNegated, booleanFlags, dest) {
|
|
1353
|
+
const arg = argv[i];
|
|
1354
|
+
dest.push(arg);
|
|
1355
|
+
if (shouldConsumeValue(arg, resolvedName, isNegated, argv[i + 1], booleanFlags)) {
|
|
1356
|
+
dest.push(argv[i + 1]);
|
|
1357
|
+
return 2;
|
|
1358
|
+
}
|
|
1359
|
+
return 1;
|
|
1360
|
+
}
|
|
1361
|
+
/**
|
|
1362
|
+
* Scan argv to find the subcommand position, skipping over global flags.
|
|
1363
|
+
*
|
|
1364
|
+
* Walks argv and recognizes global flags (long, short, --no-*) so that
|
|
1365
|
+
* `my-cli --verbose build --output dist` correctly identifies `build` as
|
|
1366
|
+
* the subcommand (index 1) rather than treating `--verbose` as the subcommand.
|
|
1367
|
+
*
|
|
1368
|
+
* Limitation: flags appearing before the subcommand name are matched only
|
|
1369
|
+
* against the global schema. If a flag is defined in both global and a
|
|
1370
|
+
* subcommand's local schema, the pre-subcommand occurrence is always treated
|
|
1371
|
+
* as global because the local schema is not available until the subcommand is
|
|
1372
|
+
* identified (lazy-loaded commands make eager checking infeasible). Place
|
|
1373
|
+
* colliding flags after the subcommand name so that `separateGlobalArgs` can
|
|
1374
|
+
* apply local-precedence logic.
|
|
1375
|
+
*
|
|
1376
|
+
* @param argv - Command line arguments
|
|
1377
|
+
* @param subCommandNames - Valid subcommand names
|
|
1378
|
+
* @param globalExtracted - Extracted fields from global args schema
|
|
1379
|
+
* @returns Scan result with subcommand position and token separation
|
|
1380
|
+
*/
|
|
1381
|
+
function scanForSubcommand(argv, subCommandNames, globalExtracted) {
|
|
1382
|
+
const lookup = buildGlobalFlagLookup(globalExtracted);
|
|
1383
|
+
const subCommandNameSet = new Set(subCommandNames);
|
|
1384
|
+
const globalTokensBefore = [];
|
|
1385
|
+
let i = 0;
|
|
1386
|
+
while (i < argv.length) {
|
|
1387
|
+
const arg = argv[i];
|
|
1388
|
+
if (arg === "--" || BUILTIN_FLAGS.has(arg)) break;
|
|
1389
|
+
if (!arg.startsWith("-") && subCommandNameSet.has(arg)) return {
|
|
1390
|
+
subCommandIndex: i,
|
|
1391
|
+
globalTokensBefore,
|
|
1392
|
+
tokensAfterSubcommand: argv.slice(i + 1)
|
|
1393
|
+
};
|
|
1394
|
+
if (arg.startsWith("--")) {
|
|
1395
|
+
const { resolvedName, isNegated, isGlobal } = resolveGlobalLongOption(arg, lookup);
|
|
1396
|
+
if (isGlobal) {
|
|
1397
|
+
i += collectGlobalFlag(argv, i, resolvedName, isNegated, lookup.booleanFlags, globalTokensBefore);
|
|
1398
|
+
continue;
|
|
1399
|
+
}
|
|
1400
|
+
break;
|
|
1401
|
+
}
|
|
1402
|
+
if (arg.startsWith("-") && arg.length > 1) {
|
|
1403
|
+
const withoutDash = arg.includes("=") ? arg.slice(1, arg.indexOf("=")) : arg.slice(1);
|
|
1404
|
+
if (withoutDash.length === 1) {
|
|
1405
|
+
const resolvedName = lookup.aliasMap.get(withoutDash) ?? withoutDash;
|
|
1406
|
+
if (lookup.aliases.has(withoutDash) || lookup.flagNames.has(resolvedName)) {
|
|
1407
|
+
i += collectGlobalFlag(argv, i, resolvedName, false, lookup.booleanFlags, globalTokensBefore);
|
|
1408
|
+
continue;
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
break;
|
|
1412
|
+
}
|
|
1413
|
+
break;
|
|
1414
|
+
}
|
|
1415
|
+
return {
|
|
1416
|
+
subCommandIndex: -1,
|
|
1417
|
+
globalTokensBefore,
|
|
1418
|
+
tokensAfterSubcommand: []
|
|
1419
|
+
};
|
|
1420
|
+
}
|
|
1421
|
+
const BUILTIN_FLAGS = new Set([
|
|
1422
|
+
"--help",
|
|
1423
|
+
"-h",
|
|
1424
|
+
"--help-all",
|
|
1425
|
+
"-H",
|
|
1426
|
+
"--version"
|
|
1427
|
+
]);
|
|
1428
|
+
/**
|
|
1429
|
+
* Find the first positional argument in argv, properly skipping global flag values.
|
|
1430
|
+
* Without globalExtracted, falls back to the first non-flag token.
|
|
1431
|
+
*/
|
|
1432
|
+
function findFirstPositional(argv, globalExtracted) {
|
|
1433
|
+
if (!globalExtracted) return argv.find((arg) => !arg.startsWith("-"));
|
|
1434
|
+
const lookup = buildGlobalFlagLookup(globalExtracted);
|
|
1435
|
+
for (let i = 0; i < argv.length; i++) {
|
|
1436
|
+
const arg = argv[i];
|
|
1437
|
+
if (!arg.startsWith("-")) return arg;
|
|
1438
|
+
if (arg === "--") return void 0;
|
|
1439
|
+
if (arg.startsWith("--")) {
|
|
1440
|
+
const { resolvedName, isNegated, isGlobal } = resolveGlobalLongOption(arg, lookup);
|
|
1441
|
+
if (isGlobal && shouldConsumeValue(arg, resolvedName, isNegated, argv[i + 1], lookup.booleanFlags)) i++;
|
|
1442
|
+
continue;
|
|
1443
|
+
}
|
|
1444
|
+
if (arg.length === 2) {
|
|
1445
|
+
const ch = arg[1];
|
|
1446
|
+
if (lookup.aliases.has(ch)) {
|
|
1447
|
+
if (shouldConsumeValue(arg, lookup.aliasMap.get(ch) ?? ch, false, argv[i + 1], lookup.booleanFlags)) i++;
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1259
1453
|
//#endregion
|
|
1260
1454
|
//#region src/parser/arg-parser.ts
|
|
1261
1455
|
/**
|
|
@@ -1269,7 +1463,23 @@ function mergeWithPositionals(parsed, extracted) {
|
|
|
1269
1463
|
function parseArgs(argv, command, options = {}) {
|
|
1270
1464
|
const subCommandNames = command.subCommands ? Object.keys(command.subCommands) : [];
|
|
1271
1465
|
const hasSubCommands = subCommandNames.length > 0;
|
|
1272
|
-
if (hasSubCommands && argv.length > 0) {
|
|
1466
|
+
if (hasSubCommands && argv.length > 0) if (options.globalExtracted) {
|
|
1467
|
+
const scanResult = scanForSubcommand(argv, subCommandNames, options.globalExtracted);
|
|
1468
|
+
if (scanResult.subCommandIndex >= 0) {
|
|
1469
|
+
const rawGlobalArgs = parseGlobalArgs(scanResult.globalTokensBefore, options.globalExtracted);
|
|
1470
|
+
return {
|
|
1471
|
+
helpRequested: false,
|
|
1472
|
+
helpAllRequested: false,
|
|
1473
|
+
versionRequested: false,
|
|
1474
|
+
subCommand: argv[scanResult.subCommandIndex],
|
|
1475
|
+
remainingArgs: scanResult.tokensAfterSubcommand,
|
|
1476
|
+
rawArgs: {},
|
|
1477
|
+
positionals: [],
|
|
1478
|
+
unknownFlags: [],
|
|
1479
|
+
rawGlobalArgs
|
|
1480
|
+
};
|
|
1481
|
+
}
|
|
1482
|
+
} else {
|
|
1273
1483
|
const firstArg = argv[0];
|
|
1274
1484
|
if (firstArg && !firstArg.startsWith("-") && subCommandNames.includes(firstArg)) return {
|
|
1275
1485
|
helpRequested: false,
|
|
@@ -1307,6 +1517,13 @@ function parseArgs(argv, command, options = {}) {
|
|
|
1307
1517
|
positionals: [],
|
|
1308
1518
|
unknownFlags: []
|
|
1309
1519
|
};
|
|
1520
|
+
let commandArgv = argv;
|
|
1521
|
+
let rawGlobalArgs;
|
|
1522
|
+
if (options.globalExtracted) {
|
|
1523
|
+
const { separated, globalParsed } = separateGlobalArgs(argv, options.globalExtracted, extracted);
|
|
1524
|
+
commandArgv = separated;
|
|
1525
|
+
rawGlobalArgs = globalParsed;
|
|
1526
|
+
}
|
|
1310
1527
|
if (!extracted) return {
|
|
1311
1528
|
helpRequested: false,
|
|
1312
1529
|
helpAllRequested: false,
|
|
@@ -1315,9 +1532,11 @@ function parseArgs(argv, command, options = {}) {
|
|
|
1315
1532
|
remainingArgs: [],
|
|
1316
1533
|
rawArgs: {},
|
|
1317
1534
|
positionals: [],
|
|
1318
|
-
unknownFlags: []
|
|
1535
|
+
unknownFlags: [],
|
|
1536
|
+
rawGlobalArgs
|
|
1319
1537
|
};
|
|
1320
|
-
const
|
|
1538
|
+
const parserOptions = buildParserOptions(extracted);
|
|
1539
|
+
const parsed = parseArgv(commandArgv, parserOptions);
|
|
1321
1540
|
const rawArgs = mergeWithPositionals(parsed, extracted);
|
|
1322
1541
|
for (const field of extracted.fields) if (field.env && rawArgs[field.name] === void 0) {
|
|
1323
1542
|
const envNames = Array.isArray(field.env) ? field.env : [field.env];
|
|
@@ -1332,6 +1551,11 @@ function parseArgs(argv, command, options = {}) {
|
|
|
1332
1551
|
const knownFlags = new Set(extracted.fields.map((f) => f.name));
|
|
1333
1552
|
const knownCliNames = new Set(extracted.fields.map((f) => f.cliName));
|
|
1334
1553
|
const knownAliases = new Set(extracted.fields.filter((f) => f.alias).map((f) => f.alias));
|
|
1554
|
+
if (options.globalExtracted) for (const f of options.globalExtracted.fields) {
|
|
1555
|
+
knownFlags.add(f.name);
|
|
1556
|
+
knownCliNames.add(f.cliName);
|
|
1557
|
+
if (f.alias) knownAliases.add(f.alias);
|
|
1558
|
+
}
|
|
1335
1559
|
const unknownFlags = [];
|
|
1336
1560
|
for (const key of Object.keys(parsed.options)) if (!knownFlags.has(key) && !knownCliNames.has(key) && !knownAliases.has(key)) unknownFlags.push(key);
|
|
1337
1561
|
return {
|
|
@@ -1343,7 +1567,64 @@ function parseArgs(argv, command, options = {}) {
|
|
|
1343
1567
|
rawArgs,
|
|
1344
1568
|
positionals: parsed.positionals,
|
|
1345
1569
|
unknownFlags,
|
|
1346
|
-
extractedFields: extracted
|
|
1570
|
+
extractedFields: extracted,
|
|
1571
|
+
rawGlobalArgs
|
|
1572
|
+
};
|
|
1573
|
+
}
|
|
1574
|
+
/**
|
|
1575
|
+
* Parse global args from a list of tokens (e.g., tokens before the subcommand).
|
|
1576
|
+
* Env fallbacks are applied later in the runner on the accumulated global args.
|
|
1577
|
+
*/
|
|
1578
|
+
function parseGlobalArgs(tokens, globalExtracted) {
|
|
1579
|
+
if (tokens.length === 0) return {};
|
|
1580
|
+
return mergeWithPositionals(parseArgv(tokens, buildParserOptions(globalExtracted)), globalExtracted);
|
|
1581
|
+
}
|
|
1582
|
+
/**
|
|
1583
|
+
* Separate global flags from command-local args in argv.
|
|
1584
|
+
* Global flags mixed with command args (e.g., `build --verbose --output dist`)
|
|
1585
|
+
* are extracted and returned separately.
|
|
1586
|
+
* When a flag is defined in both global and local schemas, the local definition
|
|
1587
|
+
* takes precedence (the flag stays in the command tokens).
|
|
1588
|
+
*
|
|
1589
|
+
* Note: Combined short flags (e.g., `-vq`) are not decomposed here; only
|
|
1590
|
+
* single-character short options are recognized as global. The underlying
|
|
1591
|
+
* `parseArgv` handles combined shorts for command-local parsing.
|
|
1592
|
+
*/
|
|
1593
|
+
function separateGlobalArgs(argv, globalExtracted, localExtracted) {
|
|
1594
|
+
const lookup = buildGlobalFlagLookup(globalExtracted);
|
|
1595
|
+
const localCliNames = new Set(localExtracted?.fields.map((f) => f.cliName) ?? []);
|
|
1596
|
+
const localAliases = new Set(localExtracted?.fields.filter((f) => f.alias).map((f) => f.alias) ?? []);
|
|
1597
|
+
const globalTokens = [];
|
|
1598
|
+
const commandTokens = [];
|
|
1599
|
+
for (let i = 0; i < argv.length; i++) {
|
|
1600
|
+
const arg = argv[i];
|
|
1601
|
+
if (arg === "--") {
|
|
1602
|
+
commandTokens.push(...argv.slice(i));
|
|
1603
|
+
break;
|
|
1604
|
+
}
|
|
1605
|
+
if (arg.startsWith("--")) {
|
|
1606
|
+
const { resolvedName, withoutDashes, isNegated, isGlobal } = resolveGlobalLongOption(arg, lookup);
|
|
1607
|
+
const flagName = isNegated ? withoutDashes.slice(3) : withoutDashes;
|
|
1608
|
+
const isLocalCollision = localCliNames.has(withoutDashes) || localCliNames.has(flagName);
|
|
1609
|
+
if (isGlobal && !isLocalCollision) {
|
|
1610
|
+
i += collectGlobalFlag(argv, i, resolvedName, isNegated, lookup.booleanFlags, globalTokens) - 1;
|
|
1611
|
+
continue;
|
|
1612
|
+
}
|
|
1613
|
+
} else if (arg.startsWith("-") && arg.length > 1) {
|
|
1614
|
+
const withoutDash = arg.includes("=") ? arg.slice(1, arg.indexOf("=")) : arg.slice(1);
|
|
1615
|
+
if (withoutDash.length === 1) {
|
|
1616
|
+
const resolvedName = lookup.aliasMap.get(withoutDash) ?? withoutDash;
|
|
1617
|
+
if ((lookup.aliases.has(withoutDash) || lookup.flagNames.has(resolvedName)) && !localAliases.has(withoutDash)) {
|
|
1618
|
+
i += collectGlobalFlag(argv, i, resolvedName, false, lookup.booleanFlags, globalTokens) - 1;
|
|
1619
|
+
continue;
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
commandTokens.push(arg);
|
|
1624
|
+
}
|
|
1625
|
+
return {
|
|
1626
|
+
separated: commandTokens,
|
|
1627
|
+
globalParsed: parseGlobalArgs(globalTokens, globalExtracted)
|
|
1347
1628
|
};
|
|
1348
1629
|
}
|
|
1349
1630
|
|
|
@@ -1526,11 +1807,11 @@ const defaultLogger = {
|
|
|
1526
1807
|
* ```
|
|
1527
1808
|
*/
|
|
1528
1809
|
async function runCommand(command, argv, options = {}) {
|
|
1810
|
+
const globalExtracted = extractAndValidateGlobal(options);
|
|
1529
1811
|
return runCommandInternal(command, argv, {
|
|
1530
1812
|
...options,
|
|
1531
1813
|
handleSignals: false,
|
|
1532
|
-
|
|
1533
|
-
logger: options.logger
|
|
1814
|
+
_globalExtracted: globalExtracted
|
|
1534
1815
|
});
|
|
1535
1816
|
}
|
|
1536
1817
|
/**
|
|
@@ -1557,16 +1838,20 @@ async function runCommand(command, argv, options = {}) {
|
|
|
1557
1838
|
* ```
|
|
1558
1839
|
*/
|
|
1559
1840
|
async function runMain(command, options = {}) {
|
|
1841
|
+
const globalExtracted = extractAndValidateGlobal(options);
|
|
1560
1842
|
const result = await runCommandInternal(command, process.argv.slice(2), {
|
|
1561
1843
|
debug: options.debug,
|
|
1562
1844
|
captureLogs: options.captureLogs,
|
|
1563
1845
|
skipValidation: options.skipValidation,
|
|
1564
1846
|
handleSignals: true,
|
|
1565
1847
|
logger: options.logger,
|
|
1848
|
+
globalArgs: options.globalArgs,
|
|
1849
|
+
_globalExtracted: globalExtracted,
|
|
1566
1850
|
_context: {
|
|
1567
1851
|
commandPath: [],
|
|
1568
1852
|
rootName: command.name,
|
|
1569
|
-
rootVersion: options.version
|
|
1853
|
+
rootVersion: options.version,
|
|
1854
|
+
globalExtracted
|
|
1570
1855
|
}
|
|
1571
1856
|
});
|
|
1572
1857
|
if (process.stdout.writableLength > 0) await new Promise((resolve) => process.stdout.once("drain", resolve));
|
|
@@ -1579,7 +1864,8 @@ async function runCommandInternal(command, argv, options = {}) {
|
|
|
1579
1864
|
const logger = options.logger ?? defaultLogger;
|
|
1580
1865
|
const context = options._context ?? {
|
|
1581
1866
|
commandPath: [],
|
|
1582
|
-
rootName: command.name
|
|
1867
|
+
rootName: command.name,
|
|
1868
|
+
globalExtracted: options._globalExtracted
|
|
1583
1869
|
};
|
|
1584
1870
|
const collector = options.captureLogs ?? false ? createLogCollector() : null;
|
|
1585
1871
|
collector?.start();
|
|
@@ -1587,12 +1873,19 @@ async function runCommandInternal(command, argv, options = {}) {
|
|
|
1587
1873
|
return mergeLogs(options._existingLogs ?? emptyLogs(), collector?.getLogs() ?? emptyLogs());
|
|
1588
1874
|
};
|
|
1589
1875
|
try {
|
|
1590
|
-
const parseResult = parseArgs(argv, command, {
|
|
1876
|
+
const parseResult = parseArgs(argv, command, {
|
|
1877
|
+
skipValidation: options.skipValidation,
|
|
1878
|
+
globalExtracted: options._globalExtracted
|
|
1879
|
+
});
|
|
1880
|
+
const accumulatedGlobalArgs = {
|
|
1881
|
+
...options._parsedGlobalArgs,
|
|
1882
|
+
...parseResult.rawGlobalArgs
|
|
1883
|
+
};
|
|
1591
1884
|
if (parseResult.helpRequested || parseResult.helpAllRequested) {
|
|
1592
1885
|
let hasUnknownSubcommand = false;
|
|
1593
1886
|
const subCmdNames = listSubCommands(command);
|
|
1594
1887
|
if (subCmdNames.length > 0) {
|
|
1595
|
-
const potentialSubCmd = argv
|
|
1888
|
+
const potentialSubCmd = findFirstPositional(argv, context.globalExtracted);
|
|
1596
1889
|
if (potentialSubCmd && !subCmdNames.includes(potentialSubCmd)) {
|
|
1597
1890
|
logger.error(formatUnknownSubcommand(potentialSubCmd, subCmdNames));
|
|
1598
1891
|
logger.error("");
|
|
@@ -1636,13 +1929,15 @@ async function runCommandInternal(command, argv, options = {}) {
|
|
|
1636
1929
|
const subContext = {
|
|
1637
1930
|
commandPath: [...context.commandPath ?? [], parseResult.subCommand],
|
|
1638
1931
|
rootName: context.rootName,
|
|
1639
|
-
rootVersion: context.rootVersion
|
|
1932
|
+
rootVersion: context.rootVersion,
|
|
1933
|
+
globalExtracted: context.globalExtracted
|
|
1640
1934
|
};
|
|
1641
1935
|
collector?.stop();
|
|
1642
1936
|
return runCommandInternal(subCmd, parseResult.remainingArgs, {
|
|
1643
1937
|
...options,
|
|
1644
1938
|
_context: subContext,
|
|
1645
|
-
_existingLogs: getCurrentLogs()
|
|
1939
|
+
_existingLogs: getCurrentLogs(),
|
|
1940
|
+
_parsedGlobalArgs: accumulatedGlobalArgs
|
|
1646
1941
|
});
|
|
1647
1942
|
}
|
|
1648
1943
|
}
|
|
@@ -1674,9 +1969,35 @@ async function runCommandInternal(command, argv, options = {}) {
|
|
|
1674
1969
|
};
|
|
1675
1970
|
} else if (unknownKeysMode === "strip") for (const flag of parseResult.unknownFlags) logger.error(formatUnknownFlagWarning(flag, knownFlags));
|
|
1676
1971
|
}
|
|
1972
|
+
let validatedGlobalArgs = {};
|
|
1973
|
+
if (options.globalArgs && options._globalExtracted) {
|
|
1974
|
+
for (const field of options._globalExtracted.fields) if (field.env && accumulatedGlobalArgs[field.name] === void 0) {
|
|
1975
|
+
const envNames = Array.isArray(field.env) ? field.env : [field.env];
|
|
1976
|
+
for (const envName of envNames) {
|
|
1977
|
+
const envValue = process.env[envName];
|
|
1978
|
+
if (envValue !== void 0) {
|
|
1979
|
+
accumulatedGlobalArgs[field.name] = envValue;
|
|
1980
|
+
break;
|
|
1981
|
+
}
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1984
|
+
const globalValidation = validateArgs(accumulatedGlobalArgs, options.globalArgs);
|
|
1985
|
+
if (!globalValidation.success) {
|
|
1986
|
+
const errorMessage = formatValidationErrors$1(globalValidation.errors);
|
|
1987
|
+
logger.error(errorMessage);
|
|
1988
|
+
collector?.stop();
|
|
1989
|
+
return {
|
|
1990
|
+
success: false,
|
|
1991
|
+
error: new Error(errorMessage),
|
|
1992
|
+
exitCode: 1,
|
|
1993
|
+
logs: getCurrentLogs()
|
|
1994
|
+
};
|
|
1995
|
+
}
|
|
1996
|
+
validatedGlobalArgs = globalValidation.data;
|
|
1997
|
+
}
|
|
1677
1998
|
if (!command.args) {
|
|
1678
1999
|
collector?.stop();
|
|
1679
|
-
return await executeLifecycle(command,
|
|
2000
|
+
return await executeLifecycle(command, validatedGlobalArgs, {
|
|
1680
2001
|
handleSignals: options.handleSignals,
|
|
1681
2002
|
captureLogs: options.captureLogs,
|
|
1682
2003
|
existingLogs: getCurrentLogs()
|
|
@@ -1693,8 +2014,12 @@ async function runCommandInternal(command, argv, options = {}) {
|
|
|
1693
2014
|
logs: getCurrentLogs()
|
|
1694
2015
|
};
|
|
1695
2016
|
}
|
|
2017
|
+
const mergedArgs = {
|
|
2018
|
+
...validatedGlobalArgs,
|
|
2019
|
+
...validationResult.data
|
|
2020
|
+
};
|
|
1696
2021
|
collector?.stop();
|
|
1697
|
-
return await executeLifecycle(command,
|
|
2022
|
+
return await executeLifecycle(command, mergedArgs, {
|
|
1698
2023
|
handleSignals: options.handleSignals,
|
|
1699
2024
|
captureLogs: options.captureLogs,
|
|
1700
2025
|
existingLogs: getCurrentLogs()
|
|
@@ -1711,7 +2036,24 @@ async function runCommandInternal(command, argv, options = {}) {
|
|
|
1711
2036
|
};
|
|
1712
2037
|
}
|
|
1713
2038
|
}
|
|
2039
|
+
/**
|
|
2040
|
+
* Extract global fields from options.globalArgs and validate the schema upfront.
|
|
2041
|
+
* Rejects positional fields since global options must be flags.
|
|
2042
|
+
* Returns undefined when no globalArgs is provided.
|
|
2043
|
+
*/
|
|
2044
|
+
function extractAndValidateGlobal(options) {
|
|
2045
|
+
if (!options.globalArgs) return void 0;
|
|
2046
|
+
const extracted = extractFields(options.globalArgs);
|
|
2047
|
+
if (!options.skipValidation) {
|
|
2048
|
+
validateDuplicateFields(extracted);
|
|
2049
|
+
validateDuplicateAliases(extracted);
|
|
2050
|
+
validateReservedAliases(extracted, true);
|
|
2051
|
+
const positionalNames = extracted.fields.filter((f) => f.positional).map((f) => f.name);
|
|
2052
|
+
if (positionalNames.length > 0) throw new Error(`Global options schema must not contain positional arguments. Found: ${positionalNames.join(", ")}`);
|
|
2053
|
+
}
|
|
2054
|
+
return extracted;
|
|
2055
|
+
}
|
|
1714
2056
|
|
|
1715
2057
|
//#endregion
|
|
1716
2058
|
export { symbols as C, styles as S, renderInline as _, parseArgv as a, logger as b, validateDuplicateAliases as c, validateReservedAliases as d, DuplicateAliasError as f, generateHelp as g, ReservedAliasError as h, formatValidationErrors as i, validateDuplicateFields as l, PositionalConfigError as m, runMain as n, formatCommandValidationErrors as o, DuplicateFieldError as p, runner_exports as r, validateCommand as s, runCommand as t, validatePositionalConfig as u, renderMarkdown as v, setColorEnabled as x, isColorEnabled as y };
|
|
1717
|
-
//# sourceMappingURL=runner-
|
|
2059
|
+
//# sourceMappingURL=runner-DjG0uBxQ.js.map
|