@nan0web/ui-cli 1.0.0
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/.editorconfig +20 -0
- package/CONTRIBUTING.md +42 -0
- package/LICENSE +15 -0
- package/README.md +277 -0
- package/docs/uk/README.md +294 -0
- package/package.json +38 -0
- package/playground/forms/addressForm.js +37 -0
- package/playground/forms/ageForm.js +26 -0
- package/playground/forms/profileForm.js +33 -0
- package/playground/forms/userForm.js +36 -0
- package/playground/main.js +81 -0
- package/playground/vocabs/en.js +25 -0
- package/playground/vocabs/index.js +12 -0
- package/playground/vocabs/uk.js +25 -0
- package/src/InputAdapter.js +219 -0
- package/src/InputAdapter.test.js +117 -0
- package/src/README.md.js +459 -0
- package/src/index.js +25 -0
- package/src/ui/index.js +4 -0
- package/src/ui/input.js +63 -0
- package/src/ui/input.test.js +27 -0
- package/src/ui/next.js +70 -0
- package/src/ui/select.js +58 -0
- package/src/ui/select.test.js +34 -0
- package/system.md +99 -0
- package/tsconfig.json +23 -0
- package/types/InputAdapter.d.ts +106 -0
- package/types/README.md.d.ts +1 -0
- package/types/index.d.ts +11 -0
- package/types/test/ReadLine.d.ts +1 -0
- package/types/ui/errors.d.ts +3 -0
- package/types/ui/index.d.ts +4 -0
- package/types/ui/input.d.ts +15 -0
- package/types/ui/next.d.ts +12 -0
- package/types/ui/select.d.ts +30 -0
package/.editorconfig
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
root = true
|
|
2
|
+
|
|
3
|
+
[*]
|
|
4
|
+
indent_style = tab
|
|
5
|
+
indent_size = 2
|
|
6
|
+
charset = utf-8
|
|
7
|
+
end_of_line = lf
|
|
8
|
+
trim_trailing_whitespace = true
|
|
9
|
+
insert_final_newline = true
|
|
10
|
+
|
|
11
|
+
[*.md]
|
|
12
|
+
trim_trailing_whitespace = false
|
|
13
|
+
|
|
14
|
+
[*.jsx]
|
|
15
|
+
indent_style = tab
|
|
16
|
+
indent_size = 2
|
|
17
|
+
|
|
18
|
+
[*.{md,nano,yaml}]
|
|
19
|
+
indent_style = space
|
|
20
|
+
indent_size = 2
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
## Developer Certificate of Origin and License
|
|
4
|
+
By contributing, You accept and agree to the following terms and conditions for your present and future contributions submitted.
|
|
5
|
+
Except for the license granted herein, You reserve all right, title, and interest in and to your Contributions.
|
|
6
|
+
All contributions are subject to the Developer Certificate of Origin and license as set out in the LICENSE file.
|
|
7
|
+
|
|
8
|
+
## Code of Conduct
|
|
9
|
+
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
|
10
|
+
|
|
11
|
+
We are committed to making participation in this project a harassment-free experience for everyone, regardless of:
|
|
12
|
+
- Level of experience,
|
|
13
|
+
- Gender,
|
|
14
|
+
- Gender identity and expression,
|
|
15
|
+
- Sexual orientation,
|
|
16
|
+
- Disability,
|
|
17
|
+
- Personal appearance,
|
|
18
|
+
- Body size,
|
|
19
|
+
- Race,
|
|
20
|
+
- Ethnicity,
|
|
21
|
+
- Age,
|
|
22
|
+
- Religion.
|
|
23
|
+
|
|
24
|
+
> We recognize all people as the foundation of humanity, and our actions contribute to the continued existence and growth of our shared humanity.
|
|
25
|
+
|
|
26
|
+
### Release versioning
|
|
27
|
+
- Keep releases close to the minor versions and publish patches only if required.
|
|
28
|
+
|
|
29
|
+
### Examples of unacceptable behavior by participants:
|
|
30
|
+
- Use of sexual language or imagery.
|
|
31
|
+
- Derogatory comments or personal attacks.
|
|
32
|
+
- Trolling, public or private harassment.
|
|
33
|
+
- Insults or other unprofessional conduct.
|
|
34
|
+
|
|
35
|
+
### Enforcement
|
|
36
|
+
Project maintainers have the right and responsibility to:
|
|
37
|
+
- Remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions not aligned with this Code of Conduct.
|
|
38
|
+
- Remove maintainers who violate this Code of Conduct.
|
|
39
|
+
|
|
40
|
+
Instances of unacceptable behavior can be reported by contacting the project team.
|
|
41
|
+
|
|
42
|
+
This Code of Conduct is adapted from the [Contributor Covenant, version 1.1.0](https://contributor-covenant.org/version/1/1/0/).
|
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025, ЯRаСлав (YaRaSLove) <support@yaro.page>
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and distribute this software for any purpose
|
|
6
|
+
with or without fee is hereby granted, provided that the above copyright notice
|
|
7
|
+
and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
10
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
11
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
12
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
13
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
14
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
15
|
+
PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# @nan0web/ui-cli
|
|
2
|
+
|
|
3
|
+
A tiny, zero‑dependency UI input adapter for Java•Script projects.
|
|
4
|
+
It provides a CLI implementation that can be easily integrated
|
|
5
|
+
with application logic.
|
|
6
|
+
|
|
7
|
+
|[Status](https://github.com/nan0web/monorepo/blob/main/system.md#написання-сценаріїв)|Documentation|Test coverage|Features|Npm version|
|
|
8
|
+
|---|---|---|---|---|
|
|
9
|
+
|🟢 `96.1%` |🧪 [English 🏴](https://github.com/nan0web/ui-cli/blob/main/README.md)<br />[Українською 🇺🇦](https://github.com/nan0web/ui-cli/blob/main/docs/uk/README.md) |🟡 `77.9%` |✅ d.ts 📜 system.md 🕹️ playground |— |
|
|
10
|
+
|
|
11
|
+
## Description
|
|
12
|
+
|
|
13
|
+
The `@nan0web/ui-cli` package provides a set of tools for handling
|
|
14
|
+
CLI user input through structured forms, selections and prompts.
|
|
15
|
+
It uses an adapter pattern to seamlessly integrate with application data models.
|
|
16
|
+
|
|
17
|
+
Core classes:
|
|
18
|
+
|
|
19
|
+
- `CLIInputAdapter` — handles form, input, and select requests in CLI.
|
|
20
|
+
- `Input` — wraps user input with value and cancellation status.
|
|
21
|
+
- `CancelError` — thrown when a user cancels an operation.
|
|
22
|
+
|
|
23
|
+
These classes are perfect for building prompts, wizards, forms,
|
|
24
|
+
and interactive CLI tools with minimal overhead.
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
How to install with npm?
|
|
29
|
+
```bash
|
|
30
|
+
npm install @nan0web/ui-cli
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
How to install with pnpm?
|
|
34
|
+
```bash
|
|
35
|
+
pnpm add @nan0web/ui-cli
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
How to install with yarn?
|
|
39
|
+
```bash
|
|
40
|
+
yarn add @nan0web/ui-cli
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Usage
|
|
44
|
+
|
|
45
|
+
### CLIInputAdapter
|
|
46
|
+
|
|
47
|
+
The adapter provides methods to handle form, input, and select requests.
|
|
48
|
+
|
|
49
|
+
#### requestForm(form, options)
|
|
50
|
+
|
|
51
|
+
Displays a form and collects user input field-by-field with validation.
|
|
52
|
+
|
|
53
|
+
How to request form input via CLIInputAdapter?
|
|
54
|
+
```js
|
|
55
|
+
import { CLIInputAdapter } from '@nan0web/ui-cli'
|
|
56
|
+
const adapter = new CLIInputAdapter()
|
|
57
|
+
const fields = [
|
|
58
|
+
{ name: "name", label: "Full Name", required: true },
|
|
59
|
+
{ name: "email", label: "Email", type: "email", required: true },
|
|
60
|
+
]
|
|
61
|
+
const validateValue = (name, value) => {
|
|
62
|
+
if (name === "email" && !value.includes("@")) {
|
|
63
|
+
return { isValid: false, errors: { email: "Invalid email" } }
|
|
64
|
+
}
|
|
65
|
+
return { isValid: true, errors: {} }
|
|
66
|
+
}
|
|
67
|
+
const setData = (data) => {
|
|
68
|
+
const newForm = { ...form }
|
|
69
|
+
newForm.state = data
|
|
70
|
+
return newForm
|
|
71
|
+
}
|
|
72
|
+
const form = UIForm.from({
|
|
73
|
+
title: "User Profile",
|
|
74
|
+
fields,
|
|
75
|
+
id: "user-profile-form",
|
|
76
|
+
validateValue,
|
|
77
|
+
setData,
|
|
78
|
+
state: {},
|
|
79
|
+
validate: () => ({ isValid: true, errors: {} }),
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
const result = await adapter.requestForm(form, { silent: true })
|
|
83
|
+
|
|
84
|
+
console.info(result.form.state) // ← { name: "John Doe", email: "John.Doe@example.com" }
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
How to request select input via CLIInputAdapter?
|
|
88
|
+
```js
|
|
89
|
+
import { CLIInputAdapter } from '@nan0web/ui-cli'
|
|
90
|
+
const adapter = new CLIInputAdapter()
|
|
91
|
+
const config = {
|
|
92
|
+
title: "Choose Language:",
|
|
93
|
+
prompt: "Language (1-2): ",
|
|
94
|
+
id: "language-select",
|
|
95
|
+
options: new Map([
|
|
96
|
+
["en", "English"],
|
|
97
|
+
["uk", "Ukrainian"],
|
|
98
|
+
]),
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const result = await adapter.requestSelect(config)
|
|
102
|
+
console.info(result.value) // ← Message { body: "en", head: {} }
|
|
103
|
+
```
|
|
104
|
+
### Input Utilities
|
|
105
|
+
|
|
106
|
+
#### `Input` class
|
|
107
|
+
|
|
108
|
+
Holds user input and tracks cancelation events.
|
|
109
|
+
|
|
110
|
+
How to use the Input class?
|
|
111
|
+
```js
|
|
112
|
+
import { Input } from '@nan0web/ui-cli'
|
|
113
|
+
const input = new Input({ value: "test", stops: ["quit"] })
|
|
114
|
+
console.info(String(input)) // ← test
|
|
115
|
+
console.info(input.value) // ← test
|
|
116
|
+
console.info(input.cancelled) // ← false
|
|
117
|
+
|
|
118
|
+
input.value = "quit"
|
|
119
|
+
console.info(input.cancelled) // ← true
|
|
120
|
+
```
|
|
121
|
+
#### `ask(question)`
|
|
122
|
+
|
|
123
|
+
Prompts the user with a question and returns a promise with the answer.
|
|
124
|
+
|
|
125
|
+
How to ask a question with ask()?
|
|
126
|
+
```js
|
|
127
|
+
import { ask } from "@nan0web/ui-cli"
|
|
128
|
+
|
|
129
|
+
const result = await ask("What is your name?")
|
|
130
|
+
console.info(result)
|
|
131
|
+
```
|
|
132
|
+
#### `createInput(stops)`
|
|
133
|
+
|
|
134
|
+
Creates a configurable input handler with stop keywords.
|
|
135
|
+
|
|
136
|
+
How to use createInput handler?
|
|
137
|
+
```js
|
|
138
|
+
import { createInput } from '@nan0web/ui-cli'
|
|
139
|
+
const handler = createInput(["cancel"])
|
|
140
|
+
console.info(typeof handler === "function") // ← true
|
|
141
|
+
```
|
|
142
|
+
#### `select(config)`
|
|
143
|
+
|
|
144
|
+
Presents options to the user and returns a promise with selection.
|
|
145
|
+
|
|
146
|
+
How to prompt user with select()?
|
|
147
|
+
```js
|
|
148
|
+
import { select } from '@nan0web/ui-cli'
|
|
149
|
+
const config = {
|
|
150
|
+
title: "Choose an option:",
|
|
151
|
+
prompt: "Selection (1-3): ",
|
|
152
|
+
options: ["Option A", "Option B", "Option C"],
|
|
153
|
+
console: console,
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const result = await select(config)
|
|
157
|
+
console.info(result.value)
|
|
158
|
+
```
|
|
159
|
+
#### `next(conf)`
|
|
160
|
+
|
|
161
|
+
Waits for a keypress to continue the process.
|
|
162
|
+
|
|
163
|
+
How to pause and wait for keypress with next()?
|
|
164
|
+
```js
|
|
165
|
+
import { next } from '@nan0web/ui-cli'
|
|
166
|
+
|
|
167
|
+
const result = await next()
|
|
168
|
+
console.info(typeof result === "string")
|
|
169
|
+
```
|
|
170
|
+
#### `pause(ms)`
|
|
171
|
+
|
|
172
|
+
Returns a promise that resolves after a given delay.
|
|
173
|
+
|
|
174
|
+
How to delay execution with pause()?
|
|
175
|
+
```js
|
|
176
|
+
import { pause } from '@nan0web/ui-cli'
|
|
177
|
+
const before = Date.now()
|
|
178
|
+
await pause(10)
|
|
179
|
+
const after = Date.now()
|
|
180
|
+
console.info(after - before >= 10) // ← true
|
|
181
|
+
```
|
|
182
|
+
### Errors
|
|
183
|
+
|
|
184
|
+
#### `CancelError`
|
|
185
|
+
|
|
186
|
+
Thrown when a user interrupts a process.
|
|
187
|
+
|
|
188
|
+
How to handle CancelError?
|
|
189
|
+
```js
|
|
190
|
+
import { CancelError } from '@nan0web/ui-cli'
|
|
191
|
+
const error = new CancelError()
|
|
192
|
+
console.error(error.message) // ← Operation cancelled by user
|
|
193
|
+
```
|
|
194
|
+
## API
|
|
195
|
+
|
|
196
|
+
### CLIInputAdapter
|
|
197
|
+
|
|
198
|
+
* **Methods**
|
|
199
|
+
* `requestForm(form, options)` — (async) handles form request
|
|
200
|
+
* `requestSelect(config)` — (async) handles selection prompt
|
|
201
|
+
* `requestInput(config)` — (async) handles single input prompt
|
|
202
|
+
|
|
203
|
+
### Input
|
|
204
|
+
|
|
205
|
+
* **Properties**
|
|
206
|
+
* `value` – (string) current input value.
|
|
207
|
+
* `stops` – (array) cancellation keywords.
|
|
208
|
+
* `cancelled` – (boolean) whether input is cancelled.
|
|
209
|
+
|
|
210
|
+
* **Methods**
|
|
211
|
+
* `toString()` – returns current value as string.
|
|
212
|
+
* `static from(input)` – instantiates from input object.
|
|
213
|
+
|
|
214
|
+
### ask(question)
|
|
215
|
+
|
|
216
|
+
* **Parameters**
|
|
217
|
+
* `question` (string) – prompt text
|
|
218
|
+
* **Returns** Promise<string>
|
|
219
|
+
|
|
220
|
+
### createInput(stops)
|
|
221
|
+
|
|
222
|
+
* **Parameters**
|
|
223
|
+
* `stops` (array) – stop values
|
|
224
|
+
* **Returns** function handler
|
|
225
|
+
|
|
226
|
+
### select(config)
|
|
227
|
+
|
|
228
|
+
* **Parameters**
|
|
229
|
+
* `config.title` (string) – selection title
|
|
230
|
+
* `config.prompt` (string) – prompt text
|
|
231
|
+
* `config.options` (array | Map) – options to choose from
|
|
232
|
+
* **Returns** Promise<{ index, value }>
|
|
233
|
+
|
|
234
|
+
### next([conf])
|
|
235
|
+
|
|
236
|
+
* **Parameters**
|
|
237
|
+
* `conf` (string) – accepted key sequence
|
|
238
|
+
* **Returns** Promise<string>
|
|
239
|
+
|
|
240
|
+
### pause(ms)
|
|
241
|
+
|
|
242
|
+
* **Parameters**
|
|
243
|
+
* `ms` (number) – delay in milliseconds
|
|
244
|
+
* **Returns** Promise<void>
|
|
245
|
+
|
|
246
|
+
### CancelError
|
|
247
|
+
|
|
248
|
+
Extends `Error`, thrown when an input is cancelled.
|
|
249
|
+
|
|
250
|
+
All exported classes and functions should pass basic tests
|
|
251
|
+
|
|
252
|
+
## Java•Script
|
|
253
|
+
|
|
254
|
+
Uses `d.ts` files for autocompletion
|
|
255
|
+
|
|
256
|
+
## Playground
|
|
257
|
+
|
|
258
|
+
How to run playground script?
|
|
259
|
+
```bash
|
|
260
|
+
# Clone the repository and run the CLI playground
|
|
261
|
+
git clone https://github.com/nan0web/ui-cli.git
|
|
262
|
+
cd ui-cli
|
|
263
|
+
npm install
|
|
264
|
+
npm run playground
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Contributing
|
|
268
|
+
|
|
269
|
+
How to contribute? - [check here](./CONTRIBUTING.md)
|
|
270
|
+
|
|
271
|
+
## License
|
|
272
|
+
|
|
273
|
+
How to license ISC? - [check here](./LICENSE)
|
|
274
|
+
```js
|
|
275
|
+
try {
|
|
276
|
+
const text = await fs.loadDocument("LICENSE")
|
|
277
|
+
```
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
# @nan0web/ui-cli
|
|
2
|
+
|
|
3
|
+
Маленький, беззалежний UI‑адаптер вводу для JavaScript‑проєктів.
|
|
4
|
+
Надає CLI‑реалізацію, яку легко інтегрувати у логіку застосунку.
|
|
5
|
+
|
|
6
|
+
|[Статус](https://github.com/nan0web/monorepo/blob/main/system.md#написання-сценаріїв)|Документація|Тестове покриття|Фічі|Версія npm|
|
|
7
|
+
|---|---|---|---|---|
|
|
8
|
+
|🟢 `96.1%`|🧪 [English 🏴](https://github.com/nan0web/ui-cli/blob/main/README.md)<br />[Українською 🇺🇦](https://github.com/nan0web/ui-cli/blob/main/docs/uk/README.md)|🟡 `77.9%`|✅ d.ts 📜 system.md 🕹️ playground|—|
|
|
9
|
+
|
|
10
|
+
## Опис
|
|
11
|
+
|
|
12
|
+
Пакет `@nan0web/ui-cli` надає набір інструментів для обробки вводу користувача в CLI через
|
|
13
|
+
структуровані форми, вибір варіантів та підказки.
|
|
14
|
+
Використовує патерн адаптера для безшовної інтеграції з моделями даних застосунку.
|
|
15
|
+
|
|
16
|
+
### Основні класи
|
|
17
|
+
|
|
18
|
+
- **`CLIInputAdapter`** — обробляє запити форм, вводу та вибору в CLI.
|
|
19
|
+
- **`Input`** — обгортає введене користувачем значення та статус скасування.
|
|
20
|
+
- **`CancelError`** — викидається, коли користувач скасовує операцію.
|
|
21
|
+
|
|
22
|
+
Ці класи ідеальні для створення підказок, майстрів, форм та інтерактивних інструментів CLI з мінімальними накладними витратами.
|
|
23
|
+
|
|
24
|
+
## Встановлення
|
|
25
|
+
|
|
26
|
+
### Через npm
|
|
27
|
+
```bash
|
|
28
|
+
npm install @nan0web/ui-cli
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Через pnpm
|
|
32
|
+
```bash
|
|
33
|
+
pnpm add @nan0web/ui-cli
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Через yarn
|
|
37
|
+
```bash
|
|
38
|
+
yarn add @nan0web/ui-cli
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Приклади використання
|
|
42
|
+
|
|
43
|
+
### CLIInputAdapter
|
|
44
|
+
|
|
45
|
+
Адаптер містить методи для роботи з формами, ввідними та вибірковими запитами.
|
|
46
|
+
|
|
47
|
+
#### `requestForm(form, options)`
|
|
48
|
+
|
|
49
|
+
Відображає форму та послідовно збирає ввід полів з валідацією.
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
import { CLIInputAdapter } from '@nan0web/ui-cli'
|
|
53
|
+
|
|
54
|
+
const adapter = new CLIInputAdapter()
|
|
55
|
+
|
|
56
|
+
const fields = [
|
|
57
|
+
{ name: "name", label: "Повне ім’я", required: true },
|
|
58
|
+
{ name: "email", label: "Email", type: "email", required: true },
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
const validateValue = (name, value) => {
|
|
62
|
+
if (name === "email" && !value.includes("@")) {
|
|
63
|
+
return { isValid: false, errors: { email: "Некоректний email" } }
|
|
64
|
+
}
|
|
65
|
+
return { isValid: true, errors: {} }
|
|
66
|
+
}
|
|
67
|
+
const setData = (data) => {
|
|
68
|
+
const newForm = { ...form }
|
|
69
|
+
newForm.state = data
|
|
70
|
+
return newForm
|
|
71
|
+
}
|
|
72
|
+
const form = UIForm.from({
|
|
73
|
+
title: "Профіль користувача",
|
|
74
|
+
fields,
|
|
75
|
+
id: "user-profile-form",
|
|
76
|
+
validateValue,
|
|
77
|
+
setData,
|
|
78
|
+
state: {},
|
|
79
|
+
validate: () => ({ isValid: true, errors: {} }),
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
const result = await adapter.requestForm(form, { silent: true })
|
|
83
|
+
|
|
84
|
+
console.info(result.form.state) // ← { name: "John Doe", email: "John.Doe@example.com" }
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
#### `requestSelect(config)`
|
|
88
|
+
|
|
89
|
+
Показує список варіантів і повертає обраний елемент.
|
|
90
|
+
|
|
91
|
+
```js
|
|
92
|
+
import { CLIInputAdapter } from '@nan0web/ui-cli'
|
|
93
|
+
|
|
94
|
+
const adapter = new CLIInputAdapter()
|
|
95
|
+
const config = {
|
|
96
|
+
title: "Виберіть мову:",
|
|
97
|
+
prompt: "Мова (1‑2): ",
|
|
98
|
+
id: "language-select",
|
|
99
|
+
options: new Map([
|
|
100
|
+
["en", "English"],
|
|
101
|
+
["uk", "Ukrainian"],
|
|
102
|
+
]),
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const result = await adapter.requestSelect(config)
|
|
106
|
+
console.info(result.value) // ← Message { body: "en", head: {} }
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Утиліти вводу
|
|
110
|
+
|
|
111
|
+
#### Клас `Input`
|
|
112
|
+
|
|
113
|
+
Зберігає введене значення і відстежує скасування.
|
|
114
|
+
|
|
115
|
+
```js
|
|
116
|
+
import { Input } from '@nan0web/ui-cli'
|
|
117
|
+
|
|
118
|
+
const input = new Input({ value: "test", stops: ["quit"] })
|
|
119
|
+
console.info(String(input)) // ← test
|
|
120
|
+
console.info(input.value) // ← test
|
|
121
|
+
console.info(input.cancelled) // ← false
|
|
122
|
+
|
|
123
|
+
input.value = "quit"
|
|
124
|
+
console.info(input.cancelled) // ← true
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
#### `ask(question)`
|
|
128
|
+
|
|
129
|
+
Виводить питання та повертає відповідь у вигляді промісу.
|
|
130
|
+
|
|
131
|
+
```js
|
|
132
|
+
import { ask } from "@nan0web/ui-cli"
|
|
133
|
+
|
|
134
|
+
const result = await ask("Яке ваше ім’я?")
|
|
135
|
+
console.info(result)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
#### `createInput(stops)`
|
|
139
|
+
|
|
140
|
+
Створює налаштовуваний обробник вводів зі словами‑стопами.
|
|
141
|
+
|
|
142
|
+
```js
|
|
143
|
+
import { createInput } from '@nan0web/ui-cli'
|
|
144
|
+
|
|
145
|
+
const handler = createInput(["cancel"])
|
|
146
|
+
console.info(typeof handler === "function") // ← true
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
#### `select(config)`
|
|
150
|
+
|
|
151
|
+
Показує список варіантів та повертає обраний елемент.
|
|
152
|
+
|
|
153
|
+
```js
|
|
154
|
+
import { select } from '@nan0web/ui-cli'
|
|
155
|
+
|
|
156
|
+
const config = {
|
|
157
|
+
title: "Оберіть варіант:",
|
|
158
|
+
prompt: "Вибір (1‑3): ",
|
|
159
|
+
options: ["Варіант A", "Варіант B", "Варіант C"],
|
|
160
|
+
console: console,
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const result = await select(config)
|
|
164
|
+
console.info(result.value)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
#### `next(conf)`
|
|
168
|
+
|
|
169
|
+
Чекає натискання клавіші (або послідовності клавіш) для продовження процесу.
|
|
170
|
+
|
|
171
|
+
```js
|
|
172
|
+
import { next } from '@nan0web/ui-cli'
|
|
173
|
+
|
|
174
|
+
const result = await next()
|
|
175
|
+
console.info(typeof result === "string")
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
#### `pause(ms)`
|
|
179
|
+
|
|
180
|
+
Повертає проміс, який виконується після заданої затримки.
|
|
181
|
+
|
|
182
|
+
```js
|
|
183
|
+
import { pause } from '@nan0web/ui-cli'
|
|
184
|
+
const before = Date.now()
|
|
185
|
+
await pause(10)
|
|
186
|
+
const after = Date.now()
|
|
187
|
+
console.info(after - before >= 10) // ← true
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Помилки
|
|
191
|
+
|
|
192
|
+
#### `CancelError`
|
|
193
|
+
|
|
194
|
+
Викидається, коли користувач перериває процес.
|
|
195
|
+
|
|
196
|
+
```js
|
|
197
|
+
import { CancelError } from '@nan0web/ui-cli'
|
|
198
|
+
|
|
199
|
+
try {
|
|
200
|
+
// ... код, який може бути скасований
|
|
201
|
+
} catch (err) {
|
|
202
|
+
if (err instanceof CancelError) {
|
|
203
|
+
console.error(err.message) // ← Операція скасована користувачем
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## API
|
|
209
|
+
|
|
210
|
+
### `CLIInputAdapter`
|
|
211
|
+
|
|
212
|
+
- **Методи**
|
|
213
|
+
- `requestForm(form, options)` — асинхронно обробляє запит форми.
|
|
214
|
+
- `requestSelect(config)` — асинхронно обробляє запит вибору.
|
|
215
|
+
- `requestInput(config)` — асинхронно обробляє запит одиничного вводу.
|
|
216
|
+
|
|
217
|
+
### `Input`
|
|
218
|
+
|
|
219
|
+
- **Властивості**
|
|
220
|
+
- `value` – (string) поточне введене значення.
|
|
221
|
+
- `stops` – (array) ключові слова‑стопи.
|
|
222
|
+
- `cancelled` – (boolean) чи було скасовано ввід.
|
|
223
|
+
- **Методи**
|
|
224
|
+
- `toString()` – повертає поточне значення як рядок.
|
|
225
|
+
- `static from(input)` – створює інстанс з об’єкта вводу.
|
|
226
|
+
|
|
227
|
+
### `ask(question)`
|
|
228
|
+
|
|
229
|
+
- **Параметри**
|
|
230
|
+
- `question` (string) – текст підказки.
|
|
231
|
+
- **Повертає**
|
|
232
|
+
- `Promise<string>` – відповідь користувача.
|
|
233
|
+
|
|
234
|
+
### `createInput(stops)`
|
|
235
|
+
|
|
236
|
+
- **Параметри**
|
|
237
|
+
- `stops` (array) – значення, при яких ввід скасовується.
|
|
238
|
+
- **Повертає**
|
|
239
|
+
- функція‑обробник.
|
|
240
|
+
|
|
241
|
+
### `select(config)`
|
|
242
|
+
|
|
243
|
+
- **Параметри**
|
|
244
|
+
- `config.title` (string) – заголовок вибору.
|
|
245
|
+
- `config.prompt` (string) – підказка.
|
|
246
|
+
- `config.options` (array | Map) – варіанти вибору.
|
|
247
|
+
- **Повертає**
|
|
248
|
+
- `Promise<{ index, value }>` – обраний елемент.
|
|
249
|
+
|
|
250
|
+
### `next([conf])`
|
|
251
|
+
|
|
252
|
+
- **Параметри**
|
|
253
|
+
- `conf` (string) – приймана послідовність клавіш.
|
|
254
|
+
- **Повертає**
|
|
255
|
+
- `Promise<string>` – натиснута клавіша.
|
|
256
|
+
|
|
257
|
+
### `pause(ms)`
|
|
258
|
+
|
|
259
|
+
- **Параметри**
|
|
260
|
+
- `ms` (number) – затримка у мілісекундах.
|
|
261
|
+
- **Повертає**
|
|
262
|
+
- `Promise<void>`.
|
|
263
|
+
|
|
264
|
+
### `CancelError`
|
|
265
|
+
|
|
266
|
+
Розширює `Error`, викидається при скасуванні вводу.
|
|
267
|
+
|
|
268
|
+
## Тестування
|
|
269
|
+
|
|
270
|
+
Усі експортовані класи та функції повинні проходити базові тести.
|
|
271
|
+
|
|
272
|
+
## JavaScript
|
|
273
|
+
|
|
274
|
+
Для автодоповнення використовується `d.ts` (type‑definition) файли.
|
|
275
|
+
|
|
276
|
+
## Playground
|
|
277
|
+
|
|
278
|
+
Як запустити скрипт Playground?
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
# Клонуємо репозиторій і запускаємо CLI playground
|
|
282
|
+
git clone https://github.com/nan0web/ui-cli.git
|
|
283
|
+
cd ui-cli
|
|
284
|
+
npm install
|
|
285
|
+
npm run playground
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## Спільна розробка
|
|
289
|
+
|
|
290
|
+
Як долучитися? – [дивіться тут](./CONTRIBUTING.md)
|
|
291
|
+
|
|
292
|
+
## Ліцензія
|
|
293
|
+
|
|
294
|
+
Як задокументовано у файлі ліцензії ISC – [дивіться тут](./LICENSE)
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nan0web/ui-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "NaN•Web UI CLI. Command line interface for One application logic (algorithm) and many UI.",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"types": "types/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"test": "node --test --test-timeout=3333 \"src/**/*.test.js\" | nan0test parse --fail",
|
|
11
|
+
"test:coverage": "node --experimental-test-coverage --test-coverage-include=\"src/**/*.js\" --test-coverage-exclude=\"src/**/*.test.js\" --test \"src/**/*.test.js\"",
|
|
12
|
+
"test:coverage:collect": "nan0test coverage",
|
|
13
|
+
"test:docs": "node --test --test-timeout=3333 src/README.md.js",
|
|
14
|
+
"test:release": "node --test \"releases/**/*.test.js\"",
|
|
15
|
+
"test:status": "nan0test status --hide-name --debug",
|
|
16
|
+
"playground": "node playground/main.js",
|
|
17
|
+
"precommit": "npm test",
|
|
18
|
+
"prepush": "npm test",
|
|
19
|
+
"prepare": "husky",
|
|
20
|
+
"release": "nan0release publish",
|
|
21
|
+
"clean": "rm -rf .cache/ && rm -rf dist/",
|
|
22
|
+
"clean:modules": "rm -rf node_modules"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"ui",
|
|
26
|
+
"cli",
|
|
27
|
+
"input",
|
|
28
|
+
"adapter"
|
|
29
|
+
],
|
|
30
|
+
"author": "ЯRаСлав (YaRaSLove) <support@yaro.page>",
|
|
31
|
+
"license": "ISC",
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@nan0web/log": "workspace:*",
|
|
34
|
+
"@nan0web/test": "workspace:*",
|
|
35
|
+
"@nan0web/ui": "workspace:*",
|
|
36
|
+
"@nan0web/db-fs": "workspace:*"
|
|
37
|
+
}
|
|
38
|
+
}
|