@optique/core 1.0.0-dev.1547 → 1.0.0-dev.1553

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/modifiers.js CHANGED
@@ -118,7 +118,7 @@ function optional(parser) {
118
118
  const wrappedDependencyMarker = innerHasWrappedDependency ? { [wrappedDependencySourceMarker]: parser[wrappedDependencySourceMarker] } : innerHasDirectDependency ? { [wrappedDependencySourceMarker]: syncParser.initialState } : {};
119
119
  const hasWrappedDependencySource = wrappedDependencySourceMarker in wrappedDependencyMarker;
120
120
  const wrappedPendingState = hasWrappedDependencySource ? wrappedDependencyMarker[wrappedDependencySourceMarker] : void 0;
121
- return {
121
+ const optionalParser = {
122
122
  $mode: parser.$mode,
123
123
  $valueType: [],
124
124
  $stateType: [],
@@ -175,6 +175,18 @@ function optional(parser) {
175
175
  return syncParser.getDocFragments(innerState, defaultValue);
176
176
  }
177
177
  };
178
+ if (typeof parser.normalizeValue === "function") {
179
+ const innerNormalize = parser.normalizeValue.bind(parser);
180
+ Object.defineProperty(optionalParser, "normalizeValue", {
181
+ value(v) {
182
+ if (v == null) return v;
183
+ return innerNormalize(v);
184
+ },
185
+ configurable: true,
186
+ enumerable: false
187
+ });
188
+ }
189
+ return optionalParser;
178
190
  }
179
191
  /**
180
192
  * Error type for structured error messages in {@link withDefault} default value callbacks.
@@ -257,12 +269,19 @@ function withDefault(parser, defaultValue, options) {
257
269
  return dispatchByMode(parser.$mode, () => parseOptionalStyleSync(context, syncParser), () => parseOptionalStyleAsync(context, parser));
258
270
  },
259
271
  complete(state) {
272
+ function evaluateDefault() {
273
+ const raw = typeof defaultValue === "function" ? defaultValue() : defaultValue;
274
+ if (typeof parser.normalizeValue === "function") try {
275
+ return parser.normalizeValue(raw);
276
+ } catch {}
277
+ return raw;
278
+ }
260
279
  if (!Array.isArray(state)) {
261
280
  if (transformsDependencyValue(parser)) {
262
281
  const innerResult = dispatchByMode(parser.$mode, () => syncParser.complete(void 0), () => parser.complete(void 0));
263
282
  const handleInnerResult = (res) => {
264
283
  if (isDependencySourceState(res)) try {
265
- const value = typeof defaultValue === "function" ? defaultValue() : defaultValue;
284
+ const value = evaluateDefault();
266
285
  return createDependencySourceState({
267
286
  success: true,
268
287
  value
@@ -274,7 +293,7 @@ function withDefault(parser, defaultValue, options) {
274
293
  };
275
294
  }
276
295
  try {
277
- const value = typeof defaultValue === "function" ? defaultValue() : defaultValue;
296
+ const value = evaluateDefault();
278
297
  return {
279
298
  success: true,
280
299
  value
@@ -289,7 +308,7 @@ function withDefault(parser, defaultValue, options) {
289
308
  return mapModeValue(parser.$mode, innerResult, handleInnerResult);
290
309
  }
291
310
  if (isWrappedDependencySource(parser)) try {
292
- const value = typeof defaultValue === "function" ? defaultValue() : defaultValue;
311
+ const value = evaluateDefault();
293
312
  const pendingState = parser[wrappedDependencySourceMarker];
294
313
  return createDependencySourceState({
295
314
  success: true,
@@ -306,7 +325,7 @@ function withDefault(parser, defaultValue, options) {
306
325
  return innerResult;
307
326
  }
308
327
  try {
309
- const value = typeof defaultValue === "function" ? defaultValue() : defaultValue;
328
+ const value = evaluateDefault();
310
329
  return {
311
330
  success: true,
312
331
  value
@@ -323,7 +342,7 @@ function withDefault(parser, defaultValue, options) {
323
342
  const innerResult = dispatchByMode(parser.$mode, () => syncParser.complete(state), () => parser.complete(state));
324
343
  const handleInnerResult = (res) => {
325
344
  if (isDependencySourceState(res)) try {
326
- const value = typeof defaultValue === "function" ? defaultValue() : defaultValue;
345
+ const value = evaluateDefault();
327
346
  return createDependencySourceState({
328
347
  success: true,
329
348
  value
@@ -335,7 +354,7 @@ function withDefault(parser, defaultValue, options) {
335
354
  };
336
355
  }
337
356
  try {
338
- const value = typeof defaultValue === "function" ? defaultValue() : defaultValue;
357
+ const value = evaluateDefault();
339
358
  return {
340
359
  success: true,
341
360
  value
@@ -350,7 +369,7 @@ function withDefault(parser, defaultValue, options) {
350
369
  return mapModeValue(parser.$mode, innerResult, handleInnerResult);
351
370
  }
352
371
  try {
353
- const value = typeof defaultValue === "function" ? defaultValue() : defaultValue;
372
+ const value = evaluateDefault();
354
373
  return createDependencySourceState({
355
374
  success: true,
356
375
  value
@@ -373,7 +392,11 @@ function withDefault(parser, defaultValue, options) {
373
392
  kind: "available",
374
393
  state: state.state[0]
375
394
  };
376
- const fragments = syncParser.getDocFragments(innerState, getDocDefaultValue(upperDefaultValue));
395
+ let docDefault = getDocDefaultValue(upperDefaultValue);
396
+ if (docDefault != null && typeof parser.normalizeValue === "function") try {
397
+ docDefault = parser.normalizeValue(docDefault);
398
+ } catch {}
399
+ const fragments = syncParser.getDocFragments(innerState, docDefault);
377
400
  if (options?.message) {
378
401
  const modifiedFragments = fragments.fragments.map((fragment) => {
379
402
  if (fragment.type === "entry") return {
@@ -397,6 +420,20 @@ function withDefault(parser, defaultValue, options) {
397
420
  configurable: true,
398
421
  enumerable: false
399
422
  });
423
+ if (typeof parser.normalizeValue === "function") {
424
+ const innerNormalize = parser.normalizeValue.bind(parser);
425
+ Object.defineProperty(withDefaultParser, "normalizeValue", {
426
+ value(v) {
427
+ try {
428
+ return innerNormalize(v);
429
+ } catch {
430
+ return v;
431
+ }
432
+ },
433
+ configurable: true,
434
+ enumerable: false
435
+ });
436
+ }
400
437
  return withDefaultParser;
401
438
  }
402
439
  /**
@@ -510,6 +547,7 @@ function map(parser, transform) {
510
547
  return parser.getDocFragments(state, void 0);
511
548
  }
512
549
  };
550
+ delete mappedParser.normalizeValue;
513
551
  if ("placeholder" in parser) Object.defineProperty(mappedParser, "placeholder", {
514
552
  get() {
515
553
  try {
@@ -828,6 +866,27 @@ function multiple(parser, options = {}) {
828
866
  configurable: true,
829
867
  enumerable: false
830
868
  });
869
+ if (typeof parser.normalizeValue === "function") {
870
+ const innerNormalize = parser.normalizeValue.bind(parser);
871
+ Object.defineProperty(resultParser, "normalizeValue", {
872
+ value(values) {
873
+ if (!Array.isArray(values)) return values;
874
+ let changed = false;
875
+ const result = values.map((v) => {
876
+ try {
877
+ const n = innerNormalize(v);
878
+ if (n !== v) changed = true;
879
+ return n;
880
+ } catch {
881
+ return v;
882
+ }
883
+ });
884
+ return changed ? result : values;
885
+ },
886
+ configurable: true,
887
+ enumerable: false
888
+ });
889
+ }
831
890
  return resultParser;
832
891
  }
833
892
  /**
@@ -916,6 +975,11 @@ function nonEmpty(parser) {
916
975
  configurable: true,
917
976
  enumerable: false
918
977
  });
978
+ if (typeof parser.normalizeValue === "function") Object.defineProperty(nonEmptyParser, "normalizeValue", {
979
+ value: parser.normalizeValue.bind(parser),
980
+ configurable: true,
981
+ enumerable: false
982
+ });
919
983
  return nonEmptyParser;
920
984
  }
921
985
 
package/dist/parser.d.cts CHANGED
@@ -225,6 +225,26 @@ interface Parser<M extends Mode = "sync", TValue = unknown, TState = unknown> {
225
225
  * @since 1.0.0
226
226
  */
227
227
  shouldDeferCompletion?(state: TState): boolean;
228
+ /**
229
+ * Normalizes a parsed value according to the underlying value parser's
230
+ * configuration. When present, {@link withDefault} calls this method
231
+ * on default values so that runtime defaults match the representation
232
+ * that the value parser's `parse()` would produce.
233
+ *
234
+ * Primitive parsers ({@link option}, {@link argument}) implement this
235
+ * by delegating to {@link ValueParser.normalize}. Combinator wrappers
236
+ * ({@link optional}, {@link withDefault}) forward it from inner parsers.
237
+ *
238
+ * Exclusive combinators ({@link or}, `longestMatch()`) and
239
+ * multi-source combinators (`merge()`) intentionally do *not*
240
+ * implement this method because the active branch or key ownership
241
+ * is unknown at default time.
242
+ *
243
+ * @param value The value to normalize.
244
+ * @returns The normalized value.
245
+ * @since 1.0.0
246
+ */
247
+ normalizeValue?(value: TValue): TValue;
228
248
  }
