semola 0.5.4 → 0.6.1
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 +35 -50
- package/dist/lib/api/index.cjs +1 -523
- package/dist/lib/api/index.d.cts +1 -271
- package/dist/lib/api/index.d.mts +80 -84
- package/dist/lib/api/index.mjs +1 -521
- package/dist/lib/cache/index.cjs +1 -74
- package/dist/lib/cache/index.d.cts +1 -48
- package/dist/lib/cache/index.d.mts +3 -24
- package/dist/lib/cache/index.mjs +1 -73
- package/dist/lib/cron/index.cjs +1 -735
- package/dist/lib/cron/index.d.cts +1 -146
- package/dist/lib/cron/index.d.mts +99 -36
- package/dist/lib/cron/index.mjs +1 -726
- package/dist/lib/errors/index.cjs +1 -30
- package/dist/lib/errors/index.d.cts +1 -2
- package/dist/lib/errors/index.d.mts +12 -1
- package/dist/lib/errors/index.mjs +1 -26
- package/dist/lib/i18n/index.cjs +1 -42
- package/dist/lib/i18n/index.d.cts +1 -28
- package/dist/lib/i18n/index.mjs +1 -41
- package/dist/lib/logging/index.cjs +1 -387
- package/dist/lib/logging/index.d.cts +1 -108
- package/dist/lib/logging/index.mjs +1 -374
- package/dist/lib/orm/index.cjs +1 -0
- package/dist/lib/orm/index.d.cts +1 -0
- package/dist/lib/orm/index.d.mts +404 -0
- package/dist/lib/orm/index.mjs +1 -0
- package/dist/lib/policy/index.cjs +1 -285
- package/dist/lib/policy/index.d.cts +1 -77
- package/dist/lib/policy/index.mjs +1 -265
- package/dist/lib/prompts/index.cjs +6 -769
- package/dist/lib/prompts/index.d.cts +1 -96
- package/dist/lib/prompts/index.d.mts +12 -33
- package/dist/lib/prompts/index.mjs +6 -763
- package/dist/lib/pubsub/index.cjs +1 -117
- package/dist/lib/pubsub/index.d.cts +1 -41
- package/dist/lib/pubsub/index.d.mts +3 -18
- package/dist/lib/pubsub/index.mjs +1 -116
- package/dist/lib/queue/index.cjs +1 -182
- package/dist/lib/queue/index.d.cts +1 -74
- package/dist/lib/queue/index.d.mts +11 -4
- package/dist/lib/queue/index.mjs +1 -181
- package/dist/lib/workflow/index.cjs +1 -534
- package/dist/lib/workflow/index.d.cts +1 -85
- package/dist/lib/workflow/index.d.mts +76 -11
- package/dist/lib/workflow/index.mjs +1 -533
- package/dist/rolldown-runtime-CMqjfN_6.cjs +1 -0
- package/package.json +17 -5
- package/dist/index-BhGNDjPq.d.mts +0 -13
- package/dist/index-DxSbeGP-.d.cts +0 -13
|
@@ -1,769 +1,6 @@
|
|
|
1
|
-
Object.defineProperty(exports,
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const ESC_BACKSPACE = `${ESC}\u007F`;
|
|
8
|
-
const CHAR_KEY_MAP = new Map(Object.values({
|
|
9
|
-
enterCr: {
|
|
10
|
-
value: "\r",
|
|
11
|
-
name: "enter"
|
|
12
|
-
},
|
|
13
|
-
enterLf: {
|
|
14
|
-
value: "\n",
|
|
15
|
-
name: "enter"
|
|
16
|
-
},
|
|
17
|
-
ctrlA: {
|
|
18
|
-
value: "",
|
|
19
|
-
name: "ctrl_a"
|
|
20
|
-
},
|
|
21
|
-
ctrlC: {
|
|
22
|
-
value: "",
|
|
23
|
-
name: "ctrl_c"
|
|
24
|
-
},
|
|
25
|
-
ctrlBackspace: {
|
|
26
|
-
value: "",
|
|
27
|
-
name: "ctrl_backspace"
|
|
28
|
-
},
|
|
29
|
-
backspace: {
|
|
30
|
-
value: "",
|
|
31
|
-
name: "backspace"
|
|
32
|
-
},
|
|
33
|
-
tab: {
|
|
34
|
-
value: " ",
|
|
35
|
-
name: "tab"
|
|
36
|
-
},
|
|
37
|
-
space: {
|
|
38
|
-
value: " ",
|
|
39
|
-
name: "space"
|
|
40
|
-
}
|
|
41
|
-
}).map((entry) => [entry.value, { name: entry.name }]));
|
|
42
|
-
const KNOWN_SEQUENCES = [
|
|
43
|
-
{
|
|
44
|
-
sequence: "\x1B[1;2D",
|
|
45
|
-
key: { name: "shift_left" }
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
sequence: "\x1B[1;2C",
|
|
49
|
-
key: { name: "shift_right" }
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
sequence: "\x1B[1;5D",
|
|
53
|
-
key: { name: "ctrl_left" }
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
sequence: "\x1B[1;5C",
|
|
57
|
-
key: { name: "ctrl_right" }
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
sequence: "\x1B[1;6D",
|
|
61
|
-
key: { name: "shift_ctrl_left" }
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
sequence: "\x1B[1;6C",
|
|
65
|
-
key: { name: "shift_ctrl_right" }
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
sequence: "\x1B[3~",
|
|
69
|
-
key: { name: "delete" }
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
sequence: "\x1B[H",
|
|
73
|
-
key: { name: "home" }
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
sequence: "\x1B[F",
|
|
77
|
-
key: { name: "end" }
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
sequence: "\x1B[A",
|
|
81
|
-
key: { name: "up" }
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
sequence: "\x1B[B",
|
|
85
|
-
key: { name: "down" }
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
sequence: "\x1B[C",
|
|
89
|
-
key: { name: "right" }
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
sequence: "\x1B[D",
|
|
93
|
-
key: { name: "left" }
|
|
94
|
-
}
|
|
95
|
-
];
|
|
96
|
-
const isControlChar = (char) => {
|
|
97
|
-
return char <= "" || char === "";
|
|
98
|
-
};
|
|
99
|
-
const isCsiFinalByte = (char) => {
|
|
100
|
-
if (!char) return false;
|
|
101
|
-
if (char >= "A" && char <= "Z") return true;
|
|
102
|
-
if (char >= "a" && char <= "z") return true;
|
|
103
|
-
if (char === "~") return true;
|
|
104
|
-
return false;
|
|
105
|
-
};
|
|
106
|
-
const readCsiLength = (remaining) => {
|
|
107
|
-
if (!remaining.startsWith(CSI)) return null;
|
|
108
|
-
let index = 2;
|
|
109
|
-
while (index < remaining.length) {
|
|
110
|
-
if (isCsiFinalByte(remaining[index] ?? "")) return {
|
|
111
|
-
length: index + 1,
|
|
112
|
-
incomplete: false
|
|
113
|
-
};
|
|
114
|
-
index += 1;
|
|
115
|
-
}
|
|
116
|
-
return {
|
|
117
|
-
length: 0,
|
|
118
|
-
incomplete: true
|
|
119
|
-
};
|
|
120
|
-
};
|
|
121
|
-
const parseKeys = (chunk) => {
|
|
122
|
-
const keys = [];
|
|
123
|
-
let cursor = 0;
|
|
124
|
-
while (cursor < chunk.length) {
|
|
125
|
-
const remaining = chunk.slice(cursor);
|
|
126
|
-
if (remaining.startsWith(ESC_BACKSPACE)) {
|
|
127
|
-
keys.push({ name: "ctrl_backspace" });
|
|
128
|
-
cursor += 2;
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
const knownSequence = KNOWN_SEQUENCES.find((entry) => remaining.startsWith(entry.sequence));
|
|
132
|
-
if (knownSequence) {
|
|
133
|
-
keys.push(knownSequence.key);
|
|
134
|
-
cursor += knownSequence.sequence.length;
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
const csiLength = readCsiLength(remaining);
|
|
138
|
-
if (csiLength) {
|
|
139
|
-
if (csiLength.incomplete) return {
|
|
140
|
-
keys,
|
|
141
|
-
remaining: chunk.slice(cursor)
|
|
142
|
-
};
|
|
143
|
-
cursor += csiLength.length;
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
const char = chunk[cursor] ?? "";
|
|
147
|
-
switch (char) {
|
|
148
|
-
case ESC:
|
|
149
|
-
if (cursor === chunk.length - 1) keys.push({ name: "escape" });
|
|
150
|
-
break;
|
|
151
|
-
default: {
|
|
152
|
-
const key = CHAR_KEY_MAP.get(char);
|
|
153
|
-
if (key) keys.push(key);
|
|
154
|
-
else if (!isControlChar(char)) keys.push({
|
|
155
|
-
name: "character",
|
|
156
|
-
value: char
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
cursor += 1;
|
|
161
|
-
}
|
|
162
|
-
return {
|
|
163
|
-
keys,
|
|
164
|
-
remaining: ""
|
|
165
|
-
};
|
|
166
|
-
};
|
|
167
|
-
//#endregion
|
|
168
|
-
//#region src/lib/prompts/core/runtime.ts
|
|
169
|
-
const HIDE_CURSOR = "\x1B[?25l";
|
|
170
|
-
const SHOW_CURSOR = "\x1B[?25h";
|
|
171
|
-
const countLines = (text) => {
|
|
172
|
-
let count = 1;
|
|
173
|
-
for (let i = 0; i < text.length; i++) if (text[i] === "\n") count += 1;
|
|
174
|
-
return count;
|
|
175
|
-
};
|
|
176
|
-
var NodePromptRuntime = class {
|
|
177
|
-
stdin;
|
|
178
|
-
stdout;
|
|
179
|
-
queue = [];
|
|
180
|
-
waiters = [];
|
|
181
|
-
initialized = false;
|
|
182
|
-
previousLines = 0;
|
|
183
|
-
buffer = "";
|
|
184
|
-
constructor(stdin = process.stdin, stdout = process.stdout) {
|
|
185
|
-
this.stdin = stdin;
|
|
186
|
-
this.stdout = stdout;
|
|
187
|
-
}
|
|
188
|
-
isInteractive() {
|
|
189
|
-
return Boolean(this.stdin.isTTY && this.stdout.isTTY && typeof this.stdin.setRawMode === "function");
|
|
190
|
-
}
|
|
191
|
-
init() {
|
|
192
|
-
if (!this.isInteractive()) return require_lib_errors_index.err("PromptEnvironmentError", "Interactive prompts require a TTY with raw mode support");
|
|
193
|
-
if (this.initialized) return require_lib_errors_index.ok(void 0);
|
|
194
|
-
const [initError] = require_lib_errors_index.mightThrowSync(() => {
|
|
195
|
-
this.stdin.setRawMode(true);
|
|
196
|
-
this.stdin.setEncoding("utf8");
|
|
197
|
-
this.stdin.resume();
|
|
198
|
-
this.stdin.on("data", this.onData);
|
|
199
|
-
this.stdout.write(HIDE_CURSOR);
|
|
200
|
-
});
|
|
201
|
-
if (initError) return require_lib_errors_index.err("PromptIOError", "Unable to initialize prompt runtime");
|
|
202
|
-
this.initialized = true;
|
|
203
|
-
return require_lib_errors_index.ok(void 0);
|
|
204
|
-
}
|
|
205
|
-
readKey() {
|
|
206
|
-
const queued = this.queue.shift();
|
|
207
|
-
if (queued) return Promise.resolve(require_lib_errors_index.ok(queued));
|
|
208
|
-
return new Promise((resolve) => {
|
|
209
|
-
this.waiters.push(resolve);
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
render(frame) {
|
|
213
|
-
const [renderError] = require_lib_errors_index.mightThrowSync(() => {
|
|
214
|
-
if (this.previousLines > 1) this.stdout.write(`\u001B[${this.previousLines - 1}A`);
|
|
215
|
-
this.stdout.write("\r\x1B[J");
|
|
216
|
-
this.stdout.write(frame);
|
|
217
|
-
this.previousLines = countLines(frame);
|
|
218
|
-
});
|
|
219
|
-
if (renderError) return require_lib_errors_index.err("PromptIOError", "Unable to render prompt frame");
|
|
220
|
-
return require_lib_errors_index.ok(void 0);
|
|
221
|
-
}
|
|
222
|
-
done(frame) {
|
|
223
|
-
const [doneError] = require_lib_errors_index.mightThrowSync(() => {
|
|
224
|
-
if (this.previousLines > 1) this.stdout.write(`\u001B[${this.previousLines - 1}A`);
|
|
225
|
-
this.stdout.write("\r\x1B[J");
|
|
226
|
-
this.stdout.write(`${frame}\n`);
|
|
227
|
-
this.previousLines = 0;
|
|
228
|
-
});
|
|
229
|
-
if (doneError) return require_lib_errors_index.err("PromptIOError", "Unable to finalize prompt frame");
|
|
230
|
-
return require_lib_errors_index.ok(void 0);
|
|
231
|
-
}
|
|
232
|
-
close() {
|
|
233
|
-
if (!this.initialized) return require_lib_errors_index.ok(void 0);
|
|
234
|
-
this.initialized = false;
|
|
235
|
-
const [closeError] = require_lib_errors_index.mightThrowSync(() => {
|
|
236
|
-
this.stdin.off("data", this.onData);
|
|
237
|
-
this.stdin.setRawMode(false);
|
|
238
|
-
this.stdin.pause?.();
|
|
239
|
-
this.stdout.write(SHOW_CURSOR);
|
|
240
|
-
});
|
|
241
|
-
if (closeError) return require_lib_errors_index.err("PromptIOError", "Unable to close prompt runtime");
|
|
242
|
-
return require_lib_errors_index.ok(void 0);
|
|
243
|
-
}
|
|
244
|
-
interrupt() {
|
|
245
|
-
this.close();
|
|
246
|
-
process.exit(0);
|
|
247
|
-
}
|
|
248
|
-
onData = (chunk) => {
|
|
249
|
-
const value = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
250
|
-
const combined = `${this.buffer}${value}`;
|
|
251
|
-
this.buffer = "";
|
|
252
|
-
const [parseError, result] = require_lib_errors_index.mightThrowSync(() => parseKeys(combined));
|
|
253
|
-
if (parseError || !result) {
|
|
254
|
-
for (const waiter of this.waiters.splice(0)) waiter(require_lib_errors_index.err("PromptIOError", "Failed to parse input"));
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
|
-
this.buffer = result.remaining;
|
|
258
|
-
for (const key of result.keys) {
|
|
259
|
-
const waiter = this.waiters.shift();
|
|
260
|
-
if (waiter) waiter(require_lib_errors_index.ok(key));
|
|
261
|
-
else this.queue.push(key);
|
|
262
|
-
}
|
|
263
|
-
};
|
|
264
|
-
};
|
|
265
|
-
const createNodePromptRuntime = () => {
|
|
266
|
-
return new NodePromptRuntime();
|
|
267
|
-
};
|
|
268
|
-
//#endregion
|
|
269
|
-
//#region src/lib/prompts/core/session.ts
|
|
270
|
-
const CANCEL_MESSAGE = "Interrupted, bye!";
|
|
271
|
-
const resolveOutput = async (options, value) => {
|
|
272
|
-
if (!options.transform) return require_lib_errors_index.ok(value);
|
|
273
|
-
const [transformError, transformed] = await require_lib_errors_index.mightThrow(Promise.resolve().then(() => options.transform?.(value)));
|
|
274
|
-
if (transformError || transformed === null || transformed === void 0) return require_lib_errors_index.err("PromptIOError", "Prompt transform callback failed unexpectedly");
|
|
275
|
-
return require_lib_errors_index.ok(transformed);
|
|
276
|
-
};
|
|
277
|
-
const runValidation = async (options, value) => {
|
|
278
|
-
if (!options.validate) return require_lib_errors_index.ok(null);
|
|
279
|
-
const [validationError, validationMessage] = await require_lib_errors_index.mightThrow(Promise.resolve().then(() => options.validate?.(value)));
|
|
280
|
-
if (validationError) return require_lib_errors_index.err("PromptIOError", "Prompt validate callback failed unexpectedly");
|
|
281
|
-
if (typeof validationMessage === "string" && validationMessage.length > 0) return require_lib_errors_index.ok(validationMessage);
|
|
282
|
-
return require_lib_errors_index.ok(null);
|
|
283
|
-
};
|
|
284
|
-
const isCancelKey = (key) => {
|
|
285
|
-
if (key.name === "ctrl_c") return true;
|
|
286
|
-
if (key.name === "escape") return true;
|
|
287
|
-
return false;
|
|
288
|
-
};
|
|
289
|
-
const runPromptSession = async (params) => {
|
|
290
|
-
const [initError] = params.runtime.init();
|
|
291
|
-
if (initError) return require_lib_errors_index.err(initError.type, initError.message);
|
|
292
|
-
let state = params.initialState;
|
|
293
|
-
let errorMessage = null;
|
|
294
|
-
const closeAndDone = (message) => {
|
|
295
|
-
const [closeErr] = params.runtime.close();
|
|
296
|
-
if (closeErr) return require_lib_errors_index.err(closeErr.type, closeErr.message);
|
|
297
|
-
const [doneErr] = params.runtime.done(message);
|
|
298
|
-
if (doneErr) return require_lib_errors_index.err(doneErr.type, doneErr.message);
|
|
299
|
-
return null;
|
|
300
|
-
};
|
|
301
|
-
while (true) {
|
|
302
|
-
const [renderError] = params.runtime.render(params.render({
|
|
303
|
-
options: params.options,
|
|
304
|
-
state,
|
|
305
|
-
errorMessage
|
|
306
|
-
}));
|
|
307
|
-
if (renderError) {
|
|
308
|
-
params.runtime.close();
|
|
309
|
-
return require_lib_errors_index.err(renderError.type, renderError.message);
|
|
310
|
-
}
|
|
311
|
-
const [readError, key] = await params.runtime.readKey();
|
|
312
|
-
if (readError || !key) {
|
|
313
|
-
params.runtime.close();
|
|
314
|
-
return require_lib_errors_index.err(readError?.type ?? "PromptIOError", readError?.message ?? "Unable to read prompt input");
|
|
315
|
-
}
|
|
316
|
-
if (isCancelKey(key)) {
|
|
317
|
-
const [closeError] = params.runtime.close();
|
|
318
|
-
if (closeError) return require_lib_errors_index.err(closeError.type, closeError.message);
|
|
319
|
-
const [doneError] = params.runtime.done(`✖ ${CANCEL_MESSAGE}`);
|
|
320
|
-
if (doneError) return require_lib_errors_index.err(doneError.type, doneError.message);
|
|
321
|
-
if (params.runtime.interrupt) {
|
|
322
|
-
const [interruptError] = params.runtime.interrupt(CANCEL_MESSAGE);
|
|
323
|
-
if (interruptError) return require_lib_errors_index.err(interruptError.type, interruptError.message);
|
|
324
|
-
}
|
|
325
|
-
return require_lib_errors_index.err("PromptCancelledError", CANCEL_MESSAGE);
|
|
326
|
-
}
|
|
327
|
-
if (key.name !== "enter") {
|
|
328
|
-
state = params.onKey(state, key);
|
|
329
|
-
errorMessage = null;
|
|
330
|
-
continue;
|
|
331
|
-
}
|
|
332
|
-
const submitResult = params.onSubmit(state);
|
|
333
|
-
if ("errorMessage" in submitResult) {
|
|
334
|
-
errorMessage = submitResult.errorMessage;
|
|
335
|
-
continue;
|
|
336
|
-
}
|
|
337
|
-
const rawValue = submitResult.value;
|
|
338
|
-
const [validationRunError, validationErrorMessage] = await runValidation(params.options, rawValue);
|
|
339
|
-
if (validationRunError) {
|
|
340
|
-
const closeDoneErr = closeAndDone(`✖ ${params.options.message}`);
|
|
341
|
-
if (closeDoneErr) return closeDoneErr;
|
|
342
|
-
return require_lib_errors_index.err(validationRunError.type, validationRunError.message);
|
|
343
|
-
}
|
|
344
|
-
if (validationErrorMessage) {
|
|
345
|
-
errorMessage = validationErrorMessage;
|
|
346
|
-
continue;
|
|
347
|
-
}
|
|
348
|
-
const [transformError, finalValue] = await resolveOutput(params.options, rawValue);
|
|
349
|
-
if (transformError) {
|
|
350
|
-
const closeDoneErr = closeAndDone(`✖ ${params.options.message}`);
|
|
351
|
-
if (closeDoneErr) return closeDoneErr;
|
|
352
|
-
return require_lib_errors_index.err(transformError.type, transformError.message);
|
|
353
|
-
}
|
|
354
|
-
if (finalValue === null) return require_lib_errors_index.err("PromptIOError", "Unable to transform prompt value");
|
|
355
|
-
const closeDoneErr = closeAndDone(params.complete({
|
|
356
|
-
options: params.options,
|
|
357
|
-
state,
|
|
358
|
-
value: finalValue
|
|
359
|
-
}));
|
|
360
|
-
if (closeDoneErr) return closeDoneErr;
|
|
361
|
-
return require_lib_errors_index.ok(finalValue);
|
|
362
|
-
}
|
|
363
|
-
};
|
|
364
|
-
//#endregion
|
|
365
|
-
//#region src/lib/prompts/index.ts
|
|
366
|
-
const pointer = (active) => {
|
|
367
|
-
return active ? paint("cyan", "❯") : " ";
|
|
368
|
-
};
|
|
369
|
-
const addErrorLine = (content, errorMessage) => {
|
|
370
|
-
if (!errorMessage) return content;
|
|
371
|
-
return `${content}\n${errorMark()} ${paint("red", errorMessage)}`;
|
|
372
|
-
};
|
|
373
|
-
const insertAt = (value, at, character) => {
|
|
374
|
-
return `${value.slice(0, at)}${character}${value.slice(at)}`;
|
|
375
|
-
};
|
|
376
|
-
const INVERSE = "\x1B[7m";
|
|
377
|
-
const RESET = "\x1B[0m";
|
|
378
|
-
const WHITESPACE = /\s/;
|
|
379
|
-
const NUMBER_CHAR = /[0-9.-]/;
|
|
380
|
-
const CURSOR_BLOCK = `${INVERSE} ${RESET}`;
|
|
381
|
-
const paint = (color, text) => {
|
|
382
|
-
return (0, node_util.styleText)(color, text, { validateStream: false });
|
|
383
|
-
};
|
|
384
|
-
const questionMark = () => paint("cyan", "?");
|
|
385
|
-
const successMark = () => paint("green", "✔");
|
|
386
|
-
const errorMark = () => paint("red", "✖");
|
|
387
|
-
const renderQuestionLine = (message, content) => {
|
|
388
|
-
return `${questionMark()} ${paint("cyan", message)} ${content}`;
|
|
389
|
-
};
|
|
390
|
-
const renderSuccessLine = (message, content) => {
|
|
391
|
-
return `${successMark()} ${message} ${content}`;
|
|
392
|
-
};
|
|
393
|
-
const createTextState = (value) => {
|
|
394
|
-
return {
|
|
395
|
-
value,
|
|
396
|
-
cursor: value.length,
|
|
397
|
-
selectionAnchor: null
|
|
398
|
-
};
|
|
399
|
-
};
|
|
400
|
-
const submitTextValue = (state, options) => {
|
|
401
|
-
const value = state.value.length > 0 ? state.value : options.defaultValue ?? "";
|
|
402
|
-
if (options.required && value.trim().length === 0) return { errorMessage: options.requiredMessage ?? "A value is required" };
|
|
403
|
-
return { value };
|
|
404
|
-
};
|
|
405
|
-
const getSelectionRange = (state) => {
|
|
406
|
-
if (state.selectionAnchor === null || state.selectionAnchor === state.cursor) return null;
|
|
407
|
-
return {
|
|
408
|
-
start: Math.min(state.selectionAnchor, state.cursor),
|
|
409
|
-
end: Math.max(state.selectionAnchor, state.cursor)
|
|
410
|
-
};
|
|
411
|
-
};
|
|
412
|
-
const moveCursor = (state, cursor, keepSelection) => {
|
|
413
|
-
if (!keepSelection) return {
|
|
414
|
-
...state,
|
|
415
|
-
cursor,
|
|
416
|
-
selectionAnchor: null
|
|
417
|
-
};
|
|
418
|
-
return {
|
|
419
|
-
...state,
|
|
420
|
-
cursor,
|
|
421
|
-
selectionAnchor: state.selectionAnchor ?? state.cursor
|
|
422
|
-
};
|
|
423
|
-
};
|
|
424
|
-
const deleteRange = (state, start, end) => {
|
|
425
|
-
return {
|
|
426
|
-
value: `${state.value.slice(0, start)}${state.value.slice(end)}`,
|
|
427
|
-
cursor: start,
|
|
428
|
-
selectionAnchor: null
|
|
429
|
-
};
|
|
430
|
-
};
|
|
431
|
-
const deleteSelectedRange = (state) => {
|
|
432
|
-
const selection = getSelectionRange(state);
|
|
433
|
-
if (!selection) return state;
|
|
434
|
-
return deleteRange(state, selection.start, selection.end);
|
|
435
|
-
};
|
|
436
|
-
const findWordStart = (value, cursor) => {
|
|
437
|
-
let index = cursor;
|
|
438
|
-
while (index > 0 && WHITESPACE.test(value[index - 1] ?? "")) index -= 1;
|
|
439
|
-
while (index > 0 && !WHITESPACE.test(value[index - 1] ?? "")) index -= 1;
|
|
440
|
-
return index;
|
|
441
|
-
};
|
|
442
|
-
const findWordEnd = (value, cursor) => {
|
|
443
|
-
let index = cursor;
|
|
444
|
-
while (index < value.length && WHITESPACE.test(value[index] ?? "")) index += 1;
|
|
445
|
-
while (index < value.length && !WHITESPACE.test(value[index] ?? "")) index += 1;
|
|
446
|
-
return index;
|
|
447
|
-
};
|
|
448
|
-
const renderTextSelection = (state, mask) => {
|
|
449
|
-
const selection = getSelectionRange(state);
|
|
450
|
-
const content = mask ? mask.repeat(state.value.length) : state.value;
|
|
451
|
-
const boundedCursor = Math.max(0, Math.min(state.cursor, content.length));
|
|
452
|
-
if (!selection) {
|
|
453
|
-
if (content.length === 0) return CURSOR_BLOCK;
|
|
454
|
-
if (boundedCursor === content.length) return `${content}${CURSOR_BLOCK}`;
|
|
455
|
-
const focusedChar = content[boundedCursor] ?? " ";
|
|
456
|
-
return `${content.slice(0, boundedCursor)}${INVERSE}${focusedChar}${RESET}${content.slice(boundedCursor + 1)}`;
|
|
457
|
-
}
|
|
458
|
-
const selected = content.slice(selection.start, selection.end);
|
|
459
|
-
return `${content.slice(0, selection.start)}${INVERSE}${selected}${RESET}${content.slice(selection.end)}`;
|
|
460
|
-
};
|
|
461
|
-
const textOnKey = (state, key) => {
|
|
462
|
-
switch (key.name) {
|
|
463
|
-
case "ctrl_a": return {
|
|
464
|
-
...state,
|
|
465
|
-
cursor: state.value.length,
|
|
466
|
-
selectionAnchor: 0
|
|
467
|
-
};
|
|
468
|
-
case "home": return moveCursor(state, 0, false);
|
|
469
|
-
case "end": return moveCursor(state, state.value.length, false);
|
|
470
|
-
case "shift_ctrl_left": return moveCursor(state, findWordStart(state.value, state.cursor), true);
|
|
471
|
-
case "shift_ctrl_right": return moveCursor(state, findWordEnd(state.value, state.cursor), true);
|
|
472
|
-
case "left": return moveCursor(state, Math.max(state.cursor - 1, 0), false);
|
|
473
|
-
case "shift_left": return moveCursor(state, Math.max(state.cursor - 1, 0), true);
|
|
474
|
-
case "right": return moveCursor(state, Math.min(state.cursor + 1, state.value.length), false);
|
|
475
|
-
case "ctrl_left": return moveCursor(state, findWordStart(state.value, state.cursor), false);
|
|
476
|
-
case "ctrl_right": return moveCursor(state, findWordEnd(state.value, state.cursor), false);
|
|
477
|
-
case "shift_right": return moveCursor(state, Math.min(state.cursor + 1, state.value.length), true);
|
|
478
|
-
case "backspace": {
|
|
479
|
-
const selectionDeleted = deleteSelectedRange(state);
|
|
480
|
-
if (selectionDeleted !== state) return selectionDeleted;
|
|
481
|
-
if (state.cursor === 0) return state;
|
|
482
|
-
const nextCursor = state.cursor - 1;
|
|
483
|
-
return {
|
|
484
|
-
value: `${state.value.slice(0, nextCursor)}${state.value.slice(state.cursor)}`,
|
|
485
|
-
cursor: nextCursor,
|
|
486
|
-
selectionAnchor: null
|
|
487
|
-
};
|
|
488
|
-
}
|
|
489
|
-
case "ctrl_backspace": {
|
|
490
|
-
const selectionDeleted = deleteSelectedRange(state);
|
|
491
|
-
if (selectionDeleted !== state) return selectionDeleted;
|
|
492
|
-
if (state.cursor === 0) return state;
|
|
493
|
-
return deleteRange(state, findWordStart(state.value, state.cursor), state.cursor);
|
|
494
|
-
}
|
|
495
|
-
case "delete": {
|
|
496
|
-
const selectionDeleted = deleteSelectedRange(state);
|
|
497
|
-
if (selectionDeleted !== state) return selectionDeleted;
|
|
498
|
-
return {
|
|
499
|
-
...state,
|
|
500
|
-
value: `${state.value.slice(0, state.cursor)}${state.value.slice(state.cursor + 1)}`
|
|
501
|
-
};
|
|
502
|
-
}
|
|
503
|
-
case "character":
|
|
504
|
-
case "space": {
|
|
505
|
-
const collapsed = deleteSelectedRange(state);
|
|
506
|
-
const text = key.name === "space" ? " " : key.value ?? "";
|
|
507
|
-
return {
|
|
508
|
-
value: insertAt(collapsed.value, collapsed.cursor, text),
|
|
509
|
-
cursor: collapsed.cursor + 1,
|
|
510
|
-
selectionAnchor: null
|
|
511
|
-
};
|
|
512
|
-
}
|
|
513
|
-
default: return state;
|
|
514
|
-
}
|
|
515
|
-
};
|
|
516
|
-
const input = async (options, runtime) => {
|
|
517
|
-
return runPromptSession({
|
|
518
|
-
runtime: runtime ?? createNodePromptRuntime(),
|
|
519
|
-
options,
|
|
520
|
-
initialState: createTextState(options.defaultValue ?? ""),
|
|
521
|
-
render: ({ options: currentOptions, state, errorMessage }) => {
|
|
522
|
-
let text = renderTextSelection(state);
|
|
523
|
-
if (state.value.length === 0 && currentOptions.placeholder) text = `${CURSOR_BLOCK}${paint("dim", currentOptions.placeholder)}`;
|
|
524
|
-
return addErrorLine(renderQuestionLine(currentOptions.message, text), errorMessage);
|
|
525
|
-
},
|
|
526
|
-
complete: ({ options: currentOptions, value }) => {
|
|
527
|
-
return renderSuccessLine(currentOptions.message, value);
|
|
528
|
-
},
|
|
529
|
-
onKey: (state, key) => {
|
|
530
|
-
return textOnKey(state, key);
|
|
531
|
-
},
|
|
532
|
-
onSubmit: (state) => submitTextValue(state, options)
|
|
533
|
-
});
|
|
534
|
-
};
|
|
535
|
-
const password = async (options, runtime) => {
|
|
536
|
-
const promptRuntime = runtime ?? createNodePromptRuntime();
|
|
537
|
-
const initialValue = options.defaultValue ?? "";
|
|
538
|
-
const mask = options.mask;
|
|
539
|
-
return runPromptSession({
|
|
540
|
-
runtime: promptRuntime,
|
|
541
|
-
options,
|
|
542
|
-
initialState: createTextState(initialValue),
|
|
543
|
-
render: ({ options: currentOptions, state, errorMessage }) => {
|
|
544
|
-
let visible;
|
|
545
|
-
if (state.value.length === 0 && currentOptions.placeholder) visible = `${CURSOR_BLOCK}${paint("dim", currentOptions.placeholder)}`;
|
|
546
|
-
else if (mask !== void 0) visible = renderTextSelection(state, mask);
|
|
547
|
-
else visible = CURSOR_BLOCK;
|
|
548
|
-
return addErrorLine(renderQuestionLine(currentOptions.message, visible), errorMessage);
|
|
549
|
-
},
|
|
550
|
-
complete: ({ options: currentOptions, value }) => {
|
|
551
|
-
return renderSuccessLine(currentOptions.message, mask !== void 0 ? mask.repeat(value.length) : "");
|
|
552
|
-
},
|
|
553
|
-
onKey: (state, key) => {
|
|
554
|
-
return textOnKey(state, key);
|
|
555
|
-
},
|
|
556
|
-
onSubmit: (state) => submitTextValue(state, options)
|
|
557
|
-
});
|
|
558
|
-
};
|
|
559
|
-
const confirm = async (options, runtime) => {
|
|
560
|
-
return runPromptSession({
|
|
561
|
-
runtime: runtime ?? createNodePromptRuntime(),
|
|
562
|
-
options,
|
|
563
|
-
initialState: { value: options.defaultValue ?? false },
|
|
564
|
-
render: ({ options: currentOptions, state, errorMessage }) => {
|
|
565
|
-
const yesLabel = currentOptions.activeLabel ?? "Yes";
|
|
566
|
-
const noLabel = currentOptions.inactiveLabel ?? "No";
|
|
567
|
-
const rendered = state.value ? yesLabel : noLabel;
|
|
568
|
-
return addErrorLine([renderQuestionLine(currentOptions.message, `(${rendered})`), paint("dim", " (y/n to select, ← yes / → no, space to toggle)")].join("\n"), errorMessage);
|
|
569
|
-
},
|
|
570
|
-
complete: ({ options: currentOptions, value }) => {
|
|
571
|
-
const label = value ? currentOptions.activeLabel ?? "Yes" : currentOptions.inactiveLabel ?? "No";
|
|
572
|
-
return renderSuccessLine(currentOptions.message, label);
|
|
573
|
-
},
|
|
574
|
-
onKey: (state, key) => {
|
|
575
|
-
switch (key.name) {
|
|
576
|
-
case "left": return { value: true };
|
|
577
|
-
case "right": return { value: false };
|
|
578
|
-
case "space": return { value: !state.value };
|
|
579
|
-
case "character": {
|
|
580
|
-
const lowered = (key.value ?? "").toLowerCase();
|
|
581
|
-
if (lowered === "y") return { value: true };
|
|
582
|
-
if (lowered === "n") return { value: false };
|
|
583
|
-
return state;
|
|
584
|
-
}
|
|
585
|
-
default: return state;
|
|
586
|
-
}
|
|
587
|
-
},
|
|
588
|
-
onSubmit: (state) => {
|
|
589
|
-
return { value: state.value };
|
|
590
|
-
}
|
|
591
|
-
});
|
|
592
|
-
};
|
|
593
|
-
const number = async (options, runtime) => {
|
|
594
|
-
return runPromptSession({
|
|
595
|
-
runtime: runtime ?? createNodePromptRuntime(),
|
|
596
|
-
options,
|
|
597
|
-
initialState: createTextState(options.defaultValue === void 0 ? "" : String(options.defaultValue)),
|
|
598
|
-
render: ({ options: currentOptions, state, errorMessage }) => {
|
|
599
|
-
return addErrorLine(renderQuestionLine(currentOptions.message, renderTextSelection(state)), errorMessage);
|
|
600
|
-
},
|
|
601
|
-
complete: ({ options: currentOptions, value }) => {
|
|
602
|
-
return renderSuccessLine(currentOptions.message, String(value));
|
|
603
|
-
},
|
|
604
|
-
onKey: (state, key) => {
|
|
605
|
-
const next = textOnKey(state, key);
|
|
606
|
-
if (!(key.name === "character" || key.name === "space")) return next;
|
|
607
|
-
const value = key.name === "space" ? " " : key.value ?? "";
|
|
608
|
-
if (!NUMBER_CHAR.test(value)) return state;
|
|
609
|
-
if (value === "." || value === "-") {
|
|
610
|
-
const collapsed = deleteSelectedRange(state);
|
|
611
|
-
if (value === "." && collapsed.value.includes(".")) return state;
|
|
612
|
-
if (value === "-") {
|
|
613
|
-
if (collapsed.cursor !== 0) return state;
|
|
614
|
-
if (collapsed.value.includes("-")) return state;
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
return next;
|
|
618
|
-
},
|
|
619
|
-
onSubmit: (state) => {
|
|
620
|
-
const raw = state.value.trim();
|
|
621
|
-
if (raw.length === 0) return { errorMessage: options.requiredMessage ?? "A number is required" };
|
|
622
|
-
const parsed = Number(raw);
|
|
623
|
-
if (!Number.isFinite(parsed)) return { errorMessage: options.invalidMessage ?? "Please enter a valid number" };
|
|
624
|
-
if (options.min !== void 0 && parsed < options.min) return { errorMessage: options.minMessage ?? `Number must be greater than or equal to ${options.min}` };
|
|
625
|
-
if (options.max !== void 0 && parsed > options.max) return { errorMessage: options.maxMessage ?? `Number must be lower than or equal to ${options.max}` };
|
|
626
|
-
return { value: parsed };
|
|
627
|
-
}
|
|
628
|
-
});
|
|
629
|
-
};
|
|
630
|
-
const findFirstEnabledIndex = (choices) => {
|
|
631
|
-
const firstEnabledIndex = choices.findIndex((choice) => !choice.disabled);
|
|
632
|
-
if (firstEnabledIndex >= 0) return firstEnabledIndex;
|
|
633
|
-
return 0;
|
|
634
|
-
};
|
|
635
|
-
const findNextEnabledIndex = (choices, cursor, direction) => {
|
|
636
|
-
const total = choices.length;
|
|
637
|
-
let currentCursor = cursor;
|
|
638
|
-
for (let offset = 0; offset < total; offset++) {
|
|
639
|
-
const nextCursor = (currentCursor + direction + total) % total;
|
|
640
|
-
const nextChoice = choices[nextCursor];
|
|
641
|
-
if (nextChoice && !nextChoice.disabled) return nextCursor;
|
|
642
|
-
currentCursor = nextCursor;
|
|
643
|
-
}
|
|
644
|
-
return currentCursor;
|
|
645
|
-
};
|
|
646
|
-
const findDefaultIndex = (choices, defaultValue) => {
|
|
647
|
-
if (defaultValue === void 0) return findFirstEnabledIndex(choices);
|
|
648
|
-
const index = choices.findIndex((choice) => choice.value === defaultValue && !choice.disabled);
|
|
649
|
-
if (index >= 0) return index;
|
|
650
|
-
return findFirstEnabledIndex(choices);
|
|
651
|
-
};
|
|
652
|
-
const select = async (options, runtime) => {
|
|
653
|
-
return runPromptSession({
|
|
654
|
-
runtime: runtime ?? createNodePromptRuntime(),
|
|
655
|
-
options,
|
|
656
|
-
initialState: { cursor: findDefaultIndex(options.choices, options.defaultValue) },
|
|
657
|
-
render: ({ options: currentOptions, state, errorMessage }) => {
|
|
658
|
-
const lines = [renderQuestionLine(currentOptions.message, "")];
|
|
659
|
-
for (let index = 0; index < currentOptions.choices.length; index++) {
|
|
660
|
-
const choice = currentOptions.choices[index];
|
|
661
|
-
if (!choice) continue;
|
|
662
|
-
const active = state.cursor === index;
|
|
663
|
-
const label = choice.label ?? choice.value;
|
|
664
|
-
const hint = choice.hint ? paint("dim", ` (${choice.hint})`) : "";
|
|
665
|
-
const disabled = choice.disabled ? paint("yellow", " [disabled]") : "";
|
|
666
|
-
lines.push(`${pointer(active)} ${label}${hint}${disabled}`);
|
|
667
|
-
}
|
|
668
|
-
return addErrorLine(lines.join("\n"), errorMessage);
|
|
669
|
-
},
|
|
670
|
-
complete: ({ options: currentOptions, value }) => {
|
|
671
|
-
const selected = currentOptions.choices.find((choice) => choice.value === value);
|
|
672
|
-
return renderSuccessLine(currentOptions.message, selected?.label ?? value);
|
|
673
|
-
},
|
|
674
|
-
onKey: (state, key) => {
|
|
675
|
-
switch (key.name) {
|
|
676
|
-
case "up": return { cursor: findNextEnabledIndex(options.choices, state.cursor, -1) };
|
|
677
|
-
case "down": return { cursor: findNextEnabledIndex(options.choices, state.cursor, 1) };
|
|
678
|
-
default: return state;
|
|
679
|
-
}
|
|
680
|
-
},
|
|
681
|
-
onSubmit: (state) => {
|
|
682
|
-
const selectedChoice = options.choices[state.cursor];
|
|
683
|
-
if (!selectedChoice) return { errorMessage: "Please select an option" };
|
|
684
|
-
if (selectedChoice.disabled) return { errorMessage: "Selected option is disabled" };
|
|
685
|
-
return { value: selectedChoice.value };
|
|
686
|
-
}
|
|
687
|
-
});
|
|
688
|
-
};
|
|
689
|
-
const multiselect = async (options, runtime) => {
|
|
690
|
-
return runPromptSession({
|
|
691
|
-
runtime: runtime ?? createNodePromptRuntime(),
|
|
692
|
-
options,
|
|
693
|
-
initialState: {
|
|
694
|
-
cursor: findFirstEnabledIndex(options.choices),
|
|
695
|
-
selected: new Set(options.defaultValue ?? [])
|
|
696
|
-
},
|
|
697
|
-
render: ({ options: currentOptions, state, errorMessage }) => {
|
|
698
|
-
const lines = [renderQuestionLine(currentOptions.message, "")];
|
|
699
|
-
for (let index = 0; index < currentOptions.choices.length; index++) {
|
|
700
|
-
const choice = currentOptions.choices[index];
|
|
701
|
-
if (!choice) continue;
|
|
702
|
-
const active = state.cursor === index;
|
|
703
|
-
const checked = state.selected.has(choice.value) ? "◉" : "◯";
|
|
704
|
-
const disabled = choice.disabled ? paint("yellow", " [disabled]") : "";
|
|
705
|
-
const label = choice.label ?? choice.value;
|
|
706
|
-
const hint = choice.hint ? paint("dim", ` (${choice.hint})`) : "";
|
|
707
|
-
lines.push(`${pointer(active)} ${checked} ${label}${hint}${disabled}`);
|
|
708
|
-
}
|
|
709
|
-
lines.push(paint("dim", " (space to toggle, a to toggle all, enter to submit)"));
|
|
710
|
-
return addErrorLine(lines.join("\n"), errorMessage);
|
|
711
|
-
},
|
|
712
|
-
complete: ({ options: currentOptions, value }) => {
|
|
713
|
-
const labelMap = new Map(currentOptions.choices.map((choice) => [choice.value, choice.label]));
|
|
714
|
-
const labels = value.map((v) => labelMap.get(v) ?? v);
|
|
715
|
-
return renderSuccessLine(currentOptions.message, labels.join(", "));
|
|
716
|
-
},
|
|
717
|
-
onKey: (state, key) => {
|
|
718
|
-
switch (key.name) {
|
|
719
|
-
case "up": return {
|
|
720
|
-
...state,
|
|
721
|
-
cursor: findNextEnabledIndex(options.choices, state.cursor, -1)
|
|
722
|
-
};
|
|
723
|
-
case "down": return {
|
|
724
|
-
...state,
|
|
725
|
-
cursor: findNextEnabledIndex(options.choices, state.cursor, 1)
|
|
726
|
-
};
|
|
727
|
-
case "character":
|
|
728
|
-
if ((key.value ?? "").toLowerCase() === "a") {
|
|
729
|
-
const enabledValues = options.choices.filter((choice) => !choice.disabled).map((choice) => choice.value);
|
|
730
|
-
if (!(enabledValues.length > 0)) return state;
|
|
731
|
-
const areAllEnabledSelected = enabledValues.every((value) => state.selected.has(value));
|
|
732
|
-
const nextSelection = new Set(state.selected);
|
|
733
|
-
if (areAllEnabledSelected) for (const value of enabledValues) nextSelection.delete(value);
|
|
734
|
-
else for (const value of enabledValues) nextSelection.add(value);
|
|
735
|
-
return {
|
|
736
|
-
...state,
|
|
737
|
-
selected: nextSelection
|
|
738
|
-
};
|
|
739
|
-
}
|
|
740
|
-
return state;
|
|
741
|
-
case "space": {
|
|
742
|
-
const currentChoice = options.choices[state.cursor];
|
|
743
|
-
if (!currentChoice || currentChoice.disabled) return state;
|
|
744
|
-
const nextSelection = new Set(state.selected);
|
|
745
|
-
if (nextSelection.has(currentChoice.value)) nextSelection.delete(currentChoice.value);
|
|
746
|
-
else nextSelection.add(currentChoice.value);
|
|
747
|
-
return {
|
|
748
|
-
...state,
|
|
749
|
-
selected: nextSelection
|
|
750
|
-
};
|
|
751
|
-
}
|
|
752
|
-
default: return state;
|
|
753
|
-
}
|
|
754
|
-
},
|
|
755
|
-
onSubmit: (state) => {
|
|
756
|
-
const values = options.choices.filter((choice) => state.selected.has(choice.value)).map((choice) => choice.value);
|
|
757
|
-
if (options.min !== void 0 && values.length < options.min) return { errorMessage: `Please select at least ${options.min} options` };
|
|
758
|
-
if (options.max !== void 0 && values.length > options.max) return { errorMessage: `Please select at most ${options.max} options` };
|
|
759
|
-
return { value: values };
|
|
760
|
-
}
|
|
761
|
-
});
|
|
762
|
-
};
|
|
763
|
-
//#endregion
|
|
764
|
-
exports.confirm = confirm;
|
|
765
|
-
exports.input = input;
|
|
766
|
-
exports.multiselect = multiselect;
|
|
767
|
-
exports.number = number;
|
|
768
|
-
exports.password = password;
|
|
769
|
-
exports.select = select;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../errors/index.cjs");let t=require("node:util");var n=class extends Error{constructor(e){super(e),this.name=`PromptIOError`}},r=class extends Error{constructor(e){super(e),this.name=`PromptEnvironmentError`}},i=class extends Error{constructor(e){super(e),this.name=`PromptCancelledError`}};const a=new Map(Object.values({enterCr:{value:`\r`,name:`enter`},enterLf:{value:`
|
|
2
|
+
`,name:`enter`},ctrlA:{value:``,name:`ctrl_a`},ctrlC:{value:``,name:`ctrl_c`},ctrlBackspace:{value:``,name:`ctrl_backspace`},backspace:{value:``,name:`backspace`},tab:{value:` `,name:`tab`},space:{value:` `,name:`space`}}).map(e=>[e.value,{name:e.name}])),o=[{sequence:`\x1B[1;2D`,key:{name:`shift_left`}},{sequence:`\x1B[1;2C`,key:{name:`shift_right`}},{sequence:`\x1B[1;5D`,key:{name:`ctrl_left`}},{sequence:`\x1B[1;5C`,key:{name:`ctrl_right`}},{sequence:`\x1B[1;6D`,key:{name:`shift_ctrl_left`}},{sequence:`\x1B[1;6C`,key:{name:`shift_ctrl_right`}},{sequence:`\x1B[3~`,key:{name:`delete`}},{sequence:`\x1B[H`,key:{name:`home`}},{sequence:`\x1B[F`,key:{name:`end`}},{sequence:`\x1B[A`,key:{name:`up`}},{sequence:`\x1B[B`,key:{name:`down`}},{sequence:`\x1B[C`,key:{name:`right`}},{sequence:`\x1B[D`,key:{name:`left`}}],s=e=>e<=``||e===``,c=e=>e?e>=`A`&&e<=`Z`||e>=`a`&&e<=`z`||e===`~`:!1,l=e=>{if(!e.startsWith(`\x1B[`))return null;let t=2;for(;t<e.length;){let n=e[t]??``;if(c(n))return{length:t+1,incomplete:!1};t+=1}return{length:0,incomplete:!0}},u=e=>{let t=[],n=0;for(;n<e.length;){let r=e.slice(n);if(r.startsWith(`\x1B`)){t.push({name:`ctrl_backspace`}),n+=2;continue}let i=o.find(e=>r.startsWith(e.sequence));if(i){t.push(i.key),n+=i.sequence.length;continue}let c=l(r);if(c){if(c.incomplete)return{keys:t,remaining:e.slice(n)};n+=c.length;continue}let u=e[n]??``;switch(u){case`\x1B`:n===e.length-1&&t.push({name:`escape`});break;default:{let e=a.get(u);e?t.push(e):s(u)||t.push({name:`character`,value:u})}}n+=1}return{keys:t,remaining:``}},d=e=>{let t=1;for(let n=0;n<e.length;n++)e[n]===`
|
|
3
|
+
`&&(t+=1);return t};var f=class{stdin;stdout;queue=[];waiters=[];initialized=!1;previousLines=0;buffer=``;constructor(e=process.stdin,t=process.stdout){this.stdin=e,this.stdout=t}isInteractive(){return!!(this.stdin.isTTY&&this.stdout.isTTY&&typeof this.stdin.setRawMode==`function`)}init(){if(!this.isInteractive())throw new r(`Interactive prompts require a TTY with raw mode support`);if(this.initialized)return;let[t]=e.mightThrowSync(()=>{this.stdin.setRawMode(!0),this.stdin.setEncoding(`utf8`),this.stdin.resume(),this.stdin.on(`data`,this.onData),this.stdout.write(`\x1B[?25l`)});if(t)throw new n(`Unable to initialize prompt runtime`);this.initialized=!0}readKey(){let e=this.queue.shift();return e?Promise.resolve(e):new Promise((e,t)=>{this.waiters.push({resolve:e,reject:t})})}render(t){let[r]=e.mightThrowSync(()=>{this.previousLines>1&&this.stdout.write(`\u001B[${this.previousLines-1}A`),this.stdout.write(`\r\x1B[J`),this.stdout.write(t),this.previousLines=d(t)});if(r)throw new n(`Unable to render prompt frame`)}done(t){let[r]=e.mightThrowSync(()=>{this.previousLines>1&&this.stdout.write(`\u001B[${this.previousLines-1}A`),this.stdout.write(`\r\x1B[J`),this.stdout.write(`${t}\n`),this.previousLines=0});if(r)throw new n(`Unable to finalize prompt frame`)}close(){if(!this.initialized)return;this.initialized=!1;let[t]=e.mightThrowSync(()=>{this.stdin.off(`data`,this.onData),this.stdin.setRawMode(!1),this.stdin.pause?.(),this.stdout.write(`\x1B[?25h`)});if(t)throw new n(`Unable to close prompt runtime`)}interrupt(){this.close(),process.exit(0)}onData=t=>{let r=typeof t==`string`?t:t.toString(`utf8`),i=`${this.buffer}${r}`;this.buffer=``;let[a,o]=e.mightThrowSync(()=>u(i));if(a||!o){for(let e of this.waiters.splice(0))e.reject(new n(`Failed to parse input`));return}this.buffer=o.remaining;for(let e of o.keys){let t=this.waiters.shift();t?t.resolve(e):this.queue.push(e)}}};const p=()=>new f,m=`Interrupted, bye!`,h=async(t,r)=>{if(!t.transform)return r;let[i,a]=await e.mightThrow(Promise.resolve().then(()=>t.transform?.(r)));if(i||a==null)throw new n(`Prompt transform callback failed unexpectedly`);return a},g=async(t,r)=>{if(!t.validate)return null;let[i,a]=await e.mightThrow(Promise.resolve().then(()=>t.validate?.(r)));if(i)throw new n(`Prompt validate callback failed unexpectedly`);return typeof a==`string`&&a.length>0?a:null},_=e=>e.name===`ctrl_c`||e.name===`escape`,v=async t=>{t.runtime.init();let r=t.initialState,a=null,o=e=>{t.runtime.close(),t.runtime.done(e)},[s,c]=await e.mightThrow((async()=>{for(;;){t.runtime.render(t.render({options:t.options,state:r,errorMessage:a}));let e=await t.runtime.readKey();if(!e)throw new n(`Unable to read prompt input`);if(_(e))throw t.runtime.close(),t.runtime.done(`✖ ${m}`),t.runtime.interrupt&&t.runtime.interrupt(m),new i(m);if(e.name!==`enter`){r=t.onKey(r,e),a=null;continue}let s=t.onSubmit(r);if(`errorMessage`in s){a=s.errorMessage;continue}let c=s.value,l=await g(t.options,c);if(l){a=l;continue}let u=await h(t.options,c);if(u===null)throw new n(`Unable to transform prompt value`);return o(t.complete({options:t.options,state:r,value:u})),u}})());if(s)throw t.runtime.close(),s;return c},y=e=>e?D(`cyan`,`❯`):` `,b=(e,t)=>t?`${e}\n${A()} ${D(`red`,t)}`:e,x=(e,t,n)=>`${e.slice(0,t)}${n}${e.slice(t)}`,S=`\x1B[7m`,C=`\x1B[0m`,w=/\s/,T=/[0-9.-]/,E=`${S} ${C}`,D=(e,n)=>(0,t.styleText)(e,n,{validateStream:!1}),O=()=>D(`cyan`,`?`),k=()=>D(`green`,`✔`),A=()=>D(`red`,`✖`),j=(e,t)=>`${O()} ${D(`cyan`,e)} ${t}`,M=(e,t)=>`${k()} ${e} ${t}`,N=e=>({value:e,cursor:e.length,selectionAnchor:null}),P=(e,t)=>{let n=e.value.length>0?e.value:t.defaultValue??``;return t.required&&n.trim().length===0?{errorMessage:t.requiredMessage??`A value is required`}:{value:n}},F=e=>e.selectionAnchor===null||e.selectionAnchor===e.cursor?null:{start:Math.min(e.selectionAnchor,e.cursor),end:Math.max(e.selectionAnchor,e.cursor)},I=(e,t,n)=>n?{...e,cursor:t,selectionAnchor:e.selectionAnchor??e.cursor}:{...e,cursor:t,selectionAnchor:null},L=(e,t,n)=>({value:`${e.value.slice(0,t)}${e.value.slice(n)}`,cursor:t,selectionAnchor:null}),R=e=>{let t=F(e);return t?L(e,t.start,t.end):e},z=(e,t)=>{let n=t;for(;n>0&&w.test(e[n-1]??``);)--n;for(;n>0&&!w.test(e[n-1]??``);)--n;return n},B=(e,t)=>{let n=t;for(;n<e.length&&w.test(e[n]??``);)n+=1;for(;n<e.length&&!w.test(e[n]??``);)n+=1;return n},V=(e,t)=>{let n=F(e),r=t?t.repeat(e.value.length):e.value,i=Math.max(0,Math.min(e.cursor,r.length));if(!n){if(r.length===0)return E;if(i===r.length)return`${r}${E}`;let e=r[i]??` `;return`${r.slice(0,i)}${S}${e}${C}${r.slice(i+1)}`}let a=r.slice(n.start,n.end);return`${r.slice(0,n.start)}${S}${a}${C}${r.slice(n.end)}`},H=(e,t)=>{switch(t.name){case`ctrl_a`:return{...e,cursor:e.value.length,selectionAnchor:0};case`home`:return I(e,0,!1);case`end`:return I(e,e.value.length,!1);case`shift_ctrl_left`:return I(e,z(e.value,e.cursor),!0);case`shift_ctrl_right`:return I(e,B(e.value,e.cursor),!0);case`left`:return I(e,Math.max(e.cursor-1,0),!1);case`shift_left`:return I(e,Math.max(e.cursor-1,0),!0);case`right`:return I(e,Math.min(e.cursor+1,e.value.length),!1);case`ctrl_left`:return I(e,z(e.value,e.cursor),!1);case`ctrl_right`:return I(e,B(e.value,e.cursor),!1);case`shift_right`:return I(e,Math.min(e.cursor+1,e.value.length),!0);case`backspace`:{let t=R(e);if(t!==e)return t;if(e.cursor===0)return e;let n=e.cursor-1;return{value:`${e.value.slice(0,n)}${e.value.slice(e.cursor)}`,cursor:n,selectionAnchor:null}}case`ctrl_backspace`:{let t=R(e);if(t!==e)return t;if(e.cursor===0)return e;let n=z(e.value,e.cursor);return L(e,n,e.cursor)}case`delete`:{let t=R(e);return t===e?{...e,value:`${e.value.slice(0,e.cursor)}${e.value.slice(e.cursor+1)}`}:t}case`character`:case`space`:{let n=R(e),r=t.name===`space`?` `:t.value??``;return{value:x(n.value,n.cursor,r),cursor:n.cursor+1,selectionAnchor:null}}default:return e}},U=async(e,t)=>{let n=t??p(),r=e.defaultValue??``;return v({runtime:n,options:e,initialState:N(r),render:({options:e,state:t,errorMessage:n})=>{let r=V(t);return t.value.length===0&&e.placeholder&&(r=`${E}${D(`dim`,e.placeholder)}`),b(j(e.message,r),n)},complete:({options:e,value:t})=>M(e.message,t),onKey:(e,t)=>H(e,t),onSubmit:t=>P(t,e)})},W=async(e,t)=>{let n=t??p(),r=e.defaultValue??``,i=e.mask;return v({runtime:n,options:e,initialState:N(r),render:({options:e,state:t,errorMessage:n})=>{let r;return r=t.value.length===0&&e.placeholder?`${E}${D(`dim`,e.placeholder)}`:i===void 0?E:V(t,i),b(j(e.message,r),n)},complete:({options:e,value:t})=>M(e.message,i===void 0?``:i.repeat(t.length)),onKey:(e,t)=>H(e,t),onSubmit:t=>P(t,e)})},G=async(e,t)=>v({runtime:t??p(),options:e,initialState:{value:e.defaultValue??!1},render:({options:e,state:t,errorMessage:n})=>{let r=e.activeLabel??`Yes`,i=e.inactiveLabel??`No`,a=t.value?r:i;return b([j(e.message,`(${a})`),D(`dim`,` (y/n to select, ← yes / → no, space to toggle)`)].join(`
|
|
4
|
+
`),n)},complete:({options:e,value:t})=>{let n=t?e.activeLabel??`Yes`:e.inactiveLabel??`No`;return M(e.message,n)},onKey:(e,t)=>{switch(t.name){case`left`:return{value:!0};case`right`:return{value:!1};case`space`:return{value:!e.value};case`character`:{let n=(t.value??``).toLowerCase();return n===`y`?{value:!0}:n===`n`?{value:!1}:e}default:return e}},onSubmit:e=>({value:e.value})}),K=async(e,t)=>{let n=t??p(),r=e.defaultValue===void 0?``:String(e.defaultValue);return v({runtime:n,options:e,initialState:N(r),render:({options:e,state:t,errorMessage:n})=>b(j(e.message,V(t)),n),complete:({options:e,value:t})=>M(e.message,String(t)),onKey:(e,t)=>{let n=H(e,t);if(!(t.name===`character`||t.name===`space`))return n;let r=t.name===`space`?` `:t.value??``;if(!T.test(r))return e;if(r===`.`||r===`-`){let t=R(e);if(r===`.`&&t.value.includes(`.`)||r===`-`&&(t.cursor!==0||t.value.includes(`-`)))return e}return n},onSubmit:t=>{let n=t.value.trim();if(n.length===0)return{errorMessage:e.requiredMessage??`A number is required`};let r=Number(n);return Number.isFinite(r)?e.min!==void 0&&r<e.min?{errorMessage:e.minMessage??`Number must be greater than or equal to ${e.min}`}:e.max!==void 0&&r>e.max?{errorMessage:e.maxMessage??`Number must be lower than or equal to ${e.max}`}:{value:r}:{errorMessage:e.invalidMessage??`Please enter a valid number`}}})},q=e=>{let t=e.findIndex(e=>!e.disabled);return t>=0?t:0},J=(e,t,n)=>{let r=e.length,i=t;for(let t=0;t<r;t++){let t=(i+n+r)%r,a=e[t];if(a&&!a.disabled)return t;i=t}return i},Y=(e,t)=>{if(t===void 0)return q(e);let n=e.findIndex(e=>e.value===t&&!e.disabled);return n>=0?n:q(e)},X=async(e,t)=>v({runtime:t??p(),options:e,initialState:{cursor:Y(e.choices,e.defaultValue)},render:({options:e,state:t,errorMessage:n})=>{let r=[j(e.message,``)];for(let n=0;n<e.choices.length;n++){let i=e.choices[n];if(!i)continue;let a=t.cursor===n,o=i.label??i.value,s=i.hint?D(`dim`,` (${i.hint})`):``,c=i.disabled?D(`yellow`,` [disabled]`):``;r.push(`${y(a)} ${o}${s}${c}`)}return b(r.join(`
|
|
5
|
+
`),n)},complete:({options:e,value:t})=>{let n=e.choices.find(e=>e.value===t);return M(e.message,n?.label??t)},onKey:(t,n)=>{switch(n.name){case`up`:return{cursor:J(e.choices,t.cursor,-1)};case`down`:return{cursor:J(e.choices,t.cursor,1)};default:return t}},onSubmit:t=>{let n=e.choices[t.cursor];return n?n.disabled?{errorMessage:`Selected option is disabled`}:{value:n.value}:{errorMessage:`Please select an option`}}}),Z=async(e,t)=>v({runtime:t??p(),options:e,initialState:{cursor:q(e.choices),selected:new Set(e.defaultValue??[])},render:({options:e,state:t,errorMessage:n})=>{let r=[j(e.message,``)];for(let n=0;n<e.choices.length;n++){let i=e.choices[n];if(!i)continue;let a=t.cursor===n,o=t.selected.has(i.value)?`◉`:`◯`,s=i.disabled?D(`yellow`,` [disabled]`):``,c=i.label??i.value,l=i.hint?D(`dim`,` (${i.hint})`):``;r.push(`${y(a)} ${o} ${c}${l}${s}`)}return r.push(D(`dim`,` (space to toggle, a to toggle all, enter to submit)`)),b(r.join(`
|
|
6
|
+
`),n)},complete:({options:e,value:t})=>{let n=new Map(e.choices.map(e=>[e.value,e.label])),r=t.map(e=>n.get(e)??e);return M(e.message,r.join(`, `))},onKey:(t,n)=>{switch(n.name){case`up`:return{...t,cursor:J(e.choices,t.cursor,-1)};case`down`:return{...t,cursor:J(e.choices,t.cursor,1)};case`character`:if((n.value??``).toLowerCase()===`a`){let n=e.choices.filter(e=>!e.disabled).map(e=>e.value);if(!(n.length>0))return t;let r=n.every(e=>t.selected.has(e)),i=new Set(t.selected);if(r)for(let e of n)i.delete(e);else for(let e of n)i.add(e);return{...t,selected:i}}return t;case`space`:{let n=e.choices[t.cursor];if(!n||n.disabled)return t;let r=new Set(t.selected);return r.has(n.value)?r.delete(n.value):r.add(n.value),{...t,selected:r}}default:return t}},onSubmit:t=>{let n=e.choices.filter(e=>t.selected.has(e.value)).map(e=>e.value);return e.min!==void 0&&n.length<e.min?{errorMessage:`Please select at least ${e.min} options`}:e.max!==void 0&&n.length>e.max?{errorMessage:`Please select at most ${e.max} options`}:{value:n}}});exports.confirm=G,exports.input=U,exports.multiselect=Z,exports.number=K,exports.password=W,exports.select=X;
|