@reliverse/relinka 1.0.0
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/LICENSE.md +21 -0
- package/README.md +141 -0
- package/output/components/animate.d.ts +13 -0
- package/output/components/animate.js +55 -0
- package/output/components/any-key.d.ts +7 -0
- package/output/components/any-key.js +56 -0
- package/output/components/ascii-art.d.ts +6 -0
- package/output/components/ascii-art.js +12 -0
- package/output/components/confirm.d.ts +3 -0
- package/output/components/confirm.js +99 -0
- package/output/components/date.d.ts +6 -0
- package/output/components/date.js +125 -0
- package/output/components/end.d.ts +2 -0
- package/output/components/end.js +36 -0
- package/output/components/mono.d.ts +5 -0
- package/output/components/mono.js +64 -0
- package/output/components/next-steps.d.ts +2 -0
- package/output/components/next-steps.js +25 -0
- package/output/components/num-multi-select.d.ts +3 -0
- package/output/components/num-multi-select.js +108 -0
- package/output/components/num-select.d.ts +5 -0
- package/output/components/num-select.js +122 -0
- package/output/components/number.d.ts +3 -0
- package/output/components/number.js +92 -0
- package/output/components/password.d.ts +3 -0
- package/output/components/password.js +117 -0
- package/output/components/results.d.ts +10 -0
- package/output/components/results.js +34 -0
- package/output/components/select.d.ts +2 -0
- package/output/components/select.js +97 -0
- package/output/components/spinner.d.ts +15 -0
- package/output/components/spinner.js +110 -0
- package/output/components/start.d.ts +2 -0
- package/output/components/start.js +33 -0
- package/output/components/text.d.ts +3 -0
- package/output/components/text.js +88 -0
- package/output/hooks/useKeyPress.d.ts +4 -0
- package/output/hooks/useKeyPress.js +14 -0
- package/output/main.d.ts +16 -0
- package/output/main.js +16 -0
- package/output/types/prod.d.ts +83 -0
- package/output/types/prod.js +0 -0
- package/output/utils/colorize.d.ts +2 -0
- package/output/utils/colorize.js +129 -0
- package/output/utils/errors.d.ts +1 -0
- package/output/utils/errors.js +11 -0
- package/output/utils/mapping.d.ts +4 -0
- package/output/utils/mapping.js +49 -0
- package/output/utils/messages.d.ts +17 -0
- package/output/utils/messages.js +203 -0
- package/output/utils/platforms.d.ts +1 -0
- package/output/utils/platforms.js +22 -0
- package/output/utils/prompt-tmp.d.ts +13 -0
- package/output/utils/prompt-tmp.js +254 -0
- package/output/utils/prompt.d.ts +13 -0
- package/output/utils/prompt.js +254 -0
- package/output/utils/readline.d.ts +2 -0
- package/output/utils/readline.js +9 -0
- package/output/utils/terminal.d.ts +5 -0
- package/output/utils/terminal.js +33 -0
- package/output/utils/variants.d.ts +9 -0
- package/output/utils/variants.js +49 -0
- package/package.json +96 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { confirmPrompt } from "../components/confirm";
|
|
2
|
+
import { datePrompt } from "../components/date";
|
|
3
|
+
import { endPrompt } from "../components/end";
|
|
4
|
+
import { nextStepsPrompt } from "../components/next-steps";
|
|
5
|
+
import { numberPrompt } from "../components/number";
|
|
6
|
+
import { passwordPrompt } from "../components/password";
|
|
7
|
+
import { startPrompt } from "../components/start";
|
|
8
|
+
import { textPrompt } from "../components/text";
|
|
9
|
+
import { numSelectPrompt } from "./num-select.js";
|
|
10
|
+
export async function prompt(options) {
|
|
11
|
+
const { type, id, action } = options;
|
|
12
|
+
let value;
|
|
13
|
+
switch (type) {
|
|
14
|
+
case "start":
|
|
15
|
+
await startPrompt(options);
|
|
16
|
+
value = null;
|
|
17
|
+
break;
|
|
18
|
+
case "text":
|
|
19
|
+
value = await textPrompt(options);
|
|
20
|
+
break;
|
|
21
|
+
case "number":
|
|
22
|
+
value = await numberPrompt(options);
|
|
23
|
+
break;
|
|
24
|
+
case "confirm":
|
|
25
|
+
value = await confirmPrompt(options);
|
|
26
|
+
break;
|
|
27
|
+
case "numSelect":
|
|
28
|
+
value = await numSelectPrompt(options);
|
|
29
|
+
break;
|
|
30
|
+
// case "select":
|
|
31
|
+
// value = await selectPrompt(options);
|
|
32
|
+
// break;
|
|
33
|
+
// case "multiSelect":
|
|
34
|
+
// value = await multiSelectPrompt(options);
|
|
35
|
+
// break;
|
|
36
|
+
// case "numMultiSelect":
|
|
37
|
+
// value = await numMultiSelectPrompt(options);
|
|
38
|
+
// break;
|
|
39
|
+
case "password":
|
|
40
|
+
value = await passwordPrompt(options);
|
|
41
|
+
break;
|
|
42
|
+
case "date":
|
|
43
|
+
value = await datePrompt({
|
|
44
|
+
...options,
|
|
45
|
+
dateFormat: "DD/MM/YYYY",
|
|
46
|
+
dateKind: "other"
|
|
47
|
+
});
|
|
48
|
+
break;
|
|
49
|
+
case "nextSteps":
|
|
50
|
+
await nextStepsPrompt(options);
|
|
51
|
+
value = null;
|
|
52
|
+
break;
|
|
53
|
+
case "end":
|
|
54
|
+
await endPrompt(options);
|
|
55
|
+
value = null;
|
|
56
|
+
break;
|
|
57
|
+
default:
|
|
58
|
+
throw new Error(`Unknown prompt type: ${type}`);
|
|
59
|
+
}
|
|
60
|
+
if (action) {
|
|
61
|
+
await action();
|
|
62
|
+
}
|
|
63
|
+
return { [id]: value };
|
|
64
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { msg } from "../utils/messages";
|
|
2
|
+
export async function nextStepsPrompt(options) {
|
|
3
|
+
const {
|
|
4
|
+
title,
|
|
5
|
+
titleColor = "cyanBright",
|
|
6
|
+
answerColor = "none",
|
|
7
|
+
titleVariant,
|
|
8
|
+
titleTypography = "bold",
|
|
9
|
+
content,
|
|
10
|
+
contentColor,
|
|
11
|
+
contentVariant,
|
|
12
|
+
contentTypography
|
|
13
|
+
} = options;
|
|
14
|
+
msg({
|
|
15
|
+
type: "M_INFO",
|
|
16
|
+
title,
|
|
17
|
+
titleColor,
|
|
18
|
+
titleVariant,
|
|
19
|
+
titleTypography,
|
|
20
|
+
content,
|
|
21
|
+
contentColor,
|
|
22
|
+
contentVariant,
|
|
23
|
+
contentTypography
|
|
24
|
+
});
|
|
25
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
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";
|
|
5
|
+
import { bar, fmt, msg } from "../utils/messages";
|
|
6
|
+
import { countLines, deleteLastLine, deleteLastLines } from "../utils/terminal";
|
|
7
|
+
export async function numMultiSelectPrompt(options) {
|
|
8
|
+
const {
|
|
9
|
+
title,
|
|
10
|
+
choices,
|
|
11
|
+
schema,
|
|
12
|
+
defaultValue,
|
|
13
|
+
titleColor = "cyanBright",
|
|
14
|
+
answerColor = "none",
|
|
15
|
+
titleTypography = "bold",
|
|
16
|
+
titleVariant,
|
|
17
|
+
hint,
|
|
18
|
+
content,
|
|
19
|
+
contentColor = "dim",
|
|
20
|
+
contentTypography,
|
|
21
|
+
contentVariant,
|
|
22
|
+
borderColor = "viceGradient",
|
|
23
|
+
variantOptions
|
|
24
|
+
} = options;
|
|
25
|
+
if (!choices || choices.length === 0) {
|
|
26
|
+
throw new Error("Choices are required for multiselect prompt.");
|
|
27
|
+
}
|
|
28
|
+
const rl = readline.createInterface({ input, output });
|
|
29
|
+
const formattedBar = bar({ borderColor });
|
|
30
|
+
let linesToDelete = 0;
|
|
31
|
+
let errorMessage = "";
|
|
32
|
+
try {
|
|
33
|
+
while (true) {
|
|
34
|
+
if (linesToDelete > 0) {
|
|
35
|
+
deleteLastLines(linesToDelete);
|
|
36
|
+
}
|
|
37
|
+
const question = fmt({
|
|
38
|
+
type: errorMessage !== "" ? "M_ERROR" : "M_GENERAL",
|
|
39
|
+
title: `${title}${defaultValue ? ` [Default: ${Array.isArray(defaultValue) ? defaultValue.join(", ") : defaultValue}]` : ""}`,
|
|
40
|
+
titleColor,
|
|
41
|
+
titleTypography,
|
|
42
|
+
titleVariant,
|
|
43
|
+
content,
|
|
44
|
+
contentColor,
|
|
45
|
+
contentTypography,
|
|
46
|
+
contentVariant,
|
|
47
|
+
borderColor,
|
|
48
|
+
hint,
|
|
49
|
+
variantOptions,
|
|
50
|
+
errorMessage,
|
|
51
|
+
addNewLineBefore: false,
|
|
52
|
+
addNewLineAfter: false
|
|
53
|
+
});
|
|
54
|
+
const choicesText = choices.map(
|
|
55
|
+
(choice, index) => `${formattedBar} ${index + 1}) ${choice.title}${choice.description ? ` - ${choice.description}` : ""}`
|
|
56
|
+
).join("\n");
|
|
57
|
+
const fullPrompt = `${question}
|
|
58
|
+
${choicesText}
|
|
59
|
+
${formattedBar} ${colorize(`Enter your choices (comma-separated numbers between 1-${choices.length})`, contentColor)}:
|
|
60
|
+
${formattedBar} `;
|
|
61
|
+
const formattedPrompt = fmt({
|
|
62
|
+
type: "M_NULL",
|
|
63
|
+
title: fullPrompt
|
|
64
|
+
});
|
|
65
|
+
const questionLines = countLines(formattedPrompt);
|
|
66
|
+
linesToDelete = questionLines + 1;
|
|
67
|
+
const answer = (await rl.question(formattedPrompt)).trim();
|
|
68
|
+
if (!answer && defaultValue !== void 0) {
|
|
69
|
+
deleteLastLine();
|
|
70
|
+
msg({
|
|
71
|
+
type: "M_MIDDLE",
|
|
72
|
+
title: ` ${Array.isArray(defaultValue) ? defaultValue.join(", ") : defaultValue}`,
|
|
73
|
+
titleColor: answerColor
|
|
74
|
+
});
|
|
75
|
+
msg({ type: "M_NEWLINE" });
|
|
76
|
+
return defaultValue;
|
|
77
|
+
}
|
|
78
|
+
const selections = answer.split(",").map((s) => s.trim());
|
|
79
|
+
const invalidSelections = selections.filter((s) => {
|
|
80
|
+
const num = Number(s);
|
|
81
|
+
return isNaN(num) || num < 1 || num > choices.length;
|
|
82
|
+
});
|
|
83
|
+
if (invalidSelections.length > 0) {
|
|
84
|
+
errorMessage = `Invalid selections: ${invalidSelections.join(
|
|
85
|
+
", "
|
|
86
|
+
)}. Please enter numbers between 1 and ${choices.length}.`;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const selectedValues = selections.map((s) => choices[Number(s) - 1]?.id);
|
|
90
|
+
let isValid = true;
|
|
91
|
+
errorMessage = "";
|
|
92
|
+
if (schema) {
|
|
93
|
+
isValid = Value.Check(schema, selectedValues);
|
|
94
|
+
if (!isValid) {
|
|
95
|
+
const errors = [...Value.Errors(schema, selectedValues)];
|
|
96
|
+
errorMessage = errors.length > 0 ? errors[0]?.message ?? "Invalid input." : "Invalid input.";
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (isValid) {
|
|
100
|
+
msg({ type: "M_NEWLINE" });
|
|
101
|
+
rl.close();
|
|
102
|
+
return selectedValues;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
} finally {
|
|
106
|
+
rl.close();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
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";
|
|
5
|
+
import { fmt, msg, bar } from "../utils/messages";
|
|
6
|
+
import { countLines, deleteLastLine, deleteLastLines } from "../utils/terminal";
|
|
7
|
+
export async function numSelectPrompt(options) {
|
|
8
|
+
const {
|
|
9
|
+
title,
|
|
10
|
+
hint,
|
|
11
|
+
validate,
|
|
12
|
+
defaultValue,
|
|
13
|
+
schema,
|
|
14
|
+
titleColor = "cyanBright",
|
|
15
|
+
answerColor = "none",
|
|
16
|
+
titleTypography = "bold",
|
|
17
|
+
titleVariant,
|
|
18
|
+
content,
|
|
19
|
+
contentColor,
|
|
20
|
+
contentTypography,
|
|
21
|
+
contentVariant,
|
|
22
|
+
borderColor = "viceGradient",
|
|
23
|
+
variantOptions,
|
|
24
|
+
inline = true,
|
|
25
|
+
choices
|
|
26
|
+
} = options;
|
|
27
|
+
if (!choices || choices.length === 0) {
|
|
28
|
+
throw new Error("Choices are required for select prompt.");
|
|
29
|
+
}
|
|
30
|
+
const rl = readline.createInterface({ input, output });
|
|
31
|
+
const formattedBar = bar({ borderColor });
|
|
32
|
+
let linesToDelete = 0;
|
|
33
|
+
let errorMessage = "";
|
|
34
|
+
while (true) {
|
|
35
|
+
if (linesToDelete > 0) {
|
|
36
|
+
deleteLastLines(linesToDelete);
|
|
37
|
+
}
|
|
38
|
+
const question = fmt({
|
|
39
|
+
type: errorMessage !== "" ? "M_ERROR" : "M_GENERAL",
|
|
40
|
+
title,
|
|
41
|
+
titleColor,
|
|
42
|
+
titleTypography,
|
|
43
|
+
titleVariant,
|
|
44
|
+
content,
|
|
45
|
+
contentColor,
|
|
46
|
+
contentTypography,
|
|
47
|
+
contentVariant,
|
|
48
|
+
borderColor,
|
|
49
|
+
hint,
|
|
50
|
+
variantOptions,
|
|
51
|
+
errorMessage
|
|
52
|
+
});
|
|
53
|
+
let choicesText = "";
|
|
54
|
+
if (inline) {
|
|
55
|
+
choicesText = choices.map(
|
|
56
|
+
(choice, index) => `${index + 1}) ${choice.title}${choice.description ? ` (${choice.description})` : ""}`
|
|
57
|
+
).join(" / ");
|
|
58
|
+
} else {
|
|
59
|
+
choicesText = choices.map(
|
|
60
|
+
(choice, index) => `${index + 1}) ${choice.title}${choice.description ? ` - ${choice.description}` : ""}`
|
|
61
|
+
).join(`
|
|
62
|
+
${formattedBar} `);
|
|
63
|
+
}
|
|
64
|
+
const formattedPrompt = fmt({
|
|
65
|
+
type: "M_NULL",
|
|
66
|
+
title: `${question}${choicesText}
|
|
67
|
+
${formattedBar} ${colorize(
|
|
68
|
+
`Enter your choice:`,
|
|
69
|
+
contentColor
|
|
70
|
+
)}
|
|
71
|
+
${formattedBar} `
|
|
72
|
+
});
|
|
73
|
+
const questionLines = countLines(formattedPrompt);
|
|
74
|
+
linesToDelete = questionLines + 1;
|
|
75
|
+
const prompt = await rl.question(formattedPrompt);
|
|
76
|
+
const answer = prompt.trim() || defaultValue;
|
|
77
|
+
if (!prompt.trim() && defaultValue !== void 0) {
|
|
78
|
+
deleteLastLine();
|
|
79
|
+
msg({
|
|
80
|
+
type: "M_MIDDLE",
|
|
81
|
+
title: ` ${defaultValue}`,
|
|
82
|
+
titleColor: answerColor
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
const num = Number(answer);
|
|
86
|
+
if (isNaN(num) || num < 1 || num > choices.length) {
|
|
87
|
+
errorMessage = `Please enter a number between 1 and ${choices.length}.`;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
const selectedChoice = choices[num - 1];
|
|
91
|
+
const selectedValue = selectedChoice?.id ?? num;
|
|
92
|
+
let isValid = true;
|
|
93
|
+
errorMessage = "";
|
|
94
|
+
if (schema) {
|
|
95
|
+
isValid = Value.Check(schema, selectedValue);
|
|
96
|
+
if (!isValid) {
|
|
97
|
+
const errors = [...Value.Errors(schema, selectedValue)];
|
|
98
|
+
if (errors.length > 0) {
|
|
99
|
+
errorMessage = errors[0]?.message ?? "Invalid input.";
|
|
100
|
+
} else {
|
|
101
|
+
errorMessage = "Invalid input.";
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (validate && isValid) {
|
|
106
|
+
const validation = await validate(selectedValue);
|
|
107
|
+
if (validation !== true) {
|
|
108
|
+
isValid = false;
|
|
109
|
+
errorMessage = typeof validation === "string" ? validation : "Invalid input.";
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (isValid) {
|
|
113
|
+
msg({ type: "M_NEWLINE" });
|
|
114
|
+
rl.close();
|
|
115
|
+
if (selectedChoice?.action) {
|
|
116
|
+
await selectedChoice.action();
|
|
117
|
+
}
|
|
118
|
+
return selectedValue;
|
|
119
|
+
} else {
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
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 { fmt, msg } from "../utils/messages";
|
|
5
|
+
import { countLines, deleteLastLine, deleteLastLines } from "../utils/terminal";
|
|
6
|
+
export async function numberPrompt(options) {
|
|
7
|
+
const {
|
|
8
|
+
title,
|
|
9
|
+
hint,
|
|
10
|
+
validate,
|
|
11
|
+
defaultValue,
|
|
12
|
+
schema,
|
|
13
|
+
titleColor = "cyanBright",
|
|
14
|
+
answerColor = "none",
|
|
15
|
+
titleTypography = "bold",
|
|
16
|
+
titleVariant,
|
|
17
|
+
content,
|
|
18
|
+
contentColor,
|
|
19
|
+
contentTypography,
|
|
20
|
+
contentVariant,
|
|
21
|
+
borderColor = "viceGradient",
|
|
22
|
+
variantOptions
|
|
23
|
+
} = options;
|
|
24
|
+
const rl = readline.createInterface({ input, output });
|
|
25
|
+
let linesToDelete = 0;
|
|
26
|
+
let errorMessage = "";
|
|
27
|
+
while (true) {
|
|
28
|
+
if (linesToDelete > 0) {
|
|
29
|
+
deleteLastLines(linesToDelete);
|
|
30
|
+
}
|
|
31
|
+
const question = fmt({
|
|
32
|
+
type: errorMessage !== "" ? "M_ERROR" : "M_GENERAL",
|
|
33
|
+
title,
|
|
34
|
+
titleColor,
|
|
35
|
+
titleTypography,
|
|
36
|
+
titleVariant,
|
|
37
|
+
content,
|
|
38
|
+
contentColor,
|
|
39
|
+
contentTypography,
|
|
40
|
+
contentVariant,
|
|
41
|
+
borderColor,
|
|
42
|
+
hint,
|
|
43
|
+
variantOptions,
|
|
44
|
+
errorMessage
|
|
45
|
+
});
|
|
46
|
+
const questionLines = countLines(question);
|
|
47
|
+
const prompt = await rl.question(question);
|
|
48
|
+
linesToDelete = questionLines + 1;
|
|
49
|
+
const answer = prompt.trim() || defaultValue;
|
|
50
|
+
if (prompt.trim() === "" && defaultValue !== void 0) {
|
|
51
|
+
deleteLastLine();
|
|
52
|
+
const defaultMsg = fmt({
|
|
53
|
+
type: "M_MIDDLE",
|
|
54
|
+
title: ` ${defaultValue}`,
|
|
55
|
+
borderColor
|
|
56
|
+
});
|
|
57
|
+
console.log(defaultMsg);
|
|
58
|
+
linesToDelete += countLines(defaultMsg);
|
|
59
|
+
}
|
|
60
|
+
const num = Number(answer);
|
|
61
|
+
if (isNaN(num)) {
|
|
62
|
+
errorMessage = "Please enter a valid number.";
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
let isValid = true;
|
|
66
|
+
errorMessage = "";
|
|
67
|
+
if (schema) {
|
|
68
|
+
isValid = Value.Check(schema, num);
|
|
69
|
+
if (!isValid) {
|
|
70
|
+
const errors = [...Value.Errors(schema, num)];
|
|
71
|
+
if (errors.length > 0) {
|
|
72
|
+
errorMessage = errors[0]?.message ?? "Invalid input.";
|
|
73
|
+
} else {
|
|
74
|
+
errorMessage = "Invalid input.";
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (validate && isValid) {
|
|
79
|
+
const validation = await validate(num);
|
|
80
|
+
if (validation !== true) {
|
|
81
|
+
isValid = false;
|
|
82
|
+
errorMessage = typeof validation === "string" ? validation : "Invalid input.";
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (isValid) {
|
|
86
|
+
msg({ type: "M_NEWLINE" });
|
|
87
|
+
rl.close();
|
|
88
|
+
return num;
|
|
89
|
+
} else {
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { Value } from "@sinclair/typebox/value";
|
|
2
|
+
import { bar, fmt } from "../utils/messages";
|
|
3
|
+
import { countLines, deleteLastLines } from "../utils/terminal";
|
|
4
|
+
export async function passwordPrompt(options) {
|
|
5
|
+
const {
|
|
6
|
+
title,
|
|
7
|
+
hint,
|
|
8
|
+
validate,
|
|
9
|
+
schema,
|
|
10
|
+
defaultValue,
|
|
11
|
+
titleColor = "cyanBright",
|
|
12
|
+
answerColor = "none",
|
|
13
|
+
titleTypography = "bold",
|
|
14
|
+
titleVariant,
|
|
15
|
+
content,
|
|
16
|
+
contentColor,
|
|
17
|
+
contentTypography,
|
|
18
|
+
contentVariant,
|
|
19
|
+
borderColor = "viceGradient",
|
|
20
|
+
variantOptions
|
|
21
|
+
} = options;
|
|
22
|
+
let linesToDelete = 0;
|
|
23
|
+
let errorMessage = "";
|
|
24
|
+
while (true) {
|
|
25
|
+
const question = fmt({
|
|
26
|
+
type: errorMessage !== "" ? "M_ERROR" : "M_GENERAL",
|
|
27
|
+
title: `${title}${defaultValue ? ` [Default: ****]` : ""}`,
|
|
28
|
+
titleColor,
|
|
29
|
+
titleTypography,
|
|
30
|
+
titleVariant,
|
|
31
|
+
content,
|
|
32
|
+
contentColor,
|
|
33
|
+
contentTypography,
|
|
34
|
+
contentVariant,
|
|
35
|
+
borderColor,
|
|
36
|
+
hint,
|
|
37
|
+
variantOptions,
|
|
38
|
+
errorMessage
|
|
39
|
+
});
|
|
40
|
+
const questionLines = countLines(question);
|
|
41
|
+
if (linesToDelete > 0) {
|
|
42
|
+
deleteLastLines(linesToDelete);
|
|
43
|
+
}
|
|
44
|
+
process.stdout.write(question);
|
|
45
|
+
const password = await readPassword(borderColor);
|
|
46
|
+
linesToDelete = questionLines + 1;
|
|
47
|
+
const formattedBar = bar({ borderColor });
|
|
48
|
+
if (!password.trim() && defaultValue !== void 0) {
|
|
49
|
+
deleteLastLines(2);
|
|
50
|
+
process.stdout.write(`${formattedBar} ****`);
|
|
51
|
+
console.log(`
|
|
52
|
+
${formattedBar}`);
|
|
53
|
+
return defaultValue;
|
|
54
|
+
}
|
|
55
|
+
let isValid = true;
|
|
56
|
+
errorMessage = "";
|
|
57
|
+
if (schema) {
|
|
58
|
+
isValid = Value.Check(schema, password);
|
|
59
|
+
if (!isValid) {
|
|
60
|
+
const errors = [...Value.Errors(schema, password)];
|
|
61
|
+
if (errors.length > 0) {
|
|
62
|
+
errorMessage = errors[0]?.message ?? "Invalid input.";
|
|
63
|
+
} else {
|
|
64
|
+
errorMessage = "Invalid input.";
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (validate && isValid) {
|
|
69
|
+
const validation = await validate(password);
|
|
70
|
+
if (validation !== true) {
|
|
71
|
+
isValid = false;
|
|
72
|
+
errorMessage = typeof validation === "string" ? validation : "Invalid input.";
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (isValid) {
|
|
76
|
+
process.stdout.write("\n");
|
|
77
|
+
return password;
|
|
78
|
+
} else {
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function readPassword(borderColor) {
|
|
83
|
+
return new Promise((resolve, reject) => {
|
|
84
|
+
const stdin = process.stdin;
|
|
85
|
+
let password = "";
|
|
86
|
+
const formattedBar = bar({ borderColor });
|
|
87
|
+
stdin.setRawMode(true);
|
|
88
|
+
stdin.resume();
|
|
89
|
+
stdin.setEncoding("utf8");
|
|
90
|
+
const onData = function(char) {
|
|
91
|
+
char = char.toString();
|
|
92
|
+
if (char === "\n" || char === "\r" || char === "") {
|
|
93
|
+
stdin.setRawMode(false);
|
|
94
|
+
stdin.pause();
|
|
95
|
+
stdin.removeListener("data", onData);
|
|
96
|
+
process.stdout.write(`
|
|
97
|
+
${formattedBar}`);
|
|
98
|
+
resolve(password.trim());
|
|
99
|
+
} else if (char === "") {
|
|
100
|
+
stdin.setRawMode(false);
|
|
101
|
+
stdin.pause();
|
|
102
|
+
stdin.removeListener("data", onData);
|
|
103
|
+
reject(new Error("User aborted."));
|
|
104
|
+
} else if (char === "\x7F" || // Backspace
|
|
105
|
+
char === "\b" || char === "\x7F" || char === "\b") {
|
|
106
|
+
if (password.length > 0) {
|
|
107
|
+
password = password.slice(0, -1);
|
|
108
|
+
process.stdout.write("\b \b");
|
|
109
|
+
}
|
|
110
|
+
} else {
|
|
111
|
+
password += char;
|
|
112
|
+
process.stdout.write("*");
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
stdin.on("data", onData);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Static } from "@sinclair/typebox";
|
|
2
|
+
declare const ResultsSchema: import("@sinclair/typebox").TObject<{
|
|
3
|
+
username: import("@sinclair/typebox").TString;
|
|
4
|
+
}>;
|
|
5
|
+
type ResultsType = Static<typeof ResultsSchema>;
|
|
6
|
+
export declare function promptsDisplayResults({ results, inline, }: {
|
|
7
|
+
results: ResultsType;
|
|
8
|
+
inline?: boolean;
|
|
9
|
+
}): Promise<void>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { Value } from "@sinclair/typebox/value";
|
|
3
|
+
import { msg } from "../utils/messages";
|
|
4
|
+
const ResultsSchema = Type.Object({
|
|
5
|
+
username: Type.String()
|
|
6
|
+
});
|
|
7
|
+
export async function promptsDisplayResults({
|
|
8
|
+
results,
|
|
9
|
+
inline = true
|
|
10
|
+
}) {
|
|
11
|
+
if (!Value.Check(ResultsSchema, results)) {
|
|
12
|
+
throw new Error("Invalid results structure.");
|
|
13
|
+
}
|
|
14
|
+
const title = "Your input results:";
|
|
15
|
+
if (inline) {
|
|
16
|
+
const formattedResults = Object.entries(results).map(([key, value]) => `${key}: ${value}`).join(", ");
|
|
17
|
+
msg({
|
|
18
|
+
type: "M_INFO",
|
|
19
|
+
title,
|
|
20
|
+
content: formattedResults,
|
|
21
|
+
titleColor: "cyan",
|
|
22
|
+
contentColor: "dim"
|
|
23
|
+
});
|
|
24
|
+
} else {
|
|
25
|
+
const formattedResults = JSON.stringify(results, null, 2);
|
|
26
|
+
msg({
|
|
27
|
+
type: "M_INFO",
|
|
28
|
+
title,
|
|
29
|
+
content: formattedResults,
|
|
30
|
+
titleColor: "cyan",
|
|
31
|
+
contentColor: "dim"
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|