@optique/clack 1.4.0-dev.2725 → 1.4.0-dev.2728

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/index.cjs CHANGED
@@ -28,6 +28,7 @@ const __optique_prompt = __toESM(require("@optique/prompt"));
28
28
  //#region src/index.ts
29
29
  const promptFunctionsOverrideSymbol = Symbol.for("@optique/clack/prompt-functions");
30
30
  const defaultPromptFunctions = {
31
+ spinner: __clack_prompts.spinner,
31
32
  text: __clack_prompts.text,
32
33
  password: __clack_prompts.password,
33
34
  confirm: __clack_prompts.confirm,
@@ -61,18 +62,60 @@ function getPromptFunctions() {
61
62
  * @param parser Inner parser that reads CLI values.
62
63
  * @param config Type-safe Clack prompt configuration, or a configuration
63
64
  * derived from dependency sources via `derivePromptConfig()`.
64
- * @param options Shared validation, retry, and cancellation options.
65
+ * @param options Shared validation, retry, cancellation, and optional pending
66
+ * indicator options.
65
67
  * @returns A parser with interactive prompt fallback, always in async mode.
66
68
  * @throws {RangeError} If `maxAttempts` is not a positive integer.
69
+ * @throws {DOMException} With name `AbortError` when an OS-delivered SIGINT or
70
+ * SIGTERM cancels the pending spinner. Interactive
71
+ * Ctrl+C follows Clack's process-exit behavior.
67
72
  * @throws {Error} If prompt execution fails with an unexpected error or if the
68
73
  * inner parser throws while parsing or completing.
69
74
  * @since 1.2.0
70
75
  * @since 1.3.0 Added shared options and the prompter context.
76
+ * @since 1.4.0 Added the optional pending indicator.
71
77
  */
72
78
  function prompt(parser, config, options) {
79
+ const pendingMessage = options?.pendingMessage;
73
80
  const promptWithAdapter = (0, __optique_prompt.createPromptAdapter)({
74
81
  execute: executePromptRaw,
75
- getDefaultValue: getConfigDefault
82
+ getDefaultValue: getConfigDefault,
83
+ ...pendingMessage == null ? {} : { async whilePending(work, { signal }) {
84
+ if (signal?.aborted) return work();
85
+ let finished = false;
86
+ let rejectCancellation;
87
+ const cancelled = new Promise((_resolve, reject) => {
88
+ rejectCancellation = reject;
89
+ });
90
+ const indicator = getPromptFunctions().spinner({
91
+ cancelMessage: pendingMessage,
92
+ onCancel() {
93
+ if (finished) return;
94
+ finished = true;
95
+ signal?.removeEventListener("abort", onAbort);
96
+ rejectCancellation(new DOMException("Prompt cancelled.", "AbortError"));
97
+ }
98
+ });
99
+ const finish = (outcome) => {
100
+ if (finished) return;
101
+ finished = true;
102
+ signal?.removeEventListener("abort", onAbort);
103
+ indicator[outcome](pendingMessage);
104
+ };
105
+ const onAbort = () => finish("cancel");
106
+ try {
107
+ indicator.start(pendingMessage);
108
+ signal?.addEventListener("abort", onAbort, { once: true });
109
+ const result = await Promise.race([work(), cancelled]);
110
+ finish("stop");
111
+ return result;
112
+ } catch (error) {
113
+ finish(signal?.aborted ? "cancel" : "error");
114
+ throw error;
115
+ } finally {
116
+ signal?.removeEventListener("abort", onAbort);
117
+ }
118
+ } }
76
119
  });
77
120
  return promptWithAdapter(parser, config, options);
78
121
  }
package/dist/index.d.cts CHANGED
@@ -176,20 +176,41 @@ type BasePromptConfig<T> = T extends boolean ? ConfirmConfig : T extends number
176
176
  * @since 1.3.0
177
177
  */
178
178
  type RuntimePromptConfig = ConfirmConfig | NumberPromptConfig | StringPromptConfig | MultiselectConfig;
179
+ /**
180
+ * Shared prompt options and Clack's derived configuration pending indicator.
181
+ *
182
+ * @typeParam TValue Value produced by the wrapped parser.
183
+ * @since 1.4.0
184
+ */
185
+ interface ClackPromptOptions<TValue> extends PromptOptions$1<TValue> {
186
+ /**
187
+ * Shows a spinner with this message while a derived configuration resolves.
188
+ * Omit it for silent resolution. An empty string also enables the spinner.
189
+ * Static configurations ignore this option. Explicit opt-in also shows the
190
+ * indicator when the resolved configuration has a custom `prompter`.
191
+ * The final line keeps this message with a success, error, or cancel symbol.
192
+ */
193
+ readonly pendingMessage?: string;
194
+ }
179
195
  /**
180
196
  * Wraps a parser with an interactive Clack prompt fallback.
181
197
  *
182
198
  * @param parser Inner parser that reads CLI values.
183
199
  * @param config Type-safe Clack prompt configuration, or a configuration
184
200
  * derived from dependency sources via `derivePromptConfig()`.
185
- * @param options Shared validation, retry, and cancellation options.
201
+ * @param options Shared validation, retry, cancellation, and optional pending
202
+ * indicator options.
186
203
  * @returns A parser with interactive prompt fallback, always in async mode.
187
204
  * @throws {RangeError} If `maxAttempts` is not a positive integer.
205
+ * @throws {DOMException} With name `AbortError` when an OS-delivered SIGINT or
206
+ * SIGTERM cancels the pending spinner. Interactive
207
+ * Ctrl+C follows Clack's process-exit behavior.
188
208
  * @throws {Error} If prompt execution fails with an unexpected error or if the
189
209
  * inner parser throws while parsing or completing.
190
210
  * @since 1.2.0
191
211
  * @since 1.3.0 Added shared options and the prompter context.
212
+ * @since 1.4.0 Added the optional pending indicator.
192
213
  */
193
- declare function prompt<M extends Mode, TValue, TState>(parser: Parser<M, TValue, TState>, config: PromptConfig<TValue> | DerivedPromptConfig$1<RuntimePromptConfig, NoInfer<TValue>>, options?: PromptOptions$1<NoInfer<TValue>>): FluentParser<"async", TValue, TState>;
214
+ declare function prompt<M extends Mode, TValue, TState>(parser: Parser<M, TValue, TState>, config: PromptConfig<TValue> | DerivedPromptConfig$1<RuntimePromptConfig, NoInfer<TValue>>, options?: ClackPromptOptions<NoInfer<TValue>>): FluentParser<"async", TValue, TState>;
194
215
  //#endregion
195
- export { ConfirmConfig, type DerivePromptConfigContext, type DerivePromptConfigNoDepsContext, type DerivePromptConfigNoDepsOptions, type DerivePromptConfigOptions, type DerivePromptConfigsContext, type DerivePromptConfigsOptions, type DerivedPromptConfig, MultiselectConfig, NumberPromptConfig, Option, PasswordConfig, PromptConfig, type PromptExecutionContext, type PromptOptions, type PromptValidator, RuntimePromptConfig, SelectConfig, StringPromptConfig, TextConfig, derivePromptConfig, isDerivedPromptConfig, prompt };
216
+ export { ClackPromptOptions, ConfirmConfig, type DerivePromptConfigContext, type DerivePromptConfigNoDepsContext, type DerivePromptConfigNoDepsOptions, type DerivePromptConfigOptions, type DerivePromptConfigsContext, type DerivePromptConfigsOptions, type DerivedPromptConfig, MultiselectConfig, NumberPromptConfig, Option, PasswordConfig, PromptConfig, type PromptExecutionContext, type PromptOptions, type PromptValidator, RuntimePromptConfig, SelectConfig, StringPromptConfig, TextConfig, derivePromptConfig, isDerivedPromptConfig, prompt };
package/dist/index.d.ts CHANGED
@@ -176,20 +176,41 @@ type BasePromptConfig<T> = T extends boolean ? ConfirmConfig : T extends number
176
176
  * @since 1.3.0
177
177
  */
178
178
  type RuntimePromptConfig = ConfirmConfig | NumberPromptConfig | StringPromptConfig | MultiselectConfig;
179
+ /**
180
+ * Shared prompt options and Clack's derived configuration pending indicator.
181
+ *
182
+ * @typeParam TValue Value produced by the wrapped parser.
183
+ * @since 1.4.0
184
+ */
185
+ interface ClackPromptOptions<TValue> extends PromptOptions$1<TValue> {
186
+ /**
187
+ * Shows a spinner with this message while a derived configuration resolves.
188
+ * Omit it for silent resolution. An empty string also enables the spinner.
189
+ * Static configurations ignore this option. Explicit opt-in also shows the
190
+ * indicator when the resolved configuration has a custom `prompter`.
191
+ * The final line keeps this message with a success, error, or cancel symbol.
192
+ */
193
+ readonly pendingMessage?: string;
194
+ }
179
195
  /**
180
196
  * Wraps a parser with an interactive Clack prompt fallback.
181
197
  *
182
198
  * @param parser Inner parser that reads CLI values.
183
199
  * @param config Type-safe Clack prompt configuration, or a configuration
184
200
  * derived from dependency sources via `derivePromptConfig()`.
185
- * @param options Shared validation, retry, and cancellation options.
201
+ * @param options Shared validation, retry, cancellation, and optional pending
202
+ * indicator options.
186
203
  * @returns A parser with interactive prompt fallback, always in async mode.
187
204
  * @throws {RangeError} If `maxAttempts` is not a positive integer.
205
+ * @throws {DOMException} With name `AbortError` when an OS-delivered SIGINT or
206
+ * SIGTERM cancels the pending spinner. Interactive
207
+ * Ctrl+C follows Clack's process-exit behavior.
188
208
  * @throws {Error} If prompt execution fails with an unexpected error or if the
189
209
  * inner parser throws while parsing or completing.
190
210
  * @since 1.2.0
191
211
  * @since 1.3.0 Added shared options and the prompter context.
212
+ * @since 1.4.0 Added the optional pending indicator.
192
213
  */
193
- declare function prompt<M extends Mode, TValue, TState>(parser: Parser<M, TValue, TState>, config: PromptConfig<TValue> | DerivedPromptConfig$1<RuntimePromptConfig, NoInfer<TValue>>, options?: PromptOptions$1<NoInfer<TValue>>): FluentParser<"async", TValue, TState>;
214
+ declare function prompt<M extends Mode, TValue, TState>(parser: Parser<M, TValue, TState>, config: PromptConfig<TValue> | DerivedPromptConfig$1<RuntimePromptConfig, NoInfer<TValue>>, options?: ClackPromptOptions<NoInfer<TValue>>): FluentParser<"async", TValue, TState>;
194
215
  //#endregion
195
- export { ConfirmConfig, type DerivePromptConfigContext, type DerivePromptConfigNoDepsContext, type DerivePromptConfigNoDepsOptions, type DerivePromptConfigOptions, type DerivePromptConfigsContext, type DerivePromptConfigsOptions, type DerivedPromptConfig, MultiselectConfig, NumberPromptConfig, Option, PasswordConfig, PromptConfig, type PromptExecutionContext, type PromptOptions, type PromptValidator, RuntimePromptConfig, SelectConfig, StringPromptConfig, TextConfig, derivePromptConfig, isDerivedPromptConfig, prompt };
216
+ export { ClackPromptOptions, ConfirmConfig, type DerivePromptConfigContext, type DerivePromptConfigNoDepsContext, type DerivePromptConfigNoDepsOptions, type DerivePromptConfigOptions, type DerivePromptConfigsContext, type DerivePromptConfigsOptions, type DerivedPromptConfig, MultiselectConfig, NumberPromptConfig, Option, PasswordConfig, PromptConfig, type PromptExecutionContext, type PromptOptions, type PromptValidator, RuntimePromptConfig, SelectConfig, StringPromptConfig, TextConfig, derivePromptConfig, isDerivedPromptConfig, prompt };
package/dist/index.js CHANGED
@@ -1,10 +1,11 @@
1
- import { confirm, isCancel, log, multiselect, password, select, text } from "@clack/prompts";
1
+ import { confirm, isCancel, log, multiselect, password, select, spinner, text } from "@clack/prompts";
2
2
  import { formatMessage, message } from "@optique/core/message";
3
3
  import { createPromptAdapter, derivePromptConfig, isDerivedPromptConfig } from "@optique/prompt";
4
4
 
5
5
  //#region src/index.ts
6
6
  const promptFunctionsOverrideSymbol = Symbol.for("@optique/clack/prompt-functions");
7
7
  const defaultPromptFunctions = {
8
+ spinner,
8
9
  text,
9
10
  password,
10
11
  confirm,
@@ -38,18 +39,60 @@ function getPromptFunctions() {
38
39
  * @param parser Inner parser that reads CLI values.
39
40
  * @param config Type-safe Clack prompt configuration, or a configuration
40
41
  * derived from dependency sources via `derivePromptConfig()`.
41
- * @param options Shared validation, retry, and cancellation options.
42
+ * @param options Shared validation, retry, cancellation, and optional pending
43
+ * indicator options.
42
44
  * @returns A parser with interactive prompt fallback, always in async mode.
43
45
  * @throws {RangeError} If `maxAttempts` is not a positive integer.
46
+ * @throws {DOMException} With name `AbortError` when an OS-delivered SIGINT or
47
+ * SIGTERM cancels the pending spinner. Interactive
48
+ * Ctrl+C follows Clack's process-exit behavior.
44
49
  * @throws {Error} If prompt execution fails with an unexpected error or if the
45
50
  * inner parser throws while parsing or completing.
46
51
  * @since 1.2.0
47
52
  * @since 1.3.0 Added shared options and the prompter context.
53
+ * @since 1.4.0 Added the optional pending indicator.
48
54
  */
49
55
  function prompt(parser, config, options) {
56
+ const pendingMessage = options?.pendingMessage;
50
57
  const promptWithAdapter = createPromptAdapter({
51
58
  execute: executePromptRaw,
52
- getDefaultValue: getConfigDefault
59
+ getDefaultValue: getConfigDefault,
60
+ ...pendingMessage == null ? {} : { async whilePending(work, { signal }) {
61
+ if (signal?.aborted) return work();
62
+ let finished = false;
63
+ let rejectCancellation;
64
+ const cancelled = new Promise((_resolve, reject) => {
65
+ rejectCancellation = reject;
66
+ });
67
+ const indicator = getPromptFunctions().spinner({
68
+ cancelMessage: pendingMessage,
69
+ onCancel() {
70
+ if (finished) return;
71
+ finished = true;
72
+ signal?.removeEventListener("abort", onAbort);
73
+ rejectCancellation(new DOMException("Prompt cancelled.", "AbortError"));
74
+ }
75
+ });
76
+ const finish = (outcome) => {
77
+ if (finished) return;
78
+ finished = true;
79
+ signal?.removeEventListener("abort", onAbort);
80
+ indicator[outcome](pendingMessage);
81
+ };
82
+ const onAbort = () => finish("cancel");
83
+ try {
84
+ indicator.start(pendingMessage);
85
+ signal?.addEventListener("abort", onAbort, { once: true });
86
+ const result = await Promise.race([work(), cancelled]);
87
+ finish("stop");
88
+ return result;
89
+ } catch (error) {
90
+ finish(signal?.aborted ? "cancel" : "error");
91
+ throw error;
92
+ } finally {
93
+ signal?.removeEventListener("abort", onAbort);
94
+ }
95
+ } }
53
96
  });
54
97
  return promptWithAdapter(parser, config, options);
55
98
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/clack",
3
- "version": "1.4.0-dev.2725",
3
+ "version": "1.4.0-dev.2728",
4
4
  "description": "Interactive prompt support for Optique via Clack",
5
5
  "keywords": [
6
6
  "CLI",
@@ -62,12 +62,12 @@
62
62
  "sideEffects": false,
63
63
  "dependencies": {
64
64
  "@clack/prompts": "^1.6.0",
65
- "@optique/core": "1.4.0-dev.2725+a2d21dc2",
66
- "@optique/prompt": "1.4.0-dev.2725+a2d21dc2"
65
+ "@optique/core": "1.4.0-dev.2728+5829a43f",
66
+ "@optique/prompt": "1.4.0-dev.2728+5829a43f"
67
67
  },
68
68
  "devDependencies": {
69
- "@optique/env": "1.4.0-dev.2725+a2d21dc2",
70
- "@optique/run": "1.4.0-dev.2725+a2d21dc2",
69
+ "@optique/env": "1.4.0-dev.2728+5829a43f",
70
+ "@optique/run": "1.4.0-dev.2728+5829a43f",
71
71
  "@types/node": "^24.0.0",
72
72
  "fast-check": "^4.7.0",
73
73
  "tsdown": "^0.13.0",
@@ -78,7 +78,7 @@
78
78
  "prepublish": "tsdown",
79
79
  "test": "node --test",
80
80
  "test:bun": "bun test",
81
- "test:deno": "deno test --allow-env",
82
- "test-all": "tsdown && node --test && bun test && deno test --allow-env"
81
+ "test:deno": "deno test --allow-env --allow-run",
82
+ "test-all": "tsdown && node --test && bun test && deno test --allow-env --allow-run"
83
83
  }
84
84
  }