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,67 @@
|
|
|
1
|
+
const crypto = require('crypto');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { spawnSync } = require('child_process');
|
|
5
|
+
|
|
6
|
+
// A folder-metadata file the OS writes on its own (Finder, Explorer); never user content.
|
|
7
|
+
// Only a regular file: a folder or link under that name is still the user's.
|
|
8
|
+
function isOsMetadata(full) {
|
|
9
|
+
return ['.DS_Store', 'Thumbs.db'].includes(path.basename(full))
|
|
10
|
+
&& fs.lstatSync(full, { throwIfNoEntry: false })?.isFile() === true;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// SHA-256 of a file with CRLF read as LF: Git for Windows checks text out with CRLF by
|
|
14
|
+
// default, and an unedited clone must still match its shipped copy.
|
|
15
|
+
function contentHash(file) {
|
|
16
|
+
const bytes = fs.readFileSync(file).toString('latin1').replace(/\r\n/g, '\n');
|
|
17
|
+
return crypto.createHash('sha256').update(bytes, 'latin1').digest('hex');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Hash every entry, including empty directories and dotfiles, except OS metadata. Links and
|
|
21
|
+
// special files are never installer-owned.
|
|
22
|
+
function fingerprint(dir) {
|
|
23
|
+
const entries = [];
|
|
24
|
+
function visit(full, relative) {
|
|
25
|
+
const stat = fs.lstatSync(full);
|
|
26
|
+
if (stat.isDirectory()) {
|
|
27
|
+
entries.push([relative, 'directory']);
|
|
28
|
+
for (const name of fs.readdirSync(full).sort()) {
|
|
29
|
+
if (isOsMetadata(path.join(full, name))) continue;
|
|
30
|
+
visit(path.join(full, name), relative ? `${relative}/${name}` : name);
|
|
31
|
+
}
|
|
32
|
+
} else if (stat.isFile()) {
|
|
33
|
+
entries.push([relative, 'file', contentHash(full)]);
|
|
34
|
+
} else {
|
|
35
|
+
throw new Error(`link or special file: ${full}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (!fs.lstatSync(dir).isDirectory()) throw new Error('not a real directory');
|
|
39
|
+
visit(dir, '');
|
|
40
|
+
return crypto.createHash('sha256').update(JSON.stringify(entries)).digest('hex');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Use the index, not status: even files deleted locally need ownership checks.
|
|
44
|
+
// Inspect the repository containing this root, including global dotfiles repos.
|
|
45
|
+
function trackedPaths(root) {
|
|
46
|
+
let cwd = root;
|
|
47
|
+
while (!fs.existsSync(cwd)) cwd = path.dirname(cwd);
|
|
48
|
+
const env = { ...process.env, LC_ALL: 'C' };
|
|
49
|
+
for (const key of ['GIT_DIR', 'GIT_WORK_TREE', 'GIT_INDEX_FILE', 'GIT_COMMON_DIR',
|
|
50
|
+
'GIT_LITERAL_PATHSPECS', 'GIT_GLOB_PATHSPECS', 'GIT_NOGLOB_PATHSPECS', 'GIT_ICASE_PATHSPECS',
|
|
51
|
+
'GIT_CEILING_DIRECTORIES', 'GIT_DISCOVERY_ACROSS_FILESYSTEM']) delete env[key];
|
|
52
|
+
const git = (args) => spawnSync('git', ['-C', cwd, ...args], { encoding: 'utf8', env });
|
|
53
|
+
const repo = git(['rev-parse', '--show-toplevel']);
|
|
54
|
+
if (repo.error?.code === 'ENOENT') return [];
|
|
55
|
+
if (repo.error) throw repo.error;
|
|
56
|
+
if (repo.status !== 0) {
|
|
57
|
+
if (repo.status === 128 && repo.stderr.includes('not a git repository')) return [];
|
|
58
|
+
throw new Error(`cannot inspect Git ownership: ${repo.stderr.trim()}`);
|
|
59
|
+
}
|
|
60
|
+
// Conservative case folding also protects index spellings on macOS/Windows volumes.
|
|
61
|
+
const files = git(['ls-files', '--full-name', '-z', '--', `:(icase,literal)${root}`]);
|
|
62
|
+
if (files.error) throw files.error;
|
|
63
|
+
if (files.status !== 0) throw new Error(`cannot inspect Git index: ${files.stderr.trim()}`);
|
|
64
|
+
return files.stdout.split('\0').filter(Boolean).map((file) => path.resolve(repo.stdout.trim(), file));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = { contentHash, fingerprint, isOsMetadata, trackedPaths };
|
|
@@ -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.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# @inquirer/ansi
|
|
2
|
+
|
|
3
|
+
A lightweight package providing ANSI escape sequences for terminal cursor manipulation and screen clearing.
|
|
4
|
+
|
|
5
|
+
# Installation
|
|
6
|
+
|
|
7
|
+
<table>
|
|
8
|
+
<tr>
|
|
9
|
+
<th>yarn</th>
|
|
10
|
+
<th>pnpm</th>
|
|
11
|
+
</tr>
|
|
12
|
+
<tr>
|
|
13
|
+
<td>
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
yarn add @inquirer/ansi
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
</td>
|
|
20
|
+
<td>
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
pnpm add @inquirer/ansi
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
</td>
|
|
27
|
+
</tr>
|
|
28
|
+
<tr>
|
|
29
|
+
<th>bun</th>
|
|
30
|
+
<th>deno</th>
|
|
31
|
+
</tr>
|
|
32
|
+
<tr>
|
|
33
|
+
<td>
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
bun add @inquirer/ansi
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
</td>
|
|
40
|
+
<td>
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
deno add npm:@inquirer/ansi
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
</td>
|
|
47
|
+
</tr>
|
|
48
|
+
<tr>
|
|
49
|
+
<th colSpan="2">npm</th>
|
|
50
|
+
</tr>
|
|
51
|
+
<tr>
|
|
52
|
+
<td colSpan="2">
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
npm install @inquirer/ansi
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
</td>
|
|
59
|
+
</tr>
|
|
60
|
+
</table>
|
|
61
|
+
|
|
62
|
+
## Usage
|
|
63
|
+
|
|
64
|
+
```js
|
|
65
|
+
import {
|
|
66
|
+
cursorUp,
|
|
67
|
+
cursorDown,
|
|
68
|
+
cursorTo,
|
|
69
|
+
cursorLeft,
|
|
70
|
+
cursorHide,
|
|
71
|
+
cursorShow,
|
|
72
|
+
eraseLines,
|
|
73
|
+
} from '@inquirer/ansi';
|
|
74
|
+
|
|
75
|
+
// Move cursor up 3 lines
|
|
76
|
+
process.stdout.write(cursorUp(3));
|
|
77
|
+
|
|
78
|
+
// Move cursor to specific position (x: 10, y: 5)
|
|
79
|
+
process.stdout.write(cursorTo(10, 5));
|
|
80
|
+
|
|
81
|
+
// Hide/show cursor
|
|
82
|
+
process.stdout.write(cursorHide);
|
|
83
|
+
process.stdout.write(cursorShow);
|
|
84
|
+
|
|
85
|
+
// Clear 5 lines
|
|
86
|
+
process.stdout.write(eraseLines(5));
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Or when used inside an inquirer prompt:
|
|
90
|
+
|
|
91
|
+
```js
|
|
92
|
+
import { cursorHide } from '@inquirer/ansi';
|
|
93
|
+
import { createPrompt } from '@inquirer/core';
|
|
94
|
+
|
|
95
|
+
export default createPrompt((config, done: (value: void) => void) => {
|
|
96
|
+
return `Choose an option${cursorHide}`;
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## API
|
|
101
|
+
|
|
102
|
+
### Cursor Movement
|
|
103
|
+
|
|
104
|
+
- **`cursorUp(count?: number)`** - Move cursor up by `count` lines (default: 1)
|
|
105
|
+
- **`cursorDown(count?: number)`** - Move cursor down by `count` lines (default: 1)
|
|
106
|
+
- **`cursorTo(x: number, y?: number)`** - Move cursor to position (x, y). If y is omitted, only moves horizontally
|
|
107
|
+
- **`cursorLeft`** - Move cursor to beginning of line
|
|
108
|
+
|
|
109
|
+
### Cursor Visibility
|
|
110
|
+
|
|
111
|
+
- **`cursorHide`** - Hide the cursor
|
|
112
|
+
- **`cursorShow`** - Show the cursor
|
|
113
|
+
|
|
114
|
+
### Screen Manipulation
|
|
115
|
+
|
|
116
|
+
- **`eraseLines(count: number)`** - Clear `count` lines and position cursor at the beginning of the first cleared line
|
|
117
|
+
|
|
118
|
+
# License
|
|
119
|
+
|
|
120
|
+
Copyright (c) 2025 Simon Boudrias (twitter: [@vaxilart](https://twitter.com/Vaxilart))<br/>
|
|
121
|
+
Licensed under the MIT license.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Move cursor to first column */
|
|
2
|
+
export declare const cursorLeft: string;
|
|
3
|
+
/** Hide the cursor */
|
|
4
|
+
export declare const cursorHide: string;
|
|
5
|
+
/** Show the cursor */
|
|
6
|
+
export declare const cursorShow: string;
|
|
7
|
+
/** Move cursor up by count rows */
|
|
8
|
+
export declare const cursorUp: (rows?: number) => string;
|
|
9
|
+
/** Move cursor down by count rows */
|
|
10
|
+
export declare const cursorDown: (rows?: number) => string;
|
|
11
|
+
/** Move cursor to position (x, y) */
|
|
12
|
+
export declare const cursorTo: (x: number, y?: number) => string;
|
|
13
|
+
/** Erase the specified number of lines above the cursor */
|
|
14
|
+
export declare const eraseLines: (lines: number) => string;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const ESC = '\u001B[';
|
|
2
|
+
/** Move cursor to first column */
|
|
3
|
+
export const cursorLeft = ESC + 'G';
|
|
4
|
+
/** Hide the cursor */
|
|
5
|
+
export const cursorHide = ESC + '?25l';
|
|
6
|
+
/** Show the cursor */
|
|
7
|
+
export const cursorShow = ESC + '?25h';
|
|
8
|
+
/** Move cursor up by count rows */
|
|
9
|
+
export const cursorUp = (rows = 1) => (rows > 0 ? `${ESC}${rows}A` : '');
|
|
10
|
+
/** Move cursor down by count rows */
|
|
11
|
+
export const cursorDown = (rows = 1) => rows > 0 ? `${ESC}${rows}B` : '';
|
|
12
|
+
/** Move cursor to position (x, y) */
|
|
13
|
+
export const cursorTo = (x, y) => {
|
|
14
|
+
if (typeof y === 'number' && !Number.isNaN(y)) {
|
|
15
|
+
return `${ESC}${y + 1};${x + 1}H`;
|
|
16
|
+
}
|
|
17
|
+
return `${ESC}${x + 1}G`;
|
|
18
|
+
};
|
|
19
|
+
const eraseLine = ESC + '2K';
|
|
20
|
+
/** Erase the specified number of lines above the cursor */
|
|
21
|
+
export const eraseLines = (lines) => lines > 0 ? (eraseLine + cursorUp(1)).repeat(lines - 1) + eraseLine + cursorLeft : '';
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@inquirer/ansi",
|
|
3
|
+
"version": "2.0.9",
|
|
4
|
+
"keywords": [
|
|
5
|
+
"ansi",
|
|
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/ansi/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
|
+
"devDependencies": {
|
|
70
|
+
"@repo/tsconfig": "0.0.0",
|
|
71
|
+
"typescript": "^6.0.2"
|
|
72
|
+
},
|
|
73
|
+
"engines": {
|
|
74
|
+
"node": ">=23.5.0 || ^22.13.0 || ^20.17.0"
|
|
75
|
+
},
|
|
76
|
+
"main": "./dist/index.js",
|
|
77
|
+
"types": "./dist/index.d.ts",
|
|
78
|
+
"gitHead": "a9436bd94d55a439df308f50e77a7cd0b2078e98"
|
|
79
|
+
}
|
|
@@ -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.
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# `@inquirer/checkbox`
|
|
2
|
+
|
|
3
|
+
Simple interactive command line prompt to display a list of checkboxes (multi select).
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
# Installation
|
|
8
|
+
|
|
9
|
+
<table>
|
|
10
|
+
<tr>
|
|
11
|
+
<th>yarn</th>
|
|
12
|
+
<th>pnpm</th>
|
|
13
|
+
</tr>
|
|
14
|
+
<tr>
|
|
15
|
+
<td>
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
yarn add @inquirer/prompts
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
</td>
|
|
22
|
+
<td>
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
pnpm add @inquirer/prompts
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
</td>
|
|
29
|
+
</tr>
|
|
30
|
+
<tr>
|
|
31
|
+
<th>bun</th>
|
|
32
|
+
<th>deno</th>
|
|
33
|
+
</tr>
|
|
34
|
+
<tr>
|
|
35
|
+
<td>
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
bun add @inquirer/prompts
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
</td>
|
|
42
|
+
<td>
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
deno add npm:@inquirer/prompts
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
</td>
|
|
49
|
+
</tr>
|
|
50
|
+
<tr>
|
|
51
|
+
<th colSpan="2">npm</th>
|
|
52
|
+
</tr>
|
|
53
|
+
<tr>
|
|
54
|
+
<td colSpan="2">
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
npm install @inquirer/prompts
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
</td>
|
|
61
|
+
</tr>
|
|
62
|
+
<tr>
|
|
63
|
+
<td colSpan="2" align="center">Or</td>
|
|
64
|
+
</tr>
|
|
65
|
+
<tr>
|
|
66
|
+
<th>yarn</th>
|
|
67
|
+
<th>pnpm</th>
|
|
68
|
+
</tr>
|
|
69
|
+
<tr>
|
|
70
|
+
<td>
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
yarn add @inquirer/checkbox
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
</td>
|
|
77
|
+
<td>
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
pnpm add @inquirer/checkbox
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
</td>
|
|
84
|
+
</tr>
|
|
85
|
+
<tr>
|
|
86
|
+
<th>bun</th>
|
|
87
|
+
<th>deno</th>
|
|
88
|
+
</tr>
|
|
89
|
+
<tr>
|
|
90
|
+
<td>
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
bun add @inquirer/checkbox
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
</td>
|
|
97
|
+
<td>
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
deno add npm:@inquirer/checkbox
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
</td>
|
|
104
|
+
</tr>
|
|
105
|
+
<tr>
|
|
106
|
+
<th colSpan="2">npm</th>
|
|
107
|
+
</tr>
|
|
108
|
+
<tr>
|
|
109
|
+
<td colSpan="2">
|
|
110
|
+
|
|
111
|
+
```sh
|
|
112
|
+
npm install @inquirer/checkbox
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
</td>
|
|
116
|
+
</tr>
|
|
117
|
+
</table>
|
|
118
|
+
|
|
119
|
+
On Deno, prompts detect the terminal's unicode and color support from the environment, so run your script with `--allow-env`.
|
|
120
|
+
|
|
121
|
+
# Usage
|
|
122
|
+
|
|
123
|
+
```js
|
|
124
|
+
import { checkbox, Separator } from '@inquirer/prompts';
|
|
125
|
+
// Or
|
|
126
|
+
// import checkbox, { Separator } from '@inquirer/checkbox';
|
|
127
|
+
|
|
128
|
+
const answer = await checkbox({
|
|
129
|
+
message: 'Select a package manager',
|
|
130
|
+
choices: [
|
|
131
|
+
{ name: 'npm', value: 'npm' },
|
|
132
|
+
{ name: 'yarn', value: 'yarn' },
|
|
133
|
+
new Separator(),
|
|
134
|
+
{ name: 'pnpm', value: 'pnpm', disabled: true },
|
|
135
|
+
{
|
|
136
|
+
name: 'pnpm',
|
|
137
|
+
value: 'pnpm',
|
|
138
|
+
disabled: '(pnpm is not available)',
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Options
|
|
145
|
+
|
|
146
|
+
| Property | Type | Required | Description |
|
|
147
|
+
| --------- | --------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
148
|
+
| message | `string` | yes | The question to ask |
|
|
149
|
+
| choices | `Choice[]` | yes | List of the available choices. |
|
|
150
|
+
| pageSize | `number` | no | By default, lists of choice longer than 7 will be paginated. Use this option to control how many choices will appear on the screen at once. |
|
|
151
|
+
| loop | `boolean` | no | Defaults to `true`. When set to `false`, the cursor will be constrained to the top and bottom of the choice list without looping. |
|
|
152
|
+
| required | `boolean` | no | When set to `true`, ensures at least one choice must be selected. |
|
|
153
|
+
| validate | `async (Choice[]) => boolean \| string` | no | On submit, validate the choices. When returning a string, it'll be used as the error message displayed to the user. Note: returning a rejected promise, we'll assume a code error happened and crash. |
|
|
154
|
+
| shortcuts | [See Shortcuts](#Shortcuts) | no | Customize shortcut keys for `all` and `invert`. |
|
|
155
|
+
| theme | [See Theming](#Theming) | no | Customize look of the prompt. |
|
|
156
|
+
|
|
157
|
+
`Separator` objects can be used in the `choices` array to render non-selectable lines in the choice list. By default it'll render a line, but you can provide the text as argument (`new Separator('-- Dependencies --')`). This option is often used to add labels to groups within long list of options.
|
|
158
|
+
|
|
159
|
+
### `Choice` object
|
|
160
|
+
|
|
161
|
+
The `Choice` object is typed as
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
type Choice<Value> = {
|
|
165
|
+
value: Value;
|
|
166
|
+
name?: string;
|
|
167
|
+
checkedName?: string;
|
|
168
|
+
description?: string;
|
|
169
|
+
short?: string;
|
|
170
|
+
checked?: boolean;
|
|
171
|
+
disabled?: boolean | string;
|
|
172
|
+
};
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Here's each property:
|
|
176
|
+
|
|
177
|
+
- `value`: The value is what will be returned by `await checkbox()`.
|
|
178
|
+
- `name`: This is the string displayed in the choice list.
|
|
179
|
+
- `checkedName`: Alternative `name` (or format) displayed when the choice is checked.
|
|
180
|
+
- `description`: Option for a longer description string that'll appear under the list when the cursor highlight a given choice.
|
|
181
|
+
- `short`: Once the prompt is done (press enter), we'll use `short` if defined to render next to the question. By default we'll use `name`.
|
|
182
|
+
- `checked`: If `true`, the option will be checked by default.
|
|
183
|
+
- `disabled`: Disallow the option from being selected. If `disabled` is a string, it'll be used as a help tip explaining why the choice isn't available.
|
|
184
|
+
|
|
185
|
+
Also note the `choices` array can contain `Separator`s to help organize long lists.
|
|
186
|
+
|
|
187
|
+
`choices` can also be an array of string, in which case the string will be used both as the `value` and the `name`.
|
|
188
|
+
|
|
189
|
+
## Keybindings
|
|
190
|
+
|
|
191
|
+
Set `INQUIRER_KEYBINDINGS=vim`, `INQUIRER_KEYBINDINGS=emacs`, or `INQUIRER_KEYBINDINGS=vim,emacs` to enable alternative navigation keybindings globally.
|
|
192
|
+
|
|
193
|
+
You can override the environment setting per prompt with `theme.keybindings`.
|
|
194
|
+
|
|
195
|
+
## Shortcuts
|
|
196
|
+
|
|
197
|
+
You can customize the shortcut keys for `all` and `invert` or disable them by setting them to `null`.
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
type Shortcuts = {
|
|
201
|
+
all?: string | null; // default: 'a'
|
|
202
|
+
invert?: string | null; // default: 'i'
|
|
203
|
+
};
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Theming
|
|
207
|
+
|
|
208
|
+
You can theme a prompt by passing a `theme` object option. The theme object only need to includes the keys you wish to modify, we'll fallback on the defaults for the rest.
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
type Theme = {
|
|
212
|
+
prefix: string | { idle: string; done: string };
|
|
213
|
+
spinner: {
|
|
214
|
+
interval: number;
|
|
215
|
+
frames: string[];
|
|
216
|
+
};
|
|
217
|
+
style: {
|
|
218
|
+
answer: (text: string) => string;
|
|
219
|
+
message: (text: string, status: 'idle' | 'done' | 'loading') => string;
|
|
220
|
+
error: (text: string) => string;
|
|
221
|
+
defaultAnswer: (text: string) => string;
|
|
222
|
+
help: (text: string) => string;
|
|
223
|
+
highlight: (text: string) => string;
|
|
224
|
+
key: (text: string) => string;
|
|
225
|
+
disabledChoice: (text: string) => string;
|
|
226
|
+
description: (text: string) => string;
|
|
227
|
+
renderSelectedChoices: <T>(
|
|
228
|
+
selectedChoices: ReadonlyArray<Choice<T>>,
|
|
229
|
+
allChoices: ReadonlyArray<Choice<T> | Separator>,
|
|
230
|
+
) => string;
|
|
231
|
+
keysHelpTip: (keys: [key: string, action: string][]) => string | undefined;
|
|
232
|
+
};
|
|
233
|
+
icon: {
|
|
234
|
+
checked: string;
|
|
235
|
+
unchecked: string;
|
|
236
|
+
cursor: string;
|
|
237
|
+
};
|
|
238
|
+
keybindings: readonly ('emacs' | 'vim')[];
|
|
239
|
+
};
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### `theme.style.keysHelpTip`
|
|
243
|
+
|
|
244
|
+
This function allows you to customize the keyboard shortcuts help tip displayed below the prompt. It receives an array of key-action pairs and should return a formatted string. You can also hook here to localize the labels to different languages.
|
|
245
|
+
|
|
246
|
+
It can also returns `undefined` to hide the help tip entirely.
|
|
247
|
+
|
|
248
|
+
```js
|
|
249
|
+
theme: {
|
|
250
|
+
style: {
|
|
251
|
+
keysHelpTip: (keys) => {
|
|
252
|
+
// Return undefined to hide the help tip completely
|
|
253
|
+
return undefined;
|
|
254
|
+
|
|
255
|
+
// Or customize the formatting. Or localize the labels.
|
|
256
|
+
return keys.map(([key, action]) => `${key}: ${action}`).join(' | ');
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
# License
|
|
263
|
+
|
|
264
|
+
Copyright (c) 2023 Simon Boudrias (twitter: [@vaxilart](https://twitter.com/Vaxilart))<br/>
|
|
265
|
+
Licensed under the MIT license.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Separator, type Theme } from '@inquirer/core';
|
|
2
|
+
import type { PartialDeep } from '@inquirer/type';
|
|
3
|
+
type CheckboxTheme = {
|
|
4
|
+
icon: {
|
|
5
|
+
checked: string;
|
|
6
|
+
unchecked: string;
|
|
7
|
+
cursor: string;
|
|
8
|
+
disabledChecked: string;
|
|
9
|
+
disabledUnchecked: string;
|
|
10
|
+
};
|
|
11
|
+
style: {
|
|
12
|
+
disabled: (text: string) => string;
|
|
13
|
+
renderSelectedChoices: <T>(selectedChoices: ReadonlyArray<NormalizedChoice<T>>, allChoices: ReadonlyArray<NormalizedChoice<T> | Separator>) => string;
|
|
14
|
+
description: (text: string) => string;
|
|
15
|
+
keysHelpTip: (keys: [key: string, action: string][]) => string | undefined;
|
|
16
|
+
};
|
|
17
|
+
i18n: {
|
|
18
|
+
disabledError: string;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
type CheckboxShortcuts = {
|
|
22
|
+
all?: string | null;
|
|
23
|
+
invert?: string | null;
|
|
24
|
+
};
|
|
25
|
+
type Choice<Value> = {
|
|
26
|
+
value: Value;
|
|
27
|
+
name?: string;
|
|
28
|
+
checkedName?: string;
|
|
29
|
+
description?: string;
|
|
30
|
+
short?: string;
|
|
31
|
+
disabled?: boolean | string;
|
|
32
|
+
checked?: boolean;
|
|
33
|
+
type?: never;
|
|
34
|
+
};
|
|
35
|
+
type NormalizedChoice<Value> = {
|
|
36
|
+
value: Value;
|
|
37
|
+
name: string;
|
|
38
|
+
checkedName: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
short: string;
|
|
41
|
+
disabled: boolean | string;
|
|
42
|
+
checked: boolean;
|
|
43
|
+
};
|
|
44
|
+
type CheckboxConfig<Value = string> = {
|
|
45
|
+
message: string;
|
|
46
|
+
prefix?: string;
|
|
47
|
+
pageSize?: number;
|
|
48
|
+
choices: ReadonlyArray<Value | Choice<Value> | Separator>;
|
|
49
|
+
loop?: boolean;
|
|
50
|
+
required?: boolean;
|
|
51
|
+
validate?: (choices: readonly NormalizedChoice<Value>[]) => boolean | string | Promise<string | boolean>;
|
|
52
|
+
theme?: PartialDeep<Theme<CheckboxTheme>>;
|
|
53
|
+
shortcuts?: CheckboxShortcuts;
|
|
54
|
+
};
|
|
55
|
+
declare const _default: <const Value>(config: {
|
|
56
|
+
message: string;
|
|
57
|
+
prefix?: string | undefined;
|
|
58
|
+
pageSize?: number | undefined;
|
|
59
|
+
choices: readonly (Separator | Value | Choice<Value>)[];
|
|
60
|
+
loop?: boolean | undefined;
|
|
61
|
+
required?: boolean | undefined;
|
|
62
|
+
validate?: ((choices: readonly NormalizedChoice<Value>[]) => boolean | string | Promise<string | boolean>) | undefined;
|
|
63
|
+
theme?: PartialDeep<Theme<CheckboxTheme>> | undefined;
|
|
64
|
+
shortcuts?: CheckboxShortcuts | undefined;
|
|
65
|
+
} & CheckboxConfig<Value>, context?: import("@inquirer/type").Context) => Promise<Value[]>;
|
|
66
|
+
export default _default;
|
|
67
|
+
export { Separator } from '@inquirer/core';
|