@optique/core 1.1.0-dev.2087 → 1.1.0-dev.2146
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/annotation-state.cjs +26 -26
- package/dist/annotation-state.d.cts +133 -1
- package/dist/annotation-state.d.ts +133 -1
- package/dist/annotations.cjs +2 -2
- package/dist/constructs.cjs +873 -73
- package/dist/constructs.d.cts +72 -1
- package/dist/constructs.d.ts +72 -1
- package/dist/constructs.js +808 -9
- package/dist/dependency-metadata.cjs +12 -12
- package/dist/dependency-metadata.d.cts +34 -3
- package/dist/dependency-metadata.d.ts +34 -3
- package/dist/dependency-runtime.cjs +37 -13
- package/dist/dependency-runtime.d.cts +197 -2
- package/dist/dependency-runtime.d.ts +197 -2
- package/dist/dependency-runtime.js +22 -1
- package/dist/dependency.cjs +7 -7
- package/dist/displaywidth.d.cts +12 -0
- package/dist/displaywidth.d.ts +12 -0
- package/dist/doc.cjs +3 -0
- package/dist/doc.js +3 -0
- package/dist/execution-context.d.cts +23 -0
- package/dist/execution-context.d.ts +23 -0
- package/dist/extension.cjs +14 -14
- package/dist/facade.cjs +49 -37
- package/dist/facade.js +34 -22
- package/dist/index.cjs +23 -21
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +4 -4
- package/dist/input-trace.d.cts +2 -1
- package/dist/input-trace.d.ts +2 -1
- package/dist/internal/annotations.cjs +3 -0
- package/dist/internal/annotations.d.cts +47 -5
- package/dist/internal/annotations.d.ts +47 -5
- package/dist/internal/annotations.js +1 -1
- package/dist/internal/command-alias.cjs +16 -0
- package/dist/internal/command-alias.js +14 -0
- package/dist/internal/dependency.cjs +131 -0
- package/dist/internal/dependency.d.cts +311 -2
- package/dist/internal/dependency.d.ts +311 -2
- package/dist/internal/dependency.js +119 -1
- package/dist/internal/parser.cjs +108 -23
- package/dist/internal/parser.d.cts +58 -3
- package/dist/internal/parser.d.ts +58 -3
- package/dist/internal/parser.js +101 -16
- package/dist/modifiers.cjs +74 -44
- package/dist/modifiers.js +34 -4
- package/dist/parser.cjs +11 -11
- package/dist/phase2-seed.cjs +2 -2
- package/dist/phase2-seed.d.cts +50 -0
- package/dist/phase2-seed.d.ts +50 -0
- package/dist/primitives.cjs +104 -33
- package/dist/primitives.d.cts +10 -0
- package/dist/primitives.d.ts +10 -0
- package/dist/primitives.js +84 -13
- package/dist/suggestion.cjs +72 -2
- package/dist/suggestion.d.cts +188 -0
- package/dist/suggestion.d.ts +188 -0
- package/dist/suggestion.js +71 -3
- package/dist/usage-internals.cjs +14 -6
- package/dist/usage-internals.js +14 -6
- package/dist/usage.cjs +33 -8
- package/dist/usage.d.cts +31 -0
- package/dist/usage.d.ts +31 -0
- package/dist/usage.js +33 -8
- package/dist/validate.cjs +1 -0
- package/dist/validate.d.cts +99 -0
- package/dist/validate.d.ts +99 -0
- package/dist/validate.js +1 -1
- package/dist/valueparser.cjs +333 -79
- package/dist/valueparser.d.cts +197 -1
- package/dist/valueparser.d.ts +197 -1
- package/dist/valueparser.js +334 -81
- package/package.json +19 -4
package/dist/valueparser.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { message, text, valueSet } from "./message.js";
|
|
1
|
+
import { cloneMessage, lineBreak, message, metavar, text, valueSet } from "./message.js";
|
|
2
|
+
import { isDerivedValueParser } from "./internal/dependency.js";
|
|
3
|
+
import { deduplicateSuggestions } from "./suggestion.js";
|
|
2
4
|
import { ensureNonEmptyString, isNonEmptyString } from "./nonempty.js";
|
|
3
5
|
|
|
4
6
|
//#region src/valueparser.ts
|
|
@@ -29,8 +31,8 @@ function choice(choices, options = {}) {
|
|
|
29
31
|
const isNumber = typeof choices[0] === "number";
|
|
30
32
|
for (const c of choices) if (isNumber ? typeof c !== "number" : typeof c !== "string") throw new TypeError(`Expected every choice to be the same type, but got both ${isNumber ? "number" : "string"} and ${typeof c}.`);
|
|
31
33
|
if (isNumber && choices.some((v) => Number.isNaN(v))) throw new TypeError("NaN is not allowed in number choices.");
|
|
32
|
-
const metavar = options.metavar ?? "TYPE";
|
|
33
|
-
ensureNonEmptyString(metavar);
|
|
34
|
+
const metavar$1 = options.metavar ?? "TYPE";
|
|
35
|
+
ensureNonEmptyString(metavar$1);
|
|
34
36
|
if (isNumber) {
|
|
35
37
|
const numberChoices = (() => {
|
|
36
38
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -57,7 +59,7 @@ function choice(choices, options = {}) {
|
|
|
57
59
|
const frozenNumberChoices = Object.freeze(numberChoices);
|
|
58
60
|
return {
|
|
59
61
|
mode: "sync",
|
|
60
|
-
metavar,
|
|
62
|
+
metavar: metavar$1,
|
|
61
63
|
placeholder: choices[0],
|
|
62
64
|
choices: frozenNumberChoices,
|
|
63
65
|
parse(input) {
|
|
@@ -139,7 +141,7 @@ function choice(choices, options = {}) {
|
|
|
139
141
|
const stringInvalidChoice = stringOptions.errors?.invalidChoice;
|
|
140
142
|
return {
|
|
141
143
|
mode: "sync",
|
|
142
|
-
metavar,
|
|
144
|
+
metavar: metavar$1,
|
|
143
145
|
placeholder: choices[0],
|
|
144
146
|
choices: stringChoices,
|
|
145
147
|
parse(input) {
|
|
@@ -294,14 +296,14 @@ function formatDefaultChoiceError(input, choices) {
|
|
|
294
296
|
*/
|
|
295
297
|
function string(options = {}) {
|
|
296
298
|
if (options.pattern != null && !(options.pattern instanceof RegExp)) throw new TypeError(`Expected pattern to be a RegExp, but got: ${Object.prototype.toString.call(options.pattern)}`);
|
|
297
|
-
const metavar = options.metavar ?? "STRING";
|
|
298
|
-
ensureNonEmptyString(metavar);
|
|
299
|
+
const metavar$1 = options.metavar ?? "STRING";
|
|
300
|
+
ensureNonEmptyString(metavar$1);
|
|
299
301
|
const patternSource = options.pattern?.source ?? null;
|
|
300
302
|
const patternFlags = options.pattern?.flags ?? null;
|
|
301
303
|
const patternMismatch = options.errors?.patternMismatch;
|
|
302
304
|
return {
|
|
303
305
|
mode: "sync",
|
|
304
|
-
metavar,
|
|
306
|
+
metavar: metavar$1,
|
|
305
307
|
placeholder: options.placeholder ?? "",
|
|
306
308
|
parse(input) {
|
|
307
309
|
if (patternSource != null && patternFlags != null) {
|
|
@@ -370,11 +372,11 @@ function integer(options) {
|
|
|
370
372
|
}
|
|
371
373
|
if (options?.min != null && options?.max != null && options.min > options.max) throw new RangeError(`Expected min to be less than or equal to max, but got min: ${options.min} and max: ${options.max}.`);
|
|
372
374
|
if (options?.type === "bigint") {
|
|
373
|
-
const metavar$
|
|
374
|
-
ensureNonEmptyString(metavar$
|
|
375
|
+
const metavar$2 = options.metavar ?? "INTEGER";
|
|
376
|
+
ensureNonEmptyString(metavar$2);
|
|
375
377
|
return {
|
|
376
378
|
mode: "sync",
|
|
377
|
-
metavar: metavar$
|
|
379
|
+
metavar: metavar$2,
|
|
378
380
|
placeholder: options?.placeholder ?? (options?.min != null && options.min > 0n ? options.min : options?.max != null && options.max < 0n ? options.max : 0n),
|
|
379
381
|
parse(input) {
|
|
380
382
|
if (!input.match(/^-?\d+$/)) return {
|
|
@@ -400,8 +402,8 @@ function integer(options) {
|
|
|
400
402
|
}
|
|
401
403
|
};
|
|
402
404
|
}
|
|
403
|
-
const metavar = options?.metavar ?? "INTEGER";
|
|
404
|
-
ensureNonEmptyString(metavar);
|
|
405
|
+
const metavar$1 = options?.metavar ?? "INTEGER";
|
|
406
|
+
ensureNonEmptyString(metavar$1);
|
|
405
407
|
const maxSafe = BigInt(Number.MAX_SAFE_INTEGER);
|
|
406
408
|
const minSafe = BigInt(Number.MIN_SAFE_INTEGER);
|
|
407
409
|
const safeMin = Math.max(options?.min ?? Number.MIN_SAFE_INTEGER, Number.MIN_SAFE_INTEGER);
|
|
@@ -418,7 +420,7 @@ function integer(options) {
|
|
|
418
420
|
}
|
|
419
421
|
return {
|
|
420
422
|
mode: "sync",
|
|
421
|
-
metavar,
|
|
423
|
+
metavar: metavar$1,
|
|
422
424
|
placeholder: options?.placeholder ?? (firstAllowed > 0 ? firstAllowed : lastAllowed < 0 ? lastAllowed : 0),
|
|
423
425
|
parse(input) {
|
|
424
426
|
if (!input.match(/^-?\d+$/)) return {
|
|
@@ -465,11 +467,11 @@ function float(options = {}) {
|
|
|
465
467
|
if (options.max != null && !Number.isFinite(options.max)) throw new RangeError(`Expected max to be a finite number, but got: ${options.max}`);
|
|
466
468
|
if (options.min != null && options.max != null && options.min > options.max) throw new RangeError(`Expected min to be less than or equal to max, but got min: ${options.min} and max: ${options.max}.`);
|
|
467
469
|
const floatRegex = /^[+-]?(?:(?:\d+\.?\d*)|(?:\d*\.\d+))(?:[eE][+-]?\d+)?$/;
|
|
468
|
-
const metavar = options.metavar ?? "NUMBER";
|
|
469
|
-
ensureNonEmptyString(metavar);
|
|
470
|
+
const metavar$1 = options.metavar ?? "NUMBER";
|
|
471
|
+
ensureNonEmptyString(metavar$1);
|
|
470
472
|
return {
|
|
471
473
|
mode: "sync",
|
|
472
|
-
metavar,
|
|
474
|
+
metavar: metavar$1,
|
|
473
475
|
placeholder: options?.placeholder ?? (options?.min != null && options.min > 0 ? options.min : options?.max != null && options.max < 0 ? options.max : 0),
|
|
474
476
|
parse(input) {
|
|
475
477
|
const invalidNumber = (i) => ({
|
|
@@ -741,8 +743,8 @@ const FILE_SIZE_UNITS = [
|
|
|
741
743
|
*/
|
|
742
744
|
function fileSize(options = {}) {
|
|
743
745
|
if (options.type !== void 0 && options.type !== "number" && options.type !== "bigint") throw new TypeError(`Expected type to be "number" or "bigint", but got: ${String(options.type)}.`);
|
|
744
|
-
const metavar = options.metavar ?? "SIZE";
|
|
745
|
-
ensureNonEmptyString(metavar);
|
|
746
|
+
const metavar$1 = options.metavar ?? "SIZE";
|
|
747
|
+
ensureNonEmptyString(metavar$1);
|
|
746
748
|
checkBooleanOption(options, "allowNegative");
|
|
747
749
|
checkBooleanOption(options, "siAsBinary");
|
|
748
750
|
checkEnumOption(options, "defaultUnit", FILE_SIZE_UNITS);
|
|
@@ -762,7 +764,7 @@ function fileSize(options = {}) {
|
|
|
762
764
|
const numberFormatUnits = siAsBinary ? FORMAT_UNITS_SI_AS_BINARY : FORMAT_UNITS_DEFAULT;
|
|
763
765
|
return {
|
|
764
766
|
mode: "sync",
|
|
765
|
-
metavar,
|
|
767
|
+
metavar: metavar$1,
|
|
766
768
|
placeholder: options.placeholder ?? 0n,
|
|
767
769
|
parse(input) {
|
|
768
770
|
const match = FILE_SIZE_REGEX.exec(input.trim());
|
|
@@ -803,7 +805,7 @@ function fileSize(options = {}) {
|
|
|
803
805
|
const formatUnits = siAsBinary ? FORMAT_UNITS_SI_AS_BINARY : FORMAT_UNITS_DEFAULT;
|
|
804
806
|
return {
|
|
805
807
|
mode: "sync",
|
|
806
|
-
metavar,
|
|
808
|
+
metavar: metavar$1,
|
|
807
809
|
placeholder: options.placeholder ?? 0,
|
|
808
810
|
parse(input) {
|
|
809
811
|
const match = FILE_SIZE_REGEX.exec(input.trim());
|
|
@@ -1802,8 +1804,8 @@ const VALID_COLOR_FORMATS = [
|
|
|
1802
1804
|
* @since 1.1.0
|
|
1803
1805
|
*/
|
|
1804
1806
|
function color(options = {}) {
|
|
1805
|
-
const metavar = options.metavar ?? "COLOR";
|
|
1806
|
-
ensureNonEmptyString(metavar);
|
|
1807
|
+
const metavar$1 = options.metavar ?? "COLOR";
|
|
1808
|
+
ensureNonEmptyString(metavar$1);
|
|
1807
1809
|
if (options.formats !== void 0) {
|
|
1808
1810
|
for (const fmt of options.formats) if (!VALID_COLOR_FORMATS.includes(fmt)) throw new TypeError(`Expected formats to contain only ${VALID_COLOR_FORMATS.map((v) => JSON.stringify(v)).join(", ")}, but got: ${JSON.stringify(fmt)}.`);
|
|
1809
1811
|
}
|
|
@@ -1835,7 +1837,7 @@ function color(options = {}) {
|
|
|
1835
1837
|
}
|
|
1836
1838
|
return {
|
|
1837
1839
|
mode: "sync",
|
|
1838
|
-
metavar,
|
|
1840
|
+
metavar: metavar$1,
|
|
1839
1841
|
placeholder: options.placeholder ?? defaultPlaceholder,
|
|
1840
1842
|
parse(input) {
|
|
1841
1843
|
const trimmed = input.trim();
|
|
@@ -2009,13 +2011,13 @@ function url(options = {}) {
|
|
|
2009
2011
|
}
|
|
2010
2012
|
const originalProtocols = options.allowedProtocols != null ? Object.freeze(originalProtocolsList) : void 0;
|
|
2011
2013
|
const allowedProtocols = options.allowedProtocols != null ? Object.freeze(normalizedProtocolsList) : void 0;
|
|
2012
|
-
const metavar = options.metavar ?? "URL";
|
|
2013
|
-
ensureNonEmptyString(metavar);
|
|
2014
|
+
const metavar$1 = options.metavar ?? "URL";
|
|
2015
|
+
ensureNonEmptyString(metavar$1);
|
|
2014
2016
|
const invalidUrl = options.errors?.invalidUrl;
|
|
2015
2017
|
const disallowedProtocol = options.errors?.disallowedProtocol;
|
|
2016
2018
|
return {
|
|
2017
2019
|
mode: "sync",
|
|
2018
|
-
metavar,
|
|
2020
|
+
metavar: metavar$1,
|
|
2019
2021
|
get placeholder() {
|
|
2020
2022
|
return new URL(`${allowedProtocols?.[0] ?? "http:"}//0.invalid`);
|
|
2021
2023
|
},
|
|
@@ -2083,11 +2085,11 @@ function url(options = {}) {
|
|
|
2083
2085
|
* objects.
|
|
2084
2086
|
*/
|
|
2085
2087
|
function locale(options = {}) {
|
|
2086
|
-
const metavar = options.metavar ?? "LOCALE";
|
|
2087
|
-
ensureNonEmptyString(metavar);
|
|
2088
|
+
const metavar$1 = options.metavar ?? "LOCALE";
|
|
2089
|
+
ensureNonEmptyString(metavar$1);
|
|
2088
2090
|
return {
|
|
2089
2091
|
mode: "sync",
|
|
2090
|
-
metavar,
|
|
2092
|
+
metavar: metavar$1,
|
|
2091
2093
|
placeholder: new Intl.Locale("und"),
|
|
2092
2094
|
parse(input) {
|
|
2093
2095
|
let locale$1;
|
|
@@ -2365,8 +2367,8 @@ function locale(options = {}) {
|
|
|
2365
2367
|
*/
|
|
2366
2368
|
function uuid(options = {}) {
|
|
2367
2369
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
2368
|
-
const metavar = options.metavar ?? "UUID";
|
|
2369
|
-
ensureNonEmptyString(metavar);
|
|
2370
|
+
const metavar$1 = options.metavar ?? "UUID";
|
|
2371
|
+
ensureNonEmptyString(metavar$1);
|
|
2370
2372
|
checkBooleanOption(options, "strict");
|
|
2371
2373
|
const strict = options.strict !== false;
|
|
2372
2374
|
const allowedVersions = options.allowedVersions != null ? (() => {
|
|
@@ -2383,7 +2385,7 @@ function uuid(options = {}) {
|
|
|
2383
2385
|
const invalidVariant = options.errors?.invalidVariant;
|
|
2384
2386
|
return {
|
|
2385
2387
|
mode: "sync",
|
|
2386
|
-
metavar,
|
|
2388
|
+
metavar: metavar$1,
|
|
2387
2389
|
placeholder: "00000000-0000-0000-0000-000000000000",
|
|
2388
2390
|
parse(input) {
|
|
2389
2391
|
if (!uuidRegex.test(input)) return {
|
|
@@ -2483,15 +2485,15 @@ function port(options) {
|
|
|
2483
2485
|
checkBooleanOption(options, "disallowWellKnown");
|
|
2484
2486
|
if (options?.type !== void 0 && options.type !== "number" && options.type !== "bigint") throw new TypeError(`Expected type to be "number" or "bigint", but got: ${String(options.type)}.`);
|
|
2485
2487
|
if (options?.type === "bigint") {
|
|
2486
|
-
const metavar$
|
|
2487
|
-
ensureNonEmptyString(metavar$
|
|
2488
|
+
const metavar$2 = options.metavar ?? "PORT";
|
|
2489
|
+
ensureNonEmptyString(metavar$2);
|
|
2488
2490
|
const min$1 = options.min ?? 1n;
|
|
2489
2491
|
const max$1 = options.max ?? 65535n;
|
|
2490
2492
|
if (min$1 > max$1) throw new RangeError(`Expected min to be less than or equal to max, but got min: ${min$1} and max: ${max$1}.`);
|
|
2491
2493
|
if (options.disallowWellKnown && min$1 < 1024n && max$1 < 1024n) throw new RangeError(`disallowWellKnown is incompatible with the configured port range: all ports ${min$1}..${max$1} are well-known.`);
|
|
2492
2494
|
return {
|
|
2493
2495
|
mode: "sync",
|
|
2494
|
-
metavar: metavar$
|
|
2496
|
+
metavar: metavar$2,
|
|
2495
2497
|
placeholder: options.placeholder ?? (options.disallowWellKnown && min$1 < 1024n ? 1024n > min$1 ? 1024n : min$1 : min$1),
|
|
2496
2498
|
parse(input) {
|
|
2497
2499
|
if (!input.match(/^-?\d+$/)) return {
|
|
@@ -2523,15 +2525,15 @@ function port(options) {
|
|
|
2523
2525
|
}
|
|
2524
2526
|
if (options?.min != null && !Number.isFinite(options.min)) throw new RangeError(`Expected min to be a finite number, but got: ${options.min}`);
|
|
2525
2527
|
if (options?.max != null && !Number.isFinite(options.max)) throw new RangeError(`Expected max to be a finite number, but got: ${options.max}`);
|
|
2526
|
-
const metavar = options?.metavar ?? "PORT";
|
|
2527
|
-
ensureNonEmptyString(metavar);
|
|
2528
|
+
const metavar$1 = options?.metavar ?? "PORT";
|
|
2529
|
+
ensureNonEmptyString(metavar$1);
|
|
2528
2530
|
const min = options?.min ?? 1;
|
|
2529
2531
|
const max = options?.max ?? 65535;
|
|
2530
2532
|
if (min > max) throw new RangeError(`Expected min to be less than or equal to max, but got min: ${min} and max: ${max}.`);
|
|
2531
2533
|
if (options?.disallowWellKnown && min < 1024 && max < 1024) throw new RangeError(`disallowWellKnown is incompatible with the configured port range: all ports ${min}..${max} are well-known.`);
|
|
2532
2534
|
return {
|
|
2533
2535
|
mode: "sync",
|
|
2534
|
-
metavar,
|
|
2536
|
+
metavar: metavar$1,
|
|
2535
2537
|
placeholder: options?.placeholder ?? (options?.disallowWellKnown && min < 1024 ? Math.max(1024, min) : min),
|
|
2536
2538
|
parse(input) {
|
|
2537
2539
|
if (!input.match(/^-?\d+$/)) return {
|
|
@@ -2615,8 +2617,8 @@ function isZeroIp(octets) {
|
|
|
2615
2617
|
* ```
|
|
2616
2618
|
*/
|
|
2617
2619
|
function ipv4(options) {
|
|
2618
|
-
const metavar = options?.metavar ?? "IPV4";
|
|
2619
|
-
ensureNonEmptyString(metavar);
|
|
2620
|
+
const metavar$1 = options?.metavar ?? "IPV4";
|
|
2621
|
+
ensureNonEmptyString(metavar$1);
|
|
2620
2622
|
const allowPrivate = options?.allowPrivate ?? true;
|
|
2621
2623
|
const allowLoopback = options?.allowLoopback ?? true;
|
|
2622
2624
|
const allowLinkLocal = options?.allowLinkLocal ?? true;
|
|
@@ -2625,7 +2627,7 @@ function ipv4(options) {
|
|
|
2625
2627
|
const allowZero = options?.allowZero ?? true;
|
|
2626
2628
|
return {
|
|
2627
2629
|
mode: "sync",
|
|
2628
|
-
metavar,
|
|
2630
|
+
metavar: metavar$1,
|
|
2629
2631
|
placeholder: allowZero ? "0.0.0.0" : allowLoopback ? "127.0.0.1" : "192.0.2.1",
|
|
2630
2632
|
parse(input) {
|
|
2631
2633
|
const octets = parseIpv4Octets(input);
|
|
@@ -2730,8 +2732,8 @@ function ipv4(options) {
|
|
|
2730
2732
|
* ```
|
|
2731
2733
|
*/
|
|
2732
2734
|
function hostname(options) {
|
|
2733
|
-
const metavar = options?.metavar ?? "HOST";
|
|
2734
|
-
ensureNonEmptyString(metavar);
|
|
2735
|
+
const metavar$1 = options?.metavar ?? "HOST";
|
|
2736
|
+
ensureNonEmptyString(metavar$1);
|
|
2735
2737
|
checkBooleanOption(options, "allowWildcard");
|
|
2736
2738
|
checkBooleanOption(options, "allowUnderscore");
|
|
2737
2739
|
checkBooleanOption(options, "allowLocalhost");
|
|
@@ -2742,7 +2744,7 @@ function hostname(options) {
|
|
|
2742
2744
|
if (!Number.isInteger(maxLength) || maxLength < 1) throw new RangeError("maxLength must be an integer greater than or equal to 1.");
|
|
2743
2745
|
return {
|
|
2744
2746
|
mode: "sync",
|
|
2745
|
-
metavar,
|
|
2747
|
+
metavar: metavar$1,
|
|
2746
2748
|
placeholder: options?.placeholder ?? (allowLocalhost ? maxLength >= 9 ? "localhost" : "a.bc" : maxLength >= 11 ? "example.com" : "a.bc"),
|
|
2747
2749
|
parse(input) {
|
|
2748
2750
|
if (input.length > maxLength) {
|
|
@@ -2860,8 +2862,8 @@ function hostname(options) {
|
|
|
2860
2862
|
};
|
|
2861
2863
|
}
|
|
2862
2864
|
function email(options) {
|
|
2863
|
-
const metavar = options?.metavar ?? "EMAIL";
|
|
2864
|
-
ensureNonEmptyString(metavar);
|
|
2865
|
+
const metavar$1 = options?.metavar ?? "EMAIL";
|
|
2866
|
+
ensureNonEmptyString(metavar$1);
|
|
2865
2867
|
const allowMultiple = options?.allowMultiple ?? false;
|
|
2866
2868
|
if (options?.placeholder != null) {
|
|
2867
2869
|
if (allowMultiple && !Array.isArray(options.placeholder)) throw new TypeError("email() placeholder must be an array when allowMultiple is true.");
|
|
@@ -2962,7 +2964,7 @@ function email(options) {
|
|
|
2962
2964
|
}
|
|
2963
2965
|
return {
|
|
2964
2966
|
mode: "sync",
|
|
2965
|
-
metavar,
|
|
2967
|
+
metavar: metavar$1,
|
|
2966
2968
|
placeholder: options?.placeholder ?? (options?.allowMultiple ? [`user@${options?.allowedDomains?.[0] ?? "example.com"}`] : `user@${options?.allowedDomains?.[0] ?? "example.com"}`),
|
|
2967
2969
|
parse(input) {
|
|
2968
2970
|
if (allowMultiple) {
|
|
@@ -3121,8 +3123,8 @@ function socketAddress(options) {
|
|
|
3121
3123
|
if (separator === "") throw new TypeError("Expected separator to not be empty.");
|
|
3122
3124
|
if (/\p{Nd}/u.test(separator)) throw new TypeError(`Expected separator to not contain digits, but got: ${JSON.stringify(separator)}.`);
|
|
3123
3125
|
const formatExample = `host${JSON.stringify(separator).slice(1, -1)}port`;
|
|
3124
|
-
const metavar = options?.metavar ?? `HOST${separator}PORT`;
|
|
3125
|
-
ensureNonEmptyString(metavar);
|
|
3126
|
+
const metavar$1 = options?.metavar ?? `HOST${separator}PORT`;
|
|
3127
|
+
ensureNonEmptyString(metavar$1);
|
|
3126
3128
|
const defaultPort = options?.defaultPort;
|
|
3127
3129
|
const requirePort = options?.requirePort ?? false;
|
|
3128
3130
|
const hostType = options?.host?.type ?? "both";
|
|
@@ -3197,7 +3199,7 @@ function socketAddress(options) {
|
|
|
3197
3199
|
}
|
|
3198
3200
|
return {
|
|
3199
3201
|
mode: "sync",
|
|
3200
|
-
metavar,
|
|
3202
|
+
metavar: metavar$1,
|
|
3201
3203
|
get placeholder() {
|
|
3202
3204
|
return {
|
|
3203
3205
|
host: hostType === "ip" ? ipParser.placeholder : hostnameParser.placeholder,
|
|
@@ -3416,8 +3418,8 @@ function portRange(options) {
|
|
|
3416
3418
|
const separator = options?.separator ?? "-";
|
|
3417
3419
|
if (separator === "") throw new TypeError("Expected separator to not be empty.");
|
|
3418
3420
|
if (/\p{Nd}/u.test(separator)) throw new TypeError(`Expected separator to not contain digits, but got: ${JSON.stringify(separator)}.`);
|
|
3419
|
-
const metavar = options?.metavar ?? `PORT${separator}PORT`;
|
|
3420
|
-
ensureNonEmptyString(metavar);
|
|
3421
|
+
const metavar$1 = options?.metavar ?? `PORT${separator}PORT`;
|
|
3422
|
+
ensureNonEmptyString(metavar$1);
|
|
3421
3423
|
const allowSingle = options?.allowSingle ?? false;
|
|
3422
3424
|
const isBigInt = options?.type === "bigint";
|
|
3423
3425
|
const portParser = isBigInt ? port({
|
|
@@ -3435,7 +3437,7 @@ function portRange(options) {
|
|
|
3435
3437
|
});
|
|
3436
3438
|
return {
|
|
3437
3439
|
mode: "sync",
|
|
3438
|
-
metavar,
|
|
3440
|
+
metavar: metavar$1,
|
|
3439
3441
|
get placeholder() {
|
|
3440
3442
|
return isBigInt ? {
|
|
3441
3443
|
start: portParser.placeholder,
|
|
@@ -3595,7 +3597,7 @@ function macAddress(options) {
|
|
|
3595
3597
|
const separator = options?.separator ?? "any";
|
|
3596
3598
|
const caseOption = options?.case ?? "preserve";
|
|
3597
3599
|
const outputSeparator = options?.outputSeparator;
|
|
3598
|
-
const metavar = options?.metavar ?? "MAC";
|
|
3600
|
+
const metavar$1 = options?.metavar ?? "MAC";
|
|
3599
3601
|
const colonRegex = /^([0-9a-fA-F]{1,2}):([0-9a-fA-F]{1,2}):([0-9a-fA-F]{1,2}):([0-9a-fA-F]{1,2}):([0-9a-fA-F]{1,2}):([0-9a-fA-F]{1,2})$/;
|
|
3600
3602
|
const hyphenRegex = /^([0-9a-fA-F]{1,2})-([0-9a-fA-F]{1,2})-([0-9a-fA-F]{1,2})-([0-9a-fA-F]{1,2})-([0-9a-fA-F]{1,2})-([0-9a-fA-F]{1,2})$/;
|
|
3601
3603
|
const dotRegex = /^([0-9a-fA-F]{4})\.([0-9a-fA-F]{4})\.([0-9a-fA-F]{4})$/;
|
|
@@ -3627,7 +3629,7 @@ function macAddress(options) {
|
|
|
3627
3629
|
}
|
|
3628
3630
|
const parserObj = {
|
|
3629
3631
|
mode: "sync",
|
|
3630
|
-
metavar,
|
|
3632
|
+
metavar: metavar$1,
|
|
3631
3633
|
get placeholder() {
|
|
3632
3634
|
const octets = [
|
|
3633
3635
|
"00",
|
|
@@ -3709,7 +3711,7 @@ function macAddress(options) {
|
|
|
3709
3711
|
};
|
|
3710
3712
|
},
|
|
3711
3713
|
format(value) {
|
|
3712
|
-
if (typeof value !== "string") return metavar;
|
|
3714
|
+
if (typeof value !== "string") return metavar$1;
|
|
3713
3715
|
return normalizeMacValue(value, value);
|
|
3714
3716
|
},
|
|
3715
3717
|
normalize(value) {
|
|
@@ -3758,7 +3760,7 @@ function macAddress(options) {
|
|
|
3758
3760
|
* @since 0.10.0
|
|
3759
3761
|
*/
|
|
3760
3762
|
function domain(options) {
|
|
3761
|
-
const metavar = options?.metavar ?? "DOMAIN";
|
|
3763
|
+
const metavar$1 = options?.metavar ?? "DOMAIN";
|
|
3762
3764
|
checkBooleanOption(options, "allowSubdomains");
|
|
3763
3765
|
checkBooleanOption(options, "lowercase");
|
|
3764
3766
|
const allowSubdomains = options?.allowSubdomains ?? true;
|
|
@@ -3791,7 +3793,7 @@ function domain(options) {
|
|
|
3791
3793
|
const tldNotAllowed = options?.errors?.tldNotAllowed;
|
|
3792
3794
|
const domainParserObj = {
|
|
3793
3795
|
mode: "sync",
|
|
3794
|
-
metavar,
|
|
3796
|
+
metavar: metavar$1,
|
|
3795
3797
|
placeholder: options?.placeholder ?? `example.${allowedTldsLower?.[0] ?? "com"}`,
|
|
3796
3798
|
parse(input) {
|
|
3797
3799
|
if (input.length > maxLength) {
|
|
@@ -3997,7 +3999,7 @@ function domain(options) {
|
|
|
3997
3999
|
};
|
|
3998
4000
|
},
|
|
3999
4001
|
format(value) {
|
|
4000
|
-
if (typeof value !== "string") return metavar;
|
|
4002
|
+
if (typeof value !== "string") return metavar$1;
|
|
4001
4003
|
if (!lowercase) return value;
|
|
4002
4004
|
return value.split(".").length >= minLabels ? value.toLowerCase() : value;
|
|
4003
4005
|
}
|
|
@@ -4007,7 +4009,7 @@ function domain(options) {
|
|
|
4007
4009
|
let domParsing = false;
|
|
4008
4010
|
Object.defineProperty(domainParserObj, "format", {
|
|
4009
4011
|
value(v) {
|
|
4010
|
-
if (typeof v !== "string") return metavar;
|
|
4012
|
+
if (typeof v !== "string") return metavar$1;
|
|
4011
4013
|
if (domParsing) return v;
|
|
4012
4014
|
domParsing = true;
|
|
4013
4015
|
try {
|
|
@@ -4072,10 +4074,10 @@ function ipv6(options) {
|
|
|
4072
4074
|
const allowMulticast = options?.allowMulticast ?? true;
|
|
4073
4075
|
const allowZero = options?.allowZero ?? true;
|
|
4074
4076
|
const errors = options?.errors;
|
|
4075
|
-
const metavar = options?.metavar ?? "IPV6";
|
|
4077
|
+
const metavar$1 = options?.metavar ?? "IPV6";
|
|
4076
4078
|
const ipv6ParserObj = {
|
|
4077
4079
|
mode: "sync",
|
|
4078
|
-
metavar,
|
|
4080
|
+
metavar: metavar$1,
|
|
4079
4081
|
placeholder: allowZero ? "::" : allowLoopback ? "::1" : "2001:db8::1",
|
|
4080
4082
|
parse(input) {
|
|
4081
4083
|
const normalized = parseAndNormalizeIpv6(input);
|
|
@@ -4227,14 +4229,14 @@ function ipv6(options) {
|
|
|
4227
4229
|
};
|
|
4228
4230
|
},
|
|
4229
4231
|
format(value) {
|
|
4230
|
-
if (typeof value !== "string") return metavar;
|
|
4232
|
+
if (typeof value !== "string") return metavar$1;
|
|
4231
4233
|
return parseAndNormalizeIpv6(value) ?? value;
|
|
4232
4234
|
}
|
|
4233
4235
|
};
|
|
4234
4236
|
let ipv6Parsing = false;
|
|
4235
4237
|
Object.defineProperty(ipv6ParserObj, "format", {
|
|
4236
4238
|
value(v) {
|
|
4237
|
-
if (typeof v !== "string") return metavar;
|
|
4239
|
+
if (typeof v !== "string") return metavar$1;
|
|
4238
4240
|
if (ipv6Parsing) return v;
|
|
4239
4241
|
ipv6Parsing = true;
|
|
4240
4242
|
try {
|
|
@@ -4511,7 +4513,7 @@ function checkIpv4MappedRestrictions(octets, normalizedIpv6, ipv4Opts, errors) {
|
|
|
4511
4513
|
*/
|
|
4512
4514
|
function ip(options) {
|
|
4513
4515
|
const version = options?.version ?? "both";
|
|
4514
|
-
const metavar = options?.metavar ?? "IP";
|
|
4516
|
+
const metavar$1 = options?.metavar ?? "IP";
|
|
4515
4517
|
const errors = options?.errors;
|
|
4516
4518
|
const ipv4Parser = version === 4 || version === "both" ? ipv4({
|
|
4517
4519
|
...options?.ipv4,
|
|
@@ -4554,7 +4556,7 @@ function ip(options) {
|
|
|
4554
4556
|
} : void 0;
|
|
4555
4557
|
const ipParserObj = {
|
|
4556
4558
|
mode: "sync",
|
|
4557
|
-
metavar,
|
|
4559
|
+
metavar: metavar$1,
|
|
4558
4560
|
placeholder: version === 6 ? ipv6Parser.placeholder : ipv4Parser.placeholder,
|
|
4559
4561
|
parse(input) {
|
|
4560
4562
|
let ipv4Error = null;
|
|
@@ -4613,14 +4615,14 @@ function ip(options) {
|
|
|
4613
4615
|
};
|
|
4614
4616
|
},
|
|
4615
4617
|
format(value) {
|
|
4616
|
-
if (typeof value !== "string") return metavar;
|
|
4618
|
+
if (typeof value !== "string") return metavar$1;
|
|
4617
4619
|
return parseAndNormalizeIpv6(value) ?? value;
|
|
4618
4620
|
}
|
|
4619
4621
|
};
|
|
4620
4622
|
let ipParsing = false;
|
|
4621
4623
|
Object.defineProperty(ipParserObj, "format", {
|
|
4622
4624
|
value(v) {
|
|
4623
|
-
if (typeof v !== "string") return metavar;
|
|
4625
|
+
if (typeof v !== "string") return metavar$1;
|
|
4624
4626
|
if (ipParsing) return v;
|
|
4625
4627
|
ipParsing = true;
|
|
4626
4628
|
try {
|
|
@@ -4690,7 +4692,7 @@ function cidr(options) {
|
|
|
4690
4692
|
const minPrefix = options?.minPrefix;
|
|
4691
4693
|
const maxPrefix = options?.maxPrefix;
|
|
4692
4694
|
const errors = options?.errors;
|
|
4693
|
-
const metavar = options?.metavar ?? "CIDR";
|
|
4695
|
+
const metavar$1 = options?.metavar ?? "CIDR";
|
|
4694
4696
|
const genericIpSentinel = [];
|
|
4695
4697
|
const ipv4Parser = version === 4 || version === "both" ? ipv4({
|
|
4696
4698
|
...options?.ipv4,
|
|
@@ -4733,7 +4735,7 @@ function cidr(options) {
|
|
|
4733
4735
|
} : void 0;
|
|
4734
4736
|
const cidrParserObj = {
|
|
4735
4737
|
mode: "sync",
|
|
4736
|
-
metavar,
|
|
4738
|
+
metavar: metavar$1,
|
|
4737
4739
|
get placeholder() {
|
|
4738
4740
|
return version === 6 || version === "both" && (minPrefix ?? 0) > 32 ? {
|
|
4739
4741
|
address: ipv6Parser.placeholder,
|
|
@@ -5102,12 +5104,12 @@ function cidr(options) {
|
|
|
5102
5104
|
}
|
|
5103
5105
|
};
|
|
5104
5106
|
},
|
|
5105
|
-
format: ((_) => metavar)
|
|
5107
|
+
format: ((_) => metavar$1)
|
|
5106
5108
|
};
|
|
5107
5109
|
let cidrParsing = false;
|
|
5108
5110
|
Object.defineProperty(cidrParserObj, "format", {
|
|
5109
5111
|
value(value) {
|
|
5110
|
-
if (typeof value !== "object" || value == null || !("address" in value) || !("prefix" in value) || !("version" in value)) return metavar;
|
|
5112
|
+
if (typeof value !== "object" || value == null || !("address" in value) || !("prefix" in value) || !("version" in value)) return metavar$1;
|
|
5111
5113
|
if (cidrParsing) return `${value.address}/${value.prefix}`;
|
|
5112
5114
|
cidrParsing = true;
|
|
5113
5115
|
try {
|
|
@@ -5155,8 +5157,8 @@ const SEMVER_SUGGESTIONS = Object.freeze([
|
|
|
5155
5157
|
]);
|
|
5156
5158
|
const SEMVER_SUGGESTIONS_WITH_PREFIX = Object.freeze([...SEMVER_SUGGESTIONS, ...SEMVER_SUGGESTIONS.map((s) => `v${s}`)]);
|
|
5157
5159
|
function semVer(options = {}) {
|
|
5158
|
-
const metavar = options.metavar ?? "SEMVER";
|
|
5159
|
-
ensureNonEmptyString(metavar);
|
|
5160
|
+
const metavar$1 = options.metavar ?? "SEMVER";
|
|
5161
|
+
ensureNonEmptyString(metavar$1);
|
|
5160
5162
|
checkEnumOption(options, "type", ["string", "object"]);
|
|
5161
5163
|
checkBooleanOption(options, "allowPrefix");
|
|
5162
5164
|
const allowPrefix = options.allowPrefix ?? false;
|
|
@@ -5171,7 +5173,7 @@ function semVer(options = {}) {
|
|
|
5171
5173
|
}
|
|
5172
5174
|
if (objectMode) return {
|
|
5173
5175
|
mode: "sync",
|
|
5174
|
-
metavar,
|
|
5176
|
+
metavar: metavar$1,
|
|
5175
5177
|
placeholder: {
|
|
5176
5178
|
major: 0,
|
|
5177
5179
|
minor: 0,
|
|
@@ -5212,7 +5214,7 @@ function semVer(options = {}) {
|
|
|
5212
5214
|
};
|
|
5213
5215
|
return {
|
|
5214
5216
|
mode: "sync",
|
|
5215
|
-
metavar,
|
|
5217
|
+
metavar: metavar$1,
|
|
5216
5218
|
placeholder: "0.0.0",
|
|
5217
5219
|
parse(input) {
|
|
5218
5220
|
const m = SEMVER_REGEX.exec(input);
|
|
@@ -5267,8 +5269,8 @@ function semVer(options = {}) {
|
|
|
5267
5269
|
* @since 1.1.0
|
|
5268
5270
|
*/
|
|
5269
5271
|
function json(options) {
|
|
5270
|
-
const metavar = options?.metavar ?? "JSON";
|
|
5271
|
-
ensureNonEmptyString(metavar);
|
|
5272
|
+
const metavar$1 = options?.metavar ?? "JSON";
|
|
5273
|
+
ensureNonEmptyString(metavar$1);
|
|
5272
5274
|
checkEnumOption(options, "rootType", [
|
|
5273
5275
|
"string",
|
|
5274
5276
|
"number",
|
|
@@ -5290,7 +5292,7 @@ function json(options) {
|
|
|
5290
5292
|
const placeholder = options?.placeholder ?? defaultPlaceholder;
|
|
5291
5293
|
return {
|
|
5292
5294
|
mode: "sync",
|
|
5293
|
-
metavar,
|
|
5295
|
+
metavar: metavar$1,
|
|
5294
5296
|
placeholder,
|
|
5295
5297
|
parse(input) {
|
|
5296
5298
|
let value;
|
|
@@ -5369,6 +5371,257 @@ function findNonFiniteNumber(root) {
|
|
|
5369
5371
|
}
|
|
5370
5372
|
return void 0;
|
|
5371
5373
|
}
|
|
5374
|
+
/**
|
|
5375
|
+
* Implementation of the {@link firstOf} combinator.
|
|
5376
|
+
*/
|
|
5377
|
+
function firstOf(...rawArgs) {
|
|
5378
|
+
const args = rawArgs.length > 0 && rawArgs.at(-1) === void 0 ? rawArgs.slice(0, -1) : rawArgs;
|
|
5379
|
+
let parsers;
|
|
5380
|
+
let options;
|
|
5381
|
+
if (args.length > 0 && Array.isArray(args[0])) {
|
|
5382
|
+
parsers = [...args[0]];
|
|
5383
|
+
options = args[1] ?? {};
|
|
5384
|
+
} else {
|
|
5385
|
+
const last = args.at(-1);
|
|
5386
|
+
if (args.length > 0 && typeof last === "object" && last != null && !isValueParser(last)) {
|
|
5387
|
+
options = last;
|
|
5388
|
+
parsers = args.slice(0, -1);
|
|
5389
|
+
} else {
|
|
5390
|
+
options = {};
|
|
5391
|
+
parsers = args;
|
|
5392
|
+
}
|
|
5393
|
+
}
|
|
5394
|
+
if (parsers.length < 2) throw new TypeError("firstOf() requires at least two value parsers.");
|
|
5395
|
+
for (const parser of parsers) {
|
|
5396
|
+
if (!isValueParser(parser)) throw new TypeError("Every firstOf() constituent must be a value parser.");
|
|
5397
|
+
if (parser.mode !== "sync") throw new TypeError("firstOf() only supports sync value parsers, but an async one was given.");
|
|
5398
|
+
if (isDerivedValueParser(parser)) throw new TypeError("firstOf() does not support dependency-derived value parsers (created via deriveFrom() or dependency().derive()); pass the derived parser directly to option() or argument() instead.");
|
|
5399
|
+
}
|
|
5400
|
+
const metavar$1 = options.metavar ?? parsers.map((parser) => parser.metavar).join("|");
|
|
5401
|
+
ensureNonEmptyString(metavar$1);
|
|
5402
|
+
const mergedChoices = parsers.every((parser) => parser.choices != null) ? Object.freeze(parsers.flatMap((parser) => [...parser.choices]).filter((value, index, all) => all.findIndex((other) => Object.is(other, value)) === index)) : void 0;
|
|
5403
|
+
function findOwner(value) {
|
|
5404
|
+
let canonicalizing;
|
|
5405
|
+
for (const parser of parsers) {
|
|
5406
|
+
if (typeof parser.validate === "function") {
|
|
5407
|
+
let result$1;
|
|
5408
|
+
try {
|
|
5409
|
+
result$1 = parser.validate(value);
|
|
5410
|
+
} catch {
|
|
5411
|
+
continue;
|
|
5412
|
+
}
|
|
5413
|
+
if (result$1.success) return {
|
|
5414
|
+
parser,
|
|
5415
|
+
result: result$1
|
|
5416
|
+
};
|
|
5417
|
+
continue;
|
|
5418
|
+
}
|
|
5419
|
+
let formatted;
|
|
5420
|
+
try {
|
|
5421
|
+
formatted = parser.format(value);
|
|
5422
|
+
} catch {
|
|
5423
|
+
continue;
|
|
5424
|
+
}
|
|
5425
|
+
if (typeof formatted !== "string") continue;
|
|
5426
|
+
const result = parser.parse(formatted);
|
|
5427
|
+
if (!result.success) continue;
|
|
5428
|
+
if (ownsRoundTrippedValue(parser, result.value, value)) return {
|
|
5429
|
+
parser,
|
|
5430
|
+
result
|
|
5431
|
+
};
|
|
5432
|
+
if (canonicalizing == null && value !== null && typeof value !== "object" && typeof result.value === typeof value) canonicalizing = {
|
|
5433
|
+
parser,
|
|
5434
|
+
result
|
|
5435
|
+
};
|
|
5436
|
+
}
|
|
5437
|
+
return canonicalizing;
|
|
5438
|
+
}
|
|
5439
|
+
const hasNormalize = parsers.some((parser) => typeof parser.normalize === "function");
|
|
5440
|
+
const hasSuggest = parsers.some((parser) => typeof parser.suggest === "function");
|
|
5441
|
+
return {
|
|
5442
|
+
mode: "sync",
|
|
5443
|
+
metavar: metavar$1,
|
|
5444
|
+
placeholder: parsers[0].placeholder,
|
|
5445
|
+
...mergedChoices != null ? { choices: mergedChoices } : {},
|
|
5446
|
+
parse(input) {
|
|
5447
|
+
const errors = [];
|
|
5448
|
+
for (const parser of parsers) {
|
|
5449
|
+
const result = parser.parse(input);
|
|
5450
|
+
if (result.success) return result;
|
|
5451
|
+
errors.push(result.error);
|
|
5452
|
+
}
|
|
5453
|
+
const noMatch = options.errors?.noMatch;
|
|
5454
|
+
return {
|
|
5455
|
+
success: false,
|
|
5456
|
+
error: noMatch == null ? firstOfNoMatchError(errors) : typeof noMatch === "function" ? noMatch(input, errors) : noMatch
|
|
5457
|
+
};
|
|
5458
|
+
},
|
|
5459
|
+
format(value) {
|
|
5460
|
+
let canonicalizing;
|
|
5461
|
+
let fallback;
|
|
5462
|
+
let firstError;
|
|
5463
|
+
let hasError = false;
|
|
5464
|
+
for (const parser of parsers) {
|
|
5465
|
+
let formatted;
|
|
5466
|
+
try {
|
|
5467
|
+
formatted = parser.format(value);
|
|
5468
|
+
} catch (e) {
|
|
5469
|
+
if (!hasError) {
|
|
5470
|
+
firstError = e;
|
|
5471
|
+
hasError = true;
|
|
5472
|
+
}
|
|
5473
|
+
continue;
|
|
5474
|
+
}
|
|
5475
|
+
if (typeof formatted !== "string") continue;
|
|
5476
|
+
if (typeof parser.validate === "function") {
|
|
5477
|
+
let owned = false;
|
|
5478
|
+
try {
|
|
5479
|
+
owned = parser.validate(value).success;
|
|
5480
|
+
} catch {}
|
|
5481
|
+
if (owned) return formatted;
|
|
5482
|
+
} else {
|
|
5483
|
+
const result = parser.parse(formatted);
|
|
5484
|
+
if (result.success) {
|
|
5485
|
+
if (ownsRoundTrippedValue(parser, result.value, value)) return formatted;
|
|
5486
|
+
if (canonicalizing == null && value !== null && typeof value !== "object" && typeof result.value === typeof value) canonicalizing = formatted;
|
|
5487
|
+
}
|
|
5488
|
+
}
|
|
5489
|
+
fallback ??= formatted;
|
|
5490
|
+
}
|
|
5491
|
+
if (canonicalizing !== void 0) return canonicalizing;
|
|
5492
|
+
if (fallback !== void 0) return fallback;
|
|
5493
|
+
if (hasError) throw firstError;
|
|
5494
|
+
throw new TypeError("No constituent parser could format the given value.");
|
|
5495
|
+
},
|
|
5496
|
+
validate(value) {
|
|
5497
|
+
const owner = findOwner(value);
|
|
5498
|
+
if (owner == null) return {
|
|
5499
|
+
success: false,
|
|
5500
|
+
error: message`Expected a value matching ${metavar(metavar$1)}.`
|
|
5501
|
+
};
|
|
5502
|
+
return owner.result;
|
|
5503
|
+
},
|
|
5504
|
+
...hasNormalize ? { normalize(value) {
|
|
5505
|
+
const owner = findOwner(value);
|
|
5506
|
+
if (owner == null || typeof owner.parser.normalize !== "function") return value;
|
|
5507
|
+
return owner.parser.normalize(value);
|
|
5508
|
+
} } : {},
|
|
5509
|
+
...hasSuggest ? { *suggest(prefix) {
|
|
5510
|
+
const collected = [];
|
|
5511
|
+
for (const parser of parsers) {
|
|
5512
|
+
if (typeof parser.suggest !== "function") continue;
|
|
5513
|
+
for (const suggestion of parser.suggest(prefix)) collected.push(suggestion);
|
|
5514
|
+
}
|
|
5515
|
+
yield* deduplicateSuggestions(collected);
|
|
5516
|
+
} } : {}
|
|
5517
|
+
};
|
|
5518
|
+
}
|
|
5519
|
+
/**
|
|
5520
|
+
* Builds the default error message for {@link firstOf} when every
|
|
5521
|
+
* constituent parser fails: a header followed by each constituent's error
|
|
5522
|
+
* on its own line.
|
|
5523
|
+
*/
|
|
5524
|
+
function firstOfNoMatchError(errors) {
|
|
5525
|
+
const terms = [text("Expected one of the following:")];
|
|
5526
|
+
for (const error of errors) terms.push(lineBreak(), text("- "), ...cloneMessage(error));
|
|
5527
|
+
return terms;
|
|
5528
|
+
}
|
|
5529
|
+
/**
|
|
5530
|
+
* Determines whether a {@link firstOf} constituent owns a value, given the
|
|
5531
|
+
* result of round-tripping the value through the constituent's `format()`
|
|
5532
|
+
* and `parse()`. The constituent owns the value when the round-trip
|
|
5533
|
+
* preserves it exactly, when it yields the constituent's own normalization
|
|
5534
|
+
* of it (e.g. a MAC address parser canonicalizing separators and case), or
|
|
5535
|
+
* when the round-trip is a recognized parse-level canonicalization: a
|
|
5536
|
+
* case-insensitive string match (e.g. a case-insensitive `choice()`
|
|
5537
|
+
* folding `"INFO"` to `"info"`) or numeric equality (a number parser
|
|
5538
|
+
* folding `-0` to `0`)—the same acceptance the constituent alone would
|
|
5539
|
+
* grant a fallback value through round-trip validation. Parsers with
|
|
5540
|
+
* richer parse-level canonicalization should expose it via `normalize()`.
|
|
5541
|
+
* A merely *successful* round-trip is not enough otherwise: an arbitrary
|
|
5542
|
+
* same-type change means data loss rather than canonicalization (e.g. a
|
|
5543
|
+
* clamping `format()` folding 15 into 10), a round-trip that changes the
|
|
5544
|
+
* primitive type means the string form belongs to a different branch of
|
|
5545
|
+
* the union (e.g. `choice(["1"])` capturing the integer 1), and for
|
|
5546
|
+
* object values structural equality is the only way to tell
|
|
5547
|
+
* canonicalization from data loss (e.g. a lossy `color()` `format()`
|
|
5548
|
+
* dropping fields that belong to a later, more faithful constituent).
|
|
5549
|
+
*/
|
|
5550
|
+
function ownsRoundTrippedValue(parser, roundTripped, value) {
|
|
5551
|
+
if (valuesEqual(roundTripped, value)) return true;
|
|
5552
|
+
if (typeof parser.normalize === "function") {
|
|
5553
|
+
let normalized;
|
|
5554
|
+
try {
|
|
5555
|
+
normalized = parser.normalize(value);
|
|
5556
|
+
} catch {
|
|
5557
|
+
return false;
|
|
5558
|
+
}
|
|
5559
|
+
if (valuesEqual(roundTripped, normalized)) return true;
|
|
5560
|
+
}
|
|
5561
|
+
if (typeof value === "string" && typeof roundTripped === "string") return value.toLowerCase() === roundTripped.toLowerCase();
|
|
5562
|
+
if (typeof value === "number" && typeof roundTripped === "number") return value === roundTripped;
|
|
5563
|
+
return false;
|
|
5564
|
+
}
|
|
5565
|
+
/**
|
|
5566
|
+
* Structural equality for parsed CLI values: primitives compare with
|
|
5567
|
+
* `Object.is` (so `NaN` equals itself and `0` differs from `-0`, matching
|
|
5568
|
+
* the distinction `choice()` makes), `Date` and `URL` instances compare by
|
|
5569
|
+
* time value and href respectively, arrays and plain objects compare
|
|
5570
|
+
* recursively, and other class instances compare by their overridden
|
|
5571
|
+
* `toString()` serialization. Recursion is bounded by the structure of
|
|
5572
|
+
* the second argument, which in {@link firstOf} is always a freshly
|
|
5573
|
+
* parsed (acyclic) value.
|
|
5574
|
+
*/
|
|
5575
|
+
function valuesEqual(a, b) {
|
|
5576
|
+
if (Object.is(a, b)) return true;
|
|
5577
|
+
if (typeof a !== "object" || typeof b !== "object" || a == null || b == null) return false;
|
|
5578
|
+
if (Array.isArray(a) || Array.isArray(b)) return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((item, i) => valuesEqual(item, b[i]));
|
|
5579
|
+
if (a instanceof Date || b instanceof Date) return a instanceof Date && b instanceof Date && a.getTime() === b.getTime();
|
|
5580
|
+
if (a instanceof URL || b instanceof URL) return a instanceof URL && b instanceof URL && a.href === b.href;
|
|
5581
|
+
const prototypeA = Object.getPrototypeOf(a);
|
|
5582
|
+
const prototypeB = Object.getPrototypeOf(b);
|
|
5583
|
+
const plainA = prototypeA === Object.prototype || prototypeA === null;
|
|
5584
|
+
const plainB = prototypeB === Object.prototype || prototypeB === null;
|
|
5585
|
+
if (plainA !== plainB) return false;
|
|
5586
|
+
if (!plainA) {
|
|
5587
|
+
if (prototypeA !== prototypeB) return false;
|
|
5588
|
+
const overridesA = hasCustomToString(a);
|
|
5589
|
+
const overridesB = hasCustomToString(b);
|
|
5590
|
+
if (overridesA !== overridesB) return false;
|
|
5591
|
+
const hasKeys = Object.keys(a).length > 0 || Object.keys(b).length > 0;
|
|
5592
|
+
if (hasKeys && !plainObjectsEqual(a, b)) return false;
|
|
5593
|
+
if (!overridesA) return hasKeys;
|
|
5594
|
+
try {
|
|
5595
|
+
return String(a) === String(b);
|
|
5596
|
+
} catch {
|
|
5597
|
+
return false;
|
|
5598
|
+
}
|
|
5599
|
+
}
|
|
5600
|
+
return plainObjectsEqual(a, b);
|
|
5601
|
+
}
|
|
5602
|
+
/**
|
|
5603
|
+
* Checks whether an object provides a `toString()` implementation other
|
|
5604
|
+
* than the generic `Object.prototype.toString`.
|
|
5605
|
+
*/
|
|
5606
|
+
function hasCustomToString(value) {
|
|
5607
|
+
try {
|
|
5608
|
+
const toString = value.toString;
|
|
5609
|
+
return typeof toString === "function" && toString !== Object.prototype.toString;
|
|
5610
|
+
} catch {
|
|
5611
|
+
return false;
|
|
5612
|
+
}
|
|
5613
|
+
}
|
|
5614
|
+
/**
|
|
5615
|
+
* Compares two objects by their enumerable own keys, recursing into the
|
|
5616
|
+
* values with {@link valuesEqual}.
|
|
5617
|
+
*/
|
|
5618
|
+
function plainObjectsEqual(a, b) {
|
|
5619
|
+
const aKeys = Object.keys(a);
|
|
5620
|
+
const bKeys = Object.keys(b);
|
|
5621
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
5622
|
+
const bRecord = b;
|
|
5623
|
+
return aKeys.every((key) => Object.hasOwn(b, key) && valuesEqual(a[key], bRecord[key]));
|
|
5624
|
+
}
|
|
5372
5625
|
|
|
5373
5626
|
//#endregion
|
|
5374
|
-
export { checkBooleanOption, checkEnumOption, choice, cidr, color, domain, email, ensureNonEmptyString, fileSize, float, hostname, integer, ip, ipv4, ipv6, isNonEmptyString, isValueParser, json, locale, macAddress, port, portRange, semVer, socketAddress, string, url, uuid };
|
|
5627
|
+
export { checkBooleanOption, checkEnumOption, choice, cidr, color, domain, email, ensureNonEmptyString, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isNonEmptyString, isValueParser, json, locale, macAddress, port, portRange, semVer, socketAddress, string, url, uuid };
|