politty 0.4.15 → 0.5.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/{arg-registry-Dw0f11Zc.d.ts → arg-registry--NRaNFJM.d.cts} +238 -6
- package/dist/arg-registry--NRaNFJM.d.cts.map +1 -0
- package/dist/{arg-registry-CB5gGtzp.d.cts → arg-registry-6E0WHOh_.d.ts} +238 -6
- package/dist/arg-registry-6E0WHOh_.d.ts.map +1 -0
- package/dist/augment.d.cts +1 -1
- package/dist/augment.d.cts.map +1 -1
- package/dist/augment.d.ts +1 -1
- package/dist/augment.d.ts.map +1 -1
- package/dist/completion/index.cjs +2 -1
- package/dist/completion/index.d.cts +3 -2
- package/dist/completion/index.d.ts +3 -2
- package/dist/completion/index.js +2 -2
- package/dist/completion-BA5JMvVG.js +4067 -0
- package/dist/completion-BA5JMvVG.js.map +1 -0
- package/dist/completion-Cqs1Ja7C.cjs +4169 -0
- package/dist/completion-Cqs1Ja7C.cjs.map +1 -0
- package/dist/docs/index.cjs +89 -29
- package/dist/docs/index.cjs.map +1 -1
- package/dist/docs/index.d.cts +1 -1
- package/dist/docs/index.d.cts.map +1 -1
- package/dist/docs/index.d.ts +1 -1
- package/dist/docs/index.d.ts.map +1 -1
- package/dist/docs/index.js +92 -31
- package/dist/docs/index.js.map +1 -1
- package/dist/{index-C1gGgUeB.d.cts → index-DBMfKZ34.d.ts} +189 -17
- package/dist/index-DBMfKZ34.d.ts.map +1 -0
- package/dist/{index-Dg9Fpz0R.d.ts → index-DJp8k5Bq.d.cts} +189 -17
- package/dist/index-DJp8k5Bq.d.cts.map +1 -0
- package/dist/index.cjs +12 -10
- package/dist/index.d.cts +36 -4
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +36 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/log-collector-Cd2_mv87.cjs.map +1 -1
- package/dist/log-collector-Cu6MCtAx.js.map +1 -1
- package/dist/prompt/clack/index.cjs.map +1 -1
- package/dist/prompt/clack/index.d.cts +1 -1
- package/dist/prompt/clack/index.d.cts.map +1 -1
- package/dist/prompt/clack/index.d.ts +1 -1
- package/dist/prompt/clack/index.d.ts.map +1 -1
- package/dist/prompt/clack/index.js.map +1 -1
- package/dist/prompt/index.d.cts +1 -1
- package/dist/prompt/index.d.cts.map +1 -1
- package/dist/prompt/index.d.ts +1 -1
- package/dist/prompt/index.d.ts.map +1 -1
- package/dist/prompt/inquirer/index.cjs.map +1 -1
- package/dist/prompt/inquirer/index.d.cts +1 -1
- package/dist/prompt/inquirer/index.d.cts.map +1 -1
- package/dist/prompt/inquirer/index.d.ts +1 -1
- package/dist/prompt/inquirer/index.d.ts.map +1 -1
- package/dist/prompt/inquirer/index.js.map +1 -1
- package/dist/prompt-BKHqGrFw.js.map +1 -1
- package/dist/prompt-aXfSf27y.cjs.map +1 -1
- package/dist/{runner-DKAQBNNh.js → runner-BmSEiD9A.js} +319 -52
- package/dist/runner-BmSEiD9A.js.map +1 -0
- package/dist/{runner-CriXJlm4.cjs → runner-CRZ_7Y9i.cjs} +366 -87
- package/dist/runner-CRZ_7Y9i.cjs.map +1 -0
- package/dist/{subcommand-router-ENeCymvX.js → schema-extractor-C50R-1re.js} +175 -137
- package/dist/schema-extractor-C50R-1re.js.map +1 -0
- package/dist/{subcommand-router-CqZX3orq.cjs → schema-extractor-SLPgBNgZ.cjs} +174 -136
- package/dist/schema-extractor-SLPgBNgZ.cjs.map +1 -0
- package/package.json +16 -16
- package/dist/arg-registry-CB5gGtzp.d.cts.map +0 -1
- package/dist/arg-registry-Dw0f11Zc.d.ts.map +0 -1
- package/dist/completion-B5fgnUGm.cjs +0 -1940
- package/dist/completion-B5fgnUGm.cjs.map +0 -1
- package/dist/completion-Ca5ESJlG.js +0 -1844
- package/dist/completion-Ca5ESJlG.js.map +0 -1
- package/dist/index-C1gGgUeB.d.cts.map +0 -1
- package/dist/index-Dg9Fpz0R.d.ts.map +0 -1
- package/dist/runner-CriXJlm4.cjs.map +0 -1
- package/dist/runner-DKAQBNNh.js.map +0 -1
- package/dist/subcommand-router-CqZX3orq.cjs.map +0 -1
- package/dist/subcommand-router-ENeCymvX.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_log_collector = require('./log-collector-Cd2_mv87.cjs');
|
|
2
|
-
const
|
|
2
|
+
const require_schema_extractor = require('./schema-extractor-SLPgBNgZ.cjs');
|
|
3
3
|
let node_util = require("node:util");
|
|
4
4
|
let string_width = require("string-width");
|
|
5
5
|
string_width = require_log_collector.__toESM(string_width, 1);
|
|
@@ -19,9 +19,9 @@ function createDualCaseProxy(obj) {
|
|
|
19
19
|
get(target, prop, receiver) {
|
|
20
20
|
if (typeof prop === "string") {
|
|
21
21
|
if (prop in target) return Reflect.get(target, prop, receiver);
|
|
22
|
-
const camel =
|
|
22
|
+
const camel = require_schema_extractor.toCamelCase(prop);
|
|
23
23
|
if (camel !== prop && camel in target) return Reflect.get(target, camel, receiver);
|
|
24
|
-
const kebab =
|
|
24
|
+
const kebab = require_schema_extractor.toKebabCase(prop);
|
|
25
25
|
if (kebab !== prop && kebab in target) return Reflect.get(target, kebab, receiver);
|
|
26
26
|
}
|
|
27
27
|
return Reflect.get(target, prop, receiver);
|
|
@@ -29,9 +29,9 @@ function createDualCaseProxy(obj) {
|
|
|
29
29
|
has(target, prop) {
|
|
30
30
|
if (typeof prop === "string") {
|
|
31
31
|
if (prop in target) return true;
|
|
32
|
-
const camel =
|
|
32
|
+
const camel = require_schema_extractor.toCamelCase(prop);
|
|
33
33
|
if (camel !== prop && camel in target) return true;
|
|
34
|
-
const kebab =
|
|
34
|
+
const kebab = require_schema_extractor.toKebabCase(prop);
|
|
35
35
|
if (kebab !== prop && kebab in target) return true;
|
|
36
36
|
}
|
|
37
37
|
return Reflect.has(target, prop);
|
|
@@ -220,24 +220,45 @@ const symbols = {
|
|
|
220
220
|
* Logger for CLI output
|
|
221
221
|
*/
|
|
222
222
|
const logger = {
|
|
223
|
+
/**
|
|
224
|
+
* Log informational message
|
|
225
|
+
*/
|
|
223
226
|
info(message) {
|
|
224
227
|
console.log(message);
|
|
225
228
|
},
|
|
229
|
+
/**
|
|
230
|
+
* Log success message
|
|
231
|
+
*/
|
|
226
232
|
success(message) {
|
|
227
233
|
console.log(`${symbols.success} ${styles.success(message)}`);
|
|
228
234
|
},
|
|
235
|
+
/**
|
|
236
|
+
* Log warning message
|
|
237
|
+
*/
|
|
229
238
|
warn(message) {
|
|
230
239
|
console.warn(`${symbols.warning} ${styles.warning(message)}`);
|
|
231
240
|
},
|
|
241
|
+
/**
|
|
242
|
+
* Log error message
|
|
243
|
+
*/
|
|
232
244
|
error(message) {
|
|
233
245
|
console.error(`${symbols.error} ${styles.error(message)}`);
|
|
234
246
|
},
|
|
247
|
+
/**
|
|
248
|
+
* Log raw message without prefix
|
|
249
|
+
*/
|
|
235
250
|
log(message) {
|
|
236
251
|
console.log(message);
|
|
237
252
|
},
|
|
253
|
+
/**
|
|
254
|
+
* Log empty line
|
|
255
|
+
*/
|
|
238
256
|
newline() {
|
|
239
257
|
console.log("");
|
|
240
258
|
},
|
|
259
|
+
/**
|
|
260
|
+
* Log debug message with dim color
|
|
261
|
+
*/
|
|
241
262
|
debug(message) {
|
|
242
263
|
console.log(styles.dim(message));
|
|
243
264
|
}
|
|
@@ -593,7 +614,7 @@ function renderUsageLine(command, context) {
|
|
|
593
614
|
const name = buildUsageCommandName(command, context);
|
|
594
615
|
parts.push(styles.commandName(name));
|
|
595
616
|
if (context?.globalExtracted?.fields.length) parts.push(styles.placeholder("[global options]"));
|
|
596
|
-
const extracted =
|
|
617
|
+
const extracted = require_schema_extractor.getExtractedFields(command);
|
|
597
618
|
if (extracted) {
|
|
598
619
|
const positionals = extracted.fields.filter((a) => a.positional);
|
|
599
620
|
if (extracted.fields.filter((a) => !a.positional).length > 0) parts.push(styles.placeholder("[options]"));
|
|
@@ -613,9 +634,9 @@ function renderOptions(command, descriptions = {}, context) {
|
|
|
613
634
|
helpAll: descriptions.helpAll ?? defaultBuiltinDescriptions.helpAll,
|
|
614
635
|
version: descriptions.version ?? defaultBuiltinDescriptions.version
|
|
615
636
|
};
|
|
616
|
-
const extracted =
|
|
617
|
-
const hasUserDefinedh = extracted?.fields.some((f) => f.overrideBuiltinAlias === true &&
|
|
618
|
-
const hasUserDefinedH = extracted?.fields.some((f) => f.overrideBuiltinAlias === true &&
|
|
637
|
+
const extracted = require_schema_extractor.getExtractedFields(command);
|
|
638
|
+
const hasUserDefinedh = extracted?.fields.some((f) => f.overrideBuiltinAlias === true && require_schema_extractor.getAllAliases(f).includes("h")) ?? false;
|
|
639
|
+
const hasUserDefinedH = extracted?.fields.some((f) => f.overrideBuiltinAlias === true && require_schema_extractor.getAllAliases(f).includes("H")) ?? false;
|
|
619
640
|
if (hasUserDefinedh) lines.push(formatOption(styles.option("--help"), desc.help));
|
|
620
641
|
else lines.push(formatOption(`${styles.option("-h")}, ${styles.option("--help")}`, desc.help));
|
|
621
642
|
if (hasUserDefinedH) lines.push(formatOption(styles.option("--help-all"), desc.helpAll));
|
|
@@ -634,10 +655,21 @@ function renderOptions(command, descriptions = {}, context) {
|
|
|
634
655
|
const envInfo = formatEnvInfo(opt.env);
|
|
635
656
|
if (envInfo) desc += ` ${envInfo}`;
|
|
636
657
|
lines.push(formatOption(flags, desc));
|
|
658
|
+
const negationLine = formatNegationLine(opt);
|
|
659
|
+
if (negationLine) lines.push(negationLine);
|
|
637
660
|
}
|
|
638
661
|
return lines.join("\n");
|
|
639
662
|
}
|
|
640
663
|
/**
|
|
664
|
+
* Render a separate line for the custom negation option when a
|
|
665
|
+
* `negationDescription` is provided. When no description is given, the
|
|
666
|
+
* negation is shown inline by `formatFlags`.
|
|
667
|
+
*/
|
|
668
|
+
function formatNegationLine(opt, indent = 0, extraDescPadding = 0) {
|
|
669
|
+
if (!opt.negationDisplay || !opt.negationDescription) return null;
|
|
670
|
+
return formatOption(styles.option(`--${opt.negationDisplay}`), `${opt.negationDescription} ${styles.dim(`(↔ --${opt.cliName})`)}`, indent, extraDescPadding);
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
641
673
|
* Render options for discriminated union with variants
|
|
642
674
|
*/
|
|
643
675
|
function renderDiscriminatedUnionOptions(extracted, _command, lines) {
|
|
@@ -666,6 +698,8 @@ function renderDiscriminatedUnionOptions(extracted, _command, lines) {
|
|
|
666
698
|
const envInfo = formatEnvInfo(field.env);
|
|
667
699
|
if (envInfo) desc += ` ${envInfo}`;
|
|
668
700
|
lines.push(formatOption(flags, desc));
|
|
701
|
+
const negationLine = formatNegationLine(field);
|
|
702
|
+
if (negationLine) lines.push(negationLine);
|
|
669
703
|
}
|
|
670
704
|
}
|
|
671
705
|
for (const variant of variants) {
|
|
@@ -681,7 +715,9 @@ function renderDiscriminatedUnionOptions(extracted, _command, lines) {
|
|
|
681
715
|
if (field.required) desc += ` ${styles.required("(required)")}`;
|
|
682
716
|
const envInfo = formatEnvInfo(field.env);
|
|
683
717
|
if (envInfo) desc += ` ${envInfo}`;
|
|
684
|
-
lines.push(formatOption(
|
|
718
|
+
lines.push(formatOption(flags, desc, 1));
|
|
719
|
+
const negationLine = formatNegationLine(field, 1);
|
|
720
|
+
if (negationLine) lines.push(negationLine);
|
|
685
721
|
}
|
|
686
722
|
}
|
|
687
723
|
}
|
|
@@ -705,6 +741,8 @@ function renderUnionOptions(extracted, _command, lines) {
|
|
|
705
741
|
const envInfo = formatEnvInfo(field.env);
|
|
706
742
|
if (envInfo) desc += ` ${envInfo}`;
|
|
707
743
|
lines.push(formatOption(flags, desc));
|
|
744
|
+
const negationLine = formatNegationLine(field);
|
|
745
|
+
if (negationLine) lines.push(negationLine);
|
|
708
746
|
}
|
|
709
747
|
}
|
|
710
748
|
for (let i = 0; i < unionOptions.length; i++) {
|
|
@@ -722,7 +760,9 @@ function renderUnionOptions(extracted, _command, lines) {
|
|
|
722
760
|
if (field.required) desc += ` ${styles.required("(required)")}`;
|
|
723
761
|
const envInfo = formatEnvInfo(field.env);
|
|
724
762
|
if (envInfo) desc += ` ${envInfo}`;
|
|
725
|
-
lines.push(formatOption(
|
|
763
|
+
lines.push(formatOption(flags, desc, 1));
|
|
764
|
+
const negationLine = formatNegationLine(field, 1);
|
|
765
|
+
if (negationLine) lines.push(negationLine);
|
|
726
766
|
}
|
|
727
767
|
} else {
|
|
728
768
|
lines.push("");
|
|
@@ -737,16 +777,16 @@ function renderUnionOptions(extracted, _command, lines) {
|
|
|
737
777
|
* Uses cliName (kebab-case) for display
|
|
738
778
|
*/
|
|
739
779
|
function formatFlags(opt) {
|
|
740
|
-
const
|
|
780
|
+
const aliasParts = [];
|
|
741
781
|
if (opt.alias) {
|
|
742
|
-
for (const alias of opt.alias) if (alias.length === 1)
|
|
782
|
+
for (const alias of opt.alias) if (alias.length === 1) aliasParts.push(styles.option(`-${alias}`));
|
|
743
783
|
}
|
|
744
784
|
let longFlag = styles.option(`--${opt.cliName}`);
|
|
745
785
|
if (opt.type !== "boolean") {
|
|
746
786
|
const placeholder = opt.placeholder ?? opt.cliName.toUpperCase();
|
|
747
787
|
longFlag += ` ${styles.placeholder(`<${placeholder}>`)}`;
|
|
748
788
|
}
|
|
749
|
-
|
|
789
|
+
aliasParts.push(longFlag);
|
|
750
790
|
if (opt.alias) {
|
|
751
791
|
for (const alias of opt.alias) if (alias.length > 1) {
|
|
752
792
|
let longAlias = styles.option(`--${alias}`);
|
|
@@ -754,10 +794,12 @@ function formatFlags(opt) {
|
|
|
754
794
|
const placeholder = opt.placeholder ?? opt.cliName.toUpperCase();
|
|
755
795
|
longAlias += ` ${styles.placeholder(`<${placeholder}>`)}`;
|
|
756
796
|
}
|
|
757
|
-
|
|
797
|
+
aliasParts.push(longAlias);
|
|
758
798
|
}
|
|
759
799
|
}
|
|
760
|
-
|
|
800
|
+
const aliasStr = aliasParts.join(", ");
|
|
801
|
+
if (opt.type === "boolean" && opt.negationDisplay && !opt.negationDescription) return `${aliasStr} / ${styles.option(`--${opt.negationDisplay}`)}`;
|
|
802
|
+
return aliasStr;
|
|
761
803
|
}
|
|
762
804
|
/**
|
|
763
805
|
* Format environment variable info for help display
|
|
@@ -809,14 +851,21 @@ function formatFieldLine(opt, indent = 0, extraDescPadding = 0) {
|
|
|
809
851
|
* Render global options section
|
|
810
852
|
*/
|
|
811
853
|
function renderGlobalOptions(globalExtracted) {
|
|
812
|
-
|
|
854
|
+
const lines = [];
|
|
855
|
+
for (const opt of globalExtracted.fields) {
|
|
856
|
+
if (opt.positional) continue;
|
|
857
|
+
lines.push(formatFieldLine(opt));
|
|
858
|
+
const negationLine = formatNegationLine(opt);
|
|
859
|
+
if (negationLine) lines.push(negationLine);
|
|
860
|
+
}
|
|
861
|
+
return lines.join("\n");
|
|
813
862
|
}
|
|
814
863
|
/**
|
|
815
864
|
* Render options for a subcommand (used by showSubcommandOptions)
|
|
816
865
|
*/
|
|
817
866
|
function renderSubcommandOptionsCompact(command, indent) {
|
|
818
867
|
const lines = [];
|
|
819
|
-
const extracted =
|
|
868
|
+
const extracted = require_schema_extractor.getExtractedFields(command);
|
|
820
869
|
if (extracted) {
|
|
821
870
|
const options = extracted.fields.filter((a) => !a.positional);
|
|
822
871
|
for (const opt of options) {
|
|
@@ -826,6 +875,8 @@ function renderSubcommandOptionsCompact(command, indent) {
|
|
|
826
875
|
const envInfo = formatEnvInfo(opt.env);
|
|
827
876
|
if (envInfo) desc += ` ${envInfo}`;
|
|
828
877
|
lines.push(formatOption(flags, desc, indent, 2));
|
|
878
|
+
const negationLine = formatNegationLine(opt, indent, 2);
|
|
879
|
+
if (negationLine) lines.push(negationLine);
|
|
829
880
|
}
|
|
830
881
|
}
|
|
831
882
|
return lines;
|
|
@@ -836,7 +887,7 @@ function renderSubcommandOptionsCompact(command, indent) {
|
|
|
836
887
|
function renderSubcommandsWithOptions(subCommands, parentPath, baseIndent) {
|
|
837
888
|
const lines = [];
|
|
838
889
|
for (const [name, subCmd] of getVisibleSubcommandEntries(subCommands)) {
|
|
839
|
-
const cmd =
|
|
890
|
+
const cmd = require_schema_extractor.resolveSubCommandMeta(subCmd);
|
|
840
891
|
const fullPath = parentPath ? `${parentPath} ${name}` : name;
|
|
841
892
|
const desc = cmd?.description ?? "";
|
|
842
893
|
const aliases = cmd?.aliases;
|
|
@@ -888,7 +939,7 @@ function generateHelp(command, options) {
|
|
|
888
939
|
} else {
|
|
889
940
|
const subLines = [];
|
|
890
941
|
for (const [name, subCmd] of Object.entries(visibleSubCommands)) {
|
|
891
|
-
const cmd =
|
|
942
|
+
const cmd = require_schema_extractor.resolveSubCommandMeta(subCmd);
|
|
892
943
|
const desc = cmd?.description ?? "";
|
|
893
944
|
const fullName = currentPath ? `${currentPath} ${name}` : name;
|
|
894
945
|
const aliases = cmd?.aliases;
|
|
@@ -973,6 +1024,17 @@ var CaseVariantCollisionError = class extends Error {
|
|
|
973
1024
|
this.name = "CaseVariantCollisionError";
|
|
974
1025
|
}
|
|
975
1026
|
};
|
|
1027
|
+
/**
|
|
1028
|
+
* Error thrown when a custom boolean negation name collides with another
|
|
1029
|
+
* field's name, cliName, alias, or another field's negation (including
|
|
1030
|
+
* derived camelCase variants).
|
|
1031
|
+
*/
|
|
1032
|
+
var DuplicateNegationError = class extends Error {
|
|
1033
|
+
constructor(message) {
|
|
1034
|
+
super(message);
|
|
1035
|
+
this.name = "DuplicateNegationError";
|
|
1036
|
+
}
|
|
1037
|
+
};
|
|
976
1038
|
|
|
977
1039
|
//#endregion
|
|
978
1040
|
//#region src/validator/command-validator.ts
|
|
@@ -1000,7 +1062,7 @@ function checkCaseVariantCollisions(extracted, commandPath) {
|
|
|
1000
1062
|
const errors = [];
|
|
1001
1063
|
const canonicalMap = /* @__PURE__ */ new Map();
|
|
1002
1064
|
for (const field of extracted.fields) {
|
|
1003
|
-
const camel =
|
|
1065
|
+
const camel = require_schema_extractor.toCamelCase(field.name);
|
|
1004
1066
|
const existing = canonicalMap.get(camel);
|
|
1005
1067
|
if (existing && existing !== field.name) errors.push({
|
|
1006
1068
|
commandPath,
|
|
@@ -1040,12 +1102,12 @@ function checkDuplicateAliases(extracted, commandPath) {
|
|
|
1040
1102
|
seenAliases.set(alias, fieldName);
|
|
1041
1103
|
};
|
|
1042
1104
|
for (const field of extracted.fields) {
|
|
1043
|
-
const allAliases =
|
|
1105
|
+
const allAliases = require_schema_extractor.getAllAliases(field);
|
|
1044
1106
|
if (allAliases.length === 0) continue;
|
|
1045
1107
|
for (const alias of allAliases) {
|
|
1046
1108
|
registerAlias(alias, field.name, false);
|
|
1047
1109
|
if (alias.length > 1 && alias.includes("-")) {
|
|
1048
|
-
const camelVariant =
|
|
1110
|
+
const camelVariant = require_schema_extractor.toCamelCase(alias);
|
|
1049
1111
|
if (camelVariant !== alias && !fieldNames.has(camelVariant)) registerAlias(camelVariant, field.name, true);
|
|
1050
1112
|
}
|
|
1051
1113
|
}
|
|
@@ -1053,6 +1115,79 @@ function checkDuplicateAliases(extracted, commandPath) {
|
|
|
1053
1115
|
return errors;
|
|
1054
1116
|
}
|
|
1055
1117
|
/**
|
|
1118
|
+
* Check for collisions involving custom boolean `negation` names
|
|
1119
|
+
*/
|
|
1120
|
+
function checkDuplicateNegations(extracted, commandPath) {
|
|
1121
|
+
const errors = [];
|
|
1122
|
+
const claimed = /* @__PURE__ */ new Map();
|
|
1123
|
+
const claim = (name, fieldName, kind) => {
|
|
1124
|
+
if (!claimed.has(name)) claimed.set(name, {
|
|
1125
|
+
field: fieldName,
|
|
1126
|
+
kind
|
|
1127
|
+
});
|
|
1128
|
+
};
|
|
1129
|
+
for (const field of extracted.fields) {
|
|
1130
|
+
claim(field.name, field.name, "field name");
|
|
1131
|
+
if (field.name.includes("-")) {
|
|
1132
|
+
const camelName = require_schema_extractor.toCamelCase(field.name);
|
|
1133
|
+
if (camelName !== field.name) claim(camelName, field.name, "field name");
|
|
1134
|
+
}
|
|
1135
|
+
if (field.cliName !== field.name) claim(field.cliName, field.name, "CLI name");
|
|
1136
|
+
if (field.cliName.includes("-")) {
|
|
1137
|
+
const camelCli = require_schema_extractor.toCamelCase(field.cliName);
|
|
1138
|
+
if (camelCli !== field.cliName) claim(camelCli, field.name, "CLI name");
|
|
1139
|
+
}
|
|
1140
|
+
for (const alias of require_schema_extractor.getAllAliases(field)) {
|
|
1141
|
+
claim(alias, field.name, "alias");
|
|
1142
|
+
if (alias.length > 1 && alias.includes("-")) {
|
|
1143
|
+
const camelVariant = require_schema_extractor.toCamelCase(alias);
|
|
1144
|
+
if (camelVariant !== alias) claim(camelVariant, field.name, "alias");
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
if (field.type === "boolean" && field.negation !== false && typeof field.negation !== "string") {
|
|
1148
|
+
const defaultKebab = `no-${field.cliName}`;
|
|
1149
|
+
claim(defaultKebab, field.name, "default negation");
|
|
1150
|
+
const camelBase = require_schema_extractor.toCamelCase(field.cliName);
|
|
1151
|
+
const defaultCamel = `no${camelBase[0]?.toUpperCase() ?? ""}${camelBase.slice(1)}`;
|
|
1152
|
+
if (defaultCamel !== defaultKebab) claim(defaultCamel, field.name, "default negation");
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
const seenNegations = /* @__PURE__ */ new Map();
|
|
1156
|
+
const register = (name, fieldName, isDerived) => {
|
|
1157
|
+
const claim = claimed.get(name);
|
|
1158
|
+
if (claim) {
|
|
1159
|
+
const qualifier = isDerived ? " (derived camelCase variant)" : "";
|
|
1160
|
+
const conflict = claim.field === fieldName ? `the same field's own ${claim.kind} "${name}"` : `${claim.kind} "${name}" of field "${claim.field}"`;
|
|
1161
|
+
errors.push({
|
|
1162
|
+
commandPath,
|
|
1163
|
+
type: "duplicate_negation",
|
|
1164
|
+
message: `Negation "${name}"${qualifier} for field "${fieldName}" conflicts with ${conflict}.`,
|
|
1165
|
+
field: fieldName
|
|
1166
|
+
});
|
|
1167
|
+
}
|
|
1168
|
+
const existing = seenNegations.get(name);
|
|
1169
|
+
if (existing && existing !== fieldName) {
|
|
1170
|
+
const qualifier = isDerived ? " (derived camelCase variant)" : "";
|
|
1171
|
+
errors.push({
|
|
1172
|
+
commandPath,
|
|
1173
|
+
type: "duplicate_negation",
|
|
1174
|
+
message: `Duplicate negation "${name}"${qualifier} detected. Both "${existing}" and "${fieldName}" use the same negation name.`,
|
|
1175
|
+
field: fieldName
|
|
1176
|
+
});
|
|
1177
|
+
}
|
|
1178
|
+
seenNegations.set(name, fieldName);
|
|
1179
|
+
};
|
|
1180
|
+
for (const field of extracted.fields) {
|
|
1181
|
+
if (typeof field.negation !== "string") continue;
|
|
1182
|
+
register(field.negation, field.name, false);
|
|
1183
|
+
if (field.negation.includes("-")) {
|
|
1184
|
+
const camelVariant = require_schema_extractor.toCamelCase(field.negation);
|
|
1185
|
+
if (camelVariant !== field.negation) register(camelVariant, field.name, true);
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
return errors;
|
|
1189
|
+
}
|
|
1190
|
+
/**
|
|
1056
1191
|
* Check positional argument configuration
|
|
1057
1192
|
*/
|
|
1058
1193
|
function checkPositionalConfig(extracted, commandPath) {
|
|
@@ -1091,7 +1226,7 @@ function checkReservedAliases(extracted, commandPath) {
|
|
|
1091
1226
|
const errors = [];
|
|
1092
1227
|
for (const field of extracted.fields) {
|
|
1093
1228
|
if (field.overrideBuiltinAlias === true) continue;
|
|
1094
|
-
for (const alias of
|
|
1229
|
+
for (const alias of require_schema_extractor.getAllAliases(field)) if (alias === "h" || alias === "H") errors.push({
|
|
1095
1230
|
commandPath,
|
|
1096
1231
|
type: "reserved_alias",
|
|
1097
1232
|
message: `Alias "${alias}" is reserved for --${alias === "h" ? "help" : "help-all"}.`,
|
|
@@ -1162,11 +1297,24 @@ function validateReservedAliases(extracted, _hasSubCommands) {
|
|
|
1162
1297
|
if (errors.length > 0) {
|
|
1163
1298
|
const field = errors[0].field ?? "unknown";
|
|
1164
1299
|
const found = extracted.fields.find((f) => f.name === field);
|
|
1165
|
-
const alias = (found ?
|
|
1300
|
+
const alias = (found ? require_schema_extractor.getAllAliases(found) : []).find((a) => a === "h" || a === "H") ?? "h";
|
|
1166
1301
|
throw new ReservedAliasError(`Alias "${alias}" is reserved for --${alias === "h" ? "help" : "help-all"}. To override this, set { overrideBuiltinAlias: true } for "${field}" and keep the alias where it is currently defined (in alias or hiddenAlias).`);
|
|
1167
1302
|
}
|
|
1168
1303
|
}
|
|
1169
1304
|
/**
|
|
1305
|
+
* Validate that custom boolean negation names do not collide with anything
|
|
1306
|
+
*
|
|
1307
|
+
* @param extracted - Extracted fields from schema
|
|
1308
|
+
* @throws {DuplicateNegationError} If a colliding negation is found
|
|
1309
|
+
*/
|
|
1310
|
+
function validateDuplicateNegations(extracted) {
|
|
1311
|
+
const errors = checkDuplicateNegations(extracted, []);
|
|
1312
|
+
if (errors.length > 0) {
|
|
1313
|
+
const err = errors[0];
|
|
1314
|
+
throw new DuplicateNegationError(err.message);
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
/**
|
|
1170
1318
|
* Validate that no case-variant collisions exist
|
|
1171
1319
|
*
|
|
1172
1320
|
* @param extracted - Extracted fields from schema
|
|
@@ -1189,9 +1337,9 @@ function validateCaseVariantCollisions(extracted) {
|
|
|
1189
1337
|
*/
|
|
1190
1338
|
function validateCrossSchemaCollisions(extractedA, extractedB) {
|
|
1191
1339
|
const canonicalMap = /* @__PURE__ */ new Map();
|
|
1192
|
-
for (const field of extractedA.fields) canonicalMap.set(
|
|
1340
|
+
for (const field of extractedA.fields) canonicalMap.set(require_schema_extractor.toCamelCase(field.name), field.name);
|
|
1193
1341
|
for (const field of extractedB.fields) {
|
|
1194
|
-
const camel =
|
|
1342
|
+
const camel = require_schema_extractor.toCamelCase(field.name);
|
|
1195
1343
|
const existing = canonicalMap.get(camel);
|
|
1196
1344
|
if (existing && existing !== field.name) throw new CaseVariantCollisionError(`Global field "${existing}" and command field "${field.name}" are case variants of each other and would collide.`);
|
|
1197
1345
|
}
|
|
@@ -1204,6 +1352,7 @@ function collectSchemaErrors(extracted, _hasSubCommands, commandPath) {
|
|
|
1204
1352
|
...checkDuplicateFields(extracted, commandPath),
|
|
1205
1353
|
...checkCaseVariantCollisions(extracted, commandPath),
|
|
1206
1354
|
...checkDuplicateAliases(extracted, commandPath),
|
|
1355
|
+
...checkDuplicateNegations(extracted, commandPath),
|
|
1207
1356
|
...checkPositionalConfig(extracted, commandPath),
|
|
1208
1357
|
...checkReservedAliases(extracted, commandPath)
|
|
1209
1358
|
];
|
|
@@ -1219,7 +1368,7 @@ function checkSubCommandAliasConflicts(command, commandPath) {
|
|
|
1219
1368
|
const nameToOwner = /* @__PURE__ */ new Map();
|
|
1220
1369
|
for (const [name] of Object.entries(command.subCommands)) nameToOwner.set(name, name);
|
|
1221
1370
|
for (const [name, subCmdValue] of Object.entries(command.subCommands)) {
|
|
1222
|
-
const resolved =
|
|
1371
|
+
const resolved = require_schema_extractor.isLazyCommand(subCmdValue) ? subCmdValue.meta : typeof subCmdValue !== "function" ? subCmdValue : null;
|
|
1223
1372
|
if (!resolved?.aliases) continue;
|
|
1224
1373
|
const subCommandPath = [...commandPath, name];
|
|
1225
1374
|
for (const alias of resolved.aliases) {
|
|
@@ -1282,12 +1431,12 @@ async function validateCommand(command, options = {}) {
|
|
|
1282
1431
|
const errors = [];
|
|
1283
1432
|
const hasSubCommands = command.subCommands ? Object.keys(command.subCommands).length > 0 : false;
|
|
1284
1433
|
if (command.args) {
|
|
1285
|
-
const extracted =
|
|
1434
|
+
const extracted = require_schema_extractor.extractFields(command.args);
|
|
1286
1435
|
errors.push(...collectSchemaErrors(extracted, hasSubCommands, commandPath));
|
|
1287
1436
|
}
|
|
1288
1437
|
errors.push(...checkSubCommandAliasConflicts(command, commandPath));
|
|
1289
1438
|
if (command.subCommands) for (const [name, subCmd] of Object.entries(command.subCommands)) {
|
|
1290
|
-
const subResult = await validateCommand(await
|
|
1439
|
+
const subResult = await validateCommand(await require_schema_extractor.resolveLazyCommand(subCmd), { commandPath: [...commandPath, name] });
|
|
1291
1440
|
if (!subResult.valid) errors.push(...subResult.errors);
|
|
1292
1441
|
}
|
|
1293
1442
|
if (errors.length === 0) return { valid: true };
|
|
@@ -1336,7 +1485,7 @@ function formatCommandValidationErrors(errors) {
|
|
|
1336
1485
|
* @returns Parsed arguments
|
|
1337
1486
|
*/
|
|
1338
1487
|
function parseArgv(argv, options = {}) {
|
|
1339
|
-
const { aliasMap = /* @__PURE__ */ new Map(), booleanFlags = /* @__PURE__ */ new Set(), arrayFlags = /* @__PURE__ */ new Set(), definedNames = /* @__PURE__ */ new Set() } = options;
|
|
1488
|
+
const { aliasMap = /* @__PURE__ */ new Map(), booleanFlags = /* @__PURE__ */ new Set(), arrayFlags = /* @__PURE__ */ new Set(), definedNames = /* @__PURE__ */ new Set(), negationMap = /* @__PURE__ */ new Map(), customNegatedFields = /* @__PURE__ */ new Set() } = options;
|
|
1340
1489
|
const result = {
|
|
1341
1490
|
options: {},
|
|
1342
1491
|
positionals: [],
|
|
@@ -1367,11 +1516,19 @@ function parseArgv(argv, options = {}) {
|
|
|
1367
1516
|
}
|
|
1368
1517
|
if (arg.startsWith("--")) {
|
|
1369
1518
|
const withoutDashes = arg.slice(2);
|
|
1519
|
+
if (!withoutDashes.includes("=")) {
|
|
1520
|
+
const negatedField = negationMap.get(withoutDashes);
|
|
1521
|
+
if (negatedField && booleanFlags.has(negatedField)) {
|
|
1522
|
+
setOption(negatedField, false);
|
|
1523
|
+
i++;
|
|
1524
|
+
continue;
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1370
1527
|
if (withoutDashes.startsWith("no-")) {
|
|
1371
1528
|
const flagName = withoutDashes.slice(3);
|
|
1372
1529
|
if (flagName === flagName.toLowerCase()) {
|
|
1373
1530
|
const resolvedName = aliasMap.get(flagName) ?? flagName;
|
|
1374
|
-
if (booleanFlags.has(resolvedName)) {
|
|
1531
|
+
if (booleanFlags.has(resolvedName) && !customNegatedFields.has(resolvedName)) {
|
|
1375
1532
|
const asIsResolved = aliasMap.get(withoutDashes) ?? withoutDashes;
|
|
1376
1533
|
if (!definedNames.has(asIsResolved)) {
|
|
1377
1534
|
setOption(flagName, false);
|
|
@@ -1384,7 +1541,7 @@ function parseArgv(argv, options = {}) {
|
|
|
1384
1541
|
if (withoutDashes.length > 2 && withoutDashes.startsWith("no") && /[A-Z]/.test(withoutDashes[2])) {
|
|
1385
1542
|
const camelFlagName = withoutDashes[2].toLowerCase() + withoutDashes.slice(3);
|
|
1386
1543
|
const resolvedName = aliasMap.get(camelFlagName) ?? camelFlagName;
|
|
1387
|
-
if (booleanFlags.has(resolvedName)) {
|
|
1544
|
+
if (booleanFlags.has(resolvedName) && !customNegatedFields.has(resolvedName)) {
|
|
1388
1545
|
const asIsResolved = aliasMap.get(withoutDashes) ?? withoutDashes;
|
|
1389
1546
|
if (!definedNames.has(asIsResolved)) {
|
|
1390
1547
|
setOption(camelFlagName, false);
|
|
@@ -1457,26 +1614,40 @@ function buildParserOptions(extracted) {
|
|
|
1457
1614
|
const booleanFlags = /* @__PURE__ */ new Set();
|
|
1458
1615
|
const arrayFlags = /* @__PURE__ */ new Set();
|
|
1459
1616
|
const definedNames = /* @__PURE__ */ new Set();
|
|
1617
|
+
const negationMap = /* @__PURE__ */ new Map();
|
|
1618
|
+
const customNegatedFields = /* @__PURE__ */ new Set();
|
|
1460
1619
|
for (const field of extracted.fields) definedNames.add(field.name);
|
|
1461
1620
|
for (const field of extracted.fields) {
|
|
1462
1621
|
if (field.cliName !== field.name) aliasMap.set(field.cliName, field.name);
|
|
1463
|
-
for (const alias of
|
|
1622
|
+
for (const alias of require_schema_extractor.getAllAliases(field)) {
|
|
1464
1623
|
aliasMap.set(alias, field.name);
|
|
1465
1624
|
if (alias.length > 1 && alias.includes("-")) {
|
|
1466
|
-
const camelAlias =
|
|
1625
|
+
const camelAlias = require_schema_extractor.toCamelCase(alias);
|
|
1467
1626
|
if (camelAlias !== alias && !definedNames.has(camelAlias) && !aliasMap.has(camelAlias)) aliasMap.set(camelAlias, field.name);
|
|
1468
1627
|
}
|
|
1469
1628
|
}
|
|
1470
|
-
const camelVariant =
|
|
1629
|
+
const camelVariant = require_schema_extractor.toCamelCase(field.name);
|
|
1471
1630
|
if (camelVariant !== field.name && !definedNames.has(camelVariant) && !aliasMap.has(camelVariant)) aliasMap.set(camelVariant, field.name);
|
|
1472
1631
|
if (field.type === "boolean") booleanFlags.add(field.name);
|
|
1473
1632
|
if (field.type === "array") arrayFlags.add(field.name);
|
|
1633
|
+
if (field.type === "boolean" && (typeof field.negation === "string" || field.negation === false)) {
|
|
1634
|
+
customNegatedFields.add(field.name);
|
|
1635
|
+
if (typeof field.negation === "string") {
|
|
1636
|
+
negationMap.set(field.negation, field.name);
|
|
1637
|
+
if (field.negation.includes("-")) {
|
|
1638
|
+
const camelNegation = require_schema_extractor.toCamelCase(field.negation);
|
|
1639
|
+
if (camelNegation !== field.negation) negationMap.set(camelNegation, field.name);
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1474
1643
|
}
|
|
1475
1644
|
return {
|
|
1476
1645
|
aliasMap,
|
|
1477
1646
|
booleanFlags,
|
|
1478
1647
|
arrayFlags,
|
|
1479
|
-
definedNames
|
|
1648
|
+
definedNames,
|
|
1649
|
+
negationMap,
|
|
1650
|
+
customNegatedFields
|
|
1480
1651
|
};
|
|
1481
1652
|
}
|
|
1482
1653
|
/**
|
|
@@ -1507,31 +1678,61 @@ function mergeWithPositionals(parsed, extracted) {
|
|
|
1507
1678
|
* Shared by scanForSubcommand, separateGlobalArgs, and findFirstPositional.
|
|
1508
1679
|
*/
|
|
1509
1680
|
function buildGlobalFlagLookup(globalExtracted) {
|
|
1510
|
-
const { aliasMap = /* @__PURE__ */ new Map(), booleanFlags = /* @__PURE__ */ new Set() } = buildParserOptions(globalExtracted);
|
|
1681
|
+
const { aliasMap = /* @__PURE__ */ new Map(), booleanFlags = /* @__PURE__ */ new Set(), negationMap = /* @__PURE__ */ new Map(), customNegatedFields = /* @__PURE__ */ new Set() } = buildParserOptions(globalExtracted);
|
|
1511
1682
|
const shortAliases = /* @__PURE__ */ new Set();
|
|
1512
|
-
for (const field of globalExtracted.fields) for (const alias of
|
|
1683
|
+
for (const field of globalExtracted.fields) for (const alias of require_schema_extractor.getAllAliases(field)) if (alias.length === 1) shortAliases.add(alias);
|
|
1513
1684
|
return {
|
|
1514
1685
|
aliasMap,
|
|
1515
1686
|
booleanFlags,
|
|
1516
1687
|
flagNames: new Set(globalExtracted.fields.map((f) => f.name)),
|
|
1517
1688
|
cliNames: new Set(globalExtracted.fields.map((f) => f.cliName)),
|
|
1518
|
-
aliases: shortAliases
|
|
1689
|
+
aliases: shortAliases,
|
|
1690
|
+
negationMap,
|
|
1691
|
+
customNegatedFields
|
|
1519
1692
|
};
|
|
1520
1693
|
}
|
|
1521
1694
|
/**
|
|
1522
|
-
* Resolve a long option (--flag, --flag=value, --no-flag)
|
|
1523
|
-
* Returns the resolved camelCase name and whether
|
|
1695
|
+
* Resolve a long option (--flag, --flag=value, --no-flag, --custom-negation)
|
|
1696
|
+
* against global flag lookup. Returns the resolved camelCase name and whether
|
|
1697
|
+
* it is a known global flag.
|
|
1698
|
+
*
|
|
1699
|
+
* `isSuppressedNegation` is true when the token matches a default `--no-X`
|
|
1700
|
+
* form that has been suppressed by a custom `negation` on the target field.
|
|
1701
|
+
* The caller may use this to keep argv scanning past such tokens (so a
|
|
1702
|
+
* trailing subcommand is still detected) even though they no longer negate.
|
|
1524
1703
|
*/
|
|
1525
1704
|
function resolveGlobalLongOption(arg, lookup) {
|
|
1526
1705
|
const withoutDashes = arg.includes("=") ? arg.slice(2, arg.indexOf("=")) : arg.slice(2);
|
|
1527
|
-
const
|
|
1528
|
-
|
|
1706
|
+
const customNegated = !arg.includes("=") ? lookup.negationMap.get(withoutDashes) : void 0;
|
|
1707
|
+
if (customNegated) return {
|
|
1708
|
+
resolvedName: customNegated,
|
|
1709
|
+
withoutDashes,
|
|
1710
|
+
isNegated: true,
|
|
1711
|
+
isGlobal: lookup.flagNames.has(customNegated),
|
|
1712
|
+
isSuppressedNegation: false
|
|
1713
|
+
};
|
|
1714
|
+
const kebabNegated = withoutDashes.startsWith("no-");
|
|
1715
|
+
const camelNegated = !kebabNegated && withoutDashes.length > 2 && withoutDashes.startsWith("no") && /[A-Z]/.test(withoutDashes[2]);
|
|
1716
|
+
if (kebabNegated || camelNegated) {
|
|
1717
|
+
const literalResolved = lookup.aliasMap.get(withoutDashes) ?? withoutDashes;
|
|
1718
|
+
if (lookup.flagNames.has(literalResolved) || lookup.cliNames.has(withoutDashes)) return {
|
|
1719
|
+
resolvedName: literalResolved,
|
|
1720
|
+
withoutDashes,
|
|
1721
|
+
isNegated: false,
|
|
1722
|
+
isGlobal: true,
|
|
1723
|
+
isSuppressedNegation: false
|
|
1724
|
+
};
|
|
1725
|
+
}
|
|
1726
|
+
const defaultIsNegated = kebabNegated || camelNegated;
|
|
1727
|
+
const flagName = kebabNegated ? withoutDashes.slice(3) : camelNegated ? withoutDashes[2].toLowerCase() + withoutDashes.slice(3) : withoutDashes;
|
|
1529
1728
|
const resolvedName = lookup.aliasMap.get(flagName) ?? flagName;
|
|
1729
|
+
const suppressDefaultNegation = defaultIsNegated && lookup.customNegatedFields.has(resolvedName);
|
|
1530
1730
|
return {
|
|
1531
1731
|
resolvedName,
|
|
1532
1732
|
withoutDashes,
|
|
1533
|
-
isNegated,
|
|
1534
|
-
isGlobal: lookup.flagNames.has(resolvedName) || lookup.cliNames.has(withoutDashes) || lookup.cliNames.has(flagName)
|
|
1733
|
+
isNegated: defaultIsNegated && !suppressDefaultNegation,
|
|
1734
|
+
isGlobal: !suppressDefaultNegation && (lookup.flagNames.has(resolvedName) || lookup.cliNames.has(withoutDashes) || lookup.cliNames.has(flagName)),
|
|
1735
|
+
isSuppressedNegation: suppressDefaultNegation
|
|
1535
1736
|
};
|
|
1536
1737
|
}
|
|
1537
1738
|
/**
|
|
@@ -1579,6 +1780,7 @@ function scanForSubcommand(argv, subCommandNames, globalExtracted) {
|
|
|
1579
1780
|
const lookup = buildGlobalFlagLookup(globalExtracted);
|
|
1580
1781
|
const subCommandNameSet = new Set(subCommandNames);
|
|
1581
1782
|
const globalTokensBefore = [];
|
|
1783
|
+
const suppressedTokens = [];
|
|
1582
1784
|
let i = 0;
|
|
1583
1785
|
while (i < argv.length) {
|
|
1584
1786
|
const arg = argv[i];
|
|
@@ -1586,14 +1788,20 @@ function scanForSubcommand(argv, subCommandNames, globalExtracted) {
|
|
|
1586
1788
|
if (!arg.startsWith("-") && subCommandNameSet.has(arg)) return {
|
|
1587
1789
|
subCommandIndex: i,
|
|
1588
1790
|
globalTokensBefore,
|
|
1589
|
-
tokensAfterSubcommand: argv.slice(i + 1)
|
|
1791
|
+
tokensAfterSubcommand: argv.slice(i + 1),
|
|
1792
|
+
suppressedTokens
|
|
1590
1793
|
};
|
|
1591
1794
|
if (arg.startsWith("--")) {
|
|
1592
|
-
const { resolvedName, isNegated, isGlobal } = resolveGlobalLongOption(arg, lookup);
|
|
1795
|
+
const { resolvedName, isNegated, isGlobal, isSuppressedNegation } = resolveGlobalLongOption(arg, lookup);
|
|
1593
1796
|
if (isGlobal) {
|
|
1594
1797
|
i += collectGlobalFlag(argv, i, resolvedName, isNegated, lookup.booleanFlags, globalTokensBefore);
|
|
1595
1798
|
continue;
|
|
1596
1799
|
}
|
|
1800
|
+
if (isSuppressedNegation) {
|
|
1801
|
+
suppressedTokens.push(arg.includes("=") ? arg.slice(2, arg.indexOf("=")) : arg.slice(2));
|
|
1802
|
+
i++;
|
|
1803
|
+
continue;
|
|
1804
|
+
}
|
|
1597
1805
|
break;
|
|
1598
1806
|
}
|
|
1599
1807
|
if (arg.startsWith("-") && arg.length > 1) {
|
|
@@ -1612,7 +1820,8 @@ function scanForSubcommand(argv, subCommandNames, globalExtracted) {
|
|
|
1612
1820
|
return {
|
|
1613
1821
|
subCommandIndex: -1,
|
|
1614
1822
|
globalTokensBefore,
|
|
1615
|
-
tokensAfterSubcommand: []
|
|
1823
|
+
tokensAfterSubcommand: [],
|
|
1824
|
+
suppressedTokens
|
|
1616
1825
|
};
|
|
1617
1826
|
}
|
|
1618
1827
|
const BUILTIN_FLAGS = new Set([
|
|
@@ -1658,7 +1867,7 @@ function findFirstPositional(argv, globalExtracted) {
|
|
|
1658
1867
|
* @returns Parse result
|
|
1659
1868
|
*/
|
|
1660
1869
|
function parseArgs(argv, command, options = {}) {
|
|
1661
|
-
const subCommandNameSet =
|
|
1870
|
+
const subCommandNameSet = require_schema_extractor.listSubCommandNamesWithAliases(command);
|
|
1662
1871
|
const subCommandNames = [...subCommandNameSet];
|
|
1663
1872
|
const hasSubCommands = subCommandNames.length > 0;
|
|
1664
1873
|
if (hasSubCommands && argv.length > 0) if (options.globalExtracted) {
|
|
@@ -1673,7 +1882,7 @@ function parseArgs(argv, command, options = {}) {
|
|
|
1673
1882
|
remainingArgs: scanResult.tokensAfterSubcommand,
|
|
1674
1883
|
rawArgs: {},
|
|
1675
1884
|
positionals: [],
|
|
1676
|
-
unknownFlags:
|
|
1885
|
+
unknownFlags: scanResult.suppressedTokens,
|
|
1677
1886
|
rawGlobalArgs
|
|
1678
1887
|
};
|
|
1679
1888
|
}
|
|
@@ -1692,21 +1901,24 @@ function parseArgs(argv, command, options = {}) {
|
|
|
1692
1901
|
}
|
|
1693
1902
|
let extracted;
|
|
1694
1903
|
if (command.args) {
|
|
1695
|
-
extracted =
|
|
1904
|
+
extracted = require_schema_extractor.extractFields(command.args);
|
|
1696
1905
|
if (!options.skipValidation) {
|
|
1697
1906
|
validateDuplicateFields(extracted);
|
|
1698
1907
|
validateCaseVariantCollisions(extracted);
|
|
1699
1908
|
validateDuplicateAliases(extracted);
|
|
1909
|
+
validateDuplicateNegations(extracted);
|
|
1700
1910
|
validatePositionalConfig(extracted);
|
|
1701
1911
|
validateReservedAliases(extracted, hasSubCommands);
|
|
1702
1912
|
if (options.globalExtracted) validateCrossSchemaCollisions(options.globalExtracted, extracted);
|
|
1703
1913
|
}
|
|
1704
1914
|
}
|
|
1705
|
-
const
|
|
1706
|
-
const
|
|
1707
|
-
const
|
|
1708
|
-
const
|
|
1709
|
-
const
|
|
1915
|
+
const ddIdx = argv.indexOf("--");
|
|
1916
|
+
const flagScanArgv = ddIdx >= 0 ? argv.slice(0, ddIdx) : argv;
|
|
1917
|
+
const hasUserDefinedH = extracted?.fields.some((f) => f.overrideBuiltinAlias === true && require_schema_extractor.getAllAliases(f).includes("H")) ?? false;
|
|
1918
|
+
const hasUserDefinedh = extracted?.fields.some((f) => f.overrideBuiltinAlias === true && require_schema_extractor.getAllAliases(f).includes("h")) ?? false;
|
|
1919
|
+
const helpAllRequested = flagScanArgv.includes("--help-all") || !hasUserDefinedH && flagScanArgv.includes("-H");
|
|
1920
|
+
const helpRequested = !helpAllRequested && (flagScanArgv.includes("--help") || !hasUserDefinedh && flagScanArgv.includes("-h"));
|
|
1921
|
+
const versionRequested = flagScanArgv.includes("--version");
|
|
1710
1922
|
if (helpRequested || helpAllRequested || versionRequested) return {
|
|
1711
1923
|
helpRequested,
|
|
1712
1924
|
helpAllRequested,
|
|
@@ -1751,11 +1963,11 @@ function parseArgs(argv, command, options = {}) {
|
|
|
1751
1963
|
const knownFlags = new Set(extracted.fields.map((f) => f.name));
|
|
1752
1964
|
const knownCliNames = new Set(extracted.fields.map((f) => f.cliName));
|
|
1753
1965
|
const knownAliases = /* @__PURE__ */ new Set();
|
|
1754
|
-
for (const f of extracted.fields) for (const alias of
|
|
1966
|
+
for (const f of extracted.fields) for (const alias of require_schema_extractor.getAllAliases(f)) knownAliases.add(alias);
|
|
1755
1967
|
if (options.globalExtracted) for (const f of options.globalExtracted.fields) {
|
|
1756
1968
|
knownFlags.add(f.name);
|
|
1757
1969
|
knownCliNames.add(f.cliName);
|
|
1758
|
-
for (const alias of
|
|
1970
|
+
for (const alias of require_schema_extractor.getAllAliases(f)) knownAliases.add(alias);
|
|
1759
1971
|
}
|
|
1760
1972
|
const unknownFlags = [];
|
|
1761
1973
|
for (const key of Object.keys(parsed.options)) if (!knownFlags.has(key) && !knownCliNames.has(key) && !knownAliases.has(key)) unknownFlags.push(key);
|
|
@@ -1806,7 +2018,7 @@ function separateGlobalArgs(argv, globalExtracted, localExtracted) {
|
|
|
1806
2018
|
}
|
|
1807
2019
|
if (arg.startsWith("--")) {
|
|
1808
2020
|
const { resolvedName, withoutDashes, isNegated, isGlobal } = resolveGlobalLongOption(arg, lookup);
|
|
1809
|
-
const flagName =
|
|
2021
|
+
const flagName = resolvedName;
|
|
1810
2022
|
const isLocalCollision = localFieldNames.has(withoutDashes) || localFieldNames.has(flagName) || localCliNames.has(withoutDashes) || localCliNames.has(flagName) || localAliasMapKeys.has(withoutDashes) || localAliasMapKeys.has(flagName);
|
|
1811
2023
|
if (isGlobal && !isLocalCollision) {
|
|
1812
2024
|
i += collectGlobalFlag(argv, i, resolvedName, isNegated, lookup.booleanFlags, globalTokens) - 1;
|
|
@@ -2042,12 +2254,36 @@ async function runCommand(command, argv, options = {}) {
|
|
|
2042
2254
|
return result;
|
|
2043
2255
|
}
|
|
2044
2256
|
/**
|
|
2257
|
+
* Hidden internal subcommands (e.g. `__refresh-completion`) are spawned
|
|
2258
|
+
* by background hooks and must not run user-provided
|
|
2259
|
+
* `setup`/`cleanup`/`prompt` or required `globalArgs`. Those exist for
|
|
2260
|
+
* the foreground CLI run; replaying them in a detached child causes
|
|
2261
|
+
* duplicate side effects, stuck prompts, and validation failures the
|
|
2262
|
+
* user never opted into.
|
|
2263
|
+
*
|
|
2264
|
+
* We treat any registered subcommand whose name starts with `__` as
|
|
2265
|
+
* internal. We use `findFirstPositional` (schema-aware) instead of the
|
|
2266
|
+
* naive "first non-flag token" so an option *value* like
|
|
2267
|
+
* `--name __refresh-completion` doesn't trip the bypass — that would
|
|
2268
|
+
* silently skip lifecycle hooks for ordinary invocations.
|
|
2269
|
+
*/
|
|
2270
|
+
function isInternalSubcommandInvocation(command, argv, globalExtracted) {
|
|
2271
|
+
const firstPositional = findFirstPositional(argv, globalExtracted);
|
|
2272
|
+
if (!firstPositional || !firstPositional.startsWith("__")) return false;
|
|
2273
|
+
return Boolean(command.subCommands?.[firstPositional]);
|
|
2274
|
+
}
|
|
2275
|
+
/**
|
|
2045
2276
|
* Run a CLI command as the main entry point
|
|
2046
2277
|
*
|
|
2047
2278
|
* This function:
|
|
2048
2279
|
* - Uses process.argv for arguments
|
|
2049
2280
|
* - Handles SIGINT/SIGTERM signals
|
|
2050
2281
|
* - Calls process.exit with the appropriate exit code
|
|
2282
|
+
* - Invokes `command.runMainHook` once before parsing if set, so plug-ins
|
|
2283
|
+
* like `withCompletionCommand` can fire detached background work
|
|
2284
|
+
* - Bypasses user `setup`/`cleanup`/`prompt` and required `globalArgs`
|
|
2285
|
+
* for registered hidden subcommands whose name starts with `__`
|
|
2286
|
+
* (e.g. `__refresh-completion`)
|
|
2051
2287
|
*
|
|
2052
2288
|
* @param command - The command to run
|
|
2053
2289
|
* @param options - Main options (version, debug)
|
|
@@ -2065,38 +2301,51 @@ async function runCommand(command, argv, options = {}) {
|
|
|
2065
2301
|
* ```
|
|
2066
2302
|
*/
|
|
2067
2303
|
async function runMain(command, options = {}) {
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2304
|
+
if (command.runMainHook) try {
|
|
2305
|
+
command.runMainHook(process.argv.slice(2));
|
|
2306
|
+
} catch {}
|
|
2307
|
+
const argv = process.argv.slice(2);
|
|
2308
|
+
let globalExtractedForBypass;
|
|
2309
|
+
if (options.globalArgs) try {
|
|
2310
|
+
globalExtractedForBypass = require_schema_extractor.extractFields(options.globalArgs);
|
|
2311
|
+
} catch {}
|
|
2312
|
+
let effectiveOptions = options;
|
|
2313
|
+
if (isInternalSubcommandInvocation(command, argv, globalExtractedForBypass)) {
|
|
2314
|
+
const { setup: _s, cleanup: _c, prompt: _p, globalArgs: _g, ...rest } = options;
|
|
2315
|
+
effectiveOptions = rest;
|
|
2316
|
+
}
|
|
2317
|
+
const globalExtracted = extractAndValidateGlobal(effectiveOptions);
|
|
2318
|
+
if (effectiveOptions.setup) try {
|
|
2319
|
+
await effectiveOptions.setup({});
|
|
2071
2320
|
} catch (e) {
|
|
2072
2321
|
const error = e instanceof Error ? e : new Error(String(e));
|
|
2073
|
-
if (
|
|
2074
|
-
await
|
|
2322
|
+
if (effectiveOptions.cleanup) try {
|
|
2323
|
+
await effectiveOptions.cleanup({ error });
|
|
2075
2324
|
} catch {}
|
|
2076
2325
|
process.exit(1);
|
|
2077
2326
|
}
|
|
2078
|
-
const result = await runCommandInternal(command,
|
|
2079
|
-
debug:
|
|
2080
|
-
captureLogs:
|
|
2081
|
-
skipValidation:
|
|
2327
|
+
const result = await runCommandInternal(command, argv, {
|
|
2328
|
+
debug: effectiveOptions.debug,
|
|
2329
|
+
captureLogs: effectiveOptions.captureLogs,
|
|
2330
|
+
skipValidation: effectiveOptions.skipValidation,
|
|
2082
2331
|
handleSignals: true,
|
|
2083
|
-
logger:
|
|
2084
|
-
globalArgs:
|
|
2085
|
-
prompt:
|
|
2332
|
+
logger: effectiveOptions.logger,
|
|
2333
|
+
globalArgs: effectiveOptions.globalArgs,
|
|
2334
|
+
prompt: effectiveOptions.prompt,
|
|
2086
2335
|
_globalExtracted: globalExtracted,
|
|
2087
|
-
_globalCleanup:
|
|
2336
|
+
_globalCleanup: effectiveOptions.cleanup,
|
|
2088
2337
|
_context: {
|
|
2089
2338
|
commandPath: [],
|
|
2090
2339
|
rootName: command.name,
|
|
2091
|
-
rootVersion:
|
|
2340
|
+
rootVersion: effectiveOptions.version,
|
|
2092
2341
|
globalExtracted
|
|
2093
2342
|
}
|
|
2094
2343
|
});
|
|
2095
|
-
if ((
|
|
2096
|
-
if (
|
|
2344
|
+
if ((effectiveOptions.displayErrors ?? true) && !result.success && result.error) (effectiveOptions.logger ?? defaultLogger).error(formatRuntimeError(result.error, effectiveOptions.debug ?? false));
|
|
2345
|
+
if (effectiveOptions.cleanup) {
|
|
2097
2346
|
const cleanupCtx = { error: !result.success ? result.error : void 0 };
|
|
2098
2347
|
try {
|
|
2099
|
-
await
|
|
2348
|
+
await effectiveOptions.cleanup(cleanupCtx);
|
|
2100
2349
|
} catch {}
|
|
2101
2350
|
}
|
|
2102
2351
|
if (process.stdout.writableLength > 0) await new Promise((resolve) => process.stdout.once("drain", resolve));
|
|
@@ -2129,8 +2378,8 @@ async function runCommandInternal(command, argv, options = {}) {
|
|
|
2129
2378
|
};
|
|
2130
2379
|
if (parseResult.helpRequested || parseResult.helpAllRequested) {
|
|
2131
2380
|
let hasUnknownSubcommand = false;
|
|
2132
|
-
const subCmdNames =
|
|
2133
|
-
const allSubCmdNameSet =
|
|
2381
|
+
const subCmdNames = require_schema_extractor.listSubCommands(command);
|
|
2382
|
+
const allSubCmdNameSet = require_schema_extractor.listSubCommandNamesWithAliases(command);
|
|
2134
2383
|
if (subCmdNames.length > 0) {
|
|
2135
2384
|
const potentialSubCmd = findFirstPositional(argv, context.globalExtracted);
|
|
2136
2385
|
if (potentialSubCmd && !allSubCmdNameSet.has(potentialSubCmd)) hasUnknownSubcommand = true;
|
|
@@ -2172,7 +2421,23 @@ async function runCommandInternal(command, argv, options = {}) {
|
|
|
2172
2421
|
};
|
|
2173
2422
|
}
|
|
2174
2423
|
if (parseResult.subCommand) {
|
|
2175
|
-
|
|
2424
|
+
if (parseResult.unknownFlags.length > 0) {
|
|
2425
|
+
const globalMode = context.globalExtracted?.unknownKeysMode ?? "strip";
|
|
2426
|
+
if (globalMode === "strict") {
|
|
2427
|
+
collector?.stop();
|
|
2428
|
+
return {
|
|
2429
|
+
success: false,
|
|
2430
|
+
error: /* @__PURE__ */ new Error(`Unknown flags: ${parseResult.unknownFlags.join(", ")}`),
|
|
2431
|
+
exitCode: 1,
|
|
2432
|
+
logs: getCurrentLogs()
|
|
2433
|
+
};
|
|
2434
|
+
}
|
|
2435
|
+
if (globalMode === "strip") {
|
|
2436
|
+
const knownGlobalFlags = context.globalExtracted?.fields.map((f) => f.name) ?? [];
|
|
2437
|
+
for (const flag of parseResult.unknownFlags) logger.error(formatUnknownFlagWarning(flag, knownGlobalFlags));
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
const resolved = await require_schema_extractor.resolveSubcommandWithAlias(command, parseResult.subCommand);
|
|
2176
2441
|
if (resolved) {
|
|
2177
2442
|
const subContext = {
|
|
2178
2443
|
commandPath: [...context.commandPath ?? [], parseResult.subCommand],
|
|
@@ -2190,7 +2455,7 @@ async function runCommandInternal(command, argv, options = {}) {
|
|
|
2190
2455
|
});
|
|
2191
2456
|
}
|
|
2192
2457
|
}
|
|
2193
|
-
if (
|
|
2458
|
+
if (require_schema_extractor.listSubCommands(command).length > 0 && !parseResult.subCommand && !command.run) {
|
|
2194
2459
|
const help = generateHelp(command, {
|
|
2195
2460
|
showSubcommands: options.showSubcommands ?? true,
|
|
2196
2461
|
context
|
|
@@ -2218,7 +2483,8 @@ async function runCommandInternal(command, argv, options = {}) {
|
|
|
2218
2483
|
} else if (unknownKeysMode === "strip") for (const flag of parseResult.unknownFlags) logger.error(formatUnknownFlagWarning(flag, knownFlags));
|
|
2219
2484
|
}
|
|
2220
2485
|
let validatedGlobalArgs = {};
|
|
2221
|
-
|
|
2486
|
+
const isCompletionInvocation = command.name === "__complete";
|
|
2487
|
+
if (options.globalArgs && options._globalExtracted && !isCompletionInvocation) {
|
|
2222
2488
|
for (const field of options._globalExtracted.fields) if (field.env && accumulatedGlobalArgs[field.name] === void 0) {
|
|
2223
2489
|
const envNames = Array.isArray(field.env) ? field.env : [field.env];
|
|
2224
2490
|
for (const envName of envNames) {
|
|
@@ -2247,7 +2513,7 @@ async function runCommandInternal(command, argv, options = {}) {
|
|
|
2247
2513
|
}
|
|
2248
2514
|
if (!command.args) {
|
|
2249
2515
|
const proxiedGlobalArgs = createDualCaseProxy(validatedGlobalArgs);
|
|
2250
|
-
if (options._globalExtracted) await runEffects(proxiedGlobalArgs, options._globalExtracted, proxiedGlobalArgs);
|
|
2516
|
+
if (options._globalExtracted && !isCompletionInvocation) await runEffects(proxiedGlobalArgs, options._globalExtracted, proxiedGlobalArgs);
|
|
2251
2517
|
collector?.stop();
|
|
2252
2518
|
return await executeLifecycle(command, proxiedGlobalArgs, {
|
|
2253
2519
|
handleSignals: options.handleSignals,
|
|
@@ -2276,8 +2542,8 @@ async function runCommandInternal(command, argv, options = {}) {
|
|
|
2276
2542
|
}
|
|
2277
2543
|
const proxiedCommandArgs = createDualCaseProxy(validationResult.data);
|
|
2278
2544
|
const proxiedGlobalArgs = createDualCaseProxy(validatedGlobalArgs);
|
|
2279
|
-
if (options._globalExtracted) await runEffects(proxiedGlobalArgs, options._globalExtracted, proxiedGlobalArgs);
|
|
2280
|
-
if (parseResult.extractedFields) await runEffects(proxiedCommandArgs, parseResult.extractedFields, proxiedGlobalArgs);
|
|
2545
|
+
if (options._globalExtracted && !isCompletionInvocation) await runEffects(proxiedGlobalArgs, options._globalExtracted, proxiedGlobalArgs);
|
|
2546
|
+
if (parseResult.extractedFields && !isCompletionInvocation) await runEffects(proxiedCommandArgs, parseResult.extractedFields, proxiedGlobalArgs);
|
|
2281
2547
|
const mergedArgs = createDualCaseProxy({
|
|
2282
2548
|
...proxiedGlobalArgs,
|
|
2283
2549
|
...proxiedCommandArgs
|
|
@@ -2307,11 +2573,12 @@ async function runCommandInternal(command, argv, options = {}) {
|
|
|
2307
2573
|
*/
|
|
2308
2574
|
function extractAndValidateGlobal(options) {
|
|
2309
2575
|
if (!options.globalArgs) return void 0;
|
|
2310
|
-
const extracted =
|
|
2576
|
+
const extracted = require_schema_extractor.extractFields(options.globalArgs);
|
|
2311
2577
|
if (!options.skipValidation) {
|
|
2312
2578
|
validateDuplicateFields(extracted);
|
|
2313
2579
|
validateCaseVariantCollisions(extracted);
|
|
2314
2580
|
validateDuplicateAliases(extracted);
|
|
2581
|
+
validateDuplicateNegations(extracted);
|
|
2315
2582
|
validateReservedAliases(extracted, true);
|
|
2316
2583
|
const positionalNames = extracted.fields.filter((f) => f.positional).map((f) => f.name);
|
|
2317
2584
|
if (positionalNames.length > 0) throw new Error(`Global options schema must not contain positional arguments. Found: ${positionalNames.join(", ")}`);
|
|
@@ -2338,6 +2605,12 @@ Object.defineProperty(exports, 'DuplicateFieldError', {
|
|
|
2338
2605
|
return DuplicateFieldError;
|
|
2339
2606
|
}
|
|
2340
2607
|
});
|
|
2608
|
+
Object.defineProperty(exports, 'DuplicateNegationError', {
|
|
2609
|
+
enumerable: true,
|
|
2610
|
+
get: function () {
|
|
2611
|
+
return DuplicateNegationError;
|
|
2612
|
+
}
|
|
2613
|
+
});
|
|
2341
2614
|
Object.defineProperty(exports, 'PositionalConfigError', {
|
|
2342
2615
|
enumerable: true,
|
|
2343
2616
|
get: function () {
|
|
@@ -2470,6 +2743,12 @@ Object.defineProperty(exports, 'validateDuplicateFields', {
|
|
|
2470
2743
|
return validateDuplicateFields;
|
|
2471
2744
|
}
|
|
2472
2745
|
});
|
|
2746
|
+
Object.defineProperty(exports, 'validateDuplicateNegations', {
|
|
2747
|
+
enumerable: true,
|
|
2748
|
+
get: function () {
|
|
2749
|
+
return validateDuplicateNegations;
|
|
2750
|
+
}
|
|
2751
|
+
});
|
|
2473
2752
|
Object.defineProperty(exports, 'validatePositionalConfig', {
|
|
2474
2753
|
enumerable: true,
|
|
2475
2754
|
get: function () {
|
|
@@ -2482,4 +2761,4 @@ Object.defineProperty(exports, 'validateReservedAliases', {
|
|
|
2482
2761
|
return validateReservedAliases;
|
|
2483
2762
|
}
|
|
2484
2763
|
});
|
|
2485
|
-
//# sourceMappingURL=runner-
|
|
2764
|
+
//# sourceMappingURL=runner-CRZ_7Y9i.cjs.map
|