@optique/core 1.0.0-dev.1565 → 1.0.0-dev.1574

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.
@@ -941,18 +941,20 @@ function isPlainObject(value) {
941
941
  function collectDependencyValues(deferredState, registry) {
942
942
  const depIds = deferredState.dependencyIds;
943
943
  if (depIds && depIds.length > 0) {
944
- const defaults = deferredState.defaultValues;
944
+ const defaults$1 = deferredState.defaultValues;
945
945
  const dependencyValues = [];
946
946
  for (let i = 0; i < depIds.length; i++) {
947
947
  const depId$1 = depIds[i];
948
948
  if (registry.has(depId$1)) dependencyValues.push(registry.get(depId$1));
949
- else if (defaults && i < defaults.length) dependencyValues.push(defaults[i]);
949
+ else if (defaults$1 && i < defaults$1.length) dependencyValues.push(defaults$1[i]);
950
950
  else return null;
951
951
  }
952
952
  return dependencyValues;
953
953
  }
954
954
  const depId = deferredState.dependencyId;
955
955
  if (registry.has(depId)) return registry.get(depId);
956
+ const defaults = deferredState.defaultValues;
957
+ if (defaults && defaults.length > 0) return defaults[0];
956
958
  return null;
957
959
  }
958
960
  /**
@@ -941,18 +941,20 @@ function isPlainObject(value) {
941
941
  function collectDependencyValues(deferredState, registry) {
942
942
  const depIds = deferredState.dependencyIds;
943
943
  if (depIds && depIds.length > 0) {
944
- const defaults = deferredState.defaultValues;
944
+ const defaults$1 = deferredState.defaultValues;
945
945
  const dependencyValues = [];
946
946
  for (let i = 0; i < depIds.length; i++) {
947
947
  const depId$1 = depIds[i];
948
948
  if (registry.has(depId$1)) dependencyValues.push(registry.get(depId$1));
949
- else if (defaults && i < defaults.length) dependencyValues.push(defaults[i]);
949
+ else if (defaults$1 && i < defaults$1.length) dependencyValues.push(defaults$1[i]);
950
950
  else return null;
951
951
  }
952
952
  return dependencyValues;
953
953
  }
954
954
  const depId = deferredState.dependencyId;
955
955
  if (registry.has(depId)) return registry.get(depId);
956
+ const defaults = deferredState.defaultValues;
957
+ if (defaults && defaults.length > 0) return defaults[0];
956
958
  return null;
957
959
  }
958
960
  /**
package/dist/message.cjs CHANGED
@@ -143,8 +143,10 @@ function value(value$1) {
143
143
  * string representations of consecutive values.
144
144
  * For example, `["42", "hello"]`.
145
145
  * @returns A {@link MessageTerm} representing the list of values.
146
+ * @throws {TypeError} If the values array is empty.
146
147
  */
147
148
  function values(values$1) {
149
+ if (values$1.length === 0) throw new TypeError("values must not be empty.");
148
150
  return {
149
151
  type: "values",
150
152
  values: [...values$1]
@@ -236,29 +238,44 @@ function link(href) {
236
238
  * to be styled independently while respecting the locale's list formatting
237
239
  * conventions.
238
240
  *
241
+ * A fallback must be provided for when the values array is empty. This can
242
+ * be either a simple string (shorthand) or an options object with a
243
+ * `fallback` field. When the values array is empty, the fallback text
244
+ * is returned as a single text term. An empty fallback string produces
245
+ * an empty {@link Message}.
246
+ *
239
247
  * @example
240
248
  * ```typescript
241
249
  * // English conjunction (default): "error", "warn", and "info"
242
- * const msg1 = message`Expected one of ${valueSet(["error", "warn", "info"])}.`;
250
+ * const msg1 = message`Expected one of ${
251
+ * valueSet(["error", "warn", "info"], "")
252
+ * }.`;
243
253
  *
244
254
  * // English disjunction: "error", "warn", or "info"
245
255
  * const msg2 = message`Expected ${
246
- * valueSet(["error", "warn", "info"], { type: "disjunction" })
256
+ * valueSet(["error", "warn", "info"], { fallback: "", type: "disjunction" })
247
257
  * }.`;
248
258
  *
249
- * // Korean disjunction: "error", "warn" 또는 "info"
250
- * const msg3 = message`${
251
- * valueSet(["error", "warn", "info"], { locale: "ko", type: "disjunction" })
252
- * } 중 하나여야 합니다.`;
259
+ * // Fallback for empty list:
260
+ * const msg3 = message`Expected one of ${valueSet([], "(none)")}.`;
261
+ * // "Expected one of (none)."
253
262
  * ```
254
263
  *
255
264
  * @param values The list of values to format.
256
- * @param options Optional formatting options including locale and list type.
265
+ * @param fallbackOrOptions A fallback string for empty lists, or an options
266
+ * object including the fallback and formatting
267
+ * options such as locale and list type.
257
268
  * @returns A {@link Message} with alternating value and text terms.
269
+ * @throws {TypeError} If the fallback parameter is missing or invalid.
258
270
  * @since 0.9.0
259
271
  */
260
- function valueSet(values$1, options) {
261
- if (values$1.length === 0) return [];
272
+ function valueSet(values$1, fallbackOrOptions) {
273
+ if (fallbackOrOptions == null || typeof fallbackOrOptions !== "string" && typeof fallbackOrOptions.fallback !== "string") throw new TypeError("valueSet() requires a fallback string or an options object with a fallback field.");
274
+ const options = typeof fallbackOrOptions === "string" ? { fallback: fallbackOrOptions } : fallbackOrOptions;
275
+ if (values$1.length === 0) return options.fallback === "" ? [] : [{
276
+ type: "text",
277
+ text: options.fallback
278
+ }];
262
279
  const formatter = new Intl.ListFormat(options?.locale, {
263
280
  type: options?.type,
264
281
  style: options?.style
@@ -233,6 +233,7 @@ declare function value(value: string): MessageTerm;
233
233
  * string representations of consecutive values.
234
234
  * For example, `["42", "hello"]`.
235
235
  * @returns A {@link MessageTerm} representing the list of values.
236
+ * @throws {TypeError} If the values array is empty.
236
237
  */
237
238
  declare function values(values: readonly string[]): MessageTerm;
238
239
  /**
@@ -319,6 +320,15 @@ interface ValueSetOptions {
319
320
  * @default `"long"`
320
321
  */
321
322
  readonly style?: "long" | "short" | "narrow";
323
+ /**
324
+ * A fallback text to return when the values array is empty. When provided
325
+ * and the values array is empty, a {@link Message} containing a single text
326
+ * term with this string is returned instead of an empty {@link Message}.
327
+ * An empty string produces an empty {@link Message}.
328
+ *
329
+ * @since 1.0.0
330
+ */
331
+ readonly fallback: string;
322
332
  }
323
333
  /**
324
334
  * Creates a {@link Message} for a formatted list of values using the
@@ -330,28 +340,38 @@ interface ValueSetOptions {
330
340
  * to be styled independently while respecting the locale's list formatting
331
341
  * conventions.
332
342
  *
343
+ * A fallback must be provided for when the values array is empty. This can
344
+ * be either a simple string (shorthand) or an options object with a
345
+ * `fallback` field. When the values array is empty, the fallback text
346
+ * is returned as a single text term. An empty fallback string produces
347
+ * an empty {@link Message}.
348
+ *
333
349
  * @example
334
350
  * ```typescript
335
351
  * // English conjunction (default): "error", "warn", and "info"
336
- * const msg1 = message`Expected one of ${valueSet(["error", "warn", "info"])}.`;
352
+ * const msg1 = message`Expected one of ${
353
+ * valueSet(["error", "warn", "info"], "")
354
+ * }.`;
337
355
  *
338
356
  * // English disjunction: "error", "warn", or "info"
339
357
  * const msg2 = message`Expected ${
340
- * valueSet(["error", "warn", "info"], { type: "disjunction" })
358
+ * valueSet(["error", "warn", "info"], { fallback: "", type: "disjunction" })
341
359
  * }.`;
342
360
  *
343
- * // Korean disjunction: "error", "warn" 또는 "info"
344
- * const msg3 = message`${
345
- * valueSet(["error", "warn", "info"], { locale: "ko", type: "disjunction" })
346
- * } 중 하나여야 합니다.`;
361
+ * // Fallback for empty list:
362
+ * const msg3 = message`Expected one of ${valueSet([], "(none)")}.`;
363
+ * // "Expected one of (none)."
347
364
  * ```
348
365
  *
349
366
  * @param values The list of values to format.
350
- * @param options Optional formatting options including locale and list type.
367
+ * @param fallbackOrOptions A fallback string for empty lists, or an options
368
+ * object including the fallback and formatting
369
+ * options such as locale and list type.
351
370
  * @returns A {@link Message} with alternating value and text terms.
371
+ * @throws {TypeError} If the fallback parameter is missing or invalid.
352
372
  * @since 0.9.0
353
373
  */
354
- declare function valueSet(values: readonly string[], options?: ValueSetOptions): Message;
374
+ declare function valueSet(values: readonly string[], fallbackOrOptions: string | ValueSetOptions): Message;
355
375
  /**
356
376
  * Options for the {@link formatMessage} function.
357
377
  */
package/dist/message.d.ts CHANGED
@@ -233,6 +233,7 @@ declare function value(value: string): MessageTerm;
233
233
  * string representations of consecutive values.
234
234
  * For example, `["42", "hello"]`.
235
235
  * @returns A {@link MessageTerm} representing the list of values.
236
+ * @throws {TypeError} If the values array is empty.
236
237
  */
237
238
  declare function values(values: readonly string[]): MessageTerm;
238
239
  /**
@@ -319,6 +320,15 @@ interface ValueSetOptions {
319
320
  * @default `"long"`
320
321
  */
321
322
  readonly style?: "long" | "short" | "narrow";
323
+ /**
324
+ * A fallback text to return when the values array is empty. When provided
325
+ * and the values array is empty, a {@link Message} containing a single text
326
+ * term with this string is returned instead of an empty {@link Message}.
327
+ * An empty string produces an empty {@link Message}.
328
+ *
329
+ * @since 1.0.0
330
+ */
331
+ readonly fallback: string;
322
332
  }
323
333
  /**
324
334
  * Creates a {@link Message} for a formatted list of values using the
@@ -330,28 +340,38 @@ interface ValueSetOptions {
330
340
  * to be styled independently while respecting the locale's list formatting
331
341
  * conventions.
332
342
  *
343
+ * A fallback must be provided for when the values array is empty. This can
344
+ * be either a simple string (shorthand) or an options object with a
345
+ * `fallback` field. When the values array is empty, the fallback text
346
+ * is returned as a single text term. An empty fallback string produces
347
+ * an empty {@link Message}.
348
+ *
333
349
  * @example
334
350
  * ```typescript
335
351
  * // English conjunction (default): "error", "warn", and "info"
336
- * const msg1 = message`Expected one of ${valueSet(["error", "warn", "info"])}.`;
352
+ * const msg1 = message`Expected one of ${
353
+ * valueSet(["error", "warn", "info"], "")
354
+ * }.`;
337
355
  *
338
356
  * // English disjunction: "error", "warn", or "info"
339
357
  * const msg2 = message`Expected ${
340
- * valueSet(["error", "warn", "info"], { type: "disjunction" })
358
+ * valueSet(["error", "warn", "info"], { fallback: "", type: "disjunction" })
341
359
  * }.`;
342
360
  *
343
- * // Korean disjunction: "error", "warn" 또는 "info"
344
- * const msg3 = message`${
345
- * valueSet(["error", "warn", "info"], { locale: "ko", type: "disjunction" })
346
- * } 중 하나여야 합니다.`;
361
+ * // Fallback for empty list:
362
+ * const msg3 = message`Expected one of ${valueSet([], "(none)")}.`;
363
+ * // "Expected one of (none)."
347
364
  * ```
348
365
  *
349
366
  * @param values The list of values to format.
350
- * @param options Optional formatting options including locale and list type.
367
+ * @param fallbackOrOptions A fallback string for empty lists, or an options
368
+ * object including the fallback and formatting
369
+ * options such as locale and list type.
351
370
  * @returns A {@link Message} with alternating value and text terms.
371
+ * @throws {TypeError} If the fallback parameter is missing or invalid.
352
372
  * @since 0.9.0
353
373
  */
354
- declare function valueSet(values: readonly string[], options?: ValueSetOptions): Message;
374
+ declare function valueSet(values: readonly string[], fallbackOrOptions: string | ValueSetOptions): Message;
355
375
  /**
356
376
  * Options for the {@link formatMessage} function.
357
377
  */
package/dist/message.js CHANGED
@@ -142,8 +142,10 @@ function value(value$1) {
142
142
  * string representations of consecutive values.
143
143
  * For example, `["42", "hello"]`.
144
144
  * @returns A {@link MessageTerm} representing the list of values.
145
+ * @throws {TypeError} If the values array is empty.
145
146
  */
146
147
  function values(values$1) {
148
+ if (values$1.length === 0) throw new TypeError("values must not be empty.");
147
149
  return {
148
150
  type: "values",
149
151
  values: [...values$1]
@@ -235,29 +237,44 @@ function link(href) {
235
237
  * to be styled independently while respecting the locale's list formatting
236
238
  * conventions.
237
239
  *
240
+ * A fallback must be provided for when the values array is empty. This can
241
+ * be either a simple string (shorthand) or an options object with a
242
+ * `fallback` field. When the values array is empty, the fallback text
243
+ * is returned as a single text term. An empty fallback string produces
244
+ * an empty {@link Message}.
245
+ *
238
246
  * @example
239
247
  * ```typescript
240
248
  * // English conjunction (default): "error", "warn", and "info"
241
- * const msg1 = message`Expected one of ${valueSet(["error", "warn", "info"])}.`;
249
+ * const msg1 = message`Expected one of ${
250
+ * valueSet(["error", "warn", "info"], "")
251
+ * }.`;
242
252
  *
243
253
  * // English disjunction: "error", "warn", or "info"
244
254
  * const msg2 = message`Expected ${
245
- * valueSet(["error", "warn", "info"], { type: "disjunction" })
255
+ * valueSet(["error", "warn", "info"], { fallback: "", type: "disjunction" })
246
256
  * }.`;
247
257
  *
248
- * // Korean disjunction: "error", "warn" 또는 "info"
249
- * const msg3 = message`${
250
- * valueSet(["error", "warn", "info"], { locale: "ko", type: "disjunction" })
251
- * } 중 하나여야 합니다.`;
258
+ * // Fallback for empty list:
259
+ * const msg3 = message`Expected one of ${valueSet([], "(none)")}.`;
260
+ * // "Expected one of (none)."
252
261
  * ```
253
262
  *
254
263
  * @param values The list of values to format.
255
- * @param options Optional formatting options including locale and list type.
264
+ * @param fallbackOrOptions A fallback string for empty lists, or an options
265
+ * object including the fallback and formatting
266
+ * options such as locale and list type.
256
267
  * @returns A {@link Message} with alternating value and text terms.
268
+ * @throws {TypeError} If the fallback parameter is missing or invalid.
257
269
  * @since 0.9.0
258
270
  */
259
- function valueSet(values$1, options) {
260
- if (values$1.length === 0) return [];
271
+ function valueSet(values$1, fallbackOrOptions) {
272
+ if (fallbackOrOptions == null || typeof fallbackOrOptions !== "string" && typeof fallbackOrOptions.fallback !== "string") throw new TypeError("valueSet() requires a fallback string or an options object with a fallback field.");
273
+ const options = typeof fallbackOrOptions === "string" ? { fallback: fallbackOrOptions } : fallbackOrOptions;
274
+ if (values$1.length === 0) return options.fallback === "" ? [] : [{
275
+ type: "text",
276
+ text: options.fallback
277
+ }];
261
278
  const formatter = new Intl.ListFormat(options?.locale, {
262
279
  type: options?.type,
263
280
  style: options?.style
@@ -543,7 +543,10 @@ function option(...args) {
543
543
  fragments: [],
544
544
  description: options.description
545
545
  };
546
- const choicesMessage = valueParser?.choices != null && valueParser.choices.length > 0 ? require_message.valueSet(valueParser.choices.map((c) => valueParser.format(c)), { type: "unit" }) : void 0;
546
+ const choicesMessage = valueParser?.choices != null && valueParser.choices.length > 0 ? require_message.valueSet(valueParser.choices.map((c) => valueParser.format(c)), {
547
+ fallback: "",
548
+ type: "unit"
549
+ }) : void 0;
547
550
  const fragments = [{
548
551
  type: "entry",
549
552
  term: {
@@ -915,7 +918,10 @@ function argument(valueParser, options = {}) {
915
918
  fragments: [],
916
919
  description: options.description
917
920
  };
918
- const choicesMessage = valueParser.choices != null && valueParser.choices.length > 0 ? require_message.valueSet(valueParser.choices.map((c) => valueParser.format(c)), { type: "unit" }) : void 0;
921
+ const choicesMessage = valueParser.choices != null && valueParser.choices.length > 0 ? require_message.valueSet(valueParser.choices.map((c) => valueParser.format(c)), {
922
+ fallback: "",
923
+ type: "unit"
924
+ }) : void 0;
919
925
  const fragments = [{
920
926
  type: "entry",
921
927
  term,
@@ -543,7 +543,10 @@ function option(...args) {
543
543
  fragments: [],
544
544
  description: options.description
545
545
  };
546
- const choicesMessage = valueParser?.choices != null && valueParser.choices.length > 0 ? valueSet(valueParser.choices.map((c) => valueParser.format(c)), { type: "unit" }) : void 0;
546
+ const choicesMessage = valueParser?.choices != null && valueParser.choices.length > 0 ? valueSet(valueParser.choices.map((c) => valueParser.format(c)), {
547
+ fallback: "",
548
+ type: "unit"
549
+ }) : void 0;
547
550
  const fragments = [{
548
551
  type: "entry",
549
552
  term: {
@@ -915,7 +918,10 @@ function argument(valueParser, options = {}) {
915
918
  fragments: [],
916
919
  description: options.description
917
920
  };
918
- const choicesMessage = valueParser.choices != null && valueParser.choices.length > 0 ? valueSet(valueParser.choices.map((c) => valueParser.format(c)), { type: "unit" }) : void 0;
921
+ const choicesMessage = valueParser.choices != null && valueParser.choices.length > 0 ? valueSet(valueParser.choices.map((c) => valueParser.format(c)), {
922
+ fallback: "",
923
+ type: "unit"
924
+ }) : void 0;
919
925
  const fragments = [{
920
926
  type: "entry",
921
927
  term,
@@ -271,7 +271,10 @@ function formatNumberChoiceError(input, validChoices, allChoices, invalidChoice)
271
271
  function formatDefaultChoiceError(input, choices) {
272
272
  const choiceStrings = choices.filter((c) => typeof c === "string" || !Number.isNaN(c)).map((c) => Object.is(c, -0) ? "-0" : String(c));
273
273
  if (choiceStrings.length === 0 && choices.length > 0) return require_message.message`No valid choices are configured, but got ${input}.`;
274
- return require_message.message`Expected one of ${require_message.valueSet(choiceStrings, { locale: "en-US" })}, but got ${input}.`;
274
+ return require_message.message`Expected one of ${require_message.valueSet(choiceStrings, {
275
+ fallback: "",
276
+ locale: "en-US"
277
+ })}, but got ${input}.`;
275
278
  }
276
279
  /**
277
280
  * Creates a {@link ValueParser} for strings.
@@ -576,7 +579,10 @@ function url(options = {}) {
576
579
  type: "text",
577
580
  text: " is not allowed. Allowed protocols: "
578
581
  },
579
- ...require_message.valueSet(originalProtocols, { locale: "en-US" }),
582
+ ...require_message.valueSet(originalProtocols, {
583
+ fallback: "",
584
+ locale: "en-US"
585
+ }),
580
586
  {
581
587
  type: "text",
582
588
  text: "."
@@ -1534,7 +1540,10 @@ function email(options) {
1534
1540
  type: "text",
1535
1541
  text: " is not allowed. Allowed domains: "
1536
1542
  },
1537
- ...require_message.valueSet(allowedDomains, { locale: "en-US" }),
1543
+ ...require_message.valueSet(allowedDomains, {
1544
+ fallback: "",
1545
+ locale: "en-US"
1546
+ }),
1538
1547
  {
1539
1548
  type: "text",
1540
1549
  text: "."
@@ -1585,7 +1594,10 @@ function email(options) {
1585
1594
  type: "text",
1586
1595
  text: " is not allowed. Allowed domains: "
1587
1596
  },
1588
- ...require_message.valueSet(allowedDomains, { locale: "en-US" }),
1597
+ ...require_message.valueSet(allowedDomains, {
1598
+ fallback: "",
1599
+ locale: "en-US"
1600
+ }),
1589
1601
  {
1590
1602
  type: "text",
1591
1603
  text: "."
@@ -2519,7 +2531,10 @@ function domain(options) {
2519
2531
  type: "text",
2520
2532
  text: " is not allowed. Allowed TLDs: "
2521
2533
  },
2522
- ...require_message.valueSet(allowedTlds, { locale: "en-US" }),
2534
+ ...require_message.valueSet(allowedTlds, {
2535
+ fallback: "",
2536
+ locale: "en-US"
2537
+ }),
2523
2538
  {
2524
2539
  type: "text",
2525
2540
  text: "."
@@ -271,7 +271,10 @@ function formatNumberChoiceError(input, validChoices, allChoices, invalidChoice)
271
271
  function formatDefaultChoiceError(input, choices) {
272
272
  const choiceStrings = choices.filter((c) => typeof c === "string" || !Number.isNaN(c)).map((c) => Object.is(c, -0) ? "-0" : String(c));
273
273
  if (choiceStrings.length === 0 && choices.length > 0) return message`No valid choices are configured, but got ${input}.`;
274
- return message`Expected one of ${valueSet(choiceStrings, { locale: "en-US" })}, but got ${input}.`;
274
+ return message`Expected one of ${valueSet(choiceStrings, {
275
+ fallback: "",
276
+ locale: "en-US"
277
+ })}, but got ${input}.`;
275
278
  }
276
279
  /**
277
280
  * Creates a {@link ValueParser} for strings.
@@ -576,7 +579,10 @@ function url(options = {}) {
576
579
  type: "text",
577
580
  text: " is not allowed. Allowed protocols: "
578
581
  },
579
- ...valueSet(originalProtocols, { locale: "en-US" }),
582
+ ...valueSet(originalProtocols, {
583
+ fallback: "",
584
+ locale: "en-US"
585
+ }),
580
586
  {
581
587
  type: "text",
582
588
  text: "."
@@ -1534,7 +1540,10 @@ function email(options) {
1534
1540
  type: "text",
1535
1541
  text: " is not allowed. Allowed domains: "
1536
1542
  },
1537
- ...valueSet(allowedDomains, { locale: "en-US" }),
1543
+ ...valueSet(allowedDomains, {
1544
+ fallback: "",
1545
+ locale: "en-US"
1546
+ }),
1538
1547
  {
1539
1548
  type: "text",
1540
1549
  text: "."
@@ -1585,7 +1594,10 @@ function email(options) {
1585
1594
  type: "text",
1586
1595
  text: " is not allowed. Allowed domains: "
1587
1596
  },
1588
- ...valueSet(allowedDomains, { locale: "en-US" }),
1597
+ ...valueSet(allowedDomains, {
1598
+ fallback: "",
1599
+ locale: "en-US"
1600
+ }),
1589
1601
  {
1590
1602
  type: "text",
1591
1603
  text: "."
@@ -2519,7 +2531,10 @@ function domain(options) {
2519
2531
  type: "text",
2520
2532
  text: " is not allowed. Allowed TLDs: "
2521
2533
  },
2522
- ...valueSet(allowedTlds, { locale: "en-US" }),
2534
+ ...valueSet(allowedTlds, {
2535
+ fallback: "",
2536
+ locale: "en-US"
2537
+ }),
2523
2538
  {
2524
2539
  type: "text",
2525
2540
  text: "."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.0.0-dev.1565+dd141298",
3
+ "version": "1.0.0-dev.1574+d9b3596d",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",