@reliverse/relinka 1.1.6 → 1.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-npm/components/anykey/index.js +57 -77
- package/dist-npm/components/block/block.js +48 -61
- package/dist-npm/components/checkbox/index.js +178 -211
- package/dist-npm/components/confirm/confirm-main.js +85 -122
- package/dist-npm/components/confirm/confirm-three.js +24 -27
- package/dist-npm/components/confirm/index.js +36 -45
- package/dist-npm/components/core/Separator.js +15 -17
- package/dist-npm/components/core/create-prompt.js +101 -124
- package/dist-npm/components/core/errors.js +19 -15
- package/dist-npm/components/core/hook-engine.js +91 -120
- package/dist-npm/components/core/index.js +12 -12
- package/dist-npm/components/core/key.js +16 -6
- package/dist-npm/components/core/lines.js +45 -54
- package/dist-npm/components/core/make-theme.js +21 -30
- package/dist-npm/components/core/position.js +27 -23
- package/dist-npm/components/core/promise-polyfill.js +11 -14
- package/dist-npm/components/core/screen-manager.js +59 -74
- package/dist-npm/components/core/theme.js +22 -32
- package/dist-npm/components/core/use-effect.js +9 -15
- package/dist-npm/components/core/use-keypress.js +19 -23
- package/dist-npm/components/core/use-memo.js +10 -16
- package/dist-npm/components/core/use-pagination.js +33 -32
- package/dist-npm/components/core/use-prefix.js +40 -38
- package/dist-npm/components/core/use-ref.js +2 -5
- package/dist-npm/components/core/use-state.js +15 -23
- package/dist-npm/components/core/useKeyPress.js +14 -17
- package/dist-npm/components/core/usePromptState.js +8 -14
- package/dist-npm/components/core/utils.js +7 -16
- package/dist-npm/components/date/date.js +173 -204
- package/dist-npm/components/editor/index.js +71 -92
- package/dist-npm/components/expand/index.js +96 -124
- package/dist-npm/components/figures/index.js +283 -294
- package/dist-npm/components/input/index.js +61 -87
- package/dist-npm/components/input/text-main.js +97 -124
- package/dist-npm/components/input/text.js +24 -28
- package/dist-npm/components/instance/basic.js +17 -25
- package/dist-npm/components/instance/browser.js +14 -18
- package/dist-npm/components/instance/reporter/basic.js +46 -65
- package/dist-npm/components/instance/reporter/browser.js +44 -47
- package/dist-npm/components/instance/reporter/fancy.js +83 -96
- package/dist-npm/components/instance/shared.js +2 -2
- package/dist-npm/components/mono/mono.js +52 -62
- package/dist-npm/components/mono/monoTwo.js +35 -49
- package/dist-npm/components/multiselect/group-multiselect.js +55 -71
- package/dist-npm/components/multiselect/multi-select-two.js +97 -130
- package/dist-npm/components/multiselect/multi-select.js +43 -49
- package/dist-npm/components/multiselect/multiselect-main.d.ts +1 -0
- package/dist-npm/components/multiselect/multiselect-main.js +158 -145
- package/dist-npm/components/multiselect/num-multi-select.js +97 -130
- package/dist-npm/components/multiselect/num-multiselect-main.js +24 -35
- package/dist-npm/components/next-steps/next-steps.js +23 -25
- package/dist-npm/components/number/index.js +78 -112
- package/dist-npm/components/number/number-main.js +95 -2
- package/dist-npm/components/password/index.js +54 -73
- package/dist-npm/components/password/password-main.js +119 -2
- package/dist-npm/components/password/password-three.js +26 -30
- package/dist-npm/components/progressbar/ProgressBar.js +45 -64
- package/dist-npm/components/progressbar/helper.js +33 -40
- package/dist-npm/components/progressbar/index.js +1 -1
- package/dist-npm/components/prompts/create.js +29 -44
- package/dist-npm/components/prompts/index.d.ts +1 -0
- package/dist-npm/components/prompts/index.js +46 -45
- package/dist-npm/components/prompts/prompt.js +211 -260
- package/dist-npm/components/prompts/promptTwo.js +561 -605
- package/dist-npm/components/prompts/relinka.js +237 -295
- package/dist-npm/components/range/range.js +247 -294
- package/dist-npm/components/rawlist/index.js +87 -107
- package/dist-npm/components/results/results.js +31 -37
- package/dist-npm/components/search/index.js +148 -193
- package/dist-npm/components/select/index.js +148 -186
- package/dist-npm/components/select/num-select-main.js +27 -27
- package/dist-npm/components/select/num-select.js +124 -5
- package/dist-npm/components/select/select-key.js +24 -25
- package/dist-npm/components/select/select-main.d.ts +1 -0
- package/dist-npm/components/select/select-main.js +143 -133
- package/dist-npm/components/select/select-three.js +32 -36
- package/dist-npm/components/select/select-two.js +94 -87
- package/dist-npm/components/spinner/index.js +107 -136
- package/dist-npm/components/st-end/end.js +34 -26
- package/dist-npm/components/st-end/start.js +29 -15
- package/dist-npm/components/toggle/index.js +113 -137
- package/dist-npm/components/visual/animate/animate.js +53 -10
- package/dist-npm/components/visual/ascii-art/ascii-art.js +12 -1
- package/dist-npm/main.js +1 -0
- package/dist-npm/testing/index.js +58 -83
- package/dist-npm/types/general.d.ts +1 -1
- package/dist-npm/types/general.js +0 -1
- package/dist-npm/types/index.js +2 -3
- package/dist-npm/types/keypress.js +35 -36
- package/dist-npm/types/readline.js +0 -1
- package/dist-npm/types/relinka.js +0 -1
- package/dist-npm/types/utils.js +0 -1
- package/dist-npm/utils/box.js +135 -137
- package/dist-npm/utils/color.js +65 -74
- package/dist-npm/utils/colorize.js +124 -156
- package/dist-npm/utils/component.js +532 -657
- package/dist-npm/utils/constants.js +64 -63
- package/dist-npm/utils/core.js +2 -3
- package/dist-npm/utils/decoder.js +244 -223
- package/dist-npm/utils/error.js +4 -9
- package/dist-npm/utils/errors.js +14 -4
- package/dist-npm/utils/format.js +19 -24
- package/dist-npm/utils/keypress.js +316 -414
- package/dist-npm/utils/log.js +11 -15
- package/dist-npm/utils/mapping.js +45 -52
- package/dist-npm/utils/messages.js +196 -183
- package/dist-npm/utils/platforms.js +16 -20
- package/dist-npm/utils/prompt-tmp.js +235 -286
- package/dist-npm/utils/prompt-two.js +235 -286
- package/dist-npm/utils/readline.js +5 -7
- package/dist-npm/utils/skeleton.js +130 -170
- package/dist-npm/utils/stream.js +2 -2
- package/dist-npm/utils/string.js +44 -58
- package/dist-npm/utils/terminal.js +23 -34
- package/dist-npm/utils/tree.js +30 -41
- package/dist-npm/utils/types.js +0 -1
- package/dist-npm/utils/utils.js +8 -8
- package/dist-npm/utils/variants.js +36 -44
- package/package.json +14 -14
- package/dist-npm/mod.js +0 -2
- /package/dist-npm/{mod.d.ts → main.d.ts} +0 -0
|
@@ -1,135 +1,98 @@
|
|
|
1
|
-
import {Value} from
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
} from
|
|
6
|
-
import
|
|
7
|
-
import {colorize} from '../../utils/colorize.js';
|
|
8
|
-
import {
|
|
9
|
-
bar,
|
|
10
|
-
fmt,
|
|
11
|
-
msg,
|
|
12
|
-
} from '../../utils/messages.js';
|
|
13
|
-
import {
|
|
14
|
-
countLines,
|
|
15
|
-
deleteLastLines,
|
|
16
|
-
} from '../../utils/terminal.js';
|
|
17
|
-
|
|
1
|
+
import { Value } from "@sinclair/typebox/value";
|
|
2
|
+
import { stdin as input, stdout as output } from "node:process";
|
|
3
|
+
import readline from "node:readline/promises";
|
|
4
|
+
import { colorize } from "../../utils/colorize.js";
|
|
5
|
+
import { bar, fmt, msg } from "../../utils/messages.js";
|
|
6
|
+
import { countLines, deleteLastLines } from "../../utils/terminal.js";
|
|
18
7
|
export async function confirmPrompt(options) {
|
|
19
|
-
|
|
8
|
+
const {
|
|
9
|
+
title,
|
|
10
|
+
defaultValue,
|
|
11
|
+
schema,
|
|
12
|
+
titleColor = "cyanBright",
|
|
13
|
+
titleTypography = "bold",
|
|
14
|
+
titleVariant,
|
|
15
|
+
content,
|
|
16
|
+
contentColor,
|
|
17
|
+
contentTypography,
|
|
18
|
+
contentVariant,
|
|
19
|
+
borderColor = "viceGradient",
|
|
20
|
+
hintColor = "dim",
|
|
21
|
+
variantOptions,
|
|
22
|
+
action
|
|
23
|
+
} = options;
|
|
24
|
+
const rl = readline.createInterface({ input, output });
|
|
25
|
+
let linesToDelete = 0;
|
|
26
|
+
let errorMessage = "";
|
|
27
|
+
try {
|
|
28
|
+
while (true) {
|
|
29
|
+
if (linesToDelete > 0) {
|
|
30
|
+
deleteLastLines(linesToDelete);
|
|
31
|
+
}
|
|
32
|
+
const question = fmt({
|
|
33
|
+
type: errorMessage !== "" ? "M_ERROR" : "M_GENERAL",
|
|
20
34
|
title,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
titleColor = 'cyanBright',
|
|
24
|
-
titleTypography = 'bold',
|
|
35
|
+
titleColor,
|
|
36
|
+
titleTypography,
|
|
25
37
|
titleVariant,
|
|
26
38
|
content,
|
|
27
39
|
contentColor,
|
|
28
40
|
contentTypography,
|
|
29
41
|
contentVariant,
|
|
30
|
-
borderColor
|
|
31
|
-
hintColor = 'dim',
|
|
42
|
+
borderColor,
|
|
32
43
|
variantOptions,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
contentColor,
|
|
57
|
-
contentTypography,
|
|
58
|
-
contentVariant,
|
|
59
|
-
borderColor,
|
|
60
|
-
variantOptions,
|
|
61
|
-
errorMessage,
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
let defaultHint = '';
|
|
65
|
-
|
|
66
|
-
if (defaultValue) {
|
|
67
|
-
defaultHint = '[Y/n]';
|
|
68
|
-
} else if (!defaultValue) {
|
|
69
|
-
defaultHint = '[y/N]';
|
|
70
|
-
} else {
|
|
71
|
-
defaultHint = '[y/n]';
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const fullPrompt = `${question}${colorize(defaultHint, hintColor)}: `;
|
|
76
|
-
|
|
77
|
-
const formattedPrompt = fmt({
|
|
78
|
-
type: 'M_NULL',
|
|
79
|
-
title: fullPrompt,
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
const questionLines = countLines(formattedPrompt);
|
|
83
|
-
|
|
84
|
-
linesToDelete = questionLines + 1;
|
|
85
|
-
const answer = (await rl.question(formattedPrompt))
|
|
86
|
-
.toLowerCase()
|
|
87
|
-
.trim();
|
|
88
|
-
let value;
|
|
89
|
-
const formattedBar = bar({
|
|
90
|
-
borderColor,
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
if (!answer && defaultValue !== void 0) {
|
|
94
|
-
const injectedAnswer = defaultValue ? 'y' : 'n';
|
|
95
|
-
|
|
96
|
-
process.stdout.write(`${formattedBar} ${injectedAnswer}
|
|
44
|
+
errorMessage
|
|
45
|
+
});
|
|
46
|
+
let defaultHint = "";
|
|
47
|
+
if (defaultValue === true) {
|
|
48
|
+
defaultHint = "[Y/n]";
|
|
49
|
+
} else if (defaultValue === false) {
|
|
50
|
+
defaultHint = "[y/N]";
|
|
51
|
+
} else {
|
|
52
|
+
defaultHint = "[y/n]";
|
|
53
|
+
}
|
|
54
|
+
const fullPrompt = `${question}${colorize(defaultHint, hintColor)}: `;
|
|
55
|
+
const formattedPrompt = fmt({
|
|
56
|
+
type: "M_NULL",
|
|
57
|
+
title: fullPrompt
|
|
58
|
+
});
|
|
59
|
+
const questionLines = countLines(formattedPrompt);
|
|
60
|
+
linesToDelete = questionLines + 1;
|
|
61
|
+
const answer = (await rl.question(formattedPrompt)).toLowerCase().trim();
|
|
62
|
+
let value;
|
|
63
|
+
const formattedBar = bar({ borderColor });
|
|
64
|
+
if (!answer && defaultValue !== void 0) {
|
|
65
|
+
const injectedAnswer = defaultValue === true ? "y" : "n";
|
|
66
|
+
process.stdout.write(`${formattedBar} ${injectedAnswer}
|
|
97
67
|
`);
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
if (!isValid) {
|
|
115
|
-
const errors = Value.Errors(schema, value);
|
|
116
|
-
errorMessage = errors.length > 0 ? errors[0]?.message ?? 'Invalid input.' : 'Invalid input.';
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (isValid) {
|
|
121
|
-
msg({
|
|
122
|
-
type: 'M_NEWLINE',
|
|
123
|
-
});
|
|
124
|
-
rl.close();
|
|
125
|
-
if (action && value) {
|
|
126
|
-
await action();
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return value;
|
|
130
|
-
}
|
|
68
|
+
value = defaultValue;
|
|
69
|
+
} else if (answer === "y" || answer === "yes") {
|
|
70
|
+
value = true;
|
|
71
|
+
} else if (answer === "n" || answer === "no") {
|
|
72
|
+
value = false;
|
|
73
|
+
} else {
|
|
74
|
+
errorMessage = 'Please answer with "y" or "n".';
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
let isValid = true;
|
|
78
|
+
errorMessage = "";
|
|
79
|
+
if (schema) {
|
|
80
|
+
isValid = Value.Check(schema, value);
|
|
81
|
+
if (!isValid) {
|
|
82
|
+
const errors = [...Value.Errors(schema, value)];
|
|
83
|
+
errorMessage = errors.length > 0 ? errors[0]?.message ?? "Invalid input." : "Invalid input.";
|
|
131
84
|
}
|
|
132
|
-
|
|
85
|
+
}
|
|
86
|
+
if (isValid) {
|
|
87
|
+
msg({ type: "M_NEWLINE" });
|
|
133
88
|
rl.close();
|
|
89
|
+
if (action && value) {
|
|
90
|
+
await action();
|
|
91
|
+
}
|
|
92
|
+
return value;
|
|
93
|
+
}
|
|
134
94
|
}
|
|
95
|
+
} finally {
|
|
96
|
+
rl.close();
|
|
97
|
+
}
|
|
135
98
|
}
|
|
@@ -1,29 +1,26 @@
|
|
|
1
|
-
import {cursor} from
|
|
2
|
-
import Prompt from
|
|
3
|
-
|
|
1
|
+
import { cursor } from "sisteransi";
|
|
2
|
+
import Prompt from "../prompts/prompt.js";
|
|
4
3
|
export default class ConfirmPrompt extends Prompt {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
});
|
|
28
|
-
}
|
|
4
|
+
get cursor() {
|
|
5
|
+
return this.value ? 0 : 1;
|
|
6
|
+
}
|
|
7
|
+
get _value() {
|
|
8
|
+
return this.cursor === 0;
|
|
9
|
+
}
|
|
10
|
+
constructor(opts) {
|
|
11
|
+
super(opts, false);
|
|
12
|
+
this.value = !!opts.initialValue;
|
|
13
|
+
this.on("value", () => {
|
|
14
|
+
this.value = this._value;
|
|
15
|
+
});
|
|
16
|
+
this.on("confirm", (confirm) => {
|
|
17
|
+
this.output.write(cursor.move(0, -1));
|
|
18
|
+
this.value = confirm;
|
|
19
|
+
this.state = "submit";
|
|
20
|
+
this.close();
|
|
21
|
+
});
|
|
22
|
+
this.on("cursor", () => {
|
|
23
|
+
this.value = !this.value;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
29
26
|
}
|
|
@@ -1,50 +1,41 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from
|
|
9
|
-
|
|
2
|
+
createPrompt,
|
|
3
|
+
useState,
|
|
4
|
+
useKeypress,
|
|
5
|
+
isEnterKey,
|
|
6
|
+
usePrefix,
|
|
7
|
+
makeTheme
|
|
8
|
+
} from "../../components/core/index.js";
|
|
10
9
|
export default createPrompt((config, done) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
answer = false;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
setValue(transformer(answer));
|
|
32
|
-
setStatus('done');
|
|
33
|
-
done(answer);
|
|
34
|
-
} else {
|
|
35
|
-
setValue(rl.line);
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
let formattedValue = value;
|
|
39
|
-
let defaultValue = '';
|
|
40
|
-
|
|
41
|
-
if (status === 'done') {
|
|
42
|
-
formattedValue = theme.style.answer(value);
|
|
10
|
+
const { transformer = (answer) => answer ? "yes" : "no" } = config;
|
|
11
|
+
const [status, setStatus] = useState("idle");
|
|
12
|
+
const [value, setValue] = useState("");
|
|
13
|
+
const theme = makeTheme(config.theme);
|
|
14
|
+
const prefix = usePrefix({ status, theme });
|
|
15
|
+
useKeypress((key, rl) => {
|
|
16
|
+
if (isEnterKey(key)) {
|
|
17
|
+
let answer = config.default;
|
|
18
|
+
if (/^(y|yes)/i.test(value)) {
|
|
19
|
+
answer = true;
|
|
20
|
+
} else if (/^(n|no)/i.test(value)) {
|
|
21
|
+
answer = false;
|
|
22
|
+
}
|
|
23
|
+
setValue(transformer(answer));
|
|
24
|
+
setStatus("done");
|
|
25
|
+
done(answer);
|
|
43
26
|
} else {
|
|
44
|
-
|
|
27
|
+
setValue(rl.line);
|
|
45
28
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
29
|
+
});
|
|
30
|
+
let formattedValue = value;
|
|
31
|
+
let defaultValue = "";
|
|
32
|
+
if (status === "done") {
|
|
33
|
+
formattedValue = theme.style.answer(value);
|
|
34
|
+
} else {
|
|
35
|
+
defaultValue = ` ${theme.style.defaultAnswer(
|
|
36
|
+
!config.default ? "y/N" : "Y/n"
|
|
37
|
+
)}`;
|
|
38
|
+
}
|
|
39
|
+
const message = theme.style.message(config.message, status);
|
|
40
|
+
return `${prefix} ${message}${defaultValue} ${formattedValue}`;
|
|
50
41
|
});
|
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
import colors from
|
|
2
|
-
import figures from
|
|
3
|
-
|
|
1
|
+
import colors from "picocolors";
|
|
2
|
+
import figures from "../../components/figures/index.js";
|
|
4
3
|
export class Separator {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (separator) {
|
|
13
|
-
this.separator = separator;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
static isSeparator(choice) {
|
|
18
|
-
return Boolean(choice && typeof choice === 'object' && 'type' in choice && choice.type === 'separator');
|
|
4
|
+
separator = colors.dim(
|
|
5
|
+
Array.from({ length: 15 }).join(figures.line)
|
|
6
|
+
);
|
|
7
|
+
type = "separator";
|
|
8
|
+
constructor(separator) {
|
|
9
|
+
if (separator) {
|
|
10
|
+
this.separator = separator;
|
|
19
11
|
}
|
|
12
|
+
}
|
|
13
|
+
static isSeparator(choice) {
|
|
14
|
+
return Boolean(
|
|
15
|
+
choice && typeof choice === "object" && "type" in choice && choice.type === "separator"
|
|
16
|
+
);
|
|
17
|
+
}
|
|
20
18
|
}
|
|
@@ -1,130 +1,107 @@
|
|
|
1
|
-
import MuteStream from
|
|
2
|
-
import {AsyncResource} from
|
|
3
|
-
import * as readline from
|
|
4
|
-
import {onExit as onSignalExit} from
|
|
5
|
-
import process from 'node:process';
|
|
1
|
+
import MuteStream from "mute-stream";
|
|
2
|
+
import { AsyncResource } from "node:async_hooks";
|
|
3
|
+
import * as readline from "node:readline";
|
|
4
|
+
import { onExit as onSignalExit } from "signal-exit";
|
|
6
5
|
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} from
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
} from './hook-engine.js';
|
|
15
|
-
import {PromisePolyfill} from './promise-polyfill.js';
|
|
16
|
-
import ScreenManager from './screen-manager.js';
|
|
17
|
-
|
|
18
|
-
const isString = (a) => typeof a === 'string';
|
|
19
|
-
|
|
6
|
+
AbortPromptError,
|
|
7
|
+
CancelPromptError,
|
|
8
|
+
ExitPromptError
|
|
9
|
+
} from "./errors.js";
|
|
10
|
+
import { withHooks, effectScheduler } from "./hook-engine.js";
|
|
11
|
+
import { PromisePolyfill } from "./promise-polyfill.js";
|
|
12
|
+
import ScreenManager from "./screen-manager.js";
|
|
20
13
|
function getCallSites() {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
} finally {
|
|
35
|
-
Error.prepareStackTrace = _prepareStackTrace;
|
|
36
|
-
}
|
|
14
|
+
const _prepareStackTrace = Error.prepareStackTrace;
|
|
15
|
+
try {
|
|
16
|
+
let result = [];
|
|
17
|
+
Error.prepareStackTrace = (_, callSites) => {
|
|
18
|
+
const callSitesWithoutCurrent = callSites.slice(1);
|
|
19
|
+
result = callSitesWithoutCurrent;
|
|
20
|
+
return callSitesWithoutCurrent;
|
|
21
|
+
};
|
|
22
|
+
new Error().stack;
|
|
23
|
+
return result;
|
|
24
|
+
} finally {
|
|
25
|
+
Error.prepareStackTrace = _prepareStackTrace;
|
|
26
|
+
}
|
|
37
27
|
}
|
|
38
|
-
|
|
39
28
|
export function createPrompt(view) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
75
|
-
|
|
29
|
+
const callSites = getCallSites();
|
|
30
|
+
const callerFilename = callSites[1]?.getFileName?.();
|
|
31
|
+
const prompt = (config, context = {}) => {
|
|
32
|
+
const { input = process.stdin, signal } = context;
|
|
33
|
+
const cleanups = new Set();
|
|
34
|
+
const output = new MuteStream();
|
|
35
|
+
output.pipe(context.output ?? process.stdout);
|
|
36
|
+
const rl = readline.createInterface({
|
|
37
|
+
terminal: true,
|
|
38
|
+
input,
|
|
39
|
+
output
|
|
40
|
+
});
|
|
41
|
+
const screen = new ScreenManager(rl);
|
|
42
|
+
const { promise, resolve, reject } = PromisePolyfill.withResolver();
|
|
43
|
+
const cancel = () => reject(new CancelPromptError());
|
|
44
|
+
if (signal) {
|
|
45
|
+
const abort = () => reject(new AbortPromptError({ cause: signal.reason }));
|
|
46
|
+
if (signal.aborted) {
|
|
47
|
+
abort();
|
|
48
|
+
return Object.assign(promise, { cancel });
|
|
49
|
+
}
|
|
50
|
+
signal.addEventListener("abort", abort);
|
|
51
|
+
cleanups.add(() => signal.removeEventListener("abort", abort));
|
|
52
|
+
}
|
|
53
|
+
cleanups.add(
|
|
54
|
+
onSignalExit((code, signal2) => {
|
|
55
|
+
reject(
|
|
56
|
+
new ExitPromptError(
|
|
57
|
+
`User force closed the prompt with ${code} ${signal2}`
|
|
58
|
+
)
|
|
59
|
+
);
|
|
60
|
+
})
|
|
61
|
+
);
|
|
62
|
+
const checkCursorPos = () => screen.checkCursorPos();
|
|
63
|
+
rl.input.on("keypress", checkCursorPos);
|
|
64
|
+
cleanups.add(() => rl.input.removeListener("keypress", checkCursorPos));
|
|
65
|
+
return withHooks(rl, (cycle) => {
|
|
66
|
+
const hooksCleanup = AsyncResource.bind(() => effectScheduler.clearAll());
|
|
67
|
+
rl.on("close", hooksCleanup);
|
|
68
|
+
cleanups.add(() => rl.removeListener("close", hooksCleanup));
|
|
69
|
+
cycle(() => {
|
|
70
|
+
try {
|
|
71
|
+
const nextView = view(config, (value) => {
|
|
72
|
+
setImmediate(() => resolve(value));
|
|
73
|
+
});
|
|
74
|
+
if (nextView === void 0) {
|
|
75
|
+
throw new Error(
|
|
76
|
+
`Prompt functions must return a string.
|
|
77
|
+
at ${callerFilename}`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
const [content, bottomContent] = typeof nextView === "string" ? [nextView] : nextView;
|
|
81
|
+
screen.render(content, bottomContent);
|
|
82
|
+
effectScheduler.run();
|
|
83
|
+
} catch (error) {
|
|
84
|
+
reject(error);
|
|
76
85
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const [content, bottomContent] = isString(nextView) ? [nextView] : nextView;
|
|
100
|
-
screen.render(content, bottomContent);
|
|
101
|
-
effectScheduler.run();
|
|
102
|
-
} catch(error) {
|
|
103
|
-
reject(error);
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
return Object.assign(promise
|
|
107
|
-
.then((answer) => {
|
|
108
|
-
effectScheduler.clearAll();
|
|
109
|
-
return answer;
|
|
110
|
-
}, (error) => {
|
|
111
|
-
effectScheduler.clearAll();
|
|
112
|
-
throw error;
|
|
113
|
-
})
|
|
114
|
-
.finally(() => {
|
|
115
|
-
for (const cleanup of cleanups)
|
|
116
|
-
cleanup();
|
|
117
|
-
|
|
118
|
-
screen.done({
|
|
119
|
-
clearContent: Boolean(context.clearPromptOnDone),
|
|
120
|
-
});
|
|
121
|
-
output.end();
|
|
122
|
-
})
|
|
123
|
-
.then(() => promise), {
|
|
124
|
-
cancel,
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
return prompt;
|
|
86
|
+
});
|
|
87
|
+
return Object.assign(
|
|
88
|
+
promise.then(
|
|
89
|
+
(answer) => {
|
|
90
|
+
effectScheduler.clearAll();
|
|
91
|
+
return answer;
|
|
92
|
+
},
|
|
93
|
+
(error) => {
|
|
94
|
+
effectScheduler.clearAll();
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
).finally(() => {
|
|
98
|
+
cleanups.forEach((cleanup) => cleanup());
|
|
99
|
+
screen.done({ clearContent: Boolean(context.clearPromptOnDone) });
|
|
100
|
+
output.end();
|
|
101
|
+
}).then(() => promise),
|
|
102
|
+
{ cancel }
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
return prompt;
|
|
130
107
|
}
|