@reliverse/rempts 1.7.65 → 2.2.7
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 +21 -21
- package/README.md +1534 -1431
- package/cleanup.mjs +33 -0
- package/dist/cancel.d.ts +31 -0
- package/dist/cancel.js +28 -0
- package/dist/ffi.d.ts +1 -0
- package/dist/ffi.js +165 -0
- package/dist/group.d.ts +16 -0
- package/dist/group.js +22 -0
- package/dist/launcher/command.d.ts +8 -0
- package/dist/launcher/command.js +10 -0
- package/dist/launcher/discovery.d.ts +3 -0
- package/dist/launcher/discovery.js +207 -0
- package/dist/launcher/errors.d.ts +15 -0
- package/dist/launcher/errors.js +31 -0
- package/dist/launcher/help.d.ts +3 -0
- package/dist/launcher/help.js +145 -0
- package/dist/launcher/mod.d.ts +12 -0
- package/dist/launcher/mod.js +222 -0
- package/dist/launcher/parser.d.ts +14 -0
- package/dist/launcher/parser.js +255 -0
- package/dist/launcher/registry.d.ts +10 -0
- package/dist/launcher/registry.js +42 -0
- package/dist/launcher/types.d.ts +78 -0
- package/dist/launcher/validator.d.ts +3 -0
- package/dist/launcher/validator.js +39 -0
- package/dist/mod.d.ts +6 -0
- package/dist/mod.js +6 -0
- package/dist/prompt.d.ts +13 -0
- package/dist/prompt.js +53 -0
- package/dist/selection.d.ts +92 -0
- package/dist/selection.js +191 -0
- package/dist/spinner.d.ts +26 -0
- package/dist/spinner.js +141 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +11 -0
- package/package.json +41 -47
- package/bin/libs/animate/animate-mod.ts.txt +0 -78
- package/bin/libs/anykey/anykey-mod.d.ts +0 -12
- package/bin/libs/anykey/anykey-mod.js +0 -125
- package/bin/libs/cancel/cancel.d.ts +0 -45
- package/bin/libs/cancel/cancel.js +0 -72
- package/bin/libs/confirm/confirm-alias.d.ts +0 -2
- package/bin/libs/confirm/confirm-alias.js +0 -2
- package/bin/libs/confirm/confirm-mod.d.ts +0 -5
- package/bin/libs/confirm/confirm-mod.js +0 -179
- package/bin/libs/date/date.d.ts +0 -2
- package/bin/libs/date/date.js +0 -254
- package/bin/libs/editor/editor-mod.d.ts +0 -25
- package/bin/libs/editor/editor-mod.js +0 -1133
- package/bin/libs/figures/figures-mod.d.ts +0 -461
- package/bin/libs/figures/figures-mod.js +0 -285
- package/bin/libs/group/group-mod.d.ts +0 -33
- package/bin/libs/group/group-mod.js +0 -89
- package/bin/libs/input/input-alias.d.ts +0 -5
- package/bin/libs/input/input-alias.js +0 -4
- package/bin/libs/input/input-mod.d.ts +0 -16
- package/bin/libs/input/input-mod.js +0 -370
- package/bin/libs/intro/intro-alias.d.ts +0 -3
- package/bin/libs/intro/intro-alias.js +0 -3
- package/bin/libs/intro/intro-mod.d.ts +0 -19
- package/bin/libs/intro/intro-mod.js +0 -71
- package/bin/libs/launcher/command-runner.d.ts +0 -31
- package/bin/libs/launcher/command-runner.js +0 -229
- package/bin/libs/launcher/launcher-alias.d.ts +0 -2
- package/bin/libs/launcher/launcher-alias.js +0 -2
- package/bin/libs/launcher/launcher-mod.d.ts +0 -66
- package/bin/libs/launcher/launcher-mod.js +0 -1037
- package/bin/libs/launcher/launcher-types.d.ts +0 -176
- package/bin/libs/launcher/launcher-types.js +0 -0
- package/bin/libs/log/log-alias.d.ts +0 -1
- package/bin/libs/log/log-alias.js +0 -2
- package/bin/libs/msg-fmt/colors.d.ts +0 -30
- package/bin/libs/msg-fmt/colors.js +0 -42
- package/bin/libs/msg-fmt/mapping.d.ts +0 -3
- package/bin/libs/msg-fmt/mapping.js +0 -41
- package/bin/libs/msg-fmt/messages.d.ts +0 -35
- package/bin/libs/msg-fmt/messages.js +0 -305
- package/bin/libs/msg-fmt/terminal.d.ts +0 -15
- package/bin/libs/msg-fmt/terminal.js +0 -60
- package/bin/libs/msg-fmt/variants.d.ts +0 -11
- package/bin/libs/msg-fmt/variants.js +0 -52
- package/bin/libs/multiselect/multiselect-alias.d.ts +0 -2
- package/bin/libs/multiselect/multiselect-alias.js +0 -2
- package/bin/libs/multiselect/multiselect-prompt.d.ts +0 -2
- package/bin/libs/multiselect/multiselect-prompt.js +0 -340
- package/bin/libs/next-steps/next-steps.d.ts +0 -13
- package/bin/libs/next-steps/next-steps.js +0 -24
- package/bin/libs/number/number-mod.d.ts +0 -28
- package/bin/libs/number/number-mod.js +0 -234
- package/bin/libs/outro/outro-alias.d.ts +0 -3
- package/bin/libs/outro/outro-alias.js +0 -3
- package/bin/libs/outro/outro-mod.d.ts +0 -7
- package/bin/libs/outro/outro-mod.js +0 -49
- package/bin/libs/reliarg/reliarg-mod.d.ts +0 -76
- package/bin/libs/reliarg/reliarg-mod.js +0 -276
- package/bin/libs/results/results.d.ts +0 -7
- package/bin/libs/results/results.js +0 -27
- package/bin/libs/select/nummultiselect-prompt.d.ts +0 -6
- package/bin/libs/select/nummultiselect-prompt.js +0 -141
- package/bin/libs/select/numselect-prompt.d.ts +0 -7
- package/bin/libs/select/numselect-prompt.js +0 -111
- package/bin/libs/select/select-alias.d.ts +0 -9
- package/bin/libs/select/select-alias.js +0 -9
- package/bin/libs/select/select-prompt.d.ts +0 -5
- package/bin/libs/select/select-prompt.js +0 -311
- package/bin/libs/select/toggle-prompt.d.ts +0 -5
- package/bin/libs/select/toggle-prompt.js +0 -207
- package/bin/libs/spinner/spinner-impl.d.ts +0 -70
- package/bin/libs/spinner/spinner-impl.js +0 -336
- package/bin/libs/spinner/spinner-mod.d.ts +0 -167
- package/bin/libs/spinner/spinner-mod.js +0 -447
- package/bin/libs/utils/colorize.d.ts +0 -2
- package/bin/libs/utils/colorize.js +0 -122
- package/bin/libs/utils/errors.d.ts +0 -1
- package/bin/libs/utils/errors.js +0 -17
- package/bin/libs/utils/prevent.d.ts +0 -8
- package/bin/libs/utils/prevent.js +0 -62
- package/bin/libs/utils/prompt-end.d.ts +0 -8
- package/bin/libs/utils/prompt-end.js +0 -36
- package/bin/libs/utils/stream-text.d.ts +0 -18
- package/bin/libs/utils/stream-text.js +0 -138
- package/bin/libs/utils/system.d.ts +0 -6
- package/bin/libs/utils/system.js +0 -7
- package/bin/libs/utils/validate.d.ts +0 -21
- package/bin/libs/utils/validate.js +0 -17
- package/bin/libs/visual/visual-mod.ts.txt +0 -19
- package/bin/mod.d.ts +0 -50
- package/bin/mod.js +0 -127
- package/bin/types.d.ts +0 -372
- /package/{bin → dist/launcher}/types.js +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
let cachedRegistry = null;
|
|
2
|
+
export const getRegistry = () => cachedRegistry;
|
|
3
|
+
export const setRegistry = (registry) => {
|
|
4
|
+
cachedRegistry = registry;
|
|
5
|
+
};
|
|
6
|
+
export const clearRegistry = () => {
|
|
7
|
+
cachedRegistry = null;
|
|
8
|
+
};
|
|
9
|
+
export const resolveCommand = (registry, cmdNameOrAlias) => {
|
|
10
|
+
const resolvedName = registry.aliases.get(cmdNameOrAlias) ?? cmdNameOrAlias;
|
|
11
|
+
return resolvedName;
|
|
12
|
+
};
|
|
13
|
+
export const resolveCommandChain = (registry, cmdChain) => {
|
|
14
|
+
if (cmdChain.length === 0) {
|
|
15
|
+
throw new Error("Empty command chain");
|
|
16
|
+
}
|
|
17
|
+
if (cmdChain.length === 1) {
|
|
18
|
+
const cmdName = resolveCommand(registry, cmdChain[0]);
|
|
19
|
+
const node = registry.hierarchy.get(cmdName);
|
|
20
|
+
if (!node) {
|
|
21
|
+
throw new Error(`Command not found: ${cmdChain[0]}`);
|
|
22
|
+
}
|
|
23
|
+
return { fullPath: [cmdName] };
|
|
24
|
+
}
|
|
25
|
+
const parentName = resolveCommand(registry, cmdChain[0]);
|
|
26
|
+
const childName = resolveCommand(registry, cmdChain[1]);
|
|
27
|
+
const parentNode = registry.hierarchy.get(parentName);
|
|
28
|
+
const childNode = registry.hierarchy.get(childName);
|
|
29
|
+
if (!parentNode) {
|
|
30
|
+
throw new Error(`Parent command not found: ${cmdChain[0]}`);
|
|
31
|
+
}
|
|
32
|
+
if (!childNode || childNode.parent !== parentName) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
`Sub-command not found: ${cmdChain[1]} under ${cmdChain[0]}`
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
parent: parentNode,
|
|
39
|
+
child: childNode,
|
|
40
|
+
fullPath: [parentName, childName]
|
|
41
|
+
};
|
|
42
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
interface BaseArg {
|
|
2
|
+
description?: string;
|
|
3
|
+
aliases?: string[];
|
|
4
|
+
positional?: boolean;
|
|
5
|
+
}
|
|
6
|
+
type StringArg = BaseArg & {
|
|
7
|
+
type: "string";
|
|
8
|
+
required?: boolean;
|
|
9
|
+
default?: string;
|
|
10
|
+
allowed?: string[];
|
|
11
|
+
validate?: (value: string) => boolean | string;
|
|
12
|
+
};
|
|
13
|
+
type BooleanArg = BaseArg & {
|
|
14
|
+
type: "boolean";
|
|
15
|
+
required?: boolean;
|
|
16
|
+
default?: boolean;
|
|
17
|
+
allowed?: boolean[];
|
|
18
|
+
};
|
|
19
|
+
type NumberArg = BaseArg & {
|
|
20
|
+
type: "number";
|
|
21
|
+
required?: boolean;
|
|
22
|
+
default?: number;
|
|
23
|
+
allowed?: number[];
|
|
24
|
+
validate?: (value: number) => boolean | string;
|
|
25
|
+
};
|
|
26
|
+
export type CmdArgDefinition = StringArg | BooleanArg | NumberArg;
|
|
27
|
+
export type CmdArgsSchema = Record<string, CmdArgDefinition>;
|
|
28
|
+
export interface CmdMeta {
|
|
29
|
+
name: string;
|
|
30
|
+
description?: string;
|
|
31
|
+
version?: string;
|
|
32
|
+
aliases?: string[];
|
|
33
|
+
examples?: string[];
|
|
34
|
+
}
|
|
35
|
+
export interface CmdDefinition<T extends CmdArgsSchema = CmdArgsSchema> {
|
|
36
|
+
handler: CmdHandler<T>;
|
|
37
|
+
args: T;
|
|
38
|
+
meta: CmdMeta;
|
|
39
|
+
}
|
|
40
|
+
export type CmdHandler<T extends CmdArgsSchema = CmdArgsSchema> = (context: {
|
|
41
|
+
args: ParsedArgs<T>;
|
|
42
|
+
parentArgs?: ParsedArgs<any>;
|
|
43
|
+
}) => Promise<void> | void;
|
|
44
|
+
type InferArgType<T extends CmdArgDefinition> = T["type"] extends "string" ? string : T["type"] extends "number" ? number : boolean;
|
|
45
|
+
type InferArgValue<T extends CmdArgDefinition> = T extends {
|
|
46
|
+
required: true;
|
|
47
|
+
} ? InferArgType<T> : T extends {
|
|
48
|
+
default: any;
|
|
49
|
+
} ? InferArgType<T> : InferArgType<T> | undefined;
|
|
50
|
+
export type ParsedArgs<T extends CmdArgsSchema> = {
|
|
51
|
+
[K in keyof T]: InferArgValue<T[K]>;
|
|
52
|
+
};
|
|
53
|
+
export type CmdLoader = () => Promise<CmdDefinition>;
|
|
54
|
+
export type CmdRegistry = Map<string, CmdLoader>;
|
|
55
|
+
export interface CmdMetadata {
|
|
56
|
+
name: string;
|
|
57
|
+
description?: string;
|
|
58
|
+
aliases?: string[];
|
|
59
|
+
version?: string;
|
|
60
|
+
examples?: string[];
|
|
61
|
+
}
|
|
62
|
+
export interface CmdNode {
|
|
63
|
+
name: string;
|
|
64
|
+
path: string;
|
|
65
|
+
depth: number;
|
|
66
|
+
parent?: string;
|
|
67
|
+
children: Map<string, CmdNode>;
|
|
68
|
+
loader: CmdLoader;
|
|
69
|
+
metadata: () => Promise<CmdMetadata>;
|
|
70
|
+
}
|
|
71
|
+
export interface DiscoveryResult {
|
|
72
|
+
registry: CmdRegistry;
|
|
73
|
+
aliases: Map<string, string>;
|
|
74
|
+
metadata: Map<string, () => Promise<CmdMetadata>>;
|
|
75
|
+
hierarchy: Map<string, CmdNode>;
|
|
76
|
+
rootCommands: Set<string>;
|
|
77
|
+
}
|
|
78
|
+
export {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { CmdArgDefinition, CmdArgsSchema } from "./types.js";
|
|
2
|
+
export declare const validateArgValue: (argName: string, value: unknown, definition: CmdArgDefinition) => boolean;
|
|
3
|
+
export declare const validateRequiredArgs: (args: Record<string, unknown>, schema: CmdArgsSchema) => void;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ArgumentValidationError } from "./errors.js";
|
|
2
|
+
export const validateArgValue = (argName, value, definition) => {
|
|
3
|
+
const expectedType = definition.type === "boolean" ? "boolean" : definition.type === "number" ? "number" : "string";
|
|
4
|
+
if (typeof value !== expectedType) {
|
|
5
|
+
throw new ArgumentValidationError(
|
|
6
|
+
argName,
|
|
7
|
+
`Expected ${expectedType}, got ${typeof value}`
|
|
8
|
+
);
|
|
9
|
+
}
|
|
10
|
+
if ("allowed" in definition && definition.allowed) {
|
|
11
|
+
if (!definition.allowed.includes(value)) {
|
|
12
|
+
const allowedValues = definition.allowed.map((v) => typeof v === "string" ? `"${v}"` : String(v)).join(", ");
|
|
13
|
+
throw new ArgumentValidationError(
|
|
14
|
+
argName,
|
|
15
|
+
`Value must be one of: ${allowedValues}. Got: ${typeof value === "string" ? `"${value}"` : value}`
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if ("validate" in definition && definition.validate) {
|
|
20
|
+
const result = definition.validate(value);
|
|
21
|
+
if (result !== true) {
|
|
22
|
+
throw new ArgumentValidationError(
|
|
23
|
+
argName,
|
|
24
|
+
typeof result === "string" ? result : "Validation failed"
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return true;
|
|
29
|
+
};
|
|
30
|
+
export const validateRequiredArgs = (args, schema) => {
|
|
31
|
+
for (const [key, def] of Object.entries(schema)) {
|
|
32
|
+
if (def.required && !(key in args)) {
|
|
33
|
+
throw new ArgumentValidationError(
|
|
34
|
+
key,
|
|
35
|
+
`Required argument "${key}" is missing`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
package/dist/mod.d.ts
ADDED
package/dist/mod.js
ADDED
package/dist/prompt.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type InputPromptOptions = {
|
|
2
|
+
message: string;
|
|
3
|
+
title?: string;
|
|
4
|
+
charLimit?: number;
|
|
5
|
+
required?: boolean;
|
|
6
|
+
echoMode?: "normal" | "password" | "none";
|
|
7
|
+
validateOkPrefix?: string;
|
|
8
|
+
validateErrPrefix?: string;
|
|
9
|
+
defaultValue?: string;
|
|
10
|
+
initialValue?: string;
|
|
11
|
+
validate?: (value: string) => boolean | string | null | undefined;
|
|
12
|
+
};
|
|
13
|
+
export declare function inputPrompt(options: InputPromptOptions): Promise<string>;
|
package/dist/prompt.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { ptr } from "bun:ffi";
|
|
2
|
+
import { cancel } from "./cancel.js";
|
|
3
|
+
import { symbols } from "./ffi.js";
|
|
4
|
+
import { encode, toStringFromPtr } from "./utils.js";
|
|
5
|
+
function formatPromptText(title, message) {
|
|
6
|
+
if (title && message) {
|
|
7
|
+
return `${title}
|
|
8
|
+
\x1B[2m${message}\x1B[0m`;
|
|
9
|
+
}
|
|
10
|
+
return message ?? title ?? "";
|
|
11
|
+
}
|
|
12
|
+
export async function inputPrompt(options) {
|
|
13
|
+
const defaultValue = options.defaultValue;
|
|
14
|
+
const initialValue = options.initialValue;
|
|
15
|
+
const originalPromptText = formatPromptText(options.title, options.message);
|
|
16
|
+
let promptText = originalPromptText;
|
|
17
|
+
let currentDefaultValue = defaultValue;
|
|
18
|
+
let currentInitialValue = initialValue;
|
|
19
|
+
while (true) {
|
|
20
|
+
const returnedPtr = symbols.CreatePrompt(
|
|
21
|
+
ptr(encode(promptText)),
|
|
22
|
+
ptr(encode(options.echoMode || "normal")),
|
|
23
|
+
ptr(encode(options.validateOkPrefix || "")),
|
|
24
|
+
ptr(encode(options.validateErrPrefix || "")),
|
|
25
|
+
ptr(encode(currentDefaultValue || "")),
|
|
26
|
+
ptr(encode(currentInitialValue || "")),
|
|
27
|
+
options.required ?? true,
|
|
28
|
+
options.charLimit || 0
|
|
29
|
+
);
|
|
30
|
+
const { value, error } = JSON.parse(toStringFromPtr(returnedPtr));
|
|
31
|
+
if (error !== "") {
|
|
32
|
+
if (error === "Cancelled") {
|
|
33
|
+
if (options.required ?? true) {
|
|
34
|
+
cancel(error);
|
|
35
|
+
}
|
|
36
|
+
return "";
|
|
37
|
+
}
|
|
38
|
+
throw new Error(error);
|
|
39
|
+
}
|
|
40
|
+
if (!options.validate) {
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
const validationResult = options.validate(value);
|
|
44
|
+
if (validationResult === true || validationResult === null || validationResult === void 0) {
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
const errorMessage = typeof validationResult === "string" ? validationResult : "Invalid input";
|
|
48
|
+
promptText = `${originalPromptText}
|
|
49
|
+
\u274C ${errorMessage}`;
|
|
50
|
+
currentDefaultValue = void 0;
|
|
51
|
+
currentInitialValue = void 0;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
export type SelectionItem<T extends string = string> = {
|
|
2
|
+
value: T;
|
|
3
|
+
label: string;
|
|
4
|
+
hint?: string;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
};
|
|
7
|
+
type ExtractValues<T extends readonly SelectionItem[]> = T[number]["value"];
|
|
8
|
+
export type SelectPromptOptions<TOptions extends readonly SelectionItem[] = SelectionItem[]> = {
|
|
9
|
+
message: string;
|
|
10
|
+
title?: string;
|
|
11
|
+
options: TOptions;
|
|
12
|
+
perPage?: number;
|
|
13
|
+
headerText?: string;
|
|
14
|
+
footerText?: string;
|
|
15
|
+
required?: boolean;
|
|
16
|
+
autocomplete?: boolean;
|
|
17
|
+
defaultValue?: string;
|
|
18
|
+
initialValue?: string;
|
|
19
|
+
};
|
|
20
|
+
export type MultiselectPromptOptions<TOptions extends readonly SelectionItem[] = SelectionItem[]> = {
|
|
21
|
+
message: string;
|
|
22
|
+
title?: string;
|
|
23
|
+
options: TOptions;
|
|
24
|
+
perPage?: number;
|
|
25
|
+
headerText?: string;
|
|
26
|
+
footerText?: string;
|
|
27
|
+
required?: boolean;
|
|
28
|
+
autocomplete?: boolean;
|
|
29
|
+
defaultValue?: string[];
|
|
30
|
+
initialValue?: string[];
|
|
31
|
+
};
|
|
32
|
+
export type ConfirmPromptOptions = {
|
|
33
|
+
message: string;
|
|
34
|
+
title?: string;
|
|
35
|
+
headerText?: string;
|
|
36
|
+
footerText?: string;
|
|
37
|
+
required?: boolean;
|
|
38
|
+
defaultValue?: boolean;
|
|
39
|
+
initialValue?: boolean;
|
|
40
|
+
};
|
|
41
|
+
export declare function selectPrompt<T extends string>(options: SelectPromptOptions<readonly SelectionItem<T>[]> & {
|
|
42
|
+
required: false;
|
|
43
|
+
}): Promise<T | null>;
|
|
44
|
+
export declare function selectPrompt<T extends string>(options: SelectPromptOptions<readonly SelectionItem<T>[]> & {
|
|
45
|
+
required?: true;
|
|
46
|
+
}): Promise<T>;
|
|
47
|
+
export declare function selectPrompt<const TOptions extends readonly SelectionItem[]>(options: SelectPromptOptions<TOptions> & {
|
|
48
|
+
required: false;
|
|
49
|
+
}): Promise<ExtractValues<TOptions> | null>;
|
|
50
|
+
export declare function selectPrompt<const TOptions extends readonly SelectionItem[]>(options: SelectPromptOptions<TOptions> & {
|
|
51
|
+
required?: true;
|
|
52
|
+
}): Promise<ExtractValues<TOptions>>;
|
|
53
|
+
export declare function multiselectPrompt<T extends string>(options: MultiselectPromptOptions<readonly SelectionItem<T>[]> & {
|
|
54
|
+
required: false;
|
|
55
|
+
}): Promise<T[] | null>;
|
|
56
|
+
export declare function multiselectPrompt<T extends string>(options: MultiselectPromptOptions<readonly SelectionItem<T>[]> & {
|
|
57
|
+
required?: true;
|
|
58
|
+
}): Promise<T[]>;
|
|
59
|
+
export declare function multiselectPrompt<const TOptions extends readonly SelectionItem[]>(options: MultiselectPromptOptions<TOptions> & {
|
|
60
|
+
required: false;
|
|
61
|
+
}): Promise<ExtractValues<TOptions>[] | null>;
|
|
62
|
+
export declare function multiselectPrompt<const TOptions extends readonly SelectionItem[]>(options: MultiselectPromptOptions<TOptions> & {
|
|
63
|
+
required?: true;
|
|
64
|
+
}): Promise<ExtractValues<TOptions>[]>;
|
|
65
|
+
export declare function confirmPrompt(options: ConfirmPromptOptions): Promise<boolean>;
|
|
66
|
+
export type GroupMultiselectPromptOptions<TOptions extends Record<string, readonly SelectionItem[]> = Record<string, readonly SelectionItem[]>> = {
|
|
67
|
+
message: string;
|
|
68
|
+
title?: string;
|
|
69
|
+
options: TOptions;
|
|
70
|
+
perPage?: number;
|
|
71
|
+
headerText?: string;
|
|
72
|
+
footerText?: string;
|
|
73
|
+
required?: boolean;
|
|
74
|
+
autocomplete?: boolean;
|
|
75
|
+
defaultValue?: string[];
|
|
76
|
+
initialValue?: string[];
|
|
77
|
+
selectableGroups?: boolean;
|
|
78
|
+
groupSpacing?: number;
|
|
79
|
+
};
|
|
80
|
+
export declare function groupMultiselectPrompt<T extends string>(options: GroupMultiselectPromptOptions<Record<string, readonly SelectionItem<T>[]>> & {
|
|
81
|
+
required: false;
|
|
82
|
+
}): Promise<T[] | null>;
|
|
83
|
+
export declare function groupMultiselectPrompt<T extends string>(options: GroupMultiselectPromptOptions<Record<string, readonly SelectionItem<T>[]>> & {
|
|
84
|
+
required?: true;
|
|
85
|
+
}): Promise<T[]>;
|
|
86
|
+
export declare function groupMultiselectPrompt<const TOptions extends Record<string, readonly SelectionItem[]>>(options: GroupMultiselectPromptOptions<TOptions> & {
|
|
87
|
+
required: false;
|
|
88
|
+
}): Promise<ExtractValues<TOptions[keyof TOptions]>[] | null>;
|
|
89
|
+
export declare function groupMultiselectPrompt<const TOptions extends Record<string, readonly SelectionItem[]>>(options: GroupMultiselectPromptOptions<TOptions> & {
|
|
90
|
+
required?: true;
|
|
91
|
+
}): Promise<ExtractValues<TOptions[keyof TOptions]>[]>;
|
|
92
|
+
export {};
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { ptr } from "bun:ffi";
|
|
2
|
+
import { cancel } from "./cancel.js";
|
|
3
|
+
import { symbols } from "./ffi.js";
|
|
4
|
+
import { encode, toStringFromPtr } from "./utils.js";
|
|
5
|
+
function formatPromptText(title, message) {
|
|
6
|
+
if (title && message) {
|
|
7
|
+
return `${title}
|
|
8
|
+
\x1B[2m${message}\x1B[0m`;
|
|
9
|
+
}
|
|
10
|
+
return message ?? title ?? "";
|
|
11
|
+
}
|
|
12
|
+
export async function selectPrompt(options) {
|
|
13
|
+
const stringifiedItems = JSON.stringify(
|
|
14
|
+
options.options.map((item) => {
|
|
15
|
+
return {
|
|
16
|
+
value: item.value,
|
|
17
|
+
label: item.label,
|
|
18
|
+
hint: item.hint ?? "",
|
|
19
|
+
disabled: item.disabled ?? false
|
|
20
|
+
};
|
|
21
|
+
})
|
|
22
|
+
);
|
|
23
|
+
const headerText = options.headerText || formatPromptText(options.title, options.message) || "Select an item: ";
|
|
24
|
+
const returnedPtr = symbols.CreateSelection(
|
|
25
|
+
ptr(encode(stringifiedItems)),
|
|
26
|
+
ptr(encode(headerText)),
|
|
27
|
+
ptr(encode(options.footerText || "")),
|
|
28
|
+
options.perPage || 5,
|
|
29
|
+
options.autocomplete ?? true,
|
|
30
|
+
ptr(encode(options.defaultValue || "")),
|
|
31
|
+
ptr(encode(options.initialValue || ""))
|
|
32
|
+
);
|
|
33
|
+
const { selectedIndex, error } = JSON.parse(toStringFromPtr(returnedPtr));
|
|
34
|
+
if (error !== "") {
|
|
35
|
+
if (error === "Cancelled") {
|
|
36
|
+
if (options.required ?? true) {
|
|
37
|
+
cancel(error);
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
throw new Error(error);
|
|
42
|
+
}
|
|
43
|
+
const index = Number(selectedIndex);
|
|
44
|
+
const selectedOption = options.options[index];
|
|
45
|
+
if (!selectedOption) {
|
|
46
|
+
throw new Error("Invalid selection index");
|
|
47
|
+
}
|
|
48
|
+
return selectedOption.value;
|
|
49
|
+
}
|
|
50
|
+
export async function multiselectPrompt(options) {
|
|
51
|
+
const stringifiedItems = JSON.stringify(
|
|
52
|
+
options.options.map((item) => {
|
|
53
|
+
return {
|
|
54
|
+
value: item.value,
|
|
55
|
+
label: item.label,
|
|
56
|
+
hint: item.hint ?? "",
|
|
57
|
+
disabled: item.disabled ?? false
|
|
58
|
+
};
|
|
59
|
+
})
|
|
60
|
+
);
|
|
61
|
+
const headerText = options.headerText || formatPromptText(options.title, options.message) || "Select items: ";
|
|
62
|
+
const preselectedValues = options.initialValue ?? options.defaultValue ?? [];
|
|
63
|
+
const preselectedValuesJson = JSON.stringify(preselectedValues);
|
|
64
|
+
const initialCursorValue = preselectedValues.length > 0 ? preselectedValues[0] : "";
|
|
65
|
+
const returnedPtr = symbols.CreateMultiselect(
|
|
66
|
+
ptr(encode(stringifiedItems)),
|
|
67
|
+
ptr(encode(headerText)),
|
|
68
|
+
ptr(encode(options.footerText || "")),
|
|
69
|
+
options.perPage || 5,
|
|
70
|
+
options.autocomplete ?? true,
|
|
71
|
+
ptr(encode(preselectedValuesJson)),
|
|
72
|
+
ptr(encode(initialCursorValue))
|
|
73
|
+
);
|
|
74
|
+
const { selectedIndices, error } = JSON.parse(
|
|
75
|
+
toStringFromPtr(returnedPtr)
|
|
76
|
+
);
|
|
77
|
+
if (error !== "") {
|
|
78
|
+
if (error === "Cancelled") {
|
|
79
|
+
if (options.required ?? true) {
|
|
80
|
+
cancel(error);
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
throw new Error(error);
|
|
85
|
+
}
|
|
86
|
+
const indices = selectedIndices.map((idx) => Number(idx));
|
|
87
|
+
const values = indices.map((index) => options.options[index]?.value).filter((value) => value !== void 0);
|
|
88
|
+
if (values.length !== indices.length) {
|
|
89
|
+
throw new Error("Invalid selection indices");
|
|
90
|
+
}
|
|
91
|
+
return values;
|
|
92
|
+
}
|
|
93
|
+
export async function confirmPrompt(options) {
|
|
94
|
+
const promptText = formatPromptText(options.title, options.message);
|
|
95
|
+
const defaultValue = options.defaultValue !== void 0 ? String(options.defaultValue) : "";
|
|
96
|
+
const initialValue = options.initialValue !== void 0 ? String(options.initialValue) : "";
|
|
97
|
+
const returnedPtr = symbols.CreateConfirm(
|
|
98
|
+
ptr(encode(promptText)),
|
|
99
|
+
ptr(encode(options.headerText || "")),
|
|
100
|
+
ptr(encode(options.footerText || "")),
|
|
101
|
+
ptr(encode(defaultValue)),
|
|
102
|
+
ptr(encode(initialValue))
|
|
103
|
+
);
|
|
104
|
+
const { confirmed, error } = JSON.parse(toStringFromPtr(returnedPtr));
|
|
105
|
+
if (error !== "") {
|
|
106
|
+
if (error === "Cancelled") {
|
|
107
|
+
if (options.required ?? true) {
|
|
108
|
+
cancel(error);
|
|
109
|
+
}
|
|
110
|
+
return options.defaultValue ?? false;
|
|
111
|
+
}
|
|
112
|
+
throw new Error(error);
|
|
113
|
+
}
|
|
114
|
+
if (confirmed === "") {
|
|
115
|
+
throw new Error("No confirmation received");
|
|
116
|
+
}
|
|
117
|
+
return confirmed === "true";
|
|
118
|
+
}
|
|
119
|
+
export async function groupMultiselectPrompt(options) {
|
|
120
|
+
const flattenedItems = [];
|
|
121
|
+
const valueToIndexMap = /* @__PURE__ */ new Map();
|
|
122
|
+
for (const [groupName, groupItems] of Object.entries(options.options)) {
|
|
123
|
+
flattenedItems.push({
|
|
124
|
+
value: `__group__${groupName}`,
|
|
125
|
+
label: groupName,
|
|
126
|
+
hint: "",
|
|
127
|
+
disabled: false,
|
|
128
|
+
isGroupHeader: true,
|
|
129
|
+
groupName
|
|
130
|
+
});
|
|
131
|
+
for (const item of groupItems) {
|
|
132
|
+
const index = flattenedItems.length;
|
|
133
|
+
valueToIndexMap.set(item.value, index);
|
|
134
|
+
flattenedItems.push({
|
|
135
|
+
...item,
|
|
136
|
+
isGroupHeader: false,
|
|
137
|
+
groupName
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const stringifiedItems = JSON.stringify(
|
|
142
|
+
flattenedItems.map((item) => {
|
|
143
|
+
return {
|
|
144
|
+
value: item.value,
|
|
145
|
+
label: item.label,
|
|
146
|
+
hint: item.hint ?? "",
|
|
147
|
+
disabled: item.disabled ?? false,
|
|
148
|
+
isGroupHeader: item.isGroupHeader,
|
|
149
|
+
groupName: item.groupName
|
|
150
|
+
};
|
|
151
|
+
})
|
|
152
|
+
);
|
|
153
|
+
const headerText = options.headerText || formatPromptText(options.title, options.message) || "Select items: ";
|
|
154
|
+
const preselectedValues = options.initialValue ?? options.defaultValue ?? [];
|
|
155
|
+
const preselectedValuesJson = JSON.stringify(preselectedValues);
|
|
156
|
+
const initialCursorValue = preselectedValues.length > 0 ? preselectedValues[0] : "";
|
|
157
|
+
const returnedPtr = symbols.CreateGroupMultiselect(
|
|
158
|
+
ptr(encode(stringifiedItems)),
|
|
159
|
+
ptr(encode(headerText)),
|
|
160
|
+
ptr(encode(options.footerText || "")),
|
|
161
|
+
options.perPage || 5,
|
|
162
|
+
options.autocomplete ?? true,
|
|
163
|
+
options.selectableGroups ?? false,
|
|
164
|
+
ptr(encode(preselectedValuesJson)),
|
|
165
|
+
ptr(encode(initialCursorValue)),
|
|
166
|
+
options.groupSpacing ?? 0
|
|
167
|
+
);
|
|
168
|
+
const { selectedIndices, error } = JSON.parse(
|
|
169
|
+
toStringFromPtr(returnedPtr)
|
|
170
|
+
);
|
|
171
|
+
if (error !== "") {
|
|
172
|
+
if (error === "Cancelled") {
|
|
173
|
+
if (options.required ?? true) {
|
|
174
|
+
cancel(error);
|
|
175
|
+
}
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
throw new Error(error);
|
|
179
|
+
}
|
|
180
|
+
const indices = selectedIndices.map((idx) => Number(idx));
|
|
181
|
+
const values = indices.map((index) => {
|
|
182
|
+
const item = flattenedItems[index];
|
|
183
|
+
return item && !item.isGroupHeader ? item.value : void 0;
|
|
184
|
+
}).filter(
|
|
185
|
+
(value) => value !== void 0
|
|
186
|
+
);
|
|
187
|
+
if (values.length !== indices.length) {
|
|
188
|
+
throw new Error("Invalid selection indices");
|
|
189
|
+
}
|
|
190
|
+
return values;
|
|
191
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type SpinnerIndicator = "timer" | "dots";
|
|
2
|
+
export interface SpinnerOptions {
|
|
3
|
+
text?: string;
|
|
4
|
+
indicator?: SpinnerIndicator;
|
|
5
|
+
frames?: string[];
|
|
6
|
+
delay?: number;
|
|
7
|
+
onCancel?: () => void;
|
|
8
|
+
cancelMessage?: string;
|
|
9
|
+
errorMessage?: string;
|
|
10
|
+
successText?: string;
|
|
11
|
+
failText?: string;
|
|
12
|
+
prefixText?: string;
|
|
13
|
+
color?: string;
|
|
14
|
+
hideCursor?: boolean;
|
|
15
|
+
silent?: boolean;
|
|
16
|
+
signal?: AbortSignal;
|
|
17
|
+
}
|
|
18
|
+
export interface SpinnerInstance {
|
|
19
|
+
start(): SpinnerInstance;
|
|
20
|
+
stop(): SpinnerInstance;
|
|
21
|
+
succeed(text?: string): SpinnerInstance;
|
|
22
|
+
fail(text?: string): SpinnerInstance;
|
|
23
|
+
updateText(text: string): SpinnerInstance;
|
|
24
|
+
}
|
|
25
|
+
export declare function spinnerPrompt(options?: SpinnerOptions): SpinnerInstance;
|
|
26
|
+
export declare function createSpinner(options?: SpinnerOptions): SpinnerInstance;
|