@optique/inquirer 1.0.0-dev.0 → 1.0.0-dev.1109
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/README.md +81 -0
- package/dist/index.cjs +299 -98
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +300 -99
- package/package.json +4 -3
package/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
@optique/inquirer
|
|
2
|
+
=================
|
|
3
|
+
|
|
4
|
+
Interactive prompt support for [Optique] via [Inquirer.js].
|
|
5
|
+
|
|
6
|
+
This package wraps any Optique parser with an interactive prompt that fires
|
|
7
|
+
when no CLI value is provided. The fallback priority is:
|
|
8
|
+
|
|
9
|
+
CLI arguments > interactive prompt.
|
|
10
|
+
|
|
11
|
+
Because interactive prompts are inherently asynchronous, the returned parser
|
|
12
|
+
always has `$mode: "async"`.
|
|
13
|
+
|
|
14
|
+
[Optique]: https://optique.dev/
|
|
15
|
+
[Inquirer.js]: https://github.com/SBoudrias/Inquirer.js
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
Installation
|
|
19
|
+
------------
|
|
20
|
+
|
|
21
|
+
~~~~ bash
|
|
22
|
+
deno add jsr:@optique/inquirer
|
|
23
|
+
npm add @optique/inquirer
|
|
24
|
+
pnpm add @optique/inquirer
|
|
25
|
+
yarn add @optique/inquirer
|
|
26
|
+
bun add @optique/inquirer
|
|
27
|
+
~~~~
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
Quick start
|
|
31
|
+
-----------
|
|
32
|
+
|
|
33
|
+
~~~~ typescript
|
|
34
|
+
import { object } from "@optique/core/constructs";
|
|
35
|
+
import { option } from "@optique/core/primitives";
|
|
36
|
+
import { integer, string } from "@optique/core/valueparser";
|
|
37
|
+
import { prompt } from "@optique/inquirer";
|
|
38
|
+
import { run } from "@optique/run";
|
|
39
|
+
|
|
40
|
+
const parser = object({
|
|
41
|
+
name: prompt(option("--name", string()), {
|
|
42
|
+
type: "input",
|
|
43
|
+
message: "Enter your name:",
|
|
44
|
+
}),
|
|
45
|
+
port: prompt(option("--port", integer()), {
|
|
46
|
+
type: "number",
|
|
47
|
+
message: "Enter the port number:",
|
|
48
|
+
default: 3000,
|
|
49
|
+
}),
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
await run(parser);
|
|
53
|
+
~~~~
|
|
54
|
+
|
|
55
|
+
When `--name` and `--port` are provided on the command line, the prompts are
|
|
56
|
+
skipped. When they are absent, the user sees interactive prompts.
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
Features
|
|
60
|
+
--------
|
|
61
|
+
|
|
62
|
+
- *Ten prompt types*: `input`, `password`, `number`, `confirm`, `select`,
|
|
63
|
+
`rawlist`, `expand`, `checkbox`, `editor`, and a custom `prompter` for
|
|
64
|
+
testing
|
|
65
|
+
- *Transparent composition* with `bindEnv()` and `bindConfig()` — the
|
|
66
|
+
prompt fires only when no higher-priority source supplies a value
|
|
67
|
+
- *Prompt-only values* via `prompt(fail<T>(), …)` when a value should not
|
|
68
|
+
be exposed as a CLI option
|
|
69
|
+
- *TTY-free testing* via the `prompter` escape hatch on every config type
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
Documentation
|
|
73
|
+
-------------
|
|
74
|
+
|
|
75
|
+
For full documentation, visit <https://optique.dev/integrations/inquirer>.
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
License
|
|
79
|
+
-------
|
|
80
|
+
|
|
81
|
+
MIT License. See [LICENSE](../../LICENSE) for details.
|
package/dist/index.cjs
CHANGED
|
@@ -23,9 +23,87 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
23
|
//#endregion
|
|
24
24
|
const __inquirer_prompts = __toESM(require("@inquirer/prompts"));
|
|
25
25
|
const __optique_core_annotations = __toESM(require("@optique/core/annotations"));
|
|
26
|
+
const __optique_core_context = __toESM(require("@optique/core/context"));
|
|
26
27
|
const __optique_core_message = __toESM(require("@optique/core/message"));
|
|
27
28
|
|
|
28
29
|
//#region src/index.ts
|
|
30
|
+
const promptFunctionsOverrideSymbol = Symbol.for("@optique/inquirer/prompt-functions");
|
|
31
|
+
const defaultPromptFunctions = {
|
|
32
|
+
confirm: __inquirer_prompts.confirm,
|
|
33
|
+
number: __inquirer_prompts.number,
|
|
34
|
+
input: __inquirer_prompts.input,
|
|
35
|
+
password: __inquirer_prompts.password,
|
|
36
|
+
editor: __inquirer_prompts.editor,
|
|
37
|
+
select: __inquirer_prompts.select,
|
|
38
|
+
rawlist: __inquirer_prompts.rawlist,
|
|
39
|
+
expand: __inquirer_prompts.expand,
|
|
40
|
+
checkbox: __inquirer_prompts.checkbox
|
|
41
|
+
};
|
|
42
|
+
function promptFunctionKeys() {
|
|
43
|
+
return Object.keys(defaultPromptFunctions);
|
|
44
|
+
}
|
|
45
|
+
function assignPromptFunctionOverride(override, key, candidate) {
|
|
46
|
+
if (typeof candidate === "function") override[key] = candidate;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Extracts valid prompt function overrides from an arbitrary value.
|
|
50
|
+
*/
|
|
51
|
+
function getPromptFunctionsOverride(value) {
|
|
52
|
+
if (typeof value !== "object" || value == null) return void 0;
|
|
53
|
+
const override = {};
|
|
54
|
+
for (const key of promptFunctionKeys()) assignPromptFunctionOverride(override, key, Reflect.get(value, key));
|
|
55
|
+
return override;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Returns the active prompt function set, applying any global test overrides.
|
|
59
|
+
*/
|
|
60
|
+
function getPromptFunctions() {
|
|
61
|
+
const override = getPromptFunctionsOverride(Reflect.get(globalThis, promptFunctionsOverrideSymbol));
|
|
62
|
+
return override != null ? {
|
|
63
|
+
...defaultPromptFunctions,
|
|
64
|
+
...override
|
|
65
|
+
} : defaultPromptFunctions;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Determines whether an error came from an interrupted Inquirer prompt.
|
|
69
|
+
*/
|
|
70
|
+
function isExitPromptError(error) {
|
|
71
|
+
return typeof error === "object" && error != null && "name" in error && error.name === "ExitPromptError";
|
|
72
|
+
}
|
|
73
|
+
const inheritParentAnnotationsKey = Symbol.for("@optique/core/inheritParentAnnotations");
|
|
74
|
+
var DeferredPromptValue = class {
|
|
75
|
+
[__optique_core_context.placeholder] = true;
|
|
76
|
+
constructor() {}
|
|
77
|
+
};
|
|
78
|
+
function shouldDeferPrompt(parser, state) {
|
|
79
|
+
return typeof parser.shouldDeferCompletion === "function" && parser.shouldDeferCompletion(state) === true;
|
|
80
|
+
}
|
|
81
|
+
function deferredPromptResult() {
|
|
82
|
+
return {
|
|
83
|
+
success: true,
|
|
84
|
+
value: new DeferredPromptValue()
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function withAnnotationView(state, annotations, run) {
|
|
88
|
+
const annotatedState = new Proxy(state, {
|
|
89
|
+
get(target, key) {
|
|
90
|
+
if (key === __optique_core_annotations.annotationKey) return annotations;
|
|
91
|
+
const value = Reflect.get(target, key, target);
|
|
92
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
93
|
+
},
|
|
94
|
+
has(target, key) {
|
|
95
|
+
return key === __optique_core_annotations.annotationKey || Reflect.has(target, key);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
return run(annotatedState);
|
|
99
|
+
}
|
|
100
|
+
function withAnnotatedInnerState(sourceState, innerState, run) {
|
|
101
|
+
const annotations = (0, __optique_core_annotations.getAnnotations)(sourceState);
|
|
102
|
+
if (annotations == null || innerState == null || typeof innerState !== "object" || typeof innerState === "object" && __optique_core_annotations.annotationKey in innerState) return run(innerState);
|
|
103
|
+
const inheritedState = (0, __optique_core_annotations.inheritAnnotations)(sourceState, innerState);
|
|
104
|
+
if (inheritedState !== innerState) return run(inheritedState);
|
|
105
|
+
return withAnnotationView(innerState, annotations, (annotatedState) => run(annotatedState));
|
|
106
|
+
}
|
|
29
107
|
/**
|
|
30
108
|
* Wraps a parser with an interactive Inquirer.js prompt fallback.
|
|
31
109
|
*
|
|
@@ -52,6 +130,8 @@ const __optique_core_message = __toESM(require("@optique/core/message"));
|
|
|
52
130
|
* @param parser Inner parser that reads CLI values.
|
|
53
131
|
* @param config Type-safe Inquirer.js prompt configuration.
|
|
54
132
|
* @returns A parser with interactive prompt fallback, always in async mode.
|
|
133
|
+
* @throws {Error} If prompt execution fails with an unexpected error or if
|
|
134
|
+
* the inner parser throws while parsing or completing.
|
|
55
135
|
* @since 1.0.0
|
|
56
136
|
*/
|
|
57
137
|
function prompt(parser, config) {
|
|
@@ -64,116 +144,170 @@ function prompt(parser, config) {
|
|
|
64
144
|
[promptBindStateKey] = true;
|
|
65
145
|
hasCliValue = false;
|
|
66
146
|
};
|
|
67
|
-
const promptBindInitialState = new PromptBindInitialStateClass();
|
|
68
147
|
let promptCache = null;
|
|
69
|
-
|
|
70
|
-
if (
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
148
|
+
function shouldAttemptInnerCompletion(cliState, state) {
|
|
149
|
+
if (cliState == null || cliState instanceof PromptBindInitialStateClass) return false;
|
|
150
|
+
const cliStateHasAnnotations = typeof cliState === "object" && __optique_core_annotations.annotationKey in cliState;
|
|
151
|
+
if (cliStateHasAnnotations) return true;
|
|
152
|
+
if ((0, __optique_core_annotations.getAnnotations)(state) == null || typeof cliState !== "object") return false;
|
|
153
|
+
if ("hasCliValue" in cliState) return true;
|
|
154
|
+
if (Array.isArray(cliState)) return typeof parser.shouldDeferCompletion === "function";
|
|
155
|
+
const prototype = Object.getPrototypeOf(cliState);
|
|
156
|
+
return prototype !== Object.prototype && prototype !== null;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Executes the configured prompt and normalizes its result.
|
|
160
|
+
*
|
|
161
|
+
* Converts `ExitPromptError` into a parse failure and returns prompt values
|
|
162
|
+
* in Optique's `ValueParserResult` shape.
|
|
163
|
+
*
|
|
164
|
+
* @returns The normalized prompt result.
|
|
165
|
+
* @throws {Error} Rethrows unexpected prompt failures after converting
|
|
166
|
+
* `ExitPromptError` cancellations into parse failures.
|
|
167
|
+
*/
|
|
168
|
+
function validatePromptedValue(result) {
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
const validPromptTypes = new Set([
|
|
172
|
+
"confirm",
|
|
173
|
+
"number",
|
|
174
|
+
"input",
|
|
175
|
+
"password",
|
|
176
|
+
"editor",
|
|
177
|
+
"select",
|
|
178
|
+
"rawlist",
|
|
179
|
+
"expand",
|
|
180
|
+
"checkbox"
|
|
181
|
+
]);
|
|
182
|
+
async function executePromptRaw() {
|
|
183
|
+
const prompts = getPromptFunctions();
|
|
184
|
+
try {
|
|
185
|
+
if (!validPromptTypes.has(cfg.type)) throw new TypeError(`Unsupported prompt type: ${cfg.type}`);
|
|
186
|
+
if ("prompter" in cfg && cfg.prompter != null) {
|
|
187
|
+
const value = await cfg.prompter();
|
|
188
|
+
if (cfg.type === "number" && value === void 0) return {
|
|
98
189
|
success: false,
|
|
99
190
|
error: __optique_core_message.message`No number provided.`
|
|
100
191
|
};
|
|
101
192
|
return {
|
|
102
193
|
success: true,
|
|
103
|
-
value
|
|
194
|
+
value
|
|
104
195
|
};
|
|
105
196
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
197
|
+
switch (cfg.type) {
|
|
198
|
+
case "confirm": return {
|
|
199
|
+
success: true,
|
|
200
|
+
value: await prompts.confirm({
|
|
201
|
+
message: cfg.message,
|
|
202
|
+
...cfg.default !== void 0 ? { default: cfg.default } : {}
|
|
203
|
+
})
|
|
204
|
+
};
|
|
205
|
+
case "number": {
|
|
206
|
+
const numResult = await prompts.number({
|
|
207
|
+
message: cfg.message,
|
|
208
|
+
...cfg.default !== void 0 ? { default: cfg.default } : {},
|
|
209
|
+
...cfg.min !== void 0 ? { min: cfg.min } : {},
|
|
210
|
+
...cfg.max !== void 0 ? { max: cfg.max } : {},
|
|
211
|
+
...cfg.step !== void 0 ? { step: cfg.step } : {}
|
|
212
|
+
});
|
|
213
|
+
if (numResult === void 0) return {
|
|
214
|
+
success: false,
|
|
215
|
+
error: __optique_core_message.message`No number provided.`
|
|
216
|
+
};
|
|
217
|
+
return {
|
|
218
|
+
success: true,
|
|
219
|
+
value: numResult
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
case "input": return {
|
|
223
|
+
success: true,
|
|
224
|
+
value: await prompts.input({
|
|
225
|
+
message: cfg.message,
|
|
226
|
+
...cfg.default !== void 0 ? { default: cfg.default } : {},
|
|
227
|
+
...cfg.validate !== void 0 ? { validate: cfg.validate } : {}
|
|
228
|
+
})
|
|
229
|
+
};
|
|
230
|
+
case "password": return {
|
|
231
|
+
success: true,
|
|
232
|
+
value: await prompts.password({
|
|
233
|
+
message: cfg.message,
|
|
234
|
+
...cfg.mask !== void 0 ? { mask: cfg.mask } : {},
|
|
235
|
+
...cfg.validate !== void 0 ? { validate: cfg.validate } : {}
|
|
236
|
+
})
|
|
237
|
+
};
|
|
238
|
+
case "editor": return {
|
|
239
|
+
success: true,
|
|
240
|
+
value: await prompts.editor({
|
|
241
|
+
message: cfg.message,
|
|
242
|
+
...cfg.default !== void 0 ? { default: cfg.default } : {},
|
|
243
|
+
...cfg.validate !== void 0 ? { validate: cfg.validate } : {}
|
|
244
|
+
})
|
|
245
|
+
};
|
|
246
|
+
case "select": return {
|
|
247
|
+
success: true,
|
|
248
|
+
value: await prompts.select({
|
|
249
|
+
message: cfg.message,
|
|
250
|
+
choices: normalizeChoices(cfg.choices),
|
|
251
|
+
...cfg.default !== void 0 ? { default: cfg.default } : {}
|
|
252
|
+
})
|
|
253
|
+
};
|
|
254
|
+
case "rawlist": return {
|
|
255
|
+
success: true,
|
|
256
|
+
value: await prompts.rawlist({
|
|
257
|
+
message: cfg.message,
|
|
258
|
+
choices: normalizeChoices(cfg.choices),
|
|
259
|
+
...cfg.default !== void 0 ? { default: cfg.default } : {}
|
|
260
|
+
})
|
|
261
|
+
};
|
|
262
|
+
case "expand": return {
|
|
263
|
+
success: true,
|
|
264
|
+
value: await prompts.expand({
|
|
265
|
+
message: cfg.message,
|
|
266
|
+
choices: cfg.choices,
|
|
267
|
+
...cfg.default !== void 0 ? { default: cfg.default } : {}
|
|
268
|
+
})
|
|
269
|
+
};
|
|
270
|
+
case "checkbox": return {
|
|
271
|
+
success: true,
|
|
272
|
+
value: await prompts.checkbox({
|
|
273
|
+
message: cfg.message,
|
|
274
|
+
choices: normalizeChoices(cfg.choices)
|
|
275
|
+
})
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
} catch (error) {
|
|
279
|
+
if (isExitPromptError(error)) return {
|
|
280
|
+
success: false,
|
|
281
|
+
error: __optique_core_message.message`Prompt cancelled.`
|
|
160
282
|
};
|
|
283
|
+
throw error;
|
|
161
284
|
}
|
|
162
285
|
}
|
|
163
|
-
|
|
286
|
+
async function executePrompt() {
|
|
287
|
+
const result = await executePromptRaw();
|
|
288
|
+
return validatePromptedValue(result);
|
|
289
|
+
}
|
|
290
|
+
function usePromptOrDefer(state, result) {
|
|
291
|
+
if (result.success) return Promise.resolve(result);
|
|
292
|
+
return shouldDeferPrompt(parser, state) ? Promise.resolve(deferredPromptResult()) : executePrompt();
|
|
293
|
+
}
|
|
294
|
+
const promptedParser = {
|
|
164
295
|
$mode: "async",
|
|
165
296
|
$valueType: parser.$valueType,
|
|
166
297
|
$stateType: parser.$stateType,
|
|
167
298
|
priority: parser.priority,
|
|
168
|
-
|
|
299
|
+
[inheritParentAnnotationsKey]: true,
|
|
300
|
+
usage: parser.usage.length === 1 && parser.usage[0].type === "optional" ? parser.usage : [{
|
|
169
301
|
type: "optional",
|
|
170
302
|
terms: parser.usage
|
|
171
303
|
}],
|
|
172
|
-
initialState
|
|
304
|
+
get initialState() {
|
|
305
|
+
return new PromptBindInitialStateClass();
|
|
306
|
+
},
|
|
173
307
|
parse: (context) => {
|
|
174
308
|
const annotations = (0, __optique_core_annotations.getAnnotations)(context.state);
|
|
175
309
|
const innerState = isPromptBindState(context.state) ? context.state.hasCliValue ? context.state.cliState : parser.initialState : context.state;
|
|
176
|
-
const
|
|
310
|
+
const baseInnerContext = innerState !== context.state ? {
|
|
177
311
|
...context,
|
|
178
312
|
state: innerState
|
|
179
313
|
} : context;
|
|
@@ -204,32 +338,98 @@ function prompt(parser, config) {
|
|
|
204
338
|
return {
|
|
205
339
|
success: true,
|
|
206
340
|
next: {
|
|
207
|
-
...
|
|
341
|
+
...baseInnerContext,
|
|
208
342
|
state: nextState
|
|
209
343
|
},
|
|
210
344
|
consumed: []
|
|
211
345
|
};
|
|
212
346
|
};
|
|
213
|
-
const result =
|
|
347
|
+
const result = withAnnotatedInnerState(context.state, innerState, (annotatedInnerState) => {
|
|
348
|
+
const innerContext = annotatedInnerState !== context.state ? {
|
|
349
|
+
...context,
|
|
350
|
+
state: annotatedInnerState
|
|
351
|
+
} : context;
|
|
352
|
+
return parser.parse(innerContext);
|
|
353
|
+
});
|
|
214
354
|
if (result instanceof Promise) return result.then(processResult);
|
|
215
355
|
return Promise.resolve(processResult(result));
|
|
216
356
|
},
|
|
217
357
|
complete: (state) => {
|
|
218
358
|
if (isPromptBindState(state) && state.hasCliValue) {
|
|
219
|
-
const r =
|
|
359
|
+
const r = withAnnotatedInnerState(state, state.cliState, (annotatedInnerState) => parser.complete(annotatedInnerState));
|
|
220
360
|
if (r instanceof Promise) return r;
|
|
221
361
|
return Promise.resolve(r);
|
|
222
362
|
}
|
|
223
|
-
if (state
|
|
224
|
-
if (promptCache
|
|
225
|
-
const cached = promptCache;
|
|
363
|
+
if (state instanceof PromptBindInitialStateClass) {
|
|
364
|
+
if (promptCache?.state === state) {
|
|
365
|
+
const cached = promptCache.result;
|
|
226
366
|
promptCache = null;
|
|
227
367
|
return cached;
|
|
228
368
|
}
|
|
229
|
-
|
|
230
|
-
|
|
369
|
+
const hasDeferHook = typeof parser.shouldDeferCompletion === "function";
|
|
370
|
+
const annotations = (0, __optique_core_annotations.getAnnotations)(state);
|
|
371
|
+
const innerInitialState = parser.initialState;
|
|
372
|
+
const effectiveInitialState = annotations != null && innerInitialState == null ? (0, __optique_core_annotations.injectAnnotations)(innerInitialState, annotations) : innerInitialState;
|
|
373
|
+
if (hasDeferHook) {
|
|
374
|
+
const annotatedR = withAnnotatedInnerState(state, effectiveInitialState, (annotatedInnerState) => parser.complete(annotatedInnerState));
|
|
375
|
+
const usePromptOrDeferSentinel = (res) => {
|
|
376
|
+
if (res.success && res.value === void 0) return usePromptOrDefer(state, {
|
|
377
|
+
success: false,
|
|
378
|
+
error: []
|
|
379
|
+
});
|
|
380
|
+
return usePromptOrDefer(state, res);
|
|
381
|
+
};
|
|
382
|
+
const cachedResult$1 = annotatedR instanceof Promise ? annotatedR.then(usePromptOrDeferSentinel) : usePromptOrDeferSentinel(annotatedR);
|
|
383
|
+
promptCache = {
|
|
384
|
+
state,
|
|
385
|
+
result: cachedResult$1
|
|
386
|
+
};
|
|
387
|
+
return cachedResult$1;
|
|
388
|
+
}
|
|
389
|
+
const simParseR = withAnnotatedInnerState(state, effectiveInitialState, (annotatedState) => parser.parse({
|
|
390
|
+
buffer: [],
|
|
391
|
+
state: annotatedState,
|
|
392
|
+
optionsTerminated: false,
|
|
393
|
+
usage: parser.usage
|
|
394
|
+
}));
|
|
395
|
+
const decideFromParse = (parseResult) => {
|
|
396
|
+
const consumed = parseResult.success ? parseResult.consumed.length : 0;
|
|
397
|
+
const cliState$1 = parseResult.success && consumed === 0 ? parseResult.next.state : void 0;
|
|
398
|
+
const hasSourceBindingMarker = (s) => s != null && typeof s === "object" && "hasCliValue" in s && Object.getOwnPropertySymbols(s).length > 0;
|
|
399
|
+
const cliStateIsPassthrough = cliState$1 != null && typeof cliState$1 === "object" && (0, __optique_core_annotations.unwrapInjectedAnnotationWrapper)(cliState$1) !== cliState$1;
|
|
400
|
+
const isSourceBinding = shouldAttemptInnerCompletion(cliState$1, state) && !cliStateIsPassthrough || hasSourceBindingMarker(cliState$1) || Array.isArray(cliState$1) && cliState$1.length === 1 && (hasSourceBindingMarker(cliState$1[0]) || typeof cliState$1[0] === "object" && cliState$1[0] != null && __optique_core_annotations.annotationKey in cliState$1[0]);
|
|
401
|
+
if (isSourceBinding) {
|
|
402
|
+
const cliStateIsInjected = cliState$1 != null && typeof cliState$1 === "object" && (0, __optique_core_annotations.unwrapInjectedAnnotationWrapper)(cliState$1) !== cliState$1;
|
|
403
|
+
const handleCompleteResult = (res) => {
|
|
404
|
+
if (res.success && res.value === void 0 && cliStateIsInjected) return executePrompt();
|
|
405
|
+
return usePromptOrDefer(state, res);
|
|
406
|
+
};
|
|
407
|
+
const completeState = parseResult.success ? parseResult.next.state : effectiveInitialState;
|
|
408
|
+
const completeR = parser.complete(completeState);
|
|
409
|
+
if (completeR instanceof Promise) return completeR.then(handleCompleteResult);
|
|
410
|
+
return handleCompleteResult(completeR);
|
|
411
|
+
}
|
|
412
|
+
return executePrompt();
|
|
413
|
+
};
|
|
414
|
+
const cachedResult = simParseR instanceof Promise ? simParseR.then(decideFromParse) : decideFromParse(simParseR);
|
|
415
|
+
promptCache = {
|
|
416
|
+
state,
|
|
417
|
+
result: cachedResult
|
|
418
|
+
};
|
|
419
|
+
return cachedResult;
|
|
420
|
+
}
|
|
421
|
+
const cliState = isPromptBindState(state) ? state.cliState : void 0;
|
|
422
|
+
const cliStateIsInjectedAnnotationWrapper = cliState != null && typeof cliState === "object" && (0, __optique_core_annotations.unwrapInjectedAnnotationWrapper)(cliState) !== cliState;
|
|
423
|
+
if (shouldAttemptInnerCompletion(cliState, state)) {
|
|
424
|
+
const useCompleteResultOrPrompt = (result) => {
|
|
425
|
+
if (result.success && result.value === void 0 && cliStateIsInjectedAnnotationWrapper) return executePrompt();
|
|
426
|
+
return usePromptOrDefer(state, result);
|
|
427
|
+
};
|
|
428
|
+
const r = withAnnotatedInnerState(state, cliState, (annotatedInnerState) => parser.complete(annotatedInnerState));
|
|
429
|
+
if (r instanceof Promise) return r.then(useCompleteResultOrPrompt);
|
|
430
|
+
return useCompleteResultOrPrompt(r);
|
|
231
431
|
}
|
|
232
|
-
return executePrompt();
|
|
432
|
+
return shouldDeferPrompt(parser, state) ? Promise.resolve(deferredPromptResult()) : executePrompt();
|
|
233
433
|
},
|
|
234
434
|
suggest: (context, prefix) => {
|
|
235
435
|
const innerState = isPromptBindState(context.state) ? context.state.hasCliValue ? context.state.cliState : parser.initialState : context.state;
|
|
@@ -248,6 +448,7 @@ function prompt(parser, config) {
|
|
|
248
448
|
return parser.getDocFragments(state, defaultValue);
|
|
249
449
|
}
|
|
250
450
|
};
|
|
451
|
+
return promptedParser;
|
|
251
452
|
}
|
|
252
453
|
/** Normalize choices to the format Inquirer.js expects. */
|
|
253
454
|
function normalizeChoices(choices) {
|
package/dist/index.d.cts
CHANGED
|
@@ -347,6 +347,8 @@ type BasePromptConfig<T> = T extends boolean ? ConfirmConfig : T extends number
|
|
|
347
347
|
* @param parser Inner parser that reads CLI values.
|
|
348
348
|
* @param config Type-safe Inquirer.js prompt configuration.
|
|
349
349
|
* @returns A parser with interactive prompt fallback, always in async mode.
|
|
350
|
+
* @throws {Error} If prompt execution fails with an unexpected error or if
|
|
351
|
+
* the inner parser throws while parsing or completing.
|
|
350
352
|
* @since 1.0.0
|
|
351
353
|
*/
|
|
352
354
|
declare function prompt<M extends Mode, TValue, TState>(parser: Parser<M, TValue, TState>, config: PromptConfig<TValue>): Parser<"async", TValue, TState>;
|
package/dist/index.d.ts
CHANGED
|
@@ -347,6 +347,8 @@ type BasePromptConfig<T> = T extends boolean ? ConfirmConfig : T extends number
|
|
|
347
347
|
* @param parser Inner parser that reads CLI values.
|
|
348
348
|
* @param config Type-safe Inquirer.js prompt configuration.
|
|
349
349
|
* @returns A parser with interactive prompt fallback, always in async mode.
|
|
350
|
+
* @throws {Error} If prompt execution fails with an unexpected error or if
|
|
351
|
+
* the inner parser throws while parsing or completing.
|
|
350
352
|
* @since 1.0.0
|
|
351
353
|
*/
|
|
352
354
|
declare function prompt<M extends Mode, TValue, TState>(parser: Parser<M, TValue, TState>, config: PromptConfig<TValue>): Parser<"async", TValue, TState>;
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,86 @@
|
|
|
1
1
|
import { Separator, checkbox, confirm, editor, expand, input, number, password, rawlist, select } from "@inquirer/prompts";
|
|
2
|
-
import { annotationKey, getAnnotations } from "@optique/core/annotations";
|
|
2
|
+
import { annotationKey, getAnnotations, inheritAnnotations, injectAnnotations, unwrapInjectedAnnotationWrapper } from "@optique/core/annotations";
|
|
3
|
+
import { placeholder } from "@optique/core/context";
|
|
3
4
|
import { message } from "@optique/core/message";
|
|
4
5
|
|
|
5
6
|
//#region src/index.ts
|
|
7
|
+
const promptFunctionsOverrideSymbol = Symbol.for("@optique/inquirer/prompt-functions");
|
|
8
|
+
const defaultPromptFunctions = {
|
|
9
|
+
confirm,
|
|
10
|
+
number,
|
|
11
|
+
input,
|
|
12
|
+
password,
|
|
13
|
+
editor,
|
|
14
|
+
select,
|
|
15
|
+
rawlist,
|
|
16
|
+
expand,
|
|
17
|
+
checkbox
|
|
18
|
+
};
|
|
19
|
+
function promptFunctionKeys() {
|
|
20
|
+
return Object.keys(defaultPromptFunctions);
|
|
21
|
+
}
|
|
22
|
+
function assignPromptFunctionOverride(override, key, candidate) {
|
|
23
|
+
if (typeof candidate === "function") override[key] = candidate;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Extracts valid prompt function overrides from an arbitrary value.
|
|
27
|
+
*/
|
|
28
|
+
function getPromptFunctionsOverride(value) {
|
|
29
|
+
if (typeof value !== "object" || value == null) return void 0;
|
|
30
|
+
const override = {};
|
|
31
|
+
for (const key of promptFunctionKeys()) assignPromptFunctionOverride(override, key, Reflect.get(value, key));
|
|
32
|
+
return override;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Returns the active prompt function set, applying any global test overrides.
|
|
36
|
+
*/
|
|
37
|
+
function getPromptFunctions() {
|
|
38
|
+
const override = getPromptFunctionsOverride(Reflect.get(globalThis, promptFunctionsOverrideSymbol));
|
|
39
|
+
return override != null ? {
|
|
40
|
+
...defaultPromptFunctions,
|
|
41
|
+
...override
|
|
42
|
+
} : defaultPromptFunctions;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Determines whether an error came from an interrupted Inquirer prompt.
|
|
46
|
+
*/
|
|
47
|
+
function isExitPromptError(error) {
|
|
48
|
+
return typeof error === "object" && error != null && "name" in error && error.name === "ExitPromptError";
|
|
49
|
+
}
|
|
50
|
+
const inheritParentAnnotationsKey = Symbol.for("@optique/core/inheritParentAnnotations");
|
|
51
|
+
var DeferredPromptValue = class {
|
|
52
|
+
[placeholder] = true;
|
|
53
|
+
constructor() {}
|
|
54
|
+
};
|
|
55
|
+
function shouldDeferPrompt(parser, state) {
|
|
56
|
+
return typeof parser.shouldDeferCompletion === "function" && parser.shouldDeferCompletion(state) === true;
|
|
57
|
+
}
|
|
58
|
+
function deferredPromptResult() {
|
|
59
|
+
return {
|
|
60
|
+
success: true,
|
|
61
|
+
value: new DeferredPromptValue()
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function withAnnotationView(state, annotations, run) {
|
|
65
|
+
const annotatedState = new Proxy(state, {
|
|
66
|
+
get(target, key) {
|
|
67
|
+
if (key === annotationKey) return annotations;
|
|
68
|
+
const value = Reflect.get(target, key, target);
|
|
69
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
70
|
+
},
|
|
71
|
+
has(target, key) {
|
|
72
|
+
return key === annotationKey || Reflect.has(target, key);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
return run(annotatedState);
|
|
76
|
+
}
|
|
77
|
+
function withAnnotatedInnerState(sourceState, innerState, run) {
|
|
78
|
+
const annotations = getAnnotations(sourceState);
|
|
79
|
+
if (annotations == null || innerState == null || typeof innerState !== "object" || typeof innerState === "object" && annotationKey in innerState) return run(innerState);
|
|
80
|
+
const inheritedState = inheritAnnotations(sourceState, innerState);
|
|
81
|
+
if (inheritedState !== innerState) return run(inheritedState);
|
|
82
|
+
return withAnnotationView(innerState, annotations, (annotatedState) => run(annotatedState));
|
|
83
|
+
}
|
|
6
84
|
/**
|
|
7
85
|
* Wraps a parser with an interactive Inquirer.js prompt fallback.
|
|
8
86
|
*
|
|
@@ -29,6 +107,8 @@ import { message } from "@optique/core/message";
|
|
|
29
107
|
* @param parser Inner parser that reads CLI values.
|
|
30
108
|
* @param config Type-safe Inquirer.js prompt configuration.
|
|
31
109
|
* @returns A parser with interactive prompt fallback, always in async mode.
|
|
110
|
+
* @throws {Error} If prompt execution fails with an unexpected error or if
|
|
111
|
+
* the inner parser throws while parsing or completing.
|
|
32
112
|
* @since 1.0.0
|
|
33
113
|
*/
|
|
34
114
|
function prompt(parser, config) {
|
|
@@ -41,116 +121,170 @@ function prompt(parser, config) {
|
|
|
41
121
|
[promptBindStateKey] = true;
|
|
42
122
|
hasCliValue = false;
|
|
43
123
|
};
|
|
44
|
-
const promptBindInitialState = new PromptBindInitialStateClass();
|
|
45
124
|
let promptCache = null;
|
|
46
|
-
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
125
|
+
function shouldAttemptInnerCompletion(cliState, state) {
|
|
126
|
+
if (cliState == null || cliState instanceof PromptBindInitialStateClass) return false;
|
|
127
|
+
const cliStateHasAnnotations = typeof cliState === "object" && annotationKey in cliState;
|
|
128
|
+
if (cliStateHasAnnotations) return true;
|
|
129
|
+
if (getAnnotations(state) == null || typeof cliState !== "object") return false;
|
|
130
|
+
if ("hasCliValue" in cliState) return true;
|
|
131
|
+
if (Array.isArray(cliState)) return typeof parser.shouldDeferCompletion === "function";
|
|
132
|
+
const prototype = Object.getPrototypeOf(cliState);
|
|
133
|
+
return prototype !== Object.prototype && prototype !== null;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Executes the configured prompt and normalizes its result.
|
|
137
|
+
*
|
|
138
|
+
* Converts `ExitPromptError` into a parse failure and returns prompt values
|
|
139
|
+
* in Optique's `ValueParserResult` shape.
|
|
140
|
+
*
|
|
141
|
+
* @returns The normalized prompt result.
|
|
142
|
+
* @throws {Error} Rethrows unexpected prompt failures after converting
|
|
143
|
+
* `ExitPromptError` cancellations into parse failures.
|
|
144
|
+
*/
|
|
145
|
+
function validatePromptedValue(result) {
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
const validPromptTypes = new Set([
|
|
149
|
+
"confirm",
|
|
150
|
+
"number",
|
|
151
|
+
"input",
|
|
152
|
+
"password",
|
|
153
|
+
"editor",
|
|
154
|
+
"select",
|
|
155
|
+
"rawlist",
|
|
156
|
+
"expand",
|
|
157
|
+
"checkbox"
|
|
158
|
+
]);
|
|
159
|
+
async function executePromptRaw() {
|
|
160
|
+
const prompts = getPromptFunctions();
|
|
161
|
+
try {
|
|
162
|
+
if (!validPromptTypes.has(cfg.type)) throw new TypeError(`Unsupported prompt type: ${cfg.type}`);
|
|
163
|
+
if ("prompter" in cfg && cfg.prompter != null) {
|
|
164
|
+
const value = await cfg.prompter();
|
|
165
|
+
if (cfg.type === "number" && value === void 0) return {
|
|
75
166
|
success: false,
|
|
76
167
|
error: message`No number provided.`
|
|
77
168
|
};
|
|
78
169
|
return {
|
|
79
170
|
success: true,
|
|
80
|
-
value
|
|
171
|
+
value
|
|
81
172
|
};
|
|
82
173
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
174
|
+
switch (cfg.type) {
|
|
175
|
+
case "confirm": return {
|
|
176
|
+
success: true,
|
|
177
|
+
value: await prompts.confirm({
|
|
178
|
+
message: cfg.message,
|
|
179
|
+
...cfg.default !== void 0 ? { default: cfg.default } : {}
|
|
180
|
+
})
|
|
181
|
+
};
|
|
182
|
+
case "number": {
|
|
183
|
+
const numResult = await prompts.number({
|
|
184
|
+
message: cfg.message,
|
|
185
|
+
...cfg.default !== void 0 ? { default: cfg.default } : {},
|
|
186
|
+
...cfg.min !== void 0 ? { min: cfg.min } : {},
|
|
187
|
+
...cfg.max !== void 0 ? { max: cfg.max } : {},
|
|
188
|
+
...cfg.step !== void 0 ? { step: cfg.step } : {}
|
|
189
|
+
});
|
|
190
|
+
if (numResult === void 0) return {
|
|
191
|
+
success: false,
|
|
192
|
+
error: message`No number provided.`
|
|
193
|
+
};
|
|
194
|
+
return {
|
|
195
|
+
success: true,
|
|
196
|
+
value: numResult
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
case "input": return {
|
|
200
|
+
success: true,
|
|
201
|
+
value: await prompts.input({
|
|
202
|
+
message: cfg.message,
|
|
203
|
+
...cfg.default !== void 0 ? { default: cfg.default } : {},
|
|
204
|
+
...cfg.validate !== void 0 ? { validate: cfg.validate } : {}
|
|
205
|
+
})
|
|
206
|
+
};
|
|
207
|
+
case "password": return {
|
|
208
|
+
success: true,
|
|
209
|
+
value: await prompts.password({
|
|
210
|
+
message: cfg.message,
|
|
211
|
+
...cfg.mask !== void 0 ? { mask: cfg.mask } : {},
|
|
212
|
+
...cfg.validate !== void 0 ? { validate: cfg.validate } : {}
|
|
213
|
+
})
|
|
214
|
+
};
|
|
215
|
+
case "editor": return {
|
|
216
|
+
success: true,
|
|
217
|
+
value: await prompts.editor({
|
|
218
|
+
message: cfg.message,
|
|
219
|
+
...cfg.default !== void 0 ? { default: cfg.default } : {},
|
|
220
|
+
...cfg.validate !== void 0 ? { validate: cfg.validate } : {}
|
|
221
|
+
})
|
|
222
|
+
};
|
|
223
|
+
case "select": return {
|
|
224
|
+
success: true,
|
|
225
|
+
value: await prompts.select({
|
|
226
|
+
message: cfg.message,
|
|
227
|
+
choices: normalizeChoices(cfg.choices),
|
|
228
|
+
...cfg.default !== void 0 ? { default: cfg.default } : {}
|
|
229
|
+
})
|
|
230
|
+
};
|
|
231
|
+
case "rawlist": return {
|
|
232
|
+
success: true,
|
|
233
|
+
value: await prompts.rawlist({
|
|
234
|
+
message: cfg.message,
|
|
235
|
+
choices: normalizeChoices(cfg.choices),
|
|
236
|
+
...cfg.default !== void 0 ? { default: cfg.default } : {}
|
|
237
|
+
})
|
|
238
|
+
};
|
|
239
|
+
case "expand": return {
|
|
240
|
+
success: true,
|
|
241
|
+
value: await prompts.expand({
|
|
242
|
+
message: cfg.message,
|
|
243
|
+
choices: cfg.choices,
|
|
244
|
+
...cfg.default !== void 0 ? { default: cfg.default } : {}
|
|
245
|
+
})
|
|
246
|
+
};
|
|
247
|
+
case "checkbox": return {
|
|
248
|
+
success: true,
|
|
249
|
+
value: await prompts.checkbox({
|
|
250
|
+
message: cfg.message,
|
|
251
|
+
choices: normalizeChoices(cfg.choices)
|
|
252
|
+
})
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
} catch (error) {
|
|
256
|
+
if (isExitPromptError(error)) return {
|
|
257
|
+
success: false,
|
|
258
|
+
error: message`Prompt cancelled.`
|
|
137
259
|
};
|
|
260
|
+
throw error;
|
|
138
261
|
}
|
|
139
262
|
}
|
|
140
|
-
|
|
263
|
+
async function executePrompt() {
|
|
264
|
+
const result = await executePromptRaw();
|
|
265
|
+
return validatePromptedValue(result);
|
|
266
|
+
}
|
|
267
|
+
function usePromptOrDefer(state, result) {
|
|
268
|
+
if (result.success) return Promise.resolve(result);
|
|
269
|
+
return shouldDeferPrompt(parser, state) ? Promise.resolve(deferredPromptResult()) : executePrompt();
|
|
270
|
+
}
|
|
271
|
+
const promptedParser = {
|
|
141
272
|
$mode: "async",
|
|
142
273
|
$valueType: parser.$valueType,
|
|
143
274
|
$stateType: parser.$stateType,
|
|
144
275
|
priority: parser.priority,
|
|
145
|
-
|
|
276
|
+
[inheritParentAnnotationsKey]: true,
|
|
277
|
+
usage: parser.usage.length === 1 && parser.usage[0].type === "optional" ? parser.usage : [{
|
|
146
278
|
type: "optional",
|
|
147
279
|
terms: parser.usage
|
|
148
280
|
}],
|
|
149
|
-
initialState
|
|
281
|
+
get initialState() {
|
|
282
|
+
return new PromptBindInitialStateClass();
|
|
283
|
+
},
|
|
150
284
|
parse: (context) => {
|
|
151
285
|
const annotations = getAnnotations(context.state);
|
|
152
286
|
const innerState = isPromptBindState(context.state) ? context.state.hasCliValue ? context.state.cliState : parser.initialState : context.state;
|
|
153
|
-
const
|
|
287
|
+
const baseInnerContext = innerState !== context.state ? {
|
|
154
288
|
...context,
|
|
155
289
|
state: innerState
|
|
156
290
|
} : context;
|
|
@@ -181,32 +315,98 @@ function prompt(parser, config) {
|
|
|
181
315
|
return {
|
|
182
316
|
success: true,
|
|
183
317
|
next: {
|
|
184
|
-
...
|
|
318
|
+
...baseInnerContext,
|
|
185
319
|
state: nextState
|
|
186
320
|
},
|
|
187
321
|
consumed: []
|
|
188
322
|
};
|
|
189
323
|
};
|
|
190
|
-
const result =
|
|
324
|
+
const result = withAnnotatedInnerState(context.state, innerState, (annotatedInnerState) => {
|
|
325
|
+
const innerContext = annotatedInnerState !== context.state ? {
|
|
326
|
+
...context,
|
|
327
|
+
state: annotatedInnerState
|
|
328
|
+
} : context;
|
|
329
|
+
return parser.parse(innerContext);
|
|
330
|
+
});
|
|
191
331
|
if (result instanceof Promise) return result.then(processResult);
|
|
192
332
|
return Promise.resolve(processResult(result));
|
|
193
333
|
},
|
|
194
334
|
complete: (state) => {
|
|
195
335
|
if (isPromptBindState(state) && state.hasCliValue) {
|
|
196
|
-
const r =
|
|
336
|
+
const r = withAnnotatedInnerState(state, state.cliState, (annotatedInnerState) => parser.complete(annotatedInnerState));
|
|
197
337
|
if (r instanceof Promise) return r;
|
|
198
338
|
return Promise.resolve(r);
|
|
199
339
|
}
|
|
200
|
-
if (state
|
|
201
|
-
if (promptCache
|
|
202
|
-
const cached = promptCache;
|
|
340
|
+
if (state instanceof PromptBindInitialStateClass) {
|
|
341
|
+
if (promptCache?.state === state) {
|
|
342
|
+
const cached = promptCache.result;
|
|
203
343
|
promptCache = null;
|
|
204
344
|
return cached;
|
|
205
345
|
}
|
|
206
|
-
|
|
207
|
-
|
|
346
|
+
const hasDeferHook = typeof parser.shouldDeferCompletion === "function";
|
|
347
|
+
const annotations = getAnnotations(state);
|
|
348
|
+
const innerInitialState = parser.initialState;
|
|
349
|
+
const effectiveInitialState = annotations != null && innerInitialState == null ? injectAnnotations(innerInitialState, annotations) : innerInitialState;
|
|
350
|
+
if (hasDeferHook) {
|
|
351
|
+
const annotatedR = withAnnotatedInnerState(state, effectiveInitialState, (annotatedInnerState) => parser.complete(annotatedInnerState));
|
|
352
|
+
const usePromptOrDeferSentinel = (res) => {
|
|
353
|
+
if (res.success && res.value === void 0) return usePromptOrDefer(state, {
|
|
354
|
+
success: false,
|
|
355
|
+
error: []
|
|
356
|
+
});
|
|
357
|
+
return usePromptOrDefer(state, res);
|
|
358
|
+
};
|
|
359
|
+
const cachedResult$1 = annotatedR instanceof Promise ? annotatedR.then(usePromptOrDeferSentinel) : usePromptOrDeferSentinel(annotatedR);
|
|
360
|
+
promptCache = {
|
|
361
|
+
state,
|
|
362
|
+
result: cachedResult$1
|
|
363
|
+
};
|
|
364
|
+
return cachedResult$1;
|
|
365
|
+
}
|
|
366
|
+
const simParseR = withAnnotatedInnerState(state, effectiveInitialState, (annotatedState) => parser.parse({
|
|
367
|
+
buffer: [],
|
|
368
|
+
state: annotatedState,
|
|
369
|
+
optionsTerminated: false,
|
|
370
|
+
usage: parser.usage
|
|
371
|
+
}));
|
|
372
|
+
const decideFromParse = (parseResult) => {
|
|
373
|
+
const consumed = parseResult.success ? parseResult.consumed.length : 0;
|
|
374
|
+
const cliState$1 = parseResult.success && consumed === 0 ? parseResult.next.state : void 0;
|
|
375
|
+
const hasSourceBindingMarker = (s) => s != null && typeof s === "object" && "hasCliValue" in s && Object.getOwnPropertySymbols(s).length > 0;
|
|
376
|
+
const cliStateIsPassthrough = cliState$1 != null && typeof cliState$1 === "object" && unwrapInjectedAnnotationWrapper(cliState$1) !== cliState$1;
|
|
377
|
+
const isSourceBinding = shouldAttemptInnerCompletion(cliState$1, state) && !cliStateIsPassthrough || hasSourceBindingMarker(cliState$1) || Array.isArray(cliState$1) && cliState$1.length === 1 && (hasSourceBindingMarker(cliState$1[0]) || typeof cliState$1[0] === "object" && cliState$1[0] != null && annotationKey in cliState$1[0]);
|
|
378
|
+
if (isSourceBinding) {
|
|
379
|
+
const cliStateIsInjected = cliState$1 != null && typeof cliState$1 === "object" && unwrapInjectedAnnotationWrapper(cliState$1) !== cliState$1;
|
|
380
|
+
const handleCompleteResult = (res) => {
|
|
381
|
+
if (res.success && res.value === void 0 && cliStateIsInjected) return executePrompt();
|
|
382
|
+
return usePromptOrDefer(state, res);
|
|
383
|
+
};
|
|
384
|
+
const completeState = parseResult.success ? parseResult.next.state : effectiveInitialState;
|
|
385
|
+
const completeR = parser.complete(completeState);
|
|
386
|
+
if (completeR instanceof Promise) return completeR.then(handleCompleteResult);
|
|
387
|
+
return handleCompleteResult(completeR);
|
|
388
|
+
}
|
|
389
|
+
return executePrompt();
|
|
390
|
+
};
|
|
391
|
+
const cachedResult = simParseR instanceof Promise ? simParseR.then(decideFromParse) : decideFromParse(simParseR);
|
|
392
|
+
promptCache = {
|
|
393
|
+
state,
|
|
394
|
+
result: cachedResult
|
|
395
|
+
};
|
|
396
|
+
return cachedResult;
|
|
397
|
+
}
|
|
398
|
+
const cliState = isPromptBindState(state) ? state.cliState : void 0;
|
|
399
|
+
const cliStateIsInjectedAnnotationWrapper = cliState != null && typeof cliState === "object" && unwrapInjectedAnnotationWrapper(cliState) !== cliState;
|
|
400
|
+
if (shouldAttemptInnerCompletion(cliState, state)) {
|
|
401
|
+
const useCompleteResultOrPrompt = (result) => {
|
|
402
|
+
if (result.success && result.value === void 0 && cliStateIsInjectedAnnotationWrapper) return executePrompt();
|
|
403
|
+
return usePromptOrDefer(state, result);
|
|
404
|
+
};
|
|
405
|
+
const r = withAnnotatedInnerState(state, cliState, (annotatedInnerState) => parser.complete(annotatedInnerState));
|
|
406
|
+
if (r instanceof Promise) return r.then(useCompleteResultOrPrompt);
|
|
407
|
+
return useCompleteResultOrPrompt(r);
|
|
208
408
|
}
|
|
209
|
-
return executePrompt();
|
|
409
|
+
return shouldDeferPrompt(parser, state) ? Promise.resolve(deferredPromptResult()) : executePrompt();
|
|
210
410
|
},
|
|
211
411
|
suggest: (context, prefix) => {
|
|
212
412
|
const innerState = isPromptBindState(context.state) ? context.state.hasCliValue ? context.state.cliState : parser.initialState : context.state;
|
|
@@ -225,6 +425,7 @@ function prompt(parser, config) {
|
|
|
225
425
|
return parser.getDocFragments(state, defaultValue);
|
|
226
426
|
}
|
|
227
427
|
};
|
|
428
|
+
return promptedParser;
|
|
228
429
|
}
|
|
229
430
|
/** Normalize choices to the format Inquirer.js expects. */
|
|
230
431
|
function normalizeChoices(choices) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@optique/inquirer",
|
|
3
|
-
"version": "1.0.0-dev.
|
|
3
|
+
"version": "1.0.0-dev.1109+fa132665",
|
|
4
4
|
"description": "Interactive prompt support for Optique via Inquirer.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"CLI",
|
|
@@ -56,12 +56,13 @@
|
|
|
56
56
|
"sideEffects": false,
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"@inquirer/prompts": "^8.3.0",
|
|
59
|
-
"@optique/core": "1.0.0"
|
|
59
|
+
"@optique/core": "1.0.0-dev.1109+fa132665"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@types/node": "^20.19.9",
|
|
63
63
|
"tsdown": "^0.13.0",
|
|
64
|
-
"typescript": "^5.8.3"
|
|
64
|
+
"typescript": "^5.8.3",
|
|
65
|
+
"@optique/env": "1.0.0-dev.1109+fa132665"
|
|
65
66
|
},
|
|
66
67
|
"scripts": {
|
|
67
68
|
"build": "tsdown",
|