@optique/core 1.0.0-dev.1495 → 1.0.0-dev.1500
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/constructs.cjs +183 -35
- package/dist/constructs.js +183 -35
- package/dist/context.cjs +1 -39
- package/dist/context.d.cts +1 -35
- package/dist/context.d.ts +1 -35
- package/dist/context.js +1 -37
- package/dist/dependency.cjs +42 -0
- package/dist/dependency.js +42 -0
- package/dist/facade.cjs +68 -268
- package/dist/facade.js +68 -268
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/modifiers.cjs +139 -21
- package/dist/modifiers.d.cts +41 -0
- package/dist/modifiers.d.ts +41 -0
- package/dist/modifiers.js +139 -21
- package/dist/parser.cjs +6 -2
- package/dist/parser.d.cts +28 -1
- package/dist/parser.d.ts +28 -1
- package/dist/parser.js +6 -2
- package/dist/primitives.cjs +44 -2
- package/dist/primitives.js +44 -2
- package/dist/suggestion.cjs +3 -0
- package/dist/suggestion.js +3 -0
- package/dist/valueparser.cjs +82 -1
- package/dist/valueparser.d.cts +125 -1
- package/dist/valueparser.d.ts +125 -1
- package/dist/valueparser.js +82 -1
- package/package.json +1 -1
package/dist/valueparser.js
CHANGED
|
@@ -6,9 +6,18 @@ import { ensureNonEmptyString, isNonEmptyString } from "./nonempty.js";
|
|
|
6
6
|
* A predicate function that checks if an object is a {@link ValueParser}.
|
|
7
7
|
* @param object The object to check.
|
|
8
8
|
* @return `true` if the object is a {@link ValueParser}, `false` otherwise.
|
|
9
|
+
* @throws {TypeError} If the object looks like a value parser (has `$mode`,
|
|
10
|
+
* `metavar`, `parse`, and `format`) but is missing the required
|
|
11
|
+
* `placeholder` property.
|
|
9
12
|
*/
|
|
10
13
|
function isValueParser(object) {
|
|
11
|
-
|
|
14
|
+
if (typeof object !== "object" || object == null || !("$mode" in object) || object.$mode !== "sync" && object.$mode !== "async") return false;
|
|
15
|
+
const hasMetavar = "metavar" in object && typeof object.metavar === "string";
|
|
16
|
+
const hasParse = "parse" in object && typeof object.parse === "function";
|
|
17
|
+
const hasFormat = "format" in object && typeof object.format === "function";
|
|
18
|
+
const hasPlaceholder = "placeholder" in object;
|
|
19
|
+
if (hasMetavar && hasParse && hasFormat && !hasPlaceholder) throw new TypeError("Value parser is missing the required placeholder property. All value parsers must define a placeholder value.");
|
|
20
|
+
return hasMetavar && hasParse && hasFormat && hasPlaceholder;
|
|
12
21
|
}
|
|
13
22
|
/**
|
|
14
23
|
* Implementation of the choice parser for both string and number types.
|
|
@@ -49,6 +58,7 @@ function choice(choices, options = {}) {
|
|
|
49
58
|
return {
|
|
50
59
|
$mode: "sync",
|
|
51
60
|
metavar,
|
|
61
|
+
placeholder: choices[0],
|
|
52
62
|
choices: frozenNumberChoices,
|
|
53
63
|
parse(input) {
|
|
54
64
|
const index = numberStrings.indexOf(input);
|
|
@@ -130,6 +140,7 @@ function choice(choices, options = {}) {
|
|
|
130
140
|
return {
|
|
131
141
|
$mode: "sync",
|
|
132
142
|
metavar,
|
|
143
|
+
placeholder: choices[0],
|
|
133
144
|
choices: stringChoices,
|
|
134
145
|
parse(input) {
|
|
135
146
|
const normalizedInput = caseInsensitive ? input.toLowerCase() : input;
|
|
@@ -288,6 +299,7 @@ function string(options = {}) {
|
|
|
288
299
|
return {
|
|
289
300
|
$mode: "sync",
|
|
290
301
|
metavar,
|
|
302
|
+
placeholder: options.placeholder ?? "",
|
|
291
303
|
parse(input) {
|
|
292
304
|
if (patternSource != null && patternFlags != null) {
|
|
293
305
|
const pattern = new RegExp(patternSource, patternFlags);
|
|
@@ -344,6 +356,8 @@ function string(options = {}) {
|
|
|
344
356
|
* integer type.
|
|
345
357
|
* @throws {TypeError} If `options.type` is provided but is neither `"number"`
|
|
346
358
|
* nor `"bigint"`.
|
|
359
|
+
* @throws {RangeError} If the configured min/max range for number mode contains
|
|
360
|
+
* no safe integers.
|
|
347
361
|
*/
|
|
348
362
|
function integer(options) {
|
|
349
363
|
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)}.`);
|
|
@@ -358,6 +372,7 @@ function integer(options) {
|
|
|
358
372
|
return {
|
|
359
373
|
$mode: "sync",
|
|
360
374
|
metavar: metavar$1,
|
|
375
|
+
placeholder: options?.placeholder ?? (options?.min != null && options.min > 0n ? options.min : options?.max != null && options.max < 0n ? options.max : 0n),
|
|
361
376
|
parse(input) {
|
|
362
377
|
if (!input.match(/^-?\d+$/)) return {
|
|
363
378
|
success: false,
|
|
@@ -386,6 +401,11 @@ function integer(options) {
|
|
|
386
401
|
ensureNonEmptyString(metavar);
|
|
387
402
|
const maxSafe = BigInt(Number.MAX_SAFE_INTEGER);
|
|
388
403
|
const minSafe = BigInt(Number.MIN_SAFE_INTEGER);
|
|
404
|
+
const safeMin = Math.max(options?.min ?? Number.MIN_SAFE_INTEGER, Number.MIN_SAFE_INTEGER);
|
|
405
|
+
const safeMax = Math.min(options?.max ?? Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER);
|
|
406
|
+
const firstAllowed = Math.ceil(safeMin);
|
|
407
|
+
const lastAllowed = Math.floor(safeMax);
|
|
408
|
+
if (firstAllowed > lastAllowed) throw new RangeError("The configured integer range contains no safe integers. Use type: \"bigint\" instead.");
|
|
389
409
|
const unsafeIntegerError = options?.errors?.unsafeInteger;
|
|
390
410
|
function makeUnsafeIntegerError(input) {
|
|
391
411
|
return {
|
|
@@ -396,6 +416,7 @@ function integer(options) {
|
|
|
396
416
|
return {
|
|
397
417
|
$mode: "sync",
|
|
398
418
|
metavar,
|
|
419
|
+
placeholder: options?.placeholder ?? (firstAllowed > 0 ? firstAllowed : lastAllowed < 0 ? lastAllowed : 0),
|
|
399
420
|
parse(input) {
|
|
400
421
|
if (!input.match(/^-?\d+$/)) return {
|
|
401
422
|
success: false,
|
|
@@ -446,6 +467,7 @@ function float(options = {}) {
|
|
|
446
467
|
return {
|
|
447
468
|
$mode: "sync",
|
|
448
469
|
metavar,
|
|
470
|
+
placeholder: options?.placeholder ?? (options?.min != null && options.min > 0 ? options.min : options?.max != null && options.max < 0 ? options.max : 0),
|
|
449
471
|
parse(input) {
|
|
450
472
|
const invalidNumber = (i) => ({
|
|
451
473
|
success: false,
|
|
@@ -530,6 +552,9 @@ function url(options = {}) {
|
|
|
530
552
|
return {
|
|
531
553
|
$mode: "sync",
|
|
532
554
|
metavar,
|
|
555
|
+
get placeholder() {
|
|
556
|
+
return new URL(`${allowedProtocols?.[0] ?? "http:"}//0.invalid`);
|
|
557
|
+
},
|
|
533
558
|
parse(input) {
|
|
534
559
|
if (!URL.canParse(input)) return {
|
|
535
560
|
success: false,
|
|
@@ -596,6 +621,7 @@ function locale(options = {}) {
|
|
|
596
621
|
return {
|
|
597
622
|
$mode: "sync",
|
|
598
623
|
metavar,
|
|
624
|
+
placeholder: new Intl.Locale("und"),
|
|
599
625
|
parse(input) {
|
|
600
626
|
let locale$1;
|
|
601
627
|
try {
|
|
@@ -891,6 +917,7 @@ function uuid(options = {}) {
|
|
|
891
917
|
return {
|
|
892
918
|
$mode: "sync",
|
|
893
919
|
metavar,
|
|
920
|
+
placeholder: "00000000-0000-0000-0000-000000000000",
|
|
894
921
|
parse(input) {
|
|
895
922
|
if (!uuidRegex.test(input)) return {
|
|
896
923
|
success: false,
|
|
@@ -994,9 +1021,11 @@ function port(options) {
|
|
|
994
1021
|
const min$1 = options.min ?? 1n;
|
|
995
1022
|
const max$1 = options.max ?? 65535n;
|
|
996
1023
|
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}.`);
|
|
1024
|
+
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.`);
|
|
997
1025
|
return {
|
|
998
1026
|
$mode: "sync",
|
|
999
1027
|
metavar: metavar$1,
|
|
1028
|
+
placeholder: options.placeholder ?? (options.disallowWellKnown && min$1 < 1024n ? 1024n > min$1 ? 1024n : min$1 : min$1),
|
|
1000
1029
|
parse(input) {
|
|
1001
1030
|
if (!input.match(/^-?\d+$/)) return {
|
|
1002
1031
|
success: false,
|
|
@@ -1032,9 +1061,11 @@ function port(options) {
|
|
|
1032
1061
|
const min = options?.min ?? 1;
|
|
1033
1062
|
const max = options?.max ?? 65535;
|
|
1034
1063
|
if (min > max) throw new RangeError(`Expected min to be less than or equal to max, but got min: ${min} and max: ${max}.`);
|
|
1064
|
+
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.`);
|
|
1035
1065
|
return {
|
|
1036
1066
|
$mode: "sync",
|
|
1037
1067
|
metavar,
|
|
1068
|
+
placeholder: options?.placeholder ?? (options?.disallowWellKnown && min < 1024 ? Math.max(1024, min) : min),
|
|
1038
1069
|
parse(input) {
|
|
1039
1070
|
if (!input.match(/^-?\d+$/)) return {
|
|
1040
1071
|
success: false,
|
|
@@ -1128,6 +1159,7 @@ function ipv4(options) {
|
|
|
1128
1159
|
return {
|
|
1129
1160
|
$mode: "sync",
|
|
1130
1161
|
metavar,
|
|
1162
|
+
placeholder: allowZero ? "0.0.0.0" : allowLoopback ? "127.0.0.1" : "192.0.2.1",
|
|
1131
1163
|
parse(input) {
|
|
1132
1164
|
const parts = input.split(".");
|
|
1133
1165
|
if (parts.length !== 4) {
|
|
@@ -1289,6 +1321,7 @@ function hostname(options) {
|
|
|
1289
1321
|
return {
|
|
1290
1322
|
$mode: "sync",
|
|
1291
1323
|
metavar,
|
|
1324
|
+
placeholder: options?.placeholder ?? (allowLocalhost ? maxLength >= 9 ? "localhost" : "a.bc" : maxLength >= 11 ? "example.com" : "a.bc"),
|
|
1292
1325
|
parse(input) {
|
|
1293
1326
|
if (input.length > maxLength) {
|
|
1294
1327
|
const errorMsg = options?.errors?.tooLong;
|
|
@@ -1408,6 +1441,10 @@ function email(options) {
|
|
|
1408
1441
|
const metavar = options?.metavar ?? "EMAIL";
|
|
1409
1442
|
ensureNonEmptyString(metavar);
|
|
1410
1443
|
const allowMultiple = options?.allowMultiple ?? false;
|
|
1444
|
+
if (options?.placeholder != null) {
|
|
1445
|
+
if (allowMultiple && !Array.isArray(options.placeholder)) throw new TypeError("email() placeholder must be an array when allowMultiple is true.");
|
|
1446
|
+
if (!allowMultiple && typeof options.placeholder !== "string") throw new TypeError("email() placeholder must be a string when allowMultiple is false.");
|
|
1447
|
+
}
|
|
1411
1448
|
const allowDisplayName = options?.allowDisplayName ?? false;
|
|
1412
1449
|
const lowercase = options?.lowercase ?? false;
|
|
1413
1450
|
const allowedDomains = options?.allowedDomains != null ? Object.freeze([...options.allowedDomains]) : void 0;
|
|
@@ -1504,6 +1541,7 @@ function email(options) {
|
|
|
1504
1541
|
return {
|
|
1505
1542
|
$mode: "sync",
|
|
1506
1543
|
metavar,
|
|
1544
|
+
placeholder: options?.placeholder ?? (options?.allowMultiple ? [`user@${options?.allowedDomains?.[0] ?? "example.com"}`] : `user@${options?.allowedDomains?.[0] ?? "example.com"}`),
|
|
1507
1545
|
parse(input) {
|
|
1508
1546
|
if (allowMultiple) {
|
|
1509
1547
|
const emails = splitEmails(input).map((e) => e.trim());
|
|
@@ -1724,6 +1762,12 @@ function socketAddress(options) {
|
|
|
1724
1762
|
return {
|
|
1725
1763
|
$mode: "sync",
|
|
1726
1764
|
metavar,
|
|
1765
|
+
get placeholder() {
|
|
1766
|
+
return {
|
|
1767
|
+
host: hostType === "ip" ? ipParser.placeholder : hostnameParser.placeholder,
|
|
1768
|
+
port: defaultPort ?? portParser.placeholder
|
|
1769
|
+
};
|
|
1770
|
+
},
|
|
1727
1771
|
parse(input) {
|
|
1728
1772
|
const trimmed = input.trim();
|
|
1729
1773
|
const canOmitPort = defaultPort !== void 0 && !requirePort;
|
|
@@ -1936,6 +1980,15 @@ function portRange(options) {
|
|
|
1936
1980
|
return {
|
|
1937
1981
|
$mode: "sync",
|
|
1938
1982
|
metavar,
|
|
1983
|
+
get placeholder() {
|
|
1984
|
+
return isBigInt ? {
|
|
1985
|
+
start: portParser.placeholder,
|
|
1986
|
+
end: portParser.placeholder
|
|
1987
|
+
} : {
|
|
1988
|
+
start: portParser.placeholder,
|
|
1989
|
+
end: portParser.placeholder
|
|
1990
|
+
};
|
|
1991
|
+
},
|
|
1939
1992
|
parse(input) {
|
|
1940
1993
|
const trimmed = input.trim();
|
|
1941
1994
|
const separatorIndex = trimmed.indexOf(separator);
|
|
@@ -2094,6 +2147,20 @@ function macAddress(options) {
|
|
|
2094
2147
|
return {
|
|
2095
2148
|
$mode: "sync",
|
|
2096
2149
|
metavar,
|
|
2150
|
+
get placeholder() {
|
|
2151
|
+
const octets = [
|
|
2152
|
+
"00",
|
|
2153
|
+
"00",
|
|
2154
|
+
"00",
|
|
2155
|
+
"00",
|
|
2156
|
+
"00",
|
|
2157
|
+
"00"
|
|
2158
|
+
];
|
|
2159
|
+
const sep = outputSeparator ?? (separator === "any" ? ":" : separator);
|
|
2160
|
+
if (sep === ".") return `${octets[0]}${octets[1]}.${octets[2]}${octets[3]}.${octets[4]}${octets[5]}`;
|
|
2161
|
+
if (sep === "none") return octets.join("");
|
|
2162
|
+
return octets.join(sep);
|
|
2163
|
+
},
|
|
2097
2164
|
parse(input) {
|
|
2098
2165
|
let octets = [];
|
|
2099
2166
|
let inputSeparator;
|
|
@@ -2250,6 +2317,7 @@ function domain(options) {
|
|
|
2250
2317
|
return {
|
|
2251
2318
|
$mode: "sync",
|
|
2252
2319
|
metavar,
|
|
2320
|
+
placeholder: options?.placeholder ?? `example.${allowedTldsLower?.[0] ?? "com"}`,
|
|
2253
2321
|
parse(input) {
|
|
2254
2322
|
if (input.length > maxLength) {
|
|
2255
2323
|
const errorMsg = tooLong;
|
|
@@ -2489,6 +2557,7 @@ function ipv6(options) {
|
|
|
2489
2557
|
return {
|
|
2490
2558
|
$mode: "sync",
|
|
2491
2559
|
metavar,
|
|
2560
|
+
placeholder: allowZero ? "::" : allowLoopback ? "::1" : "2001:db8::1",
|
|
2492
2561
|
parse(input) {
|
|
2493
2562
|
const normalized = parseAndNormalizeIpv6(input);
|
|
2494
2563
|
if (normalized === null) {
|
|
@@ -2905,6 +2974,7 @@ function ip(options) {
|
|
|
2905
2974
|
return {
|
|
2906
2975
|
$mode: "sync",
|
|
2907
2976
|
metavar,
|
|
2977
|
+
placeholder: version === 6 ? ipv6Parser.placeholder : ipv4Parser.placeholder,
|
|
2908
2978
|
parse(input) {
|
|
2909
2979
|
let ipv4Error = null;
|
|
2910
2980
|
let ipv6Error = null;
|
|
@@ -3046,6 +3116,17 @@ function cidr(options) {
|
|
|
3046
3116
|
return {
|
|
3047
3117
|
$mode: "sync",
|
|
3048
3118
|
metavar,
|
|
3119
|
+
get placeholder() {
|
|
3120
|
+
return version === 6 || version === "both" && (minPrefix ?? 0) > 32 ? {
|
|
3121
|
+
address: ipv6Parser.placeholder,
|
|
3122
|
+
prefix: minPrefix ?? 0,
|
|
3123
|
+
version: 6
|
|
3124
|
+
} : {
|
|
3125
|
+
address: ipv4Parser.placeholder,
|
|
3126
|
+
prefix: minPrefix ?? 0,
|
|
3127
|
+
version: 4
|
|
3128
|
+
};
|
|
3129
|
+
},
|
|
3049
3130
|
parse(input) {
|
|
3050
3131
|
const slashIndex = input.lastIndexOf("/");
|
|
3051
3132
|
if (slashIndex === -1) {
|