convoker 0.3.2 → 0.3.4
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/chunk-z5eko27R.mjs +13 -0
- package/dist/color-BuHvMolk.d.mts +158 -0
- package/dist/color-OlJQTTxb.mjs +172 -0
- package/dist/color.d.mts +2 -0
- package/dist/color.mjs +4 -0
- package/dist/command-BXmfoT-l.d.mts +331 -0
- package/dist/command-D2UiQBNA.mjs +583 -0
- package/dist/command.d.mts +5 -0
- package/dist/command.mjs +10 -0
- package/dist/error-C1S1gs8L.mjs +115 -0
- package/dist/error.d.mts +5 -0
- package/dist/error.mjs +3 -0
- package/dist/index-Dikc5KAP.d.mts +199 -0
- package/dist/index.d.mts +73 -0
- package/dist/index.mjs +10 -0
- package/dist/input-B12iaqb8.d.mts +187 -0
- package/dist/input-DRy_sVxZ.mjs +174 -0
- package/dist/input.d.mts +3 -0
- package/dist/input.mjs +5 -0
- package/dist/prompt/index.d.mts +5 -0
- package/dist/prompt/index.mjs +8 -0
- package/dist/prompt/raw.d.mts +2 -0
- package/dist/prompt/raw.mjs +4 -0
- package/dist/prompt-Cvufljin.mjs +248 -0
- package/dist/raw--889icsd.mjs +105 -0
- package/dist/raw-BqvlveTU.d.mts +37 -0
- package/dist/standard-schema-DBXbMy6L.mjs +17 -0
- package/dist/standard-schema-DLeKaehR.d.mts +58 -0
- package/dist/utils-ChmY93uA.mjs +45 -0
- package/package.json +24 -19
- package/dist/color.d.ts +0 -153
- package/dist/color.js +0 -143
- package/dist/command.d.ts +0 -218
- package/dist/command.js +0 -531
- package/dist/error.d.ts +0 -107
- package/dist/error.js +0 -100
- package/dist/index.d.ts +0 -6
- package/dist/index.js +0 -6
- package/dist/input.d.ts +0 -182
- package/dist/input.js +0 -185
- package/dist/log.d.ts +0 -61
- package/dist/log.js +0 -216
- package/dist/prompt/index.d.ts +0 -193
- package/dist/prompt/index.js +0 -273
- package/dist/prompt/raw.d.ts +0 -32
- package/dist/prompt/raw.js +0 -105
- package/dist/standard-schema.d.ts +0 -62
- package/dist/standard-schema.js +0 -16
- package/dist/utils.d.ts +0 -30
- package/dist/utils.js +0 -56
package/dist/log.js
DELETED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
import { DEFAULT_THEME } from "./color";
|
|
2
|
-
import { merge, isNode, isDeno, isBun } from "./utils";
|
|
3
|
-
/**
|
|
4
|
-
* Gets the default stdout, in a cross-runtime way.
|
|
5
|
-
* @returns The default stdout.
|
|
6
|
-
*/
|
|
7
|
-
async function getDefaultStdout() {
|
|
8
|
-
if (isNode && process.stdout?.writable) {
|
|
9
|
-
const { Writable } = await import("node:stream");
|
|
10
|
-
return Writable.toWeb(process.stdout);
|
|
11
|
-
}
|
|
12
|
-
if (isDeno && Deno.stdout?.writable) {
|
|
13
|
-
return Deno.stdout.writable;
|
|
14
|
-
}
|
|
15
|
-
if (isBun && Bun.stdout) {
|
|
16
|
-
return Bun.stdout;
|
|
17
|
-
}
|
|
18
|
-
// Workers: emulate with console.log
|
|
19
|
-
return new WritableStream({
|
|
20
|
-
write(chunk) {
|
|
21
|
-
console.log(String(chunk));
|
|
22
|
-
},
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Gets the default stderr, in a cross-runtime way.
|
|
27
|
-
* @returns The default stderr.
|
|
28
|
-
*/
|
|
29
|
-
async function getDefaultStderr() {
|
|
30
|
-
if (isNode && process.stderr?.writable) {
|
|
31
|
-
const { Writable } = await import("node:stream");
|
|
32
|
-
return Writable.toWeb(process.stderr);
|
|
33
|
-
}
|
|
34
|
-
if (isDeno && Deno.stderr?.writable) {
|
|
35
|
-
return Deno.stderr.writable;
|
|
36
|
-
}
|
|
37
|
-
if (isBun && Bun.stderr) {
|
|
38
|
-
return Bun.stderr;
|
|
39
|
-
}
|
|
40
|
-
// Workers: emulate with console.error
|
|
41
|
-
return new WritableStream({
|
|
42
|
-
write(chunk) {
|
|
43
|
-
console.error(String(chunk));
|
|
44
|
-
},
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Gets the default stdin, in a cross-runtime way.
|
|
49
|
-
* @returns The default stdin.
|
|
50
|
-
*/
|
|
51
|
-
async function getDefaultStdin() {
|
|
52
|
-
if (isNode && process.stdin?.readable) {
|
|
53
|
-
const { Readable } = await import("node:stream");
|
|
54
|
-
return Readable.toWeb(process.stdin);
|
|
55
|
-
}
|
|
56
|
-
if (isDeno && Deno.stdin?.readable) {
|
|
57
|
-
return Deno.stdin.readable;
|
|
58
|
-
}
|
|
59
|
-
if (isBun) {
|
|
60
|
-
return Bun.stdin.stream();
|
|
61
|
-
}
|
|
62
|
-
// Workers don't support stdin
|
|
63
|
-
return new ReadableStream({
|
|
64
|
-
start(controller) {
|
|
65
|
-
controller.close();
|
|
66
|
-
},
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
let theme = DEFAULT_THEME;
|
|
70
|
-
let config = undefined;
|
|
71
|
-
/**
|
|
72
|
-
* Sets a new theme.
|
|
73
|
-
* @param t The theme.
|
|
74
|
-
*/
|
|
75
|
-
export function setTheme(t) {
|
|
76
|
-
theme = t;
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Sets new configuration.
|
|
80
|
-
* @param c The config.
|
|
81
|
-
*/
|
|
82
|
-
export async function setConfig(c) {
|
|
83
|
-
config = merge({
|
|
84
|
-
format: "text",
|
|
85
|
-
stdout: await getDefaultStdout(),
|
|
86
|
-
stderr: await getDefaultStderr(),
|
|
87
|
-
stdin: await getDefaultStdin(),
|
|
88
|
-
}, c);
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Sets default configuration.
|
|
92
|
-
*/
|
|
93
|
-
export async function setup() {
|
|
94
|
-
await setConfig({});
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Formats a message to the correct format.
|
|
98
|
-
* @param level The level of mesage.
|
|
99
|
-
* @param msgs The messages to format.
|
|
100
|
-
* @returns The formatted message.
|
|
101
|
-
*/
|
|
102
|
-
function formatMessages(level, ...msgs) {
|
|
103
|
-
const timestamp = new Date().toISOString();
|
|
104
|
-
const msg = msgs
|
|
105
|
-
.map((m) => (typeof m === "string" ? m : JSON.stringify(m, null, 2)))
|
|
106
|
-
.join(" ");
|
|
107
|
-
switch (config.format) {
|
|
108
|
-
case "json":
|
|
109
|
-
return JSON.stringify({ timestamp, level, message: msg }) + "\n";
|
|
110
|
-
case "xml":
|
|
111
|
-
return `<log>
|
|
112
|
-
<timestamp>${timestamp}</timestamp>
|
|
113
|
-
<level>${level}</level>
|
|
114
|
-
<message>${msg}</message>
|
|
115
|
-
</log>\n`;
|
|
116
|
-
case "yaml":
|
|
117
|
-
return `- timestamp: ${timestamp}
|
|
118
|
-
level: ${level}
|
|
119
|
-
message: "${msg.replace(/"/g, '\\"')}"\n`;
|
|
120
|
-
case "csv":
|
|
121
|
-
return `"${timestamp}","${level}","${msg.replace(/"/g, '""')}"\n`;
|
|
122
|
-
case "text":
|
|
123
|
-
default:
|
|
124
|
-
return `[${timestamp}] [${level.toUpperCase()}] ${msg}\n`;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Colorizes text.
|
|
129
|
-
* @param level The log level.
|
|
130
|
-
* @param text The text to colorize.
|
|
131
|
-
* @returns The colorized text.
|
|
132
|
-
*/
|
|
133
|
-
function colorize(level, text) {
|
|
134
|
-
switch (level) {
|
|
135
|
-
case "trace":
|
|
136
|
-
return theme.secondary ? theme.secondary(text) : text;
|
|
137
|
-
case "info":
|
|
138
|
-
return theme.info ? theme.info(text) : text;
|
|
139
|
-
case "warn":
|
|
140
|
-
return theme.warning ? theme.warning(text) : text;
|
|
141
|
-
case "error":
|
|
142
|
-
return theme.error ? theme.error(text) : text;
|
|
143
|
-
case "fatal":
|
|
144
|
-
return theme.error
|
|
145
|
-
? theme.error(theme.styles?.bold?.(text) ?? text)
|
|
146
|
-
: text;
|
|
147
|
-
default:
|
|
148
|
-
return text;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Writes to a stream.
|
|
153
|
-
* @param stream The stream to write to.
|
|
154
|
-
* @param msg The message to write.
|
|
155
|
-
*/
|
|
156
|
-
async function writeToStream(stream, msg) {
|
|
157
|
-
const writer = stream.getWriter();
|
|
158
|
-
try {
|
|
159
|
-
await writer.write(msg);
|
|
160
|
-
}
|
|
161
|
-
finally {
|
|
162
|
-
writer.releaseLock();
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Prints debug information.
|
|
167
|
-
* @param msgs The messages to write.
|
|
168
|
-
*/
|
|
169
|
-
export async function trace(...msgs) {
|
|
170
|
-
const formatted = formatMessages("trace", ...msgs);
|
|
171
|
-
const colored = colorize("trace", formatted);
|
|
172
|
-
await writeToStream(config.stdout, colored);
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* Prints information.
|
|
176
|
-
* @param msgs The messages to write.
|
|
177
|
-
*/
|
|
178
|
-
export async function info(...msgs) {
|
|
179
|
-
const formatted = formatMessages("info", ...msgs);
|
|
180
|
-
const colored = colorize("info", formatted);
|
|
181
|
-
await writeToStream(config.stdout, colored);
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Prints warnings.
|
|
185
|
-
* @param msgs The messages to write.
|
|
186
|
-
*/
|
|
187
|
-
export async function warn(...msgs) {
|
|
188
|
-
const formatted = formatMessages("warn", ...msgs);
|
|
189
|
-
const colored = colorize("warn", formatted);
|
|
190
|
-
await writeToStream(config.stdout, colored);
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Prints errors.
|
|
194
|
-
* @param msgs The messages to write.
|
|
195
|
-
*/
|
|
196
|
-
export async function error(...msgs) {
|
|
197
|
-
const formatted = formatMessages("error", ...msgs);
|
|
198
|
-
const colored = colorize("error", formatted);
|
|
199
|
-
await writeToStream(config.stderr, colored);
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* Prints errors and exits.
|
|
203
|
-
* @param msgs The messages to write.
|
|
204
|
-
*/
|
|
205
|
-
export async function fatal(...msgs) {
|
|
206
|
-
const formatted = formatMessages("fatal", ...msgs);
|
|
207
|
-
const colored = colorize("fatal", formatted);
|
|
208
|
-
await writeToStream(config.stderr, colored);
|
|
209
|
-
// Exit depending on runtime
|
|
210
|
-
if (isDeno) {
|
|
211
|
-
Deno.exit(-1);
|
|
212
|
-
}
|
|
213
|
-
else if (isNode || isBun) {
|
|
214
|
-
process.exit(-1);
|
|
215
|
-
}
|
|
216
|
-
}
|
package/dist/prompt/index.d.ts
DELETED
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
import { type Theme } from "../color";
|
|
2
|
-
import { type StandardSchemaV1 } from "../standard-schema";
|
|
3
|
-
import * as raw from "./raw";
|
|
4
|
-
/**
|
|
5
|
-
* Sets the theme of the prompts.
|
|
6
|
-
* @param t The new theme.
|
|
7
|
-
*/
|
|
8
|
-
export declare function setTheme(t: Theme): void;
|
|
9
|
-
/**
|
|
10
|
-
* Base options for prompts.
|
|
11
|
-
*/
|
|
12
|
-
export interface BaseOpts<T> {
|
|
13
|
-
/**
|
|
14
|
-
* The message of the prompt.
|
|
15
|
-
*/
|
|
16
|
-
message: string;
|
|
17
|
-
/**
|
|
18
|
-
* An `AbortSignal` to cancel the prompt.
|
|
19
|
-
*/
|
|
20
|
-
signal?: AbortSignal;
|
|
21
|
-
/**
|
|
22
|
-
* The default value.
|
|
23
|
-
*/
|
|
24
|
-
default?: T;
|
|
25
|
-
/**
|
|
26
|
-
* The theme of the prompt.
|
|
27
|
-
*/
|
|
28
|
-
theme?: Theme;
|
|
29
|
-
/**
|
|
30
|
-
* A validator function, or a Standard Schema validator.
|
|
31
|
-
*/
|
|
32
|
-
validate?: StandardSchemaV1<any, T> | ((value: T) => boolean | T);
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Options for text input.
|
|
36
|
-
*/
|
|
37
|
-
export interface TextOpts extends BaseOpts<string> {
|
|
38
|
-
/**
|
|
39
|
-
* A placeholder, displayed when the user hasn't typed anything yet.
|
|
40
|
-
*/
|
|
41
|
-
placeholder?: string;
|
|
42
|
-
/**
|
|
43
|
-
* Minimum length of the input.
|
|
44
|
-
*/
|
|
45
|
-
minLength?: number;
|
|
46
|
-
/**
|
|
47
|
-
* Maximum length of the input.
|
|
48
|
-
*/
|
|
49
|
-
maxLength?: number;
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Prompts the user for text input.
|
|
53
|
-
* @param opts Options for text input.
|
|
54
|
-
* @returns The text the user typed in, or the default.
|
|
55
|
-
*/
|
|
56
|
-
export declare function text(opts: TextOpts): Promise<string>;
|
|
57
|
-
/**
|
|
58
|
-
* Options for password input.
|
|
59
|
-
*/
|
|
60
|
-
export interface PasswordOpts extends TextOpts {
|
|
61
|
-
/**
|
|
62
|
-
* The mask for the password input.
|
|
63
|
-
*/
|
|
64
|
-
mask?: string;
|
|
65
|
-
/**
|
|
66
|
-
* If the user should be asked to confirm the password, by typing it again.
|
|
67
|
-
*/
|
|
68
|
-
confirm?: boolean;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Prompts the user for a password.
|
|
72
|
-
* @param opts Options for password input.
|
|
73
|
-
* @returns The password.
|
|
74
|
-
*/
|
|
75
|
-
export declare function password(opts: PasswordOpts): Promise<string>;
|
|
76
|
-
/**
|
|
77
|
-
* An option for select input.
|
|
78
|
-
*/
|
|
79
|
-
export interface SelectOption<T> {
|
|
80
|
-
/**
|
|
81
|
-
* The label (what gets displayed) of the select option.
|
|
82
|
-
*/
|
|
83
|
-
label: string;
|
|
84
|
-
/**
|
|
85
|
-
* The value (what gets returned) of the select option.
|
|
86
|
-
*/
|
|
87
|
-
value: T;
|
|
88
|
-
/**
|
|
89
|
-
* A description of the option.
|
|
90
|
-
*/
|
|
91
|
-
hint?: string;
|
|
92
|
-
/**
|
|
93
|
-
* If this option is disabled.
|
|
94
|
-
*/
|
|
95
|
-
disabled?: boolean;
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Options for select input.
|
|
99
|
-
*/
|
|
100
|
-
export interface SelectOpts<T> extends BaseOpts<T> {
|
|
101
|
-
/**
|
|
102
|
-
* Every option the user can pick from.
|
|
103
|
-
*/
|
|
104
|
-
options: SelectOption<T>[];
|
|
105
|
-
/**
|
|
106
|
-
* The initial option selected.
|
|
107
|
-
*/
|
|
108
|
-
initialIndex?: number;
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Prompts the user to select a single option.
|
|
112
|
-
* @param opts Options for select input.
|
|
113
|
-
* @returns The selected option's value.
|
|
114
|
-
*/
|
|
115
|
-
export declare function select<T>(opts: SelectOpts<T>): Promise<T>;
|
|
116
|
-
/**
|
|
117
|
-
* Prompts the user to select multiple options.
|
|
118
|
-
* @param opts Options for select input.
|
|
119
|
-
* @returns The selected options.
|
|
120
|
-
*/
|
|
121
|
-
export declare function multiselect<T>(opts: SelectOpts<T>): Promise<T[]>;
|
|
122
|
-
/**
|
|
123
|
-
* Options for search input.
|
|
124
|
-
*/
|
|
125
|
-
export interface SearchOpts<T> extends BaseOpts<T> {
|
|
126
|
-
/**
|
|
127
|
-
* Every option the user can search through.
|
|
128
|
-
*/
|
|
129
|
-
options: SelectOption<T>[];
|
|
130
|
-
/**
|
|
131
|
-
* Placeholder for the search input.
|
|
132
|
-
*/
|
|
133
|
-
placeholder?: string;
|
|
134
|
-
/**
|
|
135
|
-
* Minimum length for a query string.
|
|
136
|
-
*/
|
|
137
|
-
minQueryLength?: number;
|
|
138
|
-
/**
|
|
139
|
-
* Filters a single option.
|
|
140
|
-
* @param query The search query.
|
|
141
|
-
* @param option The option to filter.
|
|
142
|
-
*/
|
|
143
|
-
filter?(query: string, option: SelectOption<T>): boolean;
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Prompts the user to search through a list of options.
|
|
147
|
-
* @param opts Options for search input.
|
|
148
|
-
* @returns The selected option.
|
|
149
|
-
*/
|
|
150
|
-
export declare function search<T>(opts: SearchOpts<T>): Promise<T>;
|
|
151
|
-
/**
|
|
152
|
-
* Options for confirm input.
|
|
153
|
-
*/
|
|
154
|
-
export interface ConfirmOpts extends BaseOpts<boolean> {
|
|
155
|
-
/**
|
|
156
|
-
* What gets displayed for the Yes option.
|
|
157
|
-
*/
|
|
158
|
-
yesLabel?: string;
|
|
159
|
-
/**
|
|
160
|
-
* What gets displayed for the No option.
|
|
161
|
-
*/
|
|
162
|
-
noLabel?: string;
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Prompts the user to confirm an action.
|
|
166
|
-
* @param opts Options for confirm input.
|
|
167
|
-
* @returns If the user picked Yes.
|
|
168
|
-
*/
|
|
169
|
-
export declare function confirm(opts: ConfirmOpts): Promise<boolean>;
|
|
170
|
-
/**
|
|
171
|
-
* Options for opening the system editor.
|
|
172
|
-
*/
|
|
173
|
-
export interface EditorOpts extends BaseOpts<string> {
|
|
174
|
-
/**
|
|
175
|
-
* The initial value.
|
|
176
|
-
*/
|
|
177
|
-
initial?: string;
|
|
178
|
-
/**
|
|
179
|
-
* The language of the value.
|
|
180
|
-
*/
|
|
181
|
-
language?: string;
|
|
182
|
-
/**
|
|
183
|
-
* If the input is required for continuing or not.
|
|
184
|
-
*/
|
|
185
|
-
required?: boolean;
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
* Opens the system editor, or asks for input in the terminal as fallback.
|
|
189
|
-
* @param opts Options for opening the system editor.
|
|
190
|
-
* @returns The result of the system editor.
|
|
191
|
-
*/
|
|
192
|
-
export declare function editor(opts: EditorOpts): Promise<string>;
|
|
193
|
-
export { raw };
|
package/dist/prompt/index.js
DELETED
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
import { DEFAULT_THEME } from "../color";
|
|
2
|
-
import { validate } from "../standard-schema";
|
|
3
|
-
import { InputValidationError } from "../error";
|
|
4
|
-
import { isDeno, isNode, isBun } from "../utils";
|
|
5
|
-
import * as raw from "./raw";
|
|
6
|
-
let theme = DEFAULT_THEME;
|
|
7
|
-
/**
|
|
8
|
-
* Sets the theme of the prompts.
|
|
9
|
-
* @param t The new theme.
|
|
10
|
-
*/
|
|
11
|
-
export function setTheme(t) {
|
|
12
|
-
theme = t;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Prompts the user for text input.
|
|
16
|
-
* @param opts Options for text input.
|
|
17
|
-
* @returns The text the user typed in, or the default.
|
|
18
|
-
*/
|
|
19
|
-
export async function text(opts) {
|
|
20
|
-
const th = opts.theme ?? theme;
|
|
21
|
-
const message = th.primary(opts.message) + " ";
|
|
22
|
-
const answer = await raw.readLine(message, opts.default);
|
|
23
|
-
if (opts.minLength && answer.length < opts.minLength)
|
|
24
|
-
throw new InputValidationError([
|
|
25
|
-
`Must be at least ${opts.minLength} characters`,
|
|
26
|
-
]);
|
|
27
|
-
if (opts.maxLength && answer.length > opts.maxLength)
|
|
28
|
-
throw new InputValidationError([
|
|
29
|
-
`Must be at most ${opts.maxLength} characters`,
|
|
30
|
-
]);
|
|
31
|
-
if (typeof opts.validate === "function") {
|
|
32
|
-
if (!opts.validate(answer))
|
|
33
|
-
throw new InputValidationError([
|
|
34
|
-
"Validation function returned a falsy value",
|
|
35
|
-
]);
|
|
36
|
-
}
|
|
37
|
-
else if (opts.validate) {
|
|
38
|
-
validate(opts.validate, answer);
|
|
39
|
-
}
|
|
40
|
-
return answer;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Prompts the user for a password.
|
|
44
|
-
* @param opts Options for password input.
|
|
45
|
-
* @returns The password.
|
|
46
|
-
*/
|
|
47
|
-
export async function password(opts) {
|
|
48
|
-
const th = opts.theme ?? theme;
|
|
49
|
-
const first = await raw.readLine(th.primary(opts.message) + " ", undefined, {
|
|
50
|
-
masked: true,
|
|
51
|
-
maskChar: opts.mask ?? "*",
|
|
52
|
-
});
|
|
53
|
-
if (opts.confirm) {
|
|
54
|
-
const second = await raw.readLine(th.secondary("Confirm password: "), undefined, {
|
|
55
|
-
masked: true,
|
|
56
|
-
maskChar: opts.mask ?? "*",
|
|
57
|
-
});
|
|
58
|
-
if (first !== second)
|
|
59
|
-
throw new Error(th.error("Passwords do not match"));
|
|
60
|
-
}
|
|
61
|
-
return first;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Prompts the user to select a single option.
|
|
65
|
-
* @param opts Options for select input.
|
|
66
|
-
* @returns The selected option's value.
|
|
67
|
-
*/
|
|
68
|
-
export async function select(opts) {
|
|
69
|
-
const th = opts.theme ?? theme;
|
|
70
|
-
const options = opts.options;
|
|
71
|
-
let index = opts.initialIndex ?? 0;
|
|
72
|
-
const render = () => {
|
|
73
|
-
raw.clearLines(options.length + 1);
|
|
74
|
-
console.log(th.primary(opts.message));
|
|
75
|
-
for (let i = 0; i < options.length; i++) {
|
|
76
|
-
const o = options[i];
|
|
77
|
-
const prefix = i === index ? (th.accent?.("> ") ?? "> ") : " ";
|
|
78
|
-
const label = o.disabled
|
|
79
|
-
? th.secondary(o.label)
|
|
80
|
-
: (th.foreground?.(o.label) ?? o.label);
|
|
81
|
-
console.log(prefix + label);
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
console.log(th.primary(opts.message));
|
|
85
|
-
options.forEach((o, i) => console.log(`${i === index ? "> " : " "}${o.label}`));
|
|
86
|
-
while (true) {
|
|
87
|
-
const key = await raw.readKey();
|
|
88
|
-
if (key === "up" && index > 0)
|
|
89
|
-
index--;
|
|
90
|
-
else if (key === "down" && index < options.length - 1)
|
|
91
|
-
index++;
|
|
92
|
-
else if (key === "enter") {
|
|
93
|
-
const choice = options[index];
|
|
94
|
-
if (choice.disabled)
|
|
95
|
-
continue;
|
|
96
|
-
raw.clearLines(options.length + 1);
|
|
97
|
-
console.log(th.success(`${th.symbols?.success ?? "✔"} ${choice.label}`));
|
|
98
|
-
return choice.value;
|
|
99
|
-
}
|
|
100
|
-
render();
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Prompts the user to select multiple options.
|
|
105
|
-
* @param opts Options for select input.
|
|
106
|
-
* @returns The selected options.
|
|
107
|
-
*/
|
|
108
|
-
export async function multiselect(opts) {
|
|
109
|
-
const th = opts.theme ?? theme;
|
|
110
|
-
const options = opts.options;
|
|
111
|
-
let index = opts.initialIndex ?? 0;
|
|
112
|
-
const selected = new Set();
|
|
113
|
-
const render = () => {
|
|
114
|
-
raw.clearLines();
|
|
115
|
-
console.log(th.primary(opts.message));
|
|
116
|
-
options.forEach((opt, i) => {
|
|
117
|
-
const prefix = i === index ? (th.accent?.("> ") ?? "> ") : " ";
|
|
118
|
-
const mark = selected.has(i) ? th.success("[x]") : "[ ]";
|
|
119
|
-
console.log(prefix + mark + " " + opt.label);
|
|
120
|
-
});
|
|
121
|
-
};
|
|
122
|
-
render();
|
|
123
|
-
while (true) {
|
|
124
|
-
const key = await raw.readKey();
|
|
125
|
-
if (key === "up" && index > 0)
|
|
126
|
-
index--;
|
|
127
|
-
else if (key === "down" && index < options.length - 1)
|
|
128
|
-
index++;
|
|
129
|
-
else if (key === "space") {
|
|
130
|
-
if (selected.has(index))
|
|
131
|
-
selected.delete(index);
|
|
132
|
-
else
|
|
133
|
-
selected.add(index);
|
|
134
|
-
}
|
|
135
|
-
else if (key === "return") {
|
|
136
|
-
const chosen = Array.from(selected).map((i) => options[i].value);
|
|
137
|
-
raw.clearLines(options.length + 1);
|
|
138
|
-
console.log(th.success(`${opts.message} ${chosen.length} selected`));
|
|
139
|
-
return chosen;
|
|
140
|
-
}
|
|
141
|
-
raw.cursorUp(options.length);
|
|
142
|
-
render();
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Prompts the user to search through a list of options.
|
|
147
|
-
* @param opts Options for search input.
|
|
148
|
-
* @returns The selected option.
|
|
149
|
-
*/
|
|
150
|
-
export async function search(opts) {
|
|
151
|
-
const th = opts.theme ?? theme;
|
|
152
|
-
let query = "";
|
|
153
|
-
const filter = opts.filter ?? ((q, o) => o.label.toLowerCase().includes(q.toLowerCase()));
|
|
154
|
-
while (true) {
|
|
155
|
-
raw.clearLines();
|
|
156
|
-
console.log(th.primary(opts.message));
|
|
157
|
-
const matches = opts.options.filter((o) => filter(query, o));
|
|
158
|
-
matches.forEach((o) => console.log(" " + (th.foreground?.(o.label) ?? o.label)));
|
|
159
|
-
const input = await raw.readLine(th.secondary(`Search: ${query}`));
|
|
160
|
-
if (input === "")
|
|
161
|
-
continue;
|
|
162
|
-
query = input;
|
|
163
|
-
if (matches.length === 1)
|
|
164
|
-
return matches[0].value;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Prompts the user to confirm an action.
|
|
169
|
-
* @param opts Options for confirm input.
|
|
170
|
-
* @returns If the user picked Yes.
|
|
171
|
-
*/
|
|
172
|
-
export async function confirm(opts) {
|
|
173
|
-
const th = opts.theme ?? theme;
|
|
174
|
-
const yes = opts.yesLabel ?? "y";
|
|
175
|
-
const no = opts.noLabel ?? "n";
|
|
176
|
-
const def = opts.default ? yes : no;
|
|
177
|
-
const res = await raw.readLine(`${th.primary(opts.message)} ${th.secondary(`[${yes}/${no}] (default: ${def})`)} `);
|
|
178
|
-
if (!res)
|
|
179
|
-
return !!opts.default;
|
|
180
|
-
return /^y/i.test(res.trim());
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Opens the system editor, or asks for input in the terminal as fallback.
|
|
184
|
-
* @param opts Options for opening the system editor.
|
|
185
|
-
* @returns The result of the system editor.
|
|
186
|
-
*/
|
|
187
|
-
export async function editor(opts) {
|
|
188
|
-
const th = opts.theme ?? {
|
|
189
|
-
primary: (s) => s,
|
|
190
|
-
secondary: (s) => s,
|
|
191
|
-
};
|
|
192
|
-
console.log(th.primary(opts.message ?? "Please enter text:"));
|
|
193
|
-
console.log(th.secondary("Press Ctrl+D (or save & close editor) when done."));
|
|
194
|
-
try {
|
|
195
|
-
const result = await openSystemEditor(opts.initial ?? "");
|
|
196
|
-
if (opts.required && !result.trim())
|
|
197
|
-
throw new Error("Input required.");
|
|
198
|
-
return result;
|
|
199
|
-
}
|
|
200
|
-
catch {
|
|
201
|
-
// fallback: cross-runtime multiline input
|
|
202
|
-
const value = await raw.readLine("", opts.initial, { multiline: true });
|
|
203
|
-
if (opts.required && !value.trim())
|
|
204
|
-
throw new Error("Input required.");
|
|
205
|
-
return value;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* Opens the system editor on a temporary file.
|
|
210
|
-
* @param initial Initial contents of the file.
|
|
211
|
-
* @returns The contents of the file after saving.
|
|
212
|
-
*/
|
|
213
|
-
async function openSystemEditor(initial) {
|
|
214
|
-
const tmpFile = `edit-${Date.now()}.txt`;
|
|
215
|
-
if (isDeno) {
|
|
216
|
-
const tmpDir = Deno.env.get("TMPDIR") ?? "/tmp";
|
|
217
|
-
const path = `${tmpDir}/${tmpFile}`;
|
|
218
|
-
await Deno.writeTextFile(path, initial ?? "");
|
|
219
|
-
const editor = Deno.env.get("EDITOR") ?? "vi";
|
|
220
|
-
const p = new Deno.Command(editor, {
|
|
221
|
-
args: [path],
|
|
222
|
-
stdin: "inherit",
|
|
223
|
-
stdout: "inherit",
|
|
224
|
-
stderr: "inherit",
|
|
225
|
-
}).spawn();
|
|
226
|
-
const status = await p.status;
|
|
227
|
-
if (!status.success)
|
|
228
|
-
throw new Error(`${editor} exited with ${status.code}`);
|
|
229
|
-
const text = await Deno.readTextFile(path);
|
|
230
|
-
await Deno.remove(path).catch(() => { });
|
|
231
|
-
return text;
|
|
232
|
-
}
|
|
233
|
-
if (isBun) {
|
|
234
|
-
const { $ } = await import("bun");
|
|
235
|
-
const path = `/tmp/${tmpFile}`;
|
|
236
|
-
await Bun.write(path, initial ?? "");
|
|
237
|
-
const editor = process.env.EDITOR ?? "vi";
|
|
238
|
-
await $ `${editor} ${path}`;
|
|
239
|
-
const text = await Bun.file(path).text();
|
|
240
|
-
await Bun.write(path, ""); // or remove if supported
|
|
241
|
-
return text;
|
|
242
|
-
}
|
|
243
|
-
if (isNode) {
|
|
244
|
-
const { tmpdir } = await import("node:os");
|
|
245
|
-
const { join } = await import("node:path");
|
|
246
|
-
const { promises: fs } = await import("node:fs");
|
|
247
|
-
const { spawn } = await import("node:child_process");
|
|
248
|
-
const path = join(tmpdir(), tmpFile);
|
|
249
|
-
await fs.writeFile(path, initial ?? "", "utf8");
|
|
250
|
-
const editor = process.env.EDITOR ||
|
|
251
|
-
process.env.VISUAL ||
|
|
252
|
-
(process.platform === "win32" ? "notepad" : "vi");
|
|
253
|
-
return new Promise((resolve, reject) => {
|
|
254
|
-
const child = spawn(editor, [path], { stdio: "inherit" });
|
|
255
|
-
child.on("exit", async (code) => {
|
|
256
|
-
if (code !== 0) {
|
|
257
|
-
reject(new Error(`${editor} exited with code ${code}`));
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
try {
|
|
261
|
-
const data = await fs.readFile(path, "utf8");
|
|
262
|
-
await fs.unlink(path).catch(() => { });
|
|
263
|
-
resolve(data);
|
|
264
|
-
}
|
|
265
|
-
catch (err) {
|
|
266
|
-
reject(err);
|
|
267
|
-
}
|
|
268
|
-
});
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
throw new Error("Unsupported runtime for system editor.");
|
|
272
|
-
}
|
|
273
|
-
export { raw };
|
package/dist/prompt/raw.d.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Reads a line from standard input.
|
|
3
|
-
* @param message The message.
|
|
4
|
-
* @param def Default value.
|
|
5
|
-
* @param opts Options for reading a line.
|
|
6
|
-
* @returns The line that was read.
|
|
7
|
-
*/
|
|
8
|
-
export declare function readLine(message?: string, def?: string, opts?: {
|
|
9
|
-
masked?: boolean;
|
|
10
|
-
maskChar?: string;
|
|
11
|
-
multiline?: boolean;
|
|
12
|
-
}): Promise<string>;
|
|
13
|
-
/**
|
|
14
|
-
* Reads a single key from stdin.
|
|
15
|
-
* @returns The key that was read.
|
|
16
|
-
*/
|
|
17
|
-
export declare function readKey(): Promise<string>;
|
|
18
|
-
/**
|
|
19
|
-
* Clears `lines` amount of lines.
|
|
20
|
-
* @param lines Amount of lines to clear.
|
|
21
|
-
*/
|
|
22
|
-
export declare function clearLines(lines?: number): void;
|
|
23
|
-
/**
|
|
24
|
-
* Moves the cursor up `n` times.
|
|
25
|
-
* @param n The amount of steps to move.
|
|
26
|
-
*/
|
|
27
|
-
export declare function cursorUp(n?: number): void;
|
|
28
|
-
/**
|
|
29
|
-
* Moves the cursor down `n` times.
|
|
30
|
-
* @param n The amount of steps to move.
|
|
31
|
-
*/
|
|
32
|
-
export declare function cursorDown(n?: number): void;
|