229
249
  /**
230
250
  * The context of the parser, which includes the input buffer and the state.
package/dist/parser.d.ts CHANGED
@@ -225,6 +225,26 @@ interface Parser<M extends Mode = "sync", TValue = unknown, TState = unknown> {
225
225
  * @since 1.0.0
226
226
  */
227
227
  shouldDeferCompletion?(state: TState): boolean;
228
+ /**
229
+ * Normalizes a parsed value according to the underlying value parser's
230
+ * configuration. When present, {@link withDefault} calls this method
231
+ * on default values so that runtime defaults match the representation
232
+ * that the value parser's `parse()` would produce.
233
+ *
234
+ * Primitive parsers ({@link option}, {@link argument}) implement this
235
+ * by delegating to {@link ValueParser.normalize}. Combinator wrappers
236
+ * ({@link optional}, {@link withDefault}) forward it from inner parsers.
237
+ *
238
+ * Exclusive combinators ({@link or}, `longestMatch()`) and
239
+ * multi-source combinators (`merge()`) intentionally do *not*
240
+ * implement this method because the active branch or key ownership
241
+ * is unknown at default time.
242
+ *
243
+ * @param value The value to normalize.
244
+ * @returns The normalized value.
245
+ * @since 1.0.0
246
+ */
247
+ normalizeValue?(value: TValue): TValue;
228
248
  }
