devlyn-cli 4.2.0 → 4.2.2
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 +4 -2
- package/bin/devlyn.js +184 -147
- package/bin/skill-history.json +140 -0
- package/bin/skill-ownership.js +67 -0
- package/node_modules/@inquirer/ansi/LICENSE +22 -0
- package/node_modules/@inquirer/ansi/README.md +121 -0
- package/node_modules/@inquirer/ansi/dist/index.d.ts +14 -0
- package/node_modules/@inquirer/ansi/dist/index.js +21 -0
- package/node_modules/@inquirer/ansi/package.json +79 -0
- package/node_modules/@inquirer/checkbox/LICENSE +22 -0
- package/node_modules/@inquirer/checkbox/README.md +265 -0
- package/node_modules/@inquirer/checkbox/dist/index.d.ts +67 -0
- package/node_modules/@inquirer/checkbox/dist/index.js +210 -0
- package/node_modules/@inquirer/checkbox/package.json +93 -0
- package/node_modules/@inquirer/core/LICENSE +22 -0
- package/node_modules/@inquirer/core/README.md +424 -0
- package/node_modules/@inquirer/core/dist/index.d.ts +13 -0
- package/node_modules/@inquirer/core/dist/index.js +12 -0
- package/node_modules/@inquirer/core/dist/lib/Separator.d.ts +10 -0
- package/node_modules/@inquirer/core/dist/lib/Separator.js +21 -0
- package/node_modules/@inquirer/core/dist/lib/__probe/p1.d.ts +9 -0
- package/node_modules/@inquirer/core/dist/lib/__probe/p1.js +4 -0
- package/node_modules/@inquirer/core/dist/lib/__probe/p2.d.ts +9 -0
- package/node_modules/@inquirer/core/dist/lib/__probe/p2.js +3 -0
- package/node_modules/@inquirer/core/dist/lib/__probe/p3.d.ts +9 -0
- package/node_modules/@inquirer/core/dist/lib/__probe/p3.js +5 -0
- package/node_modules/@inquirer/core/dist/lib/create-prompt.d.ts +11 -0
- package/node_modules/@inquirer/core/dist/lib/create-prompt.js +185 -0
- package/node_modules/@inquirer/core/dist/lib/errors.d.ts +20 -0
- package/node_modules/@inquirer/core/dist/lib/errors.js +21 -0
- package/node_modules/@inquirer/core/dist/lib/hook-engine.d.ts +17 -0
- package/node_modules/@inquirer/core/dist/lib/hook-engine.js +109 -0
- package/node_modules/@inquirer/core/dist/lib/key.d.ts +15 -0
- package/node_modules/@inquirer/core/dist/lib/key.js +34 -0
- package/node_modules/@inquirer/core/dist/lib/make-theme.d.ts +3 -0
- package/node_modules/@inquirer/core/dist/lib/make-theme.js +33 -0
- package/node_modules/@inquirer/core/dist/lib/pagination/use-pagination.d.ts +15 -0
- package/node_modules/@inquirer/core/dist/lib/pagination/use-pagination.js +121 -0
- package/node_modules/@inquirer/core/dist/lib/screen-manager.d.ts +14 -0
- package/node_modules/@inquirer/core/dist/lib/screen-manager.js +84 -0
- package/node_modules/@inquirer/core/dist/lib/theme.d.ts +166 -0
- package/node_modules/@inquirer/core/dist/lib/theme.js +29 -0
- package/node_modules/@inquirer/core/dist/lib/use-effect.d.ts +2 -0
- package/node_modules/@inquirer/core/dist/lib/use-effect.js +11 -0
- package/node_modules/@inquirer/core/dist/lib/use-keypress.d.ts +3 -0
- package/node_modules/@inquirer/core/dist/lib/use-keypress.js +20 -0
- package/node_modules/@inquirer/core/dist/lib/use-memo.d.ts +1 -0
- package/node_modules/@inquirer/core/dist/lib/use-memo.js +14 -0
- package/node_modules/@inquirer/core/dist/lib/use-prefix.d.ts +5 -0
- package/node_modules/@inquirer/core/dist/lib/use-prefix.js +35 -0
- package/node_modules/@inquirer/core/dist/lib/use-ref.d.ts +6 -0
- package/node_modules/@inquirer/core/dist/lib/use-ref.js +4 -0
- package/node_modules/@inquirer/core/dist/lib/use-state.d.ts +7 -0
- package/node_modules/@inquirer/core/dist/lib/use-state.js +28 -0
- package/node_modules/@inquirer/core/dist/lib/utils.d.ts +13 -0
- package/node_modules/@inquirer/core/dist/lib/utils.js +25 -0
- package/node_modules/@inquirer/core/package.json +98 -0
- package/node_modules/@inquirer/figures/LICENSE +22 -0
- package/node_modules/@inquirer/figures/dist/index.d.ts +275 -0
- package/node_modules/@inquirer/figures/dist/index.js +315 -0
- package/node_modules/@inquirer/figures/package.json +81 -0
- package/node_modules/@inquirer/select/LICENSE +22 -0
- package/node_modules/@inquirer/select/README.md +258 -0
- package/node_modules/@inquirer/select/dist/index.d.ts +42 -0
- package/node_modules/@inquirer/select/dist/index.js +191 -0
- package/node_modules/@inquirer/select/package.json +93 -0
- package/node_modules/@inquirer/type/LICENSE +22 -0
- package/node_modules/@inquirer/type/dist/index.d.ts +2 -0
- package/node_modules/@inquirer/type/dist/index.js +2 -0
- package/node_modules/@inquirer/type/dist/inquirer.d.ts +35 -0
- package/node_modules/@inquirer/type/dist/inquirer.js +1 -0
- package/node_modules/@inquirer/type/dist/utils.d.ts +45 -0
- package/node_modules/@inquirer/type/dist/utils.js +16 -0
- package/node_modules/@inquirer/type/package.json +88 -0
- package/node_modules/cli-width/LICENSE +13 -0
- package/node_modules/cli-width/README.md +71 -0
- package/node_modules/cli-width/index.d.ts +13 -0
- package/node_modules/cli-width/index.js +49 -0
- package/node_modules/cli-width/package.json +40 -0
- package/node_modules/fast-string-truncated-width/dist/index.d.ts +4 -0
- package/node_modules/fast-string-truncated-width/dist/index.js +111 -0
- package/node_modules/fast-string-truncated-width/dist/types.d.ts +19 -0
- package/node_modules/fast-string-truncated-width/dist/types.js +2 -0
- package/node_modules/fast-string-truncated-width/dist/utils.d.ts +4 -0
- package/node_modules/fast-string-truncated-width/dist/utils.js +20 -0
- package/node_modules/fast-string-truncated-width/license +21 -0
- package/node_modules/fast-string-truncated-width/package.json +35 -0
- package/node_modules/fast-string-truncated-width/readme.md +59 -0
- package/node_modules/fast-string-width/dist/index.d.ts +4 -0
- package/node_modules/fast-string-width/dist/index.js +14 -0
- package/node_modules/fast-string-width/license +21 -0
- package/node_modules/fast-string-width/package.json +34 -0
- package/node_modules/fast-string-width/readme.md +42 -0
- package/node_modules/fast-wrap-ansi/LICENSE +23 -0
- package/node_modules/fast-wrap-ansi/README.md +26 -0
- package/node_modules/fast-wrap-ansi/lib/main.d.ts +6 -0
- package/node_modules/fast-wrap-ansi/lib/main.js +218 -0
- package/node_modules/fast-wrap-ansi/package.json +51 -0
- package/node_modules/mute-stream/LICENSE +15 -0
- package/node_modules/mute-stream/README.md +68 -0
- package/node_modules/mute-stream/lib/index.js +142 -0
- package/node_modules/mute-stream/package.json +54 -0
- package/node_modules/signal-exit/LICENSE.txt +16 -0
- package/node_modules/signal-exit/README.md +74 -0
- package/node_modules/signal-exit/dist/cjs/browser.d.ts +12 -0
- package/node_modules/signal-exit/dist/cjs/browser.d.ts.map +1 -0
- package/node_modules/signal-exit/dist/cjs/browser.js +10 -0
- package/node_modules/signal-exit/dist/cjs/browser.js.map +1 -0
- package/node_modules/signal-exit/dist/cjs/index.d.ts +48 -0
- package/node_modules/signal-exit/dist/cjs/index.d.ts.map +1 -0
- package/node_modules/signal-exit/dist/cjs/index.js +279 -0
- package/node_modules/signal-exit/dist/cjs/index.js.map +1 -0
- package/node_modules/signal-exit/dist/cjs/package.json +3 -0
- package/node_modules/signal-exit/dist/cjs/signals.d.ts +29 -0
- package/node_modules/signal-exit/dist/cjs/signals.d.ts.map +1 -0
- package/node_modules/signal-exit/dist/cjs/signals.js +42 -0
- package/node_modules/signal-exit/dist/cjs/signals.js.map +1 -0
- package/node_modules/signal-exit/dist/mjs/browser.d.ts +12 -0
- package/node_modules/signal-exit/dist/mjs/browser.d.ts.map +1 -0
- package/node_modules/signal-exit/dist/mjs/browser.js +4 -0
- package/node_modules/signal-exit/dist/mjs/browser.js.map +1 -0
- package/node_modules/signal-exit/dist/mjs/index.d.ts +48 -0
- package/node_modules/signal-exit/dist/mjs/index.d.ts.map +1 -0
- package/node_modules/signal-exit/dist/mjs/index.js +275 -0
- package/node_modules/signal-exit/dist/mjs/index.js.map +1 -0
- package/node_modules/signal-exit/dist/mjs/package.json +3 -0
- package/node_modules/signal-exit/dist/mjs/signals.d.ts +29 -0
- package/node_modules/signal-exit/dist/mjs/signals.d.ts.map +1 -0
- package/node_modules/signal-exit/dist/mjs/signals.js +39 -0
- package/node_modules/signal-exit/dist/mjs/signals.js.map +1 -0
- package/node_modules/signal-exit/package.json +106 -0
- package/package.json +16 -2
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { stripVTControlCharacters } from 'node:util';
|
|
2
|
+
import { breakLines, readlineWidth } from "./utils.js";
|
|
3
|
+
import { cursorDown, cursorLeft, cursorUp, cursorTo, cursorShow, eraseLines, } from '@inquirer/ansi';
|
|
4
|
+
const height = (content) => content.split('\n').length;
|
|
5
|
+
const lastLine = (content) => content.split('\n').pop() ?? '';
|
|
6
|
+
export default class ScreenManager {
|
|
7
|
+
// These variables are keeping information to allow correct prompt re-rendering
|
|
8
|
+
height = 0;
|
|
9
|
+
extraLinesUnderPrompt = 0;
|
|
10
|
+
cursorPos;
|
|
11
|
+
rl;
|
|
12
|
+
constructor(rl) {
|
|
13
|
+
this.rl = rl;
|
|
14
|
+
this.cursorPos = rl.getCursorPos();
|
|
15
|
+
}
|
|
16
|
+
write(content) {
|
|
17
|
+
this.rl.output.unmute();
|
|
18
|
+
this.rl.output.write(content);
|
|
19
|
+
this.rl.output.mute();
|
|
20
|
+
}
|
|
21
|
+
render(content, bottomContent = '') {
|
|
22
|
+
// Write message to screen and setPrompt to control backspace
|
|
23
|
+
const promptLine = lastLine(content);
|
|
24
|
+
const rawPromptLine = stripVTControlCharacters(promptLine);
|
|
25
|
+
// Remove the rl.line from our prompt. We can't rely on the content of
|
|
26
|
+
// rl.line (mainly because of the password prompt), so just rely on it's
|
|
27
|
+
// length.
|
|
28
|
+
let prompt = rawPromptLine;
|
|
29
|
+
if (this.rl.line.length > 0) {
|
|
30
|
+
prompt = prompt.slice(0, -this.rl.line.length);
|
|
31
|
+
}
|
|
32
|
+
this.rl.setPrompt(prompt);
|
|
33
|
+
// SetPrompt will change cursor position, now we can get correct value
|
|
34
|
+
this.cursorPos = this.rl.getCursorPos();
|
|
35
|
+
const width = readlineWidth();
|
|
36
|
+
content = breakLines(content, width);
|
|
37
|
+
bottomContent = breakLines(bottomContent, width);
|
|
38
|
+
// Manually insert an extra line if we're at the end of the line.
|
|
39
|
+
// This prevent the cursor from appearing at the beginning of the
|
|
40
|
+
// current line.
|
|
41
|
+
if (rawPromptLine.length % width === 0) {
|
|
42
|
+
content += '\n';
|
|
43
|
+
}
|
|
44
|
+
let output = content + (bottomContent ? '\n' + bottomContent : '');
|
|
45
|
+
/**
|
|
46
|
+
* Re-adjust the cursor at the correct position.
|
|
47
|
+
*/
|
|
48
|
+
// We need to consider parts of the prompt under the cursor as part of the bottom
|
|
49
|
+
// content in order to correctly cleanup and re-render.
|
|
50
|
+
const promptLineUpDiff = Math.floor(rawPromptLine.length / width) - this.cursorPos.rows;
|
|
51
|
+
const bottomContentHeight = promptLineUpDiff + (bottomContent ? height(bottomContent) : 0);
|
|
52
|
+
// Return cursor to the input position (on top of the bottomContent)
|
|
53
|
+
if (bottomContentHeight > 0)
|
|
54
|
+
output += cursorUp(bottomContentHeight);
|
|
55
|
+
// Return cursor to the initial left offset.
|
|
56
|
+
output += cursorTo(this.cursorPos.cols);
|
|
57
|
+
/**
|
|
58
|
+
* Render and store state for future re-rendering
|
|
59
|
+
*/
|
|
60
|
+
this.write(cursorDown(this.extraLinesUnderPrompt) + eraseLines(this.height) + output);
|
|
61
|
+
this.extraLinesUnderPrompt = bottomContentHeight;
|
|
62
|
+
this.height = height(output);
|
|
63
|
+
}
|
|
64
|
+
checkCursorPos() {
|
|
65
|
+
const cursorPos = this.rl.getCursorPos();
|
|
66
|
+
if (cursorPos.cols !== this.cursorPos.cols) {
|
|
67
|
+
this.write(cursorTo(cursorPos.cols));
|
|
68
|
+
this.cursorPos = cursorPos;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
done({ clearContent }) {
|
|
72
|
+
this.rl.setPrompt('');
|
|
73
|
+
let output = cursorDown(this.extraLinesUnderPrompt);
|
|
74
|
+
output += clearContent ? eraseLines(this.height) : '\n';
|
|
75
|
+
// Reset cursor to column 0. On Windows terminals, \n moves the cursor
|
|
76
|
+
// down without resetting the column when the rendered prompt+answer
|
|
77
|
+
// wraps past the terminal width. Without this, all subsequent output
|
|
78
|
+
// starts at the wrong horizontal offset.
|
|
79
|
+
output += cursorLeft;
|
|
80
|
+
output += cursorShow;
|
|
81
|
+
this.write(output);
|
|
82
|
+
this.rl.close();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import type { Prettify } from '@inquirer/type';
|
|
2
|
+
import { type Keybinding } from './key.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Union type representing the possible statuses of a prompt.
|
|
5
|
+
*
|
|
6
|
+
* - `'loading'`: The prompt is currently loading.
|
|
7
|
+
* - `'idle'`: The prompt is loaded and currently waiting for the user to
|
|
8
|
+
* submit an answer.
|
|
9
|
+
* - `'done'`: The user has submitted an answer and the prompt is finished.
|
|
10
|
+
* - `string`: Any other string: The prompt is in a custom state.
|
|
11
|
+
*/
|
|
12
|
+
export type Status = 'loading' | 'idle' | 'done' | (string & {});
|
|
13
|
+
type DefaultTheme = {
|
|
14
|
+
/**
|
|
15
|
+
* Prefix to prepend to the message. If a function is provided, it will be
|
|
16
|
+
* called with the current status of the prompt, and the return value will be
|
|
17
|
+
* used as the prefix.
|
|
18
|
+
*
|
|
19
|
+
* @remarks
|
|
20
|
+
* If `status === 'loading'`, this property is ignored and the spinner (styled
|
|
21
|
+
* by the `spinner` property) will be displayed instead.
|
|
22
|
+
*
|
|
23
|
+
* @defaultValue
|
|
24
|
+
* ```ts
|
|
25
|
+
* // import { styleText } from 'node:util';
|
|
26
|
+
* (status) => status === 'done' ? styleText('green', '✔') : styleText('blue', '?')
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
prefix: string | Prettify<Omit<Record<Status, string>, 'loading'>>;
|
|
30
|
+
/**
|
|
31
|
+
* Configuration for the spinner that is displayed when the prompt is in the
|
|
32
|
+
* `'loading'` state.
|
|
33
|
+
*
|
|
34
|
+
* We recommend the use of {@link https://github.com/sindresorhus/cli-spinners|cli-spinners} for a list of available spinners.
|
|
35
|
+
*/
|
|
36
|
+
spinner: {
|
|
37
|
+
/**
|
|
38
|
+
* The time interval between frames, in milliseconds.
|
|
39
|
+
*
|
|
40
|
+
* @defaultValue
|
|
41
|
+
* ```ts
|
|
42
|
+
* 80
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
interval: number;
|
|
46
|
+
/**
|
|
47
|
+
* A list of frames to show for the spinner.
|
|
48
|
+
*
|
|
49
|
+
* @defaultValue
|
|
50
|
+
* ```ts
|
|
51
|
+
* ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
frames: string[];
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Alternative keybindings enabled for prompt navigation.
|
|
58
|
+
*
|
|
59
|
+
* @defaultValue
|
|
60
|
+
* ```ts
|
|
61
|
+
* process.env['INQUIRER_KEYBINDINGS']
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
keybindings: ReadonlyArray<Keybinding>;
|
|
65
|
+
/**
|
|
66
|
+
* Object containing functions to style different parts of the prompt.
|
|
67
|
+
*/
|
|
68
|
+
style: {
|
|
69
|
+
/**
|
|
70
|
+
* Style to apply to the user's answer once it has been submitted.
|
|
71
|
+
*
|
|
72
|
+
* @param text - The user's answer.
|
|
73
|
+
* @returns The styled answer.
|
|
74
|
+
*
|
|
75
|
+
* @defaultValue
|
|
76
|
+
* ```ts
|
|
77
|
+
* // import { styleText } from 'node:util';
|
|
78
|
+
* (text) => styleText('cyan', text)
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
answer: (text: string) => string;
|
|
82
|
+
/**
|
|
83
|
+
* Style to apply to the message displayed to the user.
|
|
84
|
+
*
|
|
85
|
+
* @param text - The message to style.
|
|
86
|
+
* @param status - The current status of the prompt.
|
|
87
|
+
* @returns The styled message.
|
|
88
|
+
*
|
|
89
|
+
* @defaultValue
|
|
90
|
+
* ```ts
|
|
91
|
+
* // import { styleText } from 'node:util';
|
|
92
|
+
* (text, status) => styleText('bold', text)
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
message: (text: string, status: Status) => string;
|
|
96
|
+
/**
|
|
97
|
+
* Style to apply to error messages.
|
|
98
|
+
*
|
|
99
|
+
* @param text - The error message.
|
|
100
|
+
* @returns The styled error message.
|
|
101
|
+
*
|
|
102
|
+
* @defaultValue
|
|
103
|
+
* ```ts
|
|
104
|
+
* // import { styleText } from 'node:util';
|
|
105
|
+
* (text) => styleText('red', `> ${text}`)
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
error: (text: string) => string;
|
|
109
|
+
/**
|
|
110
|
+
* Style to apply to the default answer when one is provided.
|
|
111
|
+
*
|
|
112
|
+
* @param text - The default answer.
|
|
113
|
+
* @returns The styled default answer.
|
|
114
|
+
*
|
|
115
|
+
* @defaultValue
|
|
116
|
+
* ```ts
|
|
117
|
+
* // import { styleText } from 'node:util';
|
|
118
|
+
* (text) => styleText('dim', `(${text})`)
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
defaultAnswer: (text: string) => string;
|
|
122
|
+
/**
|
|
123
|
+
* Style to apply to help text.
|
|
124
|
+
*
|
|
125
|
+
* @param text - The help text.
|
|
126
|
+
* @returns The styled help text.
|
|
127
|
+
*
|
|
128
|
+
* @defaultValue
|
|
129
|
+
* ```ts
|
|
130
|
+
* // import { styleText } from 'node:util';
|
|
131
|
+
* (text) => styleText('dim', text)
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
help: (text: string) => string;
|
|
135
|
+
/**
|
|
136
|
+
* Style to apply to highlighted text.
|
|
137
|
+
*
|
|
138
|
+
* @param text - The text to highlight.
|
|
139
|
+
* @returns The highlighted text.
|
|
140
|
+
*
|
|
141
|
+
* @defaultValue
|
|
142
|
+
* ```ts
|
|
143
|
+
* // import { styleText } from 'node:util';
|
|
144
|
+
* (text) => styleText('cyan', text)
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
highlight: (text: string) => string;
|
|
148
|
+
/**
|
|
149
|
+
* Style to apply to keyboard keys referred to in help texts.
|
|
150
|
+
*
|
|
151
|
+
* @param text - The key to style.
|
|
152
|
+
* @returns The styled key.
|
|
153
|
+
*
|
|
154
|
+
* @defaultValue
|
|
155
|
+
* ```ts
|
|
156
|
+
* // import { styleText } from 'node:util';
|
|
157
|
+
* (text) => styleText('cyan', styleText('bold', `<${text}>`))
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
key: (text: string) => string;
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
export type Theme<Extension extends object = object> = Extension & DefaultTheme;
|
|
164
|
+
export declare const defaultTheme: DefaultTheme;
|
|
165
|
+
export declare function getDefaultTheme(): DefaultTheme;
|
|
166
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { styleText } from 'node:util';
|
|
2
|
+
import figures from '@inquirer/figures';
|
|
3
|
+
import { getDefaultKeybindings } from "./key.js";
|
|
4
|
+
export const defaultTheme = {
|
|
5
|
+
prefix: {
|
|
6
|
+
idle: styleText('blue', '?'),
|
|
7
|
+
done: styleText('green', figures.tick),
|
|
8
|
+
},
|
|
9
|
+
spinner: {
|
|
10
|
+
interval: 80,
|
|
11
|
+
frames: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'].map((frame) => styleText('yellow', frame)),
|
|
12
|
+
},
|
|
13
|
+
keybindings: [],
|
|
14
|
+
style: {
|
|
15
|
+
answer: (text) => styleText('cyan', text),
|
|
16
|
+
message: (text) => styleText('bold', text),
|
|
17
|
+
error: (text) => styleText('red', `> ${text}`),
|
|
18
|
+
defaultAnswer: (text) => styleText('dim', `(${text})`),
|
|
19
|
+
help: (text) => styleText('dim', text),
|
|
20
|
+
highlight: (text) => styleText('cyan', text),
|
|
21
|
+
key: (text) => styleText('cyan', styleText('bold', `<${text}>`)),
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
export function getDefaultTheme() {
|
|
25
|
+
return {
|
|
26
|
+
...defaultTheme,
|
|
27
|
+
keybindings: getDefaultKeybindings(),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { withPointer, effectScheduler } from "./hook-engine.js";
|
|
2
|
+
export function useEffect(cb, depArray) {
|
|
3
|
+
withPointer((pointer) => {
|
|
4
|
+
const oldDeps = pointer.get();
|
|
5
|
+
const hasChanged = !Array.isArray(oldDeps) || depArray.some((dep, i) => !Object.is(dep, oldDeps[i]));
|
|
6
|
+
if (hasChanged) {
|
|
7
|
+
effectScheduler.queue(cb);
|
|
8
|
+
}
|
|
9
|
+
pointer.set(depArray);
|
|
10
|
+
});
|
|
11
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useRef } from "./use-ref.js";
|
|
2
|
+
import { useEffect } from "./use-effect.js";
|
|
3
|
+
import { withUpdates } from "./hook-engine.js";
|
|
4
|
+
export function useKeypress(userHandler) {
|
|
5
|
+
const signal = useRef(userHandler);
|
|
6
|
+
signal.current = userHandler;
|
|
7
|
+
useEffect((rl) => {
|
|
8
|
+
let ignore = false;
|
|
9
|
+
const handler = withUpdates((_input, event) => {
|
|
10
|
+
if (ignore)
|
|
11
|
+
return;
|
|
12
|
+
void signal.current(event, rl);
|
|
13
|
+
});
|
|
14
|
+
rl.input.on('keypress', handler);
|
|
15
|
+
return () => {
|
|
16
|
+
ignore = true;
|
|
17
|
+
rl.input.removeListener('keypress', handler);
|
|
18
|
+
};
|
|
19
|
+
}, []);
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useMemo<Value>(fn: () => Value, dependencies: ReadonlyArray<unknown>): Value;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { withPointer } from "./hook-engine.js";
|
|
2
|
+
export function useMemo(fn, dependencies) {
|
|
3
|
+
return withPointer((pointer) => {
|
|
4
|
+
const prev = pointer.get();
|
|
5
|
+
if (!pointer.initialized ||
|
|
6
|
+
prev.dependencies.length !== dependencies.length ||
|
|
7
|
+
prev.dependencies.some((dep, i) => dep !== dependencies[i])) {
|
|
8
|
+
const value = fn();
|
|
9
|
+
pointer.set({ value, dependencies });
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
12
|
+
return prev.value;
|
|
13
|
+
});
|
|
14
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { useState } from "./use-state.js";
|
|
2
|
+
import { useEffect } from "./use-effect.js";
|
|
3
|
+
import { makeTheme } from "./make-theme.js";
|
|
4
|
+
export function usePrefix({ status = 'idle', theme, }) {
|
|
5
|
+
const [showLoader, setShowLoader] = useState(false);
|
|
6
|
+
const [tick, setTick] = useState(0);
|
|
7
|
+
const { prefix, spinner } = makeTheme(theme);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
if (status === 'loading') {
|
|
10
|
+
let tickInterval;
|
|
11
|
+
let inc = -1;
|
|
12
|
+
// Delay displaying spinner by 300ms, to avoid flickering
|
|
13
|
+
const delayTimeout = setTimeout(() => {
|
|
14
|
+
setShowLoader(true);
|
|
15
|
+
tickInterval = setInterval(() => {
|
|
16
|
+
inc = inc + 1;
|
|
17
|
+
setTick(inc % spinner.frames.length);
|
|
18
|
+
}, spinner.interval);
|
|
19
|
+
}, 300);
|
|
20
|
+
return () => {
|
|
21
|
+
clearTimeout(delayTimeout);
|
|
22
|
+
clearInterval(tickInterval);
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
setShowLoader(false);
|
|
27
|
+
}
|
|
28
|
+
}, [status]);
|
|
29
|
+
if (showLoader) {
|
|
30
|
+
return spinner.frames[tick];
|
|
31
|
+
}
|
|
32
|
+
// There's a delay before we show the loader. So we want to ignore `loading` here, and pass idle instead.
|
|
33
|
+
const iconName = status === 'loading' ? 'idle' : status;
|
|
34
|
+
return typeof prefix === 'string' ? prefix : (prefix[iconName] ?? prefix['idle']);
|
|
35
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type NotFunction<T> = T extends (...args: never) => unknown ? never : T;
|
|
2
|
+
type Reducer<Value> = (currentValue: Value) => Value;
|
|
3
|
+
type SetState<Value> = (newValue: NotFunction<Value> | Reducer<Value>) => void;
|
|
4
|
+
type OptionalSetState<Value> = (newValue?: NotFunction<Value> | Reducer<Value>) => void;
|
|
5
|
+
export declare function useState<Value>(defaultValue: NotFunction<Value> | (() => Value)): [Value, SetState<Value>];
|
|
6
|
+
export declare function useState<Value>(defaultValue?: NotFunction<Value> | (() => Value)): [Value | undefined, OptionalSetState<Value | undefined>];
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { AsyncResource } from 'node:async_hooks';
|
|
2
|
+
import { withPointer, handleChange } from "./hook-engine.js";
|
|
3
|
+
function isFactory(value) {
|
|
4
|
+
return typeof value === 'function';
|
|
5
|
+
}
|
|
6
|
+
function isReducer(value) {
|
|
7
|
+
return typeof value === 'function';
|
|
8
|
+
}
|
|
9
|
+
export function useState(defaultValue) {
|
|
10
|
+
return withPointer((pointer) => {
|
|
11
|
+
const setState = AsyncResource.bind(function setState(newValue) {
|
|
12
|
+
const currentValue = pointer.get();
|
|
13
|
+
const nextValue = isReducer(newValue) ? newValue(currentValue) : newValue;
|
|
14
|
+
// Noop if the value is still the same.
|
|
15
|
+
if (!Object.is(currentValue, nextValue)) {
|
|
16
|
+
pointer.set(nextValue);
|
|
17
|
+
// Trigger re-render
|
|
18
|
+
handleChange();
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
if (pointer.initialized) {
|
|
22
|
+
return [pointer.get(), setState];
|
|
23
|
+
}
|
|
24
|
+
const value = isFactory(defaultValue) ? defaultValue() : defaultValue;
|
|
25
|
+
pointer.set(value);
|
|
26
|
+
return [value, setState];
|
|
27
|
+
});
|
|
28
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Force line returns at specific width. This function is ANSI code friendly and it'll
|
|
3
|
+
* ignore invisible codes during width calculation.
|
|
4
|
+
* @param {string} content
|
|
5
|
+
* @param {number} width
|
|
6
|
+
* @return {string}
|
|
7
|
+
*/
|
|
8
|
+
export declare function breakLines(content: string, width: number): string;
|
|
9
|
+
/**
|
|
10
|
+
* Returns the width of the active readline, or 80 as default value.
|
|
11
|
+
* @returns {number}
|
|
12
|
+
*/
|
|
13
|
+
export declare function readlineWidth(): number;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import cliWidth from 'cli-width';
|
|
2
|
+
import { wrapAnsi } from 'fast-wrap-ansi';
|
|
3
|
+
import { readline } from "./hook-engine.js";
|
|
4
|
+
/**
|
|
5
|
+
* Force line returns at specific width. This function is ANSI code friendly and it'll
|
|
6
|
+
* ignore invisible codes during width calculation.
|
|
7
|
+
* @param {string} content
|
|
8
|
+
* @param {number} width
|
|
9
|
+
* @return {string}
|
|
10
|
+
*/
|
|
11
|
+
export function breakLines(content, width) {
|
|
12
|
+
return content
|
|
13
|
+
.split('\n')
|
|
14
|
+
.flatMap((line) => wrapAnsi(line, width, { trim: false, wordWrap: false })
|
|
15
|
+
.split('\n')
|
|
16
|
+
.map((str) => str.trimEnd()))
|
|
17
|
+
.join('\n');
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Returns the width of the active readline, or 80 as default value.
|
|
21
|
+
* @returns {number}
|
|
22
|
+
*/
|
|
23
|
+
export function readlineWidth() {
|
|
24
|
+
return cliWidth({ defaultWidth: 80, output: readline().output });
|
|
25
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@inquirer/core",
|
|
3
|
+
"version": "12.0.4",
|
|
4
|
+
"description": "Core Inquirer prompt API",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"answer",
|
|
7
|
+
"answers",
|
|
8
|
+
"ask",
|
|
9
|
+
"base",
|
|
10
|
+
"cli",
|
|
11
|
+
"command",
|
|
12
|
+
"command-line",
|
|
13
|
+
"confirm",
|
|
14
|
+
"enquirer",
|
|
15
|
+
"generate",
|
|
16
|
+
"generator",
|
|
17
|
+
"hyper",
|
|
18
|
+
"input",
|
|
19
|
+
"inquire",
|
|
20
|
+
"inquirer",
|
|
21
|
+
"interface",
|
|
22
|
+
"iterm",
|
|
23
|
+
"javascript",
|
|
24
|
+
"menu",
|
|
25
|
+
"node",
|
|
26
|
+
"nodejs",
|
|
27
|
+
"prompt",
|
|
28
|
+
"promptly",
|
|
29
|
+
"prompts",
|
|
30
|
+
"question",
|
|
31
|
+
"readline",
|
|
32
|
+
"scaffold",
|
|
33
|
+
"scaffolder",
|
|
34
|
+
"scaffolding",
|
|
35
|
+
"stdin",
|
|
36
|
+
"stdout",
|
|
37
|
+
"terminal",
|
|
38
|
+
"tty",
|
|
39
|
+
"ui",
|
|
40
|
+
"yeoman",
|
|
41
|
+
"yo",
|
|
42
|
+
"zsh"
|
|
43
|
+
],
|
|
44
|
+
"homepage": "https://github.com/SBoudrias/Inquirer.js/blob/main/packages/core/README.md",
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
"author": "Simon Boudrias <admin@simonboudrias.com>",
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "https://github.com/SBoudrias/Inquirer.js.git"
|
|
50
|
+
},
|
|
51
|
+
"files": [
|
|
52
|
+
"dist"
|
|
53
|
+
],
|
|
54
|
+
"type": "module",
|
|
55
|
+
"sideEffects": false,
|
|
56
|
+
"exports": {
|
|
57
|
+
".": {
|
|
58
|
+
"types": "./dist/index.d.ts",
|
|
59
|
+
"default": "./dist/index.js"
|
|
60
|
+
},
|
|
61
|
+
"./package.json": "./package.json"
|
|
62
|
+
},
|
|
63
|
+
"publishConfig": {
|
|
64
|
+
"access": "public"
|
|
65
|
+
},
|
|
66
|
+
"scripts": {
|
|
67
|
+
"tsc": "tsc"
|
|
68
|
+
},
|
|
69
|
+
"dependencies": {
|
|
70
|
+
"@inquirer/ansi": "^2.0.9",
|
|
71
|
+
"@inquirer/figures": "^2.0.9",
|
|
72
|
+
"@inquirer/type": "4.2.0",
|
|
73
|
+
"cli-width": "^4.1.0",
|
|
74
|
+
"fast-wrap-ansi": "^0.2.0",
|
|
75
|
+
"mute-stream": "^3.0.0",
|
|
76
|
+
"signal-exit": "^4.1.0"
|
|
77
|
+
},
|
|
78
|
+
"devDependencies": {
|
|
79
|
+
"@repo/tsconfig": "0.0.0",
|
|
80
|
+
"@types/mute-stream": "^0.0.4",
|
|
81
|
+
"@types/node": "^26.1.1",
|
|
82
|
+
"typescript": "^6.0.2"
|
|
83
|
+
},
|
|
84
|
+
"peerDependencies": {
|
|
85
|
+
"@types/node": ">=18"
|
|
86
|
+
},
|
|
87
|
+
"peerDependenciesMeta": {
|
|
88
|
+
"@types/node": {
|
|
89
|
+
"optional": true
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"engines": {
|
|
93
|
+
"node": ">=23.5.0 || ^22.13.0 || ^20.17.0"
|
|
94
|
+
},
|
|
95
|
+
"main": "./dist/index.js",
|
|
96
|
+
"types": "./dist/index.d.ts",
|
|
97
|
+
"gitHead": "a9436bd94d55a439df308f50e77a7cd0b2078e98"
|
|
98
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2025 Simon Boudrias
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
|
4
|
+
obtaining a copy of this software and associated documentation
|
|
5
|
+
files (the "Software"), to deal in the Software without
|
|
6
|
+
restriction, including without limitation the rights to use,
|
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the
|
|
9
|
+
Software is furnished to do so, subject to the following
|
|
10
|
+
conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be
|
|
13
|
+
included in all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|