@optique/core 1.0.0-dev.1178 → 1.0.0-dev.1189

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.
@@ -47,12 +47,13 @@ function encodeExtensions(extensions) {
47
47
  * Replaces control characters that would corrupt shell completion protocols.
48
48
  * Shell completion formats use tabs as field delimiters and newlines as record
49
49
  * delimiters. Null bytes are used as delimiters in zsh's format.
50
- * @param description The description string to sanitize.
51
- * @returns The sanitized description with control characters replaced by spaces.
50
+ * This is used for both suggestion text and descriptions.
51
+ * @param text The string to sanitize.
52
+ * @returns The sanitized string with control characters replaced by spaces.
52
53
  * @internal
53
54
  */
54
- function sanitizeDescription(description) {
55
- return description.replace(/[\t\n\r\0]/g, " ");
55
+ function sanitizeForTransport(text) {
56
+ return text.replace(/[\t\n\r\0]/g, " ");
56
57
  }
57
58
  /**
58
59
  * The Bash shell completion generator.
@@ -287,7 +288,7 @@ complete -F _${programName} -- ${programName}
287
288
  let i = 0;
288
289
  for (const suggestion of suggestions) {
289
290
  if (i > 0) yield "\n";
290
- if (suggestion.kind === "literal") yield `${suggestion.text}`;
291
+ if (suggestion.kind === "literal") yield sanitizeForTransport(suggestion.text);
291
292
  else {
292
293
  const extensions = encodeExtensions(suggestion.extensions);
293
294
  const hidden = suggestion.includeHidden ? "1" : "0";
@@ -434,12 +435,12 @@ compdef _${programName.replace(/[^a-zA-Z0-9]/g, "_")} ${programName}
434
435
  },
435
436
  *encodeSuggestions(suggestions) {
436
437
  for (const suggestion of suggestions) if (suggestion.kind === "literal") {
437
- const description = suggestion.description == null ? "" : sanitizeDescription(require_message.formatMessage(suggestion.description, { colors: false }));
438
- yield `${suggestion.text}\0${description}\0`;
438
+ const description = suggestion.description == null ? "" : sanitizeForTransport(require_message.formatMessage(suggestion.description, { colors: false }));
439
+ yield `${sanitizeForTransport(suggestion.text)}\0${description}\0`;
439
440
  } else {
440
441
  const extensions = encodeExtensions(suggestion.extensions);
441
442
  const hidden = suggestion.includeHidden ? "1" : "0";
442
- const description = suggestion.description == null ? "" : sanitizeDescription(require_message.formatMessage(suggestion.description, { colors: false }));
443
+ const description = suggestion.description == null ? "" : sanitizeForTransport(require_message.formatMessage(suggestion.description, { colors: false }));
443
444
  const pattern = encodePattern(suggestion.pattern ?? "");
444
445
  yield `__FILE__:${suggestion.type}:${extensions}:${pattern}:${hidden}\0${description}\0`;
445
446
  }
@@ -724,12 +725,12 @@ complete -c ${programName} -f -a '(${functionName})'
724
725
  for (const suggestion of suggestions) {
725
726
  if (i > 0) yield "\n";
726
727
  if (suggestion.kind === "literal") {
727
- const description = suggestion.description == null ? "" : sanitizeDescription(require_message.formatMessage(suggestion.description, { colors: false }));
728
- yield `${suggestion.text}\t${description}`;
728
+ const description = suggestion.description == null ? "" : sanitizeForTransport(require_message.formatMessage(suggestion.description, { colors: false }));
729
+ yield `${sanitizeForTransport(suggestion.text)}\t${description}`;
729
730
  } else {
730
731
  const extensions = encodeExtensions(suggestion.extensions);
731
732
  const hidden = suggestion.includeHidden ? "1" : "0";
732
- const description = suggestion.description == null ? "" : sanitizeDescription(require_message.formatMessage(suggestion.description, { colors: false }));
733
+ const description = suggestion.description == null ? "" : sanitizeForTransport(require_message.formatMessage(suggestion.description, { colors: false }));
733
734
  const pattern = encodePattern(suggestion.pattern ?? "");
734
735
  yield `__FILE__:${suggestion.type}:${extensions}:${pattern}:${hidden}\t${description}`;
735
736
  }
@@ -1046,12 +1047,12 @@ ${functionName}-external
1046
1047
  for (const suggestion of suggestions) {
1047
1048
  if (i > 0) yield "\n";
1048
1049
  if (suggestion.kind === "literal") {
1049
- const description = suggestion.description == null ? "" : sanitizeDescription(require_message.formatMessage(suggestion.description, { colors: false }));
1050
- yield `${suggestion.text}\t${description}`;
1050
+ const description = suggestion.description == null ? "" : sanitizeForTransport(require_message.formatMessage(suggestion.description, { colors: false }));
1051
+ yield `${sanitizeForTransport(suggestion.text)}\t${description}`;
1051
1052
  } else {
1052
1053
  const extensions = encodeExtensions(suggestion.extensions);
1053
1054
  const hidden = suggestion.includeHidden ? "1" : "0";
1054
- const description = suggestion.description == null ? "" : sanitizeDescription(require_message.formatMessage(suggestion.description, { colors: false }));
1055
+ const description = suggestion.description == null ? "" : sanitizeForTransport(require_message.formatMessage(suggestion.description, { colors: false }));
1055
1056
  const pattern = encodePattern(suggestion.pattern ?? "");
1056
1057
  yield `__FILE__:${suggestion.type}:${extensions}:${pattern}:${hidden}\t${description}`;
1057
1058
  }
@@ -1257,12 +1258,13 @@ ${escapedArgs ? ` \$completionArgs += @(${escapedArgs})
1257
1258
  for (const suggestion of suggestions) {
1258
1259
  if (i > 0) yield "\n";
1259
1260
  if (suggestion.kind === "literal") {
1260
- const description = suggestion.description == null ? "" : sanitizeDescription(require_message.formatMessage(suggestion.description, { colors: false }));
1261
- yield `${suggestion.text}\t${suggestion.text}\t${description}`;
1261
+ const description = suggestion.description == null ? "" : sanitizeForTransport(require_message.formatMessage(suggestion.description, { colors: false }));
1262
+ const text = sanitizeForTransport(suggestion.text);
1263
+ yield `${text}\t${text}\t${description}`;
1262
1264
  } else {
1263
1265
  const extensions = encodeExtensions(suggestion.extensions);
1264
1266
  const hidden = suggestion.includeHidden ? "1" : "0";
1265
- const description = suggestion.description == null ? "" : sanitizeDescription(require_message.formatMessage(suggestion.description, { colors: false }));
1267
+ const description = suggestion.description == null ? "" : sanitizeForTransport(require_message.formatMessage(suggestion.description, { colors: false }));
1266
1268
  const pattern = encodePattern(suggestion.pattern ?? "");
1267
1269
  yield `__FILE__:${suggestion.type}:${extensions}:${pattern}:${hidden}\t[file]\t${description}`;
1268
1270
  }
@@ -47,12 +47,13 @@ function encodeExtensions(extensions) {
47
47
  * Replaces control characters that would corrupt shell completion protocols.
48
48
  * Shell completion formats use tabs as field delimiters and newlines as record
49
49
  * delimiters. Null bytes are used as delimiters in zsh's format.
50
- * @param description The description string to sanitize.
51
- * @returns The sanitized description with control characters replaced by spaces.
50
+ * This is used for both suggestion text and descriptions.
51
+ * @param text The string to sanitize.
52
+ * @returns The sanitized string with control characters replaced by spaces.
52
53
  * @internal
53
54
  */
54
- function sanitizeDescription(description) {
55
- return description.replace(/[\t\n\r\0]/g, " ");
55
+ function sanitizeForTransport(text) {
56
+ return text.replace(/[\t\n\r\0]/g, " ");
56
57
  }
57
58
  /**
58
59
  * The Bash shell completion generator.
@@ -287,7 +288,7 @@ complete -F _${programName} -- ${programName}
287
288
  let i = 0;
288
289
  for (const suggestion of suggestions) {
289
290
  if (i > 0) yield "\n";
290
- if (suggestion.kind === "literal") yield `${suggestion.text}`;
291
+ if (suggestion.kind === "literal") yield sanitizeForTransport(suggestion.text);
291
292
  else {
292
293
  const extensions = encodeExtensions(suggestion.extensions);
293
294
  const hidden = suggestion.includeHidden ? "1" : "0";
@@ -434,12 +435,12 @@ compdef _${programName.replace(/[^a-zA-Z0-9]/g, "_")} ${programName}
434
435
  },
435
436
  *encodeSuggestions(suggestions) {
436
437
  for (const suggestion of suggestions) if (suggestion.kind === "literal") {
437
- const description = suggestion.description == null ? "" : sanitizeDescription(formatMessage(suggestion.description, { colors: false }));
438
- yield `${suggestion.text}\0${description}\0`;
438
+ const description = suggestion.description == null ? "" : sanitizeForTransport(formatMessage(suggestion.description, { colors: false }));
439
+ yield `${sanitizeForTransport(suggestion.text)}\0${description}\0`;
439
440
  } else {
440
441
  const extensions = encodeExtensions(suggestion.extensions);
441
442
  const hidden = suggestion.includeHidden ? "1" : "0";
442
- const description = suggestion.description == null ? "" : sanitizeDescription(formatMessage(suggestion.description, { colors: false }));
443
+ const description = suggestion.description == null ? "" : sanitizeForTransport(formatMessage(suggestion.description, { colors: false }));
443
444
  const pattern = encodePattern(suggestion.pattern ?? "");
444
445
  yield `__FILE__:${suggestion.type}:${extensions}:${pattern}:${hidden}\0${description}\0`;
445
446
  }
@@ -724,12 +725,12 @@ complete -c ${programName} -f -a '(${functionName})'
724
725
  for (const suggestion of suggestions) {
725
726
  if (i > 0) yield "\n";
726
727
  if (suggestion.kind === "literal") {
727
- const description = suggestion.description == null ? "" : sanitizeDescription(formatMessage(suggestion.description, { colors: false }));
728
- yield `${suggestion.text}\t${description}`;
728
+ const description = suggestion.description == null ? "" : sanitizeForTransport(formatMessage(suggestion.description, { colors: false }));
729
+ yield `${sanitizeForTransport(suggestion.text)}\t${description}`;
729
730
  } else {
730
731
  const extensions = encodeExtensions(suggestion.extensions);
731
732
  const hidden = suggestion.includeHidden ? "1" : "0";
732
- const description = suggestion.description == null ? "" : sanitizeDescription(formatMessage(suggestion.description, { colors: false }));
733
+ const description = suggestion.description == null ? "" : sanitizeForTransport(formatMessage(suggestion.description, { colors: false }));
733
734
  const pattern = encodePattern(suggestion.pattern ?? "");
734
735
  yield `__FILE__:${suggestion.type}:${extensions}:${pattern}:${hidden}\t${description}`;
735
736
  }
@@ -1046,12 +1047,12 @@ ${functionName}-external
1046
1047
  for (const suggestion of suggestions) {
1047
1048
  if (i > 0) yield "\n";
1048
1049
  if (suggestion.kind === "literal") {
1049
- const description = suggestion.description == null ? "" : sanitizeDescription(formatMessage(suggestion.description, { colors: false }));
1050
- yield `${suggestion.text}\t${description}`;
1050
+ const description = suggestion.description == null ? "" : sanitizeForTransport(formatMessage(suggestion.description, { colors: false }));
1051
+ yield `${sanitizeForTransport(suggestion.text)}\t${description}`;
1051
1052
  } else {
1052
1053
  const extensions = encodeExtensions(suggestion.extensions);
1053
1054
  const hidden = suggestion.includeHidden ? "1" : "0";
1054
- const description = suggestion.description == null ? "" : sanitizeDescription(formatMessage(suggestion.description, { colors: false }));
1055
+ const description = suggestion.description == null ? "" : sanitizeForTransport(formatMessage(suggestion.description, { colors: false }));
1055
1056
  const pattern = encodePattern(suggestion.pattern ?? "");
1056
1057
  yield `__FILE__:${suggestion.type}:${extensions}:${pattern}:${hidden}\t${description}`;
1057
1058
  }
@@ -1257,12 +1258,13 @@ ${escapedArgs ? ` \$completionArgs += @(${escapedArgs})
1257
1258
  for (const suggestion of suggestions) {
1258
1259
  if (i > 0) yield "\n";
1259
1260
  if (suggestion.kind === "literal") {
1260
- const description = suggestion.description == null ? "" : sanitizeDescription(formatMessage(suggestion.description, { colors: false }));
1261
- yield `${suggestion.text}\t${suggestion.text}\t${description}`;
1261
+ const description = suggestion.description == null ? "" : sanitizeForTransport(formatMessage(suggestion.description, { colors: false }));
1262
+ const text = sanitizeForTransport(suggestion.text);
1263
+ yield `${text}\t${text}\t${description}`;
1262
1264
  } else {
1263
1265
  const extensions = encodeExtensions(suggestion.extensions);
1264
1266
  const hidden = suggestion.includeHidden ? "1" : "0";
1265
- const description = suggestion.description == null ? "" : sanitizeDescription(formatMessage(suggestion.description, { colors: false }));
1267
+ const description = suggestion.description == null ? "" : sanitizeForTransport(formatMessage(suggestion.description, { colors: false }));
1266
1268
  const pattern = encodePattern(suggestion.pattern ?? "");
1267
1269
  yield `__FILE__:${suggestion.type}:${extensions}:${pattern}:${hidden}\t[file]\t${description}`;
1268
1270
  }
package/dist/doc.cjs CHANGED
@@ -47,8 +47,9 @@ function defaultSectionOrder(a, b) {
47
47
  * @param page The documentation page to format
48
48
  * @param options Formatting options to customize the output
49
49
  * @returns A formatted string representation of the documentation page
50
- * @throws {TypeError} If `programName` or any non-empty section's title
51
- * contains a CR or LF character.
50
+ * @throws {TypeError} If `programName` contains a CR or LF character, or if
51
+ * any non-empty section's title is empty, whitespace-only, or contains a CR
52
+ * or LF character.
52
53
  *
53
54
  * @example
54
55
  * ```typescript
@@ -113,7 +114,7 @@ function formatDocPage(programName, page, options = {}) {
113
114
  if (section.entries.length < 1) continue;
114
115
  output += "\n";
115
116
  if (section.title != null) {
116
- if (/[\r\n]/.test(section.title)) throw new TypeError("Section title must not contain newlines.");
117
+ if (section.title.trim() === "" || /[\r\n]/.test(section.title)) throw new TypeError("Section title must not be empty, whitespace-only, or contain newlines.");
117
118
  const sectionLabel = options.colors ? `\x1b[1;2m${section.title}:\x1b[0m\n` : `${section.title}:\n`;
118
119
  output += sectionLabel;
119
120
  }
package/dist/doc.d.cts CHANGED
@@ -263,8 +263,9 @@ interface DocPageFormatOptions {
263
263
  * @param page The documentation page to format
264
264
  * @param options Formatting options to customize the output
265
265
  * @returns A formatted string representation of the documentation page
266
- * @throws {TypeError} If `programName` or any non-empty section's title
267
- * contains a CR or LF character.
266
+ * @throws {TypeError} If `programName` contains a CR or LF character, or if
267
+ * any non-empty section's title is empty, whitespace-only, or contains a CR
268
+ * or LF character.
268
269
  *
269
270
  * @example
270
271
  * ```typescript
package/dist/doc.d.ts CHANGED
@@ -263,8 +263,9 @@ interface DocPageFormatOptions {
263
263
  * @param page The documentation page to format
264
264
  * @param options Formatting options to customize the output
265
265
  * @returns A formatted string representation of the documentation page
266
- * @throws {TypeError} If `programName` or any non-empty section's title
267
- * contains a CR or LF character.
266
+ * @throws {TypeError} If `programName` contains a CR or LF character, or if
267
+ * any non-empty section's title is empty, whitespace-only, or contains a CR
268
+ * or LF character.
268
269
  *
269
270
  * @example
270
271
  * ```typescript
package/dist/doc.js CHANGED
@@ -47,8 +47,9 @@ function defaultSectionOrder(a, b) {
47
47
  * @param page The documentation page to format
48
48
  * @param options Formatting options to customize the output
49
49
  * @returns A formatted string representation of the documentation page
50
- * @throws {TypeError} If `programName` or any non-empty section's title
51
- * contains a CR or LF character.
50
+ * @throws {TypeError} If `programName` contains a CR or LF character, or if
51
+ * any non-empty section's title is empty, whitespace-only, or contains a CR
52
+ * or LF character.
52
53
  *
53
54
  * @example
54
55
  * ```typescript
@@ -113,7 +114,7 @@ function formatDocPage(programName, page, options = {}) {
113
114
  if (section.entries.length < 1) continue;
114
115
  output += "\n";
115
116
  if (section.title != null) {
116
- if (/[\r\n]/.test(section.title)) throw new TypeError("Section title must not contain newlines.");
117
+ if (section.title.trim() === "" || /[\r\n]/.test(section.title)) throw new TypeError("Section title must not be empty, whitespace-only, or contain newlines.");
117
118
  const sectionLabel = options.colors ? `\x1b[1;2m${section.title}:\x1b[0m\n` : `${section.title}:\n`;
118
119
  output += sectionLabel;
119
120
  }
@@ -1133,6 +1133,8 @@ function ipv4(options) {
1133
1133
  *
1134
1134
  * @param options - Options for hostname validation.
1135
1135
  * @returns A value parser for hostnames.
1136
+ * @throws {TypeError} If `allowWildcard`, `allowUnderscore`, or
1137
+ * `allowLocalhost` is not a boolean.
1136
1138
  * @throws {RangeError} If `maxLength` is not a positive integer.
1137
1139
  * @since 0.10.0
1138
1140
  *
@@ -1153,6 +1155,9 @@ function ipv4(options) {
1153
1155
  function hostname(options) {
1154
1156
  const metavar = options?.metavar ?? "HOST";
1155
1157
  require_nonempty.ensureNonEmptyString(metavar);
1158
+ if (options?.allowWildcard !== void 0 && typeof options.allowWildcard !== "boolean") throw new TypeError(`Expected allowWildcard to be a boolean, but got ${typeof options.allowWildcard}: ${String(options.allowWildcard)}.`);
1159
+ if (options?.allowUnderscore !== void 0 && typeof options.allowUnderscore !== "boolean") throw new TypeError(`Expected allowUnderscore to be a boolean, but got ${typeof options.allowUnderscore}: ${String(options.allowUnderscore)}.`);
1160
+ if (options?.allowLocalhost !== void 0 && typeof options.allowLocalhost !== "boolean") throw new TypeError(`Expected allowLocalhost to be a boolean, but got ${typeof options.allowLocalhost}: ${String(options.allowLocalhost)}.`);
1156
1161
  const allowWildcard = options?.allowWildcard ?? false;
1157
1162
  const allowUnderscore = options?.allowUnderscore ?? false;
1158
1163
  const allowLocalhost = options?.allowLocalhost ?? true;
@@ -1868,6 +1873,7 @@ function macAddress(options) {
1868
1873
  * @returns A parser that accepts valid domain names as strings.
1869
1874
  * @throws {RangeError} If `maxLength` is not a positive integer.
1870
1875
  * @throws {RangeError} If `minLabels` is not a positive integer.
1876
+ * @throws {TypeError} If `allowSubdomains` or `lowercase` is not a boolean.
1871
1877
  * @throws {TypeError} If any `allowedTlds` entry is not a string, is empty,
1872
1878
  * contains dots, has leading/trailing whitespace, or is not a valid DNS
1873
1879
  * label.
@@ -1896,6 +1902,8 @@ function macAddress(options) {
1896
1902
  */
1897
1903
  function domain(options) {
1898
1904
  const metavar = options?.metavar ?? "DOMAIN";
1905
+ if (options?.allowSubdomains !== void 0 && typeof options.allowSubdomains !== "boolean") throw new TypeError(`Expected allowSubdomains to be a boolean, but got ${typeof options.allowSubdomains}: ${String(options.allowSubdomains)}.`);
1906
+ if (options?.lowercase !== void 0 && typeof options.lowercase !== "boolean") throw new TypeError(`Expected lowercase to be a boolean, but got ${typeof options.lowercase}: ${String(options.lowercase)}.`);
1899
1907
  const allowSubdomains = options?.allowSubdomains ?? true;
1900
1908
  const allowedTlds = options?.allowedTlds != null ? Object.freeze([...options.allowedTlds]) : void 0;
1901
1909
  const labelRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/;
@@ -929,6 +929,8 @@ interface HostnameOptions {
929
929
  *
930
930
  * @param options - Options for hostname validation.
931
931
  * @returns A value parser for hostnames.
932
+ * @throws {TypeError} If `allowWildcard`, `allowUnderscore`, or
933
+ * `allowLocalhost` is not a boolean.
932
934
  * @throws {RangeError} If `maxLength` is not a positive integer.
933
935
  * @since 0.10.0
934
936
  *
@@ -1548,6 +1550,7 @@ interface DomainOptions {
1548
1550
  * @returns A parser that accepts valid domain names as strings.
1549
1551
  * @throws {RangeError} If `maxLength` is not a positive integer.
1550
1552
  * @throws {RangeError} If `minLabels` is not a positive integer.
1553
+ * @throws {TypeError} If `allowSubdomains` or `lowercase` is not a boolean.
1551
1554
  * @throws {TypeError} If any `allowedTlds` entry is not a string, is empty,
1552
1555
  * contains dots, has leading/trailing whitespace, or is not a valid DNS
1553
1556
  * label.
@@ -929,6 +929,8 @@ interface HostnameOptions {
929
929
  *
930
930
  * @param options - Options for hostname validation.
931
931
  * @returns A value parser for hostnames.
932
+ * @throws {TypeError} If `allowWildcard`, `allowUnderscore`, or
933
+ * `allowLocalhost` is not a boolean.
932
934
  * @throws {RangeError} If `maxLength` is not a positive integer.
933
935
  * @since 0.10.0
934
936
  *
@@ -1548,6 +1550,7 @@ interface DomainOptions {
1548
1550
  * @returns A parser that accepts valid domain names as strings.
1549
1551
  * @throws {RangeError} If `maxLength` is not a positive integer.
1550
1552
  * @throws {RangeError} If `minLabels` is not a positive integer.
1553
+ * @throws {TypeError} If `allowSubdomains` or `lowercase` is not a boolean.
1551
1554
  * @throws {TypeError} If any `allowedTlds` entry is not a string, is empty,
1552
1555
  * contains dots, has leading/trailing whitespace, or is not a valid DNS
1553
1556
  * label.
@@ -1133,6 +1133,8 @@ function ipv4(options) {
1133
1133
  *
1134
1134
  * @param options - Options for hostname validation.
1135
1135
  * @returns A value parser for hostnames.
1136
+ * @throws {TypeError} If `allowWildcard`, `allowUnderscore`, or
1137
+ * `allowLocalhost` is not a boolean.
1136
1138
  * @throws {RangeError} If `maxLength` is not a positive integer.
1137
1139
  * @since 0.10.0
1138
1140
  *
@@ -1153,6 +1155,9 @@ function ipv4(options) {
1153
1155
  function hostname(options) {
1154
1156
  const metavar = options?.metavar ?? "HOST";
1155
1157
  ensureNonEmptyString(metavar);
1158
+ if (options?.allowWildcard !== void 0 && typeof options.allowWildcard !== "boolean") throw new TypeError(`Expected allowWildcard to be a boolean, but got ${typeof options.allowWildcard}: ${String(options.allowWildcard)}.`);
1159
+ if (options?.allowUnderscore !== void 0 && typeof options.allowUnderscore !== "boolean") throw new TypeError(`Expected allowUnderscore to be a boolean, but got ${typeof options.allowUnderscore}: ${String(options.allowUnderscore)}.`);
1160
+ if (options?.allowLocalhost !== void 0 && typeof options.allowLocalhost !== "boolean") throw new TypeError(`Expected allowLocalhost to be a boolean, but got ${typeof options.allowLocalhost}: ${String(options.allowLocalhost)}.`);
1156
1161
  const allowWildcard = options?.allowWildcard ?? false;
1157
1162
  const allowUnderscore = options?.allowUnderscore ?? false;
1158
1163
  const allowLocalhost = options?.allowLocalhost ?? true;
@@ -1868,6 +1873,7 @@ function macAddress(options) {
1868
1873
  * @returns A parser that accepts valid domain names as strings.
1869
1874
  * @throws {RangeError} If `maxLength` is not a positive integer.
1870
1875
  * @throws {RangeError} If `minLabels` is not a positive integer.
1876
+ * @throws {TypeError} If `allowSubdomains` or `lowercase` is not a boolean.
1871
1877
  * @throws {TypeError} If any `allowedTlds` entry is not a string, is empty,
1872
1878
  * contains dots, has leading/trailing whitespace, or is not a valid DNS
1873
1879
  * label.
@@ -1896,6 +1902,8 @@ function macAddress(options) {
1896
1902
  */
1897
1903
  function domain(options) {
1898
1904
  const metavar = options?.metavar ?? "DOMAIN";
1905
+ if (options?.allowSubdomains !== void 0 && typeof options.allowSubdomains !== "boolean") throw new TypeError(`Expected allowSubdomains to be a boolean, but got ${typeof options.allowSubdomains}: ${String(options.allowSubdomains)}.`);
1906
+ if (options?.lowercase !== void 0 && typeof options.lowercase !== "boolean") throw new TypeError(`Expected lowercase to be a boolean, but got ${typeof options.lowercase}: ${String(options.lowercase)}.`);
1899
1907
  const allowSubdomains = options?.allowSubdomains ?? true;
1900
1908
  const allowedTlds = options?.allowedTlds != null ? Object.freeze([...options.allowedTlds]) : void 0;
1901
1909
  const labelRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.0.0-dev.1178+6b5574a3",
3
+ "version": "1.0.0-dev.1189+856a380f",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",