229
249
  /**
230
250
  * The context of the parser, which includes the input buffer and the state.
@@ -564,6 +564,20 @@ function option(...args) {
564
564
  return `option(${optionNames$1.map((o) => JSON.stringify(o)).join(", ")})`;
565
565
  }
566
566
  };
567
+ if (valueParser != null && typeof valueParser.normalize === "function") {
568
+ const normalize = valueParser.normalize.bind(valueParser);
569
+ Object.defineProperty(result, "normalizeValue", {
570
+ value(v) {
571
+ try {
572
+ return normalize(v);
573
+ } catch {
574
+ return v;
575
+ }
576
+ },
577
+ configurable: true,
578
+ enumerable: false
579
+ });
580
+ }
567
581
  if (valueParser != null) Object.defineProperty(result, "placeholder", {
568
582
  get() {
569
583
  try {
@@ -918,6 +932,20 @@ function argument(valueParser, options = {}) {
918
932
  return `argument()`;
919
933
  }
920
934
  };
935
+ if (typeof valueParser.normalize === "function") {
936
+ const normalize = valueParser.normalize.bind(valueParser);
937
+ Object.defineProperty(result, "normalizeValue", {
938
+ value(v) {
939
+ try {
940
+ return normalize(v);
941
+ } catch {
942
+ return v;
943
+ }
944
+ },
945
+ configurable: true,
946
+ enumerable: false
947
+ });
948
+ }
921
949
  Object.defineProperty(result, "placeholder", {
922
950
  get() {
923
951
  try {
@@ -1136,6 +1164,11 @@ function command(name, parser, options = {}) {
1136
1164
  return `command(${JSON.stringify(name)})`;
1137
1165
  }
1138
1166
  };
1167
+ if (typeof parser.normalizeValue === "function") Object.defineProperty(result, "normalizeValue", {
1168
+ value: parser.normalizeValue.bind(parser),
1169
+ configurable: true,
1170
+ enumerable: false
1171
+ });
1139
1172
  return result;
1140
1173
  }
1141
1174
  /**
@@ -564,6 +564,20 @@ function option(...args) {
564
564
  return `option(${optionNames$1.map((o) => JSON.stringify(o)).join(", ")})`;
565
565
  }
566
566
  };
567
+ if (valueParser != null && typeof valueParser.normalize === "function") {
568
+ const normalize = valueParser.normalize.bind(valueParser);
569
+ Object.defineProperty(result, "normalizeValue", {
570
+ value(v) {
571
+ try {
572
+ return normalize(v);
573
+ } catch {
574
+ return v;
575
+ }
576
+ },
577
+ configurable: true,
578
+ enumerable: false
579
+ });
580
+ }
567
581
  if (valueParser != null) Object.defineProperty(result, "placeholder", {
568
582
  get() {
569
583
  try {
@@ -918,6 +932,20 @@ function argument(valueParser, options = {}) {
918
932
  return `argument()`;
919
933
  }
920
934
  };
935
+ if (typeof valueParser.normalize === "function") {
936
+ const normalize = valueParser.normalize.bind(valueParser);
937
+ Object.defineProperty(result, "normalizeValue", {
938
+ value(v) {
939
+ try {
940
+ return normalize(v);
941
+ } catch {
942
+ return v;
943
+ }
944
+ },
945
+ configurable: true,
946
+ enumerable: false
947
+ });
948
+ }
921
949
  Object.defineProperty(result, "placeholder", {
922
950
  get() {
923
951
  try {
@@ -1136,6 +1164,11 @@ function command(name, parser, options = {}) {
1136
1164
  return `command(${JSON.stringify(name)})`;
1137
1165
  }
1138
1166
  };
1167
+ if (typeof parser.normalizeValue === "function") Object.defineProperty(result, "normalizeValue", {
1168
+ value: parser.normalizeValue.bind(parser),
1169
+ configurable: true,
1170
+ enumerable: false
1171
+ });
1139
1172
  return result;
1140
1173
  }
1141
1174
  /**
@@ -2144,7 +2144,48 @@ function macAddress(options) {
2144
2144
  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})$/;
2145
2145
  const dotRegex = /^([0-9a-fA-F]{4})\.([0-9a-fA-F]{4})\.([0-9a-fA-F]{4})$/;
2146
2146
  const noneRegex = /^([0-9a-fA-F]{12})$/;
2147
- return {
2147
+ function joinOctets(octets, sep) {
2148
+ let formatted = octets;
2149
+ if (caseOption === "upper") formatted = octets.map((o) => o.toUpperCase());
2150
+ else if (caseOption === "lower") formatted = octets.map((o) => o.toLowerCase());
2151
+ if (sep === ".") return [
2152
+ formatted[0] + formatted[1],
2153
+ formatted[2] + formatted[3],
2154
+ formatted[4] + formatted[5]
2155
+ ].join(".");
2156
+ if (sep === "none") return formatted.join("");
2157
+ return formatted.join(sep);
2158
+ }
2159
+ function normalizeMac(value) {
2160
+ if (typeof value !== "string") return metavar;
2161
+ let octets;
2162
+ let detectedSep;
2163
+ if (value.includes(":")) {
2164
+ octets = value.split(":");
2165
+ detectedSep = ":";
2166
+ } else if (value.includes("-")) {
2167
+ octets = value.split("-");
2168
+ detectedSep = "-";
2169
+ } else if (value.includes(".")) {
2170
+ const groups = value.split(".");
2171
+ if (groups.length !== 3 || !groups.every((g) => /^[0-9a-fA-F]{4}$/.test(g))) return value;
2172
+ octets = groups.flatMap((g) => [g.slice(0, 2), g.slice(2)]);
2173
+ detectedSep = ".";
2174
+ } else {
2175
+ if (value.length !== 12) return value;
2176
+ octets = [];
2177
+ for (let i = 0; i < value.length; i += 2) octets.push(value.slice(i, i + 2));
2178
+ detectedSep = "none";
2179
+ }
2180
+ if (octets.length !== 6 || !octets.every((o) => /^[0-9a-fA-F]{1,2}$/.test(o))) return value;
2181
+ octets = octets.map((o) => o.padStart(2, "0"));
2182
+ let sep;
2183
+ if (outputSeparator != null) sep = outputSeparator;
2184
+ else if (separator !== "any") sep = separator;
2185
+ else sep = detectedSep;
2186
+ return joinOctets(octets, sep);
2187
+ }
2188
+ const parserObj = {
2148
2189
  $mode: "sync",
2149
2190
  metavar,
2150
2191
  get placeholder() {
@@ -2221,28 +2262,51 @@ function macAddress(options) {
2221
2262
  };
2222
2263
  }
2223
2264
  octets = octets.map((o) => o.padStart(2, "0"));
2224
- let formattedOctets = octets;
2225
- if (caseOption === "upper") formattedOctets = octets.map((octet) => octet.toUpperCase());
2226
- else if (caseOption === "lower") formattedOctets = octets.map((octet) => octet.toLowerCase());
2227
2265
  const finalSeparator = outputSeparator ?? inputSeparator ?? ":";
2228
- let result;
2229
- if (finalSeparator === ":") result = formattedOctets.join(":");
2230
- else if (finalSeparator === "-") result = formattedOctets.join("-");
2231
- else if (finalSeparator === ".") result = [
2232
- formattedOctets[0] + formattedOctets[1],
2233
- formattedOctets[2] + formattedOctets[3],
2234
- formattedOctets[4] + formattedOctets[5]
2235
- ].join(".");
2236
- else result = formattedOctets.join("");
2237
2266
  return {
2238
2267
  success: true,
2239
- value: result
2268
+ value: joinOctets(octets, finalSeparator)
2240
2269
  };
2241
2270
  },
2242
- format() {
2243
- return metavar;
2244
- }
2271
+ format: normalizeMac
2245
2272
  };
2273
+ const macParser = parserObj;
2274
+ let macParsing = false;
2275
+ Object.defineProperty(parserObj, "format", {
2276
+ value(v) {
2277
+ if (typeof v !== "string") return metavar;
2278
+ if (macParsing) return v;
2279
+ macParsing = true;
2280
+ try {
2281
+ const result = macParser.parse(v);
2282
+ return result.success ? result.value : v;
2283
+ } catch {
2284
+ return v;
2285
+ } finally {
2286
+ macParsing = false;
2287
+ }
2288
+ },
2289
+ configurable: true,
2290
+ enumerable: true
2291
+ });
2292
+ Object.defineProperty(parserObj, "normalize", {
2293
+ value(v) {
2294
+ if (typeof v !== "string") return v;
2295
+ if (macParsing) return v;
2296
+ macParsing = true;
2297
+ try {
2298
+ const result = macParser.parse(v);
2299
+ return result.success ? result.value : v;
2300
+ } catch {
2301
+ return v;
2302
+ } finally {
2303
+ macParsing = false;
2304
+ }
2305
+ },
2306
+ configurable: true,
2307
+ enumerable: true
2308
+ });
2309
+ return parserObj;
2246
2310
  }
2247
2311
  /**
2248
2312
  * Creates a value parser for domain names.
@@ -2314,7 +2378,7 @@ function domain(options) {
2314
2378
  const tooFewLabels = options?.errors?.tooFewLabels;
2315
2379
  const subdomainsNotAllowed = options?.errors?.subdomainsNotAllowed;
2316
2380
  const tldNotAllowed = options?.errors?.tldNotAllowed;
2317
- return {
2381
+ const domainParserObj = {
2318
2382
  $mode: "sync",
2319
2383
  metavar,
2320
2384
  placeholder: options?.placeholder ?? `example.${allowedTldsLower?.[0] ?? "com"}`,
@@ -2518,10 +2582,51 @@ function domain(options) {
2518
2582
  value: result
2519
2583
  };
2520
2584
  },
2521
- format() {
2522
- return metavar;
2585
+ format(value) {
2586
+ if (typeof value !== "string") return metavar;
2587
+ if (!lowercase) return value;
2588
+ return value.split(".").length >= minLabels ? value.toLowerCase() : value;
2523
2589
  }
2524
2590
  };
2591
+ if (lowercase) {
2592
+ const domParser = domainParserObj;
2593
+ let domParsing = false;
2594
+ Object.defineProperty(domainParserObj, "format", {
2595
+ value(v) {
2596
+ if (typeof v !== "string") return metavar;
2597
+ if (domParsing) return v;
2598
+ domParsing = true;
2599
+ try {
2600
+ const result = domParser.parse(v);
2601
+ return result.success ? result.value : v;
2602
+ } catch {
2603
+ return v;
2604
+ } finally {
2605
+ domParsing = false;
2606
+ }
2607
+ },
2608
+ configurable: true,
2609
+ enumerable: true
2610
+ });
2611
+ Object.defineProperty(domainParserObj, "normalize", {
2612
+ value(v) {
2613
+ if (typeof v !== "string") return v;
2614
+ if (domParsing) return v;
2615
+ domParsing = true;
2616
+ try {
2617
+ const result = domParser.parse(v);
2618
+ return result.success ? result.value : v;
2619
+ } catch {
2620
+ return v;
2621
+ } finally {
2622
+ domParsing = false;
2623
+ }
2624
+ },
2625
+ configurable: true,
2626
+ enumerable: true
2627
+ });
2628
+ }
2629
+ return domainParserObj;
2525
2630
  }
2526
2631
  /**
2527
2632
  * Creates a value parser for IPv6 addresses.
@@ -2554,7 +2659,7 @@ function ipv6(options) {
2554
2659
  const allowZero = options?.allowZero ?? true;
2555
2660
  const errors = options?.errors;
2556
2661
  const metavar = options?.metavar ?? "IPV6";
2557
- return {
2662
+ const ipv6ParserObj = {
2558
2663
  $mode: "sync",
2559
2664
  metavar,
2560
2665
  placeholder: allowZero ? "::" : allowLoopback ? "::1" : "2001:db8::1",
@@ -2707,10 +2812,47 @@ function ipv6(options) {
2707
2812
  value: normalized
2708
2813
  };
2709
2814
  },
2710
- format() {
2711
- return metavar;
2815
+ format(value) {
2816
+ if (typeof value !== "string") return metavar;
2817
+ return parseAndNormalizeIpv6(value) ?? value;
2712
2818
  }
2713
2819
  };
2820
+ let ipv6Parsing = false;
2821
+ Object.defineProperty(ipv6ParserObj, "format", {
2822
+ value(v) {
2823
+ if (typeof v !== "string") return metavar;
2824
+ if (ipv6Parsing) return v;
2825
+ ipv6Parsing = true;
2826
+ try {
2827
+ const result = ipv6ParserObj.parse(v);
2828
+ return result.success ? result.value : v;
2829
+ } catch {
2830
+ return v;
2831
+ } finally {
2832
+ ipv6Parsing = false;
2833
+ }
2834
+ },
2835
+ configurable: true,
2836
+ enumerable: true
2837
+ });
2838
+ Object.defineProperty(ipv6ParserObj, "normalize", {
2839
+ value(v) {
2840
+ if (typeof v !== "string") return v;
2841
+ if (ipv6Parsing) return v;
2842
+ ipv6Parsing = true;
2843
+ try {
2844
+ const result = ipv6ParserObj.parse(v);
2845
+ return result.success ? result.value : v;
2846
+ } catch {
2847
+ return v;
2848
+ } finally {
2849
+ ipv6Parsing = false;
2850
+ }
2851
+ },
2852
+ configurable: true,
2853
+ enumerable: true
2854
+ });
2855
+ return ipv6ParserObj;
2714
2856
  }
2715
2857
  /**
2716
2858
  * Parses and normalizes an IPv6 address to canonical form.
@@ -2971,7 +3113,7 @@ function ip(options) {
2971
3113
  broadcastNotAllowed: errors?.broadcastNotAllowed,
2972
3114
  zeroNotAllowed: errors?.zeroNotAllowed
2973
3115
  } : void 0;
2974
- return {
3116
+ const ipParserObj = {
2975
3117
  $mode: "sync",
2976
3118
  metavar,
2977
3119
  placeholder: version === 6 ? ipv6Parser.placeholder : ipv4Parser.placeholder,
@@ -3031,10 +3173,47 @@ function ip(options) {
3031
3173
  error: msg
3032
3174
  };
3033
3175
  },
3034
- format() {
3035
- return metavar;
3176
+ format(value) {
3177
+ if (typeof value !== "string") return metavar;
3178
+ return parseAndNormalizeIpv6(value) ?? value;
3036
3179
  }
3037
3180
  };
3181
+ let ipParsing = false;
3182
+ Object.defineProperty(ipParserObj, "format", {
3183
+ value(v) {
3184
+ if (typeof v !== "string") return metavar;
3185
+ if (ipParsing) return v;
3186
+ ipParsing = true;
3187
+ try {
3188
+ const result = ipParserObj.parse(v);
3189
+ return result.success ? result.value : v;
3190
+ } catch {
3191
+ return v;
3192
+ } finally {
3193
+ ipParsing = false;
3194
+ }
3195
+ },
3196
+ configurable: true,
3197
+ enumerable: true
3198
+ });
3199
+ Object.defineProperty(ipParserObj, "normalize", {
3200
+ value(v) {
3201
+ if (typeof v !== "string") return v;
3202
+ if (ipParsing) return v;
3203
+ ipParsing = true;
3204
+ try {
3205
+ const result = ipParserObj.parse(v);
3206
+ return result.success ? result.value : v;
3207
+ } catch {
3208
+ return v;
3209
+ } finally {
3210
+ ipParsing = false;
3211
+ }
3212
+ },
3213
+ configurable: true,
3214
+ enumerable: true
3215
+ });
3216
+ return ipParserObj;
3038
3217
  }
3039
3218
  /**
3040
3219
  * Creates a value parser for CIDR notation (IP address with prefix length).
@@ -3113,7 +3292,7 @@ function cidr(options) {
3113
3292
  broadcastNotAllowed: errors?.broadcastNotAllowed,
3114
3293
  zeroNotAllowed: errors?.zeroNotAllowed
3115
3294
  } : void 0;
3116
- return {
3295
+ const cidrParserObj = {
3117
3296
  $mode: "sync",
3118
3297
  metavar,
3119
3298
  get placeholder() {
@@ -3484,10 +3663,47 @@ function cidr(options) {
3484
3663
  }
3485
3664
  };
3486
3665
  },
3487
- format() {
3488
- return metavar;
3489
- }
3666
+ format: ((_) => metavar)
3490
3667
  };
3668
+ let cidrParsing = false;
3669
+ Object.defineProperty(cidrParserObj, "format", {
3670
+ value(value) {
3671
+ if (typeof value !== "object" || value == null || !("address" in value) || !("prefix" in value) || !("version" in value)) return metavar;
3672
+ if (cidrParsing) return `${value.address}/${value.prefix}`;
3673
+ cidrParsing = true;
3674
+ try {
3675
+ const raw = `${value.address}/${value.prefix}`;
3676
+ const result = cidrParserObj.parse(raw);
3677
+ return result.success && result.value.version === value.version ? `${result.value.address}/${result.value.prefix}` : raw;
3678
+ } catch {
3679
+ return `${value.address}/${value.prefix}`;
3680
+ } finally {
3681
+ cidrParsing = false;
3682
+ }
3683
+ },
3684
+ configurable: true,
3685
+ enumerable: true
3686
+ });
3687
+ Object.defineProperty(cidrParserObj, "normalize", {
3688
+ value(v) {
3689
+ if (typeof v !== "object" || v == null || !("address" in v) || !("prefix" in v) || !("version" in v)) return v;
3690
+ if (cidrParsing) return v;
3691
+ cidrParsing = true;
3692
+ const formatted = `${v.address}/${v.prefix}`;
3693
+ try {
3694
+ const result = cidrParserObj.parse(formatted);
3695
+ if (result.success && result.value.version === v.version) return result.value;
3696
+ return v;
3697
+ } catch {
3698
+ return v;
3699
+ } finally {
3700
+ cidrParsing = false;
3701
+ }
3702
+ },
3703
+ configurable: true,
3704
+ enumerable: true
3705
+ });
3706
+ return cidrParserObj;
3491
3707
  }
3492
3708
 
3493
3709
  //#endregion