toolcraft-openapi 0.0.38 → 0.0.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -0
- package/dist/bin/generate.d.ts +9 -0
- package/dist/bin/generate.js +122 -6
- package/dist/config.d.ts +53 -0
- package/dist/config.js +266 -0
- package/dist/define-client.js +4 -0
- package/dist/diagnose.d.ts +4 -0
- package/dist/diagnose.js +93 -0
- package/dist/diagnostics.d.ts +19 -0
- package/dist/diagnostics.js +19 -0
- package/dist/generate.d.ts +13 -1
- package/dist/generate.js +165 -12
- package/dist/http.d.ts +30 -25
- package/dist/http.js +184 -42
- package/dist/index.d.ts +7 -2
- package/dist/index.js +5 -2
- package/dist/runtime.d.ts +7 -0
- package/dist/runtime.js +30 -5
- package/node_modules/@poe-code/frontmatter/README.md +35 -0
- package/node_modules/@poe-code/frontmatter/dist/fences.d.ts +8 -0
- package/node_modules/@poe-code/frontmatter/dist/fences.js +72 -0
- package/node_modules/@poe-code/frontmatter/dist/index.d.ts +3 -0
- package/node_modules/@poe-code/frontmatter/dist/index.js +3 -0
- package/node_modules/@poe-code/frontmatter/dist/parse.d.ts +20 -0
- package/node_modules/@poe-code/frontmatter/dist/parse.js +137 -0
- package/node_modules/@poe-code/frontmatter/dist/stringify.d.ts +1 -0
- package/node_modules/@poe-code/frontmatter/dist/stringify.js +35 -0
- package/node_modules/@poe-code/frontmatter/package.json +25 -0
- package/node_modules/toolcraft-design/README.md +12 -0
- package/node_modules/toolcraft-design/dist/prompts/index.d.ts +39 -14
- package/node_modules/toolcraft-design/dist/prompts/index.js +10 -6
- package/node_modules/toolcraft-design/dist/prompts/interactive/cancel-symbol.d.ts +2 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/cancel-symbol.js +4 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/confirm.d.ts +9 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/confirm.js +47 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/core.d.ts +55 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/core.js +274 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/glyphs.d.ts +20 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/glyphs.js +53 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/index.d.ts +6 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/index.js +6 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/keys.d.ts +2 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/keys.js +28 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/multiselect.d.ts +13 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/multiselect.js +131 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/pagination.d.ts +10 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/pagination.js +52 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/password.d.ts +10 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/password.js +55 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/select.d.ts +18 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/select.js +89 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/test-helpers.d.ts +21 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/test-helpers.js +32 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/text.d.ts +12 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/text.js +60 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/wrap.d.ts +4 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/wrap.js +18 -0
- package/node_modules/toolcraft-design/dist/prompts/primitives/cancel.d.ts +1 -1
- package/node_modules/toolcraft-design/dist/prompts/primitives/cancel.js +1 -1
- package/node_modules/toolcraft-design/dist/terminal-markdown/parser/frontmatter.js +20 -453
- package/node_modules/toolcraft-design/package.json +6 -3
- package/package.json +7 -7
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { LineCounter, parse, parseDocument } from "yaml";
|
|
2
|
+
import { splitFrontmatterBlock } from "./fences.js";
|
|
3
|
+
export class FrontmatterParseError extends Error {
|
|
4
|
+
constructor(message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = "FrontmatterParseError";
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export function parseFrontmatter(source, options = {}) {
|
|
10
|
+
const split = splitFrontmatter(source);
|
|
11
|
+
if (split.raw === undefined) {
|
|
12
|
+
return {
|
|
13
|
+
frontmatter: {},
|
|
14
|
+
body: split.body
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
frontmatter: parseYamlFrontmatter(split.raw, options),
|
|
19
|
+
body: split.body
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function parseFrontmatterDocument(source, options = {}) {
|
|
23
|
+
const split = splitFrontmatter(source);
|
|
24
|
+
const lineCounter = new LineCounter();
|
|
25
|
+
if (split.raw === undefined) {
|
|
26
|
+
return {
|
|
27
|
+
frontmatter: {},
|
|
28
|
+
body: split.body,
|
|
29
|
+
errors: [],
|
|
30
|
+
lineCounter
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
const document = parseDocument(normalizeYamlLineEndings(split.raw), {
|
|
34
|
+
lineCounter,
|
|
35
|
+
prettyErrors: false,
|
|
36
|
+
uniqueKeys: options.uniqueKeys ?? false
|
|
37
|
+
});
|
|
38
|
+
const errors = document.errors.map((error) => ({
|
|
39
|
+
message: error.message,
|
|
40
|
+
...(error.pos === undefined ? {} : { pos: error.pos })
|
|
41
|
+
}));
|
|
42
|
+
if (errors.length > 0) {
|
|
43
|
+
return {
|
|
44
|
+
frontmatter: {},
|
|
45
|
+
body: split.body,
|
|
46
|
+
errors,
|
|
47
|
+
lineCounter
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
frontmatter: normalizeYamlFrontmatter(document.toJSON()),
|
|
52
|
+
body: split.body,
|
|
53
|
+
errors,
|
|
54
|
+
lineCounter
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function splitFrontmatter(source) {
|
|
58
|
+
try {
|
|
59
|
+
return splitFrontmatterBlock(source);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
if (error instanceof Error) {
|
|
63
|
+
throw new FrontmatterParseError(error.message);
|
|
64
|
+
}
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function parseYamlFrontmatter(yamlBlock, options) {
|
|
69
|
+
let parsed;
|
|
70
|
+
try {
|
|
71
|
+
parsed = parse(normalizeYamlLineEndings(yamlBlock), {
|
|
72
|
+
uniqueKeys: options.uniqueKeys ?? false
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
const message = error instanceof Error ? error.message : "Unknown YAML parse error";
|
|
77
|
+
throw new FrontmatterParseError(`Invalid YAML frontmatter: ${message}`);
|
|
78
|
+
}
|
|
79
|
+
return normalizeYamlFrontmatter(parsed);
|
|
80
|
+
}
|
|
81
|
+
function normalizeYamlLineEndings(value) {
|
|
82
|
+
if (!value.includes("\r")) {
|
|
83
|
+
return value;
|
|
84
|
+
}
|
|
85
|
+
let normalized = "";
|
|
86
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
87
|
+
const character = value[index];
|
|
88
|
+
if (character !== "\r") {
|
|
89
|
+
normalized += character;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (value[index + 1] === "\n") {
|
|
93
|
+
normalized += "\r\n";
|
|
94
|
+
index += 1;
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
normalized += "\n";
|
|
98
|
+
}
|
|
99
|
+
return normalized;
|
|
100
|
+
}
|
|
101
|
+
function normalizeYamlFrontmatter(value) {
|
|
102
|
+
if (value === null || value === undefined) {
|
|
103
|
+
return {};
|
|
104
|
+
}
|
|
105
|
+
if (!isRecord(value)) {
|
|
106
|
+
throw new FrontmatterParseError("YAML frontmatter must parse to an object.");
|
|
107
|
+
}
|
|
108
|
+
return normalizeYamlValue(value);
|
|
109
|
+
}
|
|
110
|
+
function normalizeYamlValue(value) {
|
|
111
|
+
if (Array.isArray(value)) {
|
|
112
|
+
return value.map((item) => normalizeYamlValue(item));
|
|
113
|
+
}
|
|
114
|
+
if (!isPlainRecord(value)) {
|
|
115
|
+
return value;
|
|
116
|
+
}
|
|
117
|
+
const normalized = {};
|
|
118
|
+
for (const [key, entryValue] of Object.entries(value)) {
|
|
119
|
+
Object.defineProperty(normalized, key, {
|
|
120
|
+
configurable: true,
|
|
121
|
+
enumerable: true,
|
|
122
|
+
value: normalizeYamlValue(entryValue),
|
|
123
|
+
writable: true
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
return normalized;
|
|
127
|
+
}
|
|
128
|
+
function isRecord(value) {
|
|
129
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
130
|
+
}
|
|
131
|
+
function isPlainRecord(value) {
|
|
132
|
+
if (!isRecord(value)) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
const prototype = Object.getPrototypeOf(value);
|
|
136
|
+
return prototype === Object.prototype || prototype === null;
|
|
137
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function stringifyFrontmatter(frontmatter: Record<string, unknown>, body: string): string;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { stringify } from "yaml";
|
|
2
|
+
import { FrontmatterParseError } from "./parse.js";
|
|
3
|
+
export function stringifyFrontmatter(frontmatter, body) {
|
|
4
|
+
try {
|
|
5
|
+
assertAcyclic(frontmatter);
|
|
6
|
+
return `---\n${stringify(frontmatter, { aliasDuplicateObjects: false }).trimEnd()}\n---\n${body}`;
|
|
7
|
+
}
|
|
8
|
+
catch (error) {
|
|
9
|
+
if (error instanceof FrontmatterParseError) {
|
|
10
|
+
throw error;
|
|
11
|
+
}
|
|
12
|
+
const message = error instanceof Error ? error.message : "Unknown YAML stringify error";
|
|
13
|
+
throw new FrontmatterParseError(`Invalid YAML frontmatter: ${message}`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function assertAcyclic(value, seen = new WeakSet()) {
|
|
17
|
+
if (typeof value !== "object" || value === null) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (seen.has(value)) {
|
|
21
|
+
throw new FrontmatterParseError("Cannot stringify cyclic frontmatter.");
|
|
22
|
+
}
|
|
23
|
+
seen.add(value);
|
|
24
|
+
if (Array.isArray(value)) {
|
|
25
|
+
for (const item of value) {
|
|
26
|
+
assertAcyclic(item, seen);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
for (const item of Object.values(value)) {
|
|
31
|
+
assertAcyclic(item, seen);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
seen.delete(value);
|
|
35
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@poe-code/frontmatter",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "node ../../scripts/guard-package-dist.mjs && tsc",
|
|
16
|
+
"test": "cd ../.. && vitest run packages/frontmatter/src",
|
|
17
|
+
"test:unit": "cd ../.. && vitest run packages/frontmatter/src"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"yaml": "^2.8.2"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -139,6 +139,18 @@ The registry key and `Brand.name` should match. Brand primary colors are CSS-sty
|
|
|
139
139
|
- `VSCODE_COLOR_THEME_KIND`: automatic VS Code theme hint used after the macOS hint.
|
|
140
140
|
- `COLORFGBG`: terminal foreground/background hint used after the macOS and VS Code hints. Rendering defaults to dark when no hint resolves a mode.
|
|
141
141
|
|
|
142
|
+
### Prompts
|
|
143
|
+
|
|
144
|
+
- `POE_NO_PROMPT`: when set to `1` in non-TTY contexts, `confirm`, `select`, and `multiselect` accept their default or initial values instead of throwing an interactive TTY error.
|
|
145
|
+
|
|
146
|
+
### Node 18 Smoke
|
|
147
|
+
|
|
148
|
+
After building the package, verify the prompt entrypoint under Node 18 with:
|
|
149
|
+
|
|
150
|
+
```sh
|
|
151
|
+
nvm exec 18.18 node packages/toolcraft-design/scripts/check-node18.mjs
|
|
152
|
+
```
|
|
153
|
+
|
|
142
154
|
### Output and Color
|
|
143
155
|
|
|
144
156
|
- `OUTPUT_FORMAT`: selects `terminal`, `markdown`, or `json` output for components that use the output-format resolver. Invalid or missing values default to `terminal`.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { CANCEL } from "./interactive/cancel-symbol.js";
|
|
2
|
+
import { type SelectOption } from "./interactive/select.js";
|
|
2
3
|
import { cancel, isCancel } from "./primitives/cancel.js";
|
|
3
4
|
import { intro } from "./primitives/intro.js";
|
|
4
5
|
import { log } from "./primitives/log.js";
|
|
@@ -10,15 +11,24 @@ export { intro, outro, note, spinner };
|
|
|
10
11
|
export declare function introPlain(title: string): void;
|
|
11
12
|
export interface SelectOptions<Value> {
|
|
12
13
|
message: string;
|
|
13
|
-
options: Array<
|
|
14
|
-
value: Value;
|
|
15
|
-
label: string;
|
|
16
|
-
hint?: string;
|
|
17
|
-
}>;
|
|
14
|
+
options: Array<SelectOption<Value>>;
|
|
18
15
|
initialValue?: Value;
|
|
16
|
+
maxItems?: number;
|
|
17
|
+
signal?: AbortSignal;
|
|
18
|
+
input?: NodeJS.ReadableStream;
|
|
19
|
+
output?: NodeJS.WritableStream;
|
|
20
|
+
}
|
|
21
|
+
export declare function select<Value>(opts: SelectOptions<Value>): Promise<Value | typeof CANCEL>;
|
|
22
|
+
export interface MultiselectOptions<Value> {
|
|
23
|
+
message: string;
|
|
24
|
+
options: Array<SelectOption<Value>>;
|
|
25
|
+
initialValues?: Value[];
|
|
26
|
+
required?: boolean;
|
|
27
|
+
maxItems?: number;
|
|
28
|
+
signal?: AbortSignal;
|
|
29
|
+
input?: NodeJS.ReadableStream;
|
|
30
|
+
output?: NodeJS.WritableStream;
|
|
19
31
|
}
|
|
20
|
-
export declare function select<Value>(opts: SelectOptions<Value>): Promise<Value | symbol>;
|
|
21
|
-
export type MultiselectOptions<Value> = Parameters<typeof clack.multiselect<Value>>[0];
|
|
22
32
|
/**
|
|
23
33
|
* Prompts the user to select one or more values from a list.
|
|
24
34
|
*
|
|
@@ -35,23 +45,38 @@ export type MultiselectOptions<Value> = Parameters<typeof clack.multiselect<Valu
|
|
|
35
45
|
* // result is Value[]
|
|
36
46
|
* }
|
|
37
47
|
*/
|
|
38
|
-
export declare function multiselect<Value>(opts: MultiselectOptions<Value>): Promise<Value[] |
|
|
39
|
-
export
|
|
40
|
-
|
|
48
|
+
export declare function multiselect<Value>(opts: MultiselectOptions<Value>): Promise<Value[] | typeof CANCEL>;
|
|
49
|
+
export interface TextOptions {
|
|
50
|
+
message: string;
|
|
51
|
+
placeholder?: string;
|
|
52
|
+
defaultValue?: string;
|
|
53
|
+
initialValue?: string;
|
|
54
|
+
validate?: (value: string) => string | Error | undefined;
|
|
55
|
+
signal?: AbortSignal;
|
|
56
|
+
input?: NodeJS.ReadableStream;
|
|
57
|
+
output?: NodeJS.WritableStream;
|
|
58
|
+
}
|
|
59
|
+
export declare function text(opts: TextOptions): Promise<string | typeof CANCEL>;
|
|
41
60
|
export interface ConfirmOptions {
|
|
42
61
|
message: string;
|
|
43
62
|
initialValue?: boolean;
|
|
63
|
+
signal?: AbortSignal;
|
|
64
|
+
input?: NodeJS.ReadableStream;
|
|
65
|
+
output?: NodeJS.WritableStream;
|
|
44
66
|
}
|
|
45
|
-
export declare function confirm(opts: ConfirmOptions): Promise<boolean |
|
|
67
|
+
export declare function confirm(opts: ConfirmOptions): Promise<boolean | typeof CANCEL>;
|
|
46
68
|
export declare class PromptCancelledError extends Error {
|
|
47
69
|
constructor(message?: string);
|
|
48
70
|
}
|
|
49
71
|
export declare function confirmOrCancel(opts: ConfirmOptions): Promise<boolean>;
|
|
50
72
|
export interface PasswordOptions {
|
|
51
73
|
message: string;
|
|
52
|
-
validate?: (value: string) => string | undefined;
|
|
74
|
+
validate?: (value: string) => string | Error | undefined;
|
|
75
|
+
signal?: AbortSignal;
|
|
76
|
+
input?: NodeJS.ReadableStream;
|
|
77
|
+
output?: NodeJS.WritableStream;
|
|
53
78
|
}
|
|
54
|
-
export declare function password(opts: PasswordOptions): Promise<string |
|
|
79
|
+
export declare function password(opts: PasswordOptions): Promise<string | typeof CANCEL>;
|
|
55
80
|
export type SpinnerOptions = {
|
|
56
81
|
start: (message?: string) => void;
|
|
57
82
|
stop: (message?: string, code?: number) => void;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { color } from "../components/color.js";
|
|
2
|
-
import * as clack from "@clack/prompts";
|
|
3
2
|
import { resolveOutputFormat } from "../internal/output-format.js";
|
|
4
3
|
import { stripAnsi } from "../internal/strip-ansi.js";
|
|
4
|
+
import { confirmPrompt } from "./interactive/confirm.js";
|
|
5
|
+
import { multiselectPrompt } from "./interactive/multiselect.js";
|
|
6
|
+
import { passwordPrompt } from "./interactive/password.js";
|
|
7
|
+
import { selectPrompt } from "./interactive/select.js";
|
|
8
|
+
import { textPrompt } from "./interactive/text.js";
|
|
5
9
|
import { cancel, isCancel } from "./primitives/cancel.js";
|
|
6
10
|
import { intro } from "./primitives/intro.js";
|
|
7
11
|
import { log } from "./primitives/log.js";
|
|
@@ -22,7 +26,7 @@ export function introPlain(title) {
|
|
|
22
26
|
process.stdout.write(`${color.gray("┌")} ${title}\n`);
|
|
23
27
|
}
|
|
24
28
|
export async function select(opts) {
|
|
25
|
-
return
|
|
29
|
+
return selectPrompt(opts);
|
|
26
30
|
}
|
|
27
31
|
/**
|
|
28
32
|
* Prompts the user to select one or more values from a list.
|
|
@@ -41,13 +45,13 @@ export async function select(opts) {
|
|
|
41
45
|
* }
|
|
42
46
|
*/
|
|
43
47
|
export async function multiselect(opts) {
|
|
44
|
-
return
|
|
48
|
+
return multiselectPrompt(opts);
|
|
45
49
|
}
|
|
46
50
|
export async function text(opts) {
|
|
47
|
-
return
|
|
51
|
+
return textPrompt(opts);
|
|
48
52
|
}
|
|
49
53
|
export async function confirm(opts) {
|
|
50
|
-
return
|
|
54
|
+
return confirmPrompt(opts);
|
|
51
55
|
}
|
|
52
56
|
export class PromptCancelledError extends Error {
|
|
53
57
|
constructor(message = "Operation cancelled.") {
|
|
@@ -67,7 +71,7 @@ export async function confirmOrCancel(opts) {
|
|
|
67
71
|
return result === true;
|
|
68
72
|
}
|
|
69
73
|
export async function password(opts) {
|
|
70
|
-
return
|
|
74
|
+
return passwordPrompt(opts);
|
|
71
75
|
}
|
|
72
76
|
function formatElapsed(ms) {
|
|
73
77
|
const totalSeconds = Math.floor(ms / 1000);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { CANCEL } from "./cancel-symbol.js";
|
|
2
|
+
export interface ConfirmOptions {
|
|
3
|
+
message: string;
|
|
4
|
+
initialValue?: boolean;
|
|
5
|
+
signal?: AbortSignal;
|
|
6
|
+
input?: NodeJS.ReadableStream;
|
|
7
|
+
output?: NodeJS.WritableStream;
|
|
8
|
+
}
|
|
9
|
+
export declare function confirmPrompt(opts: ConfirmOptions): Promise<boolean | typeof CANCEL>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { color } from "../../components/color.js";
|
|
2
|
+
import { GLYPHS, symbol, symbolBar } from "./glyphs.js";
|
|
3
|
+
import { Prompt } from "./core.js";
|
|
4
|
+
class ConfirmPrompt extends Prompt {
|
|
5
|
+
constructor(opts) {
|
|
6
|
+
super({
|
|
7
|
+
...opts,
|
|
8
|
+
initialValue: opts.initialValue ?? true,
|
|
9
|
+
render: (prompt) => renderConfirmPrompt(prompt, opts)
|
|
10
|
+
}, false);
|
|
11
|
+
this.on("confirm", (value) => {
|
|
12
|
+
this.setValue(value);
|
|
13
|
+
this.state = "submit";
|
|
14
|
+
this.emit("finalize");
|
|
15
|
+
this.render();
|
|
16
|
+
this.close();
|
|
17
|
+
});
|
|
18
|
+
this.on("cursor", (action) => {
|
|
19
|
+
if (action === "up" || action === "down" || action === "left" || action === "right") {
|
|
20
|
+
this.setValue(!this.value);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
promptNonTty() {
|
|
25
|
+
if (process.env.POE_NO_PROMPT === "1") {
|
|
26
|
+
return Promise.resolve(this.value ?? true);
|
|
27
|
+
}
|
|
28
|
+
return super.promptNonTty();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function choices(value) {
|
|
32
|
+
const yes = value ? `${color.green(GLYPHS.radioActive)} ${color.bold("Yes")}` : `${color.dim(GLYPHS.radioInactive)} ${color.dim("Yes")}`;
|
|
33
|
+
const no = value ? `${color.dim(GLYPHS.radioInactive)} ${color.dim("No")}` : `${color.green(GLYPHS.radioActive)} ${color.bold("No")}`;
|
|
34
|
+
return `${yes} ${color.dim("/")} ${no}`;
|
|
35
|
+
}
|
|
36
|
+
function renderConfirmPrompt(prompt, opts) {
|
|
37
|
+
if (prompt.state === "submit") {
|
|
38
|
+
return `${color.gray(GLYPHS.barStart)} ${symbol(prompt.state)} ${opts.message}\n${color.gray(GLYPHS.bar)} ${color.dim(prompt.value ? "Yes" : "No")}\n${color.green(GLYPHS.barEnd)}`;
|
|
39
|
+
}
|
|
40
|
+
if (prompt.state === "cancel") {
|
|
41
|
+
return `${color.gray(GLYPHS.barStart)} ${symbol(prompt.state)} ${opts.message}\n${color.gray(GLYPHS.bar)} ${color.dim.strikethrough(prompt.value ? "Yes" : "No")}\n${color.red(GLYPHS.barEnd)}`;
|
|
42
|
+
}
|
|
43
|
+
return `${color.gray(GLYPHS.barStart)} ${symbol(prompt.state)} ${opts.message}\n${symbolBar(prompt.state)} ${choices(prompt.value)}\n${color.cyan(GLYPHS.barEnd)}`;
|
|
44
|
+
}
|
|
45
|
+
export function confirmPrompt(opts) {
|
|
46
|
+
return new ConfirmPrompt(opts).prompt();
|
|
47
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import { CANCEL } from "./cancel-symbol.js";
|
|
3
|
+
export type PromptStateName = "initial" | "active" | "submit" | "cancel" | "error";
|
|
4
|
+
export interface PromptState<Value> {
|
|
5
|
+
state: PromptStateName;
|
|
6
|
+
value: Value | undefined;
|
|
7
|
+
error: string;
|
|
8
|
+
cursor: number;
|
|
9
|
+
userInput: string;
|
|
10
|
+
}
|
|
11
|
+
export interface PromptOptions<Value> {
|
|
12
|
+
render: (state: Prompt<Value>) => string;
|
|
13
|
+
initialValue?: Value;
|
|
14
|
+
initialUserInput?: string;
|
|
15
|
+
validate?: (value: Value | undefined) => string | Error | undefined;
|
|
16
|
+
signal?: AbortSignal;
|
|
17
|
+
input?: NodeJS.ReadableStream;
|
|
18
|
+
output?: NodeJS.WritableStream;
|
|
19
|
+
}
|
|
20
|
+
type InputStream = NodeJS.ReadableStream & {
|
|
21
|
+
isTTY?: boolean;
|
|
22
|
+
setRawMode?: (enabled: boolean) => void;
|
|
23
|
+
unpipe?: () => void;
|
|
24
|
+
};
|
|
25
|
+
export declare class Prompt<Value> extends EventEmitter {
|
|
26
|
+
state: PromptStateName;
|
|
27
|
+
value: Value | undefined;
|
|
28
|
+
error: string;
|
|
29
|
+
userInput: string;
|
|
30
|
+
protected _cursor: number;
|
|
31
|
+
protected input: InputStream;
|
|
32
|
+
protected output: NodeJS.WritableStream;
|
|
33
|
+
private readonly renderFrame;
|
|
34
|
+
private readonly validate?;
|
|
35
|
+
private readonly signal?;
|
|
36
|
+
private readonly trackValue;
|
|
37
|
+
private previousFrame;
|
|
38
|
+
private readlineInterface?;
|
|
39
|
+
private abortListener?;
|
|
40
|
+
private closed;
|
|
41
|
+
constructor(opts: PromptOptions<Value>, trackValue?: boolean);
|
|
42
|
+
get cursor(): number;
|
|
43
|
+
prompt(): Promise<Value | typeof CANCEL>;
|
|
44
|
+
protected promptNonTty(): Promise<Value | typeof CANCEL>;
|
|
45
|
+
protected readNonTtyLine(): Promise<string>;
|
|
46
|
+
protected setValue(value: Value | undefined): void;
|
|
47
|
+
protected setError(message: string): void;
|
|
48
|
+
protected setUserInput(value: string): void;
|
|
49
|
+
protected clearUserInput(): void;
|
|
50
|
+
private readonly onKeypress;
|
|
51
|
+
private updateTrackedInput;
|
|
52
|
+
protected readonly render: () => void;
|
|
53
|
+
protected close(): void;
|
|
54
|
+
}
|
|
55
|
+
export {};
|