@nan0web/ui-cli 1.0.0 → 1.0.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 +2 -11
- package/package.json +17 -7
- package/src/CLI.js +141 -0
- package/src/Command.js +210 -0
- package/src/CommandError.js +35 -0
- package/src/CommandHelp.js +204 -0
- package/src/CommandMessage.js +181 -0
- package/src/CommandParser.js +217 -0
- package/src/InputAdapter.js +78 -149
- package/src/README.md.js +7 -6
- package/src/index.js +36 -14
- package/src/ui/index.js +3 -3
- package/src/ui/input.js +68 -11
- package/src/ui/next.js +30 -26
- package/src/ui/select.js +41 -31
- package/src/utils/parse.js +41 -0
- package/types/CLI.d.ts +44 -0
- package/types/Command.d.ts +72 -0
- package/types/CommandError.d.ts +19 -0
- package/types/CommandHelp.d.ts +85 -0
- package/types/CommandMessage.d.ts +65 -0
- package/types/CommandParser.d.ts +28 -0
- package/types/InputAdapter.d.ts +28 -85
- package/types/index.d.ts +12 -9
- package/types/ui/index.d.ts +2 -3
- package/types/ui/input.d.ts +50 -6
- package/types/ui/next.d.ts +11 -8
- package/types/ui/select.d.ts +50 -20
- package/types/utils/parse.d.ts +13 -0
- package/.editorconfig +0 -20
- package/CONTRIBUTING.md +0 -42
- package/docs/uk/README.md +0 -294
- package/playground/forms/addressForm.js +0 -37
- package/playground/forms/ageForm.js +0 -26
- package/playground/forms/profileForm.js +0 -33
- package/playground/forms/userForm.js +0 -36
- package/playground/main.js +0 -81
- package/playground/vocabs/en.js +0 -25
- package/playground/vocabs/index.js +0 -12
- package/playground/vocabs/uk.js +0 -25
- package/src/InputAdapter.test.js +0 -117
- package/src/ui/input.test.js +0 -27
- package/src/ui/select.test.js +0 -34
- package/system.md +0 -99
- package/tsconfig.json +0 -23
- package/types/test/ReadLine.d.ts +0 -1
- package/types/ui/errors.d.ts +0 -3
package/docs/uk/README.md
DELETED
|
@@ -1,294 +0,0 @@
|
|
|
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)
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { UIForm, FormInput } from '@nan0web/ui'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Creates an address information form
|
|
5
|
-
* @param {Function} t - Translation function
|
|
6
|
-
* @returns {UIForm} Address form
|
|
7
|
-
*/
|
|
8
|
-
export function createAddressForm(t) {
|
|
9
|
-
return new UIForm({
|
|
10
|
-
title: t('Address information'),
|
|
11
|
-
id: 'address-form',
|
|
12
|
-
state: {},
|
|
13
|
-
fields: [
|
|
14
|
-
new FormInput({
|
|
15
|
-
name: 'street',
|
|
16
|
-
label: t('Street'),
|
|
17
|
-
required: true
|
|
18
|
-
}),
|
|
19
|
-
new FormInput({
|
|
20
|
-
name: 'city',
|
|
21
|
-
label: t('City'),
|
|
22
|
-
required: true
|
|
23
|
-
}),
|
|
24
|
-
new FormInput({
|
|
25
|
-
name: 'postalCode',
|
|
26
|
-
label: t('Postal code'),
|
|
27
|
-
type: FormInput.TYPES.TEXT,
|
|
28
|
-
required: false
|
|
29
|
-
}),
|
|
30
|
-
new FormInput({
|
|
31
|
-
name: 'country',
|
|
32
|
-
label: t('Country'),
|
|
33
|
-
required: true
|
|
34
|
-
})
|
|
35
|
-
]
|
|
36
|
-
})
|
|
37
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { UIForm, FormInput } from '@nan0web/ui'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Creates an age confirmation form
|
|
5
|
-
* @param {Function} t - Translation function
|
|
6
|
-
* @returns {UIForm} Age confirmation form
|
|
7
|
-
*/
|
|
8
|
-
export function createAgeForm(t) {
|
|
9
|
-
return new UIForm({
|
|
10
|
-
title: t('Age confirmation form'),
|
|
11
|
-
id: 'age-confirmation',
|
|
12
|
-
state: {},
|
|
13
|
-
fields: [
|
|
14
|
-
new FormInput({
|
|
15
|
-
name: 'age',
|
|
16
|
-
label: t('Please enter your age'),
|
|
17
|
-
type: FormInput.TYPES.NUMBER,
|
|
18
|
-
validator: (value) => {
|
|
19
|
-
const num = Number(value)
|
|
20
|
-
return num >= 18 ? null : t('You must be at least 18 years old')
|
|
21
|
-
},
|
|
22
|
-
required: true
|
|
23
|
-
})
|
|
24
|
-
]
|
|
25
|
-
})
|
|
26
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { UIForm, FormInput } from '@nan0web/ui'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Creates a profile update form
|
|
5
|
-
* @param {Function} t - Translation function
|
|
6
|
-
* @returns {UIForm} Profile update form
|
|
7
|
-
*/
|
|
8
|
-
export function createProfileForm(t) {
|
|
9
|
-
return new UIForm({
|
|
10
|
-
title: t('Profile update form'),
|
|
11
|
-
id: 'profile-update',
|
|
12
|
-
state: {},
|
|
13
|
-
fields: [
|
|
14
|
-
new FormInput({
|
|
15
|
-
name: 'username',
|
|
16
|
-
label: t('Username'),
|
|
17
|
-
required: true
|
|
18
|
-
}),
|
|
19
|
-
new FormInput({
|
|
20
|
-
name: 'bio',
|
|
21
|
-
label: t('Biography'),
|
|
22
|
-
type: FormInput.TYPES.TEXTAREA,
|
|
23
|
-
required: false
|
|
24
|
-
}),
|
|
25
|
-
new FormInput({
|
|
26
|
-
name: 'newsletter',
|
|
27
|
-
label: t('Subscribe to newsletter'),
|
|
28
|
-
type: FormInput.TYPES.CHECKBOX,
|
|
29
|
-
required: false
|
|
30
|
-
})
|
|
31
|
-
]
|
|
32
|
-
})
|
|
33
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { UIForm, FormInput } from '@nan0web/ui'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Creates a user registration form
|
|
5
|
-
* @param {Function} t - Translation function
|
|
6
|
-
* @returns {UIForm} User registration form
|
|
7
|
-
*/
|
|
8
|
-
export function createUserForm(t) {
|
|
9
|
-
return new UIForm({
|
|
10
|
-
title: t('User Registration Form'),
|
|
11
|
-
id: 'user-registration',
|
|
12
|
-
state: {},
|
|
13
|
-
fields: [
|
|
14
|
-
new FormInput({
|
|
15
|
-
name: 'name',
|
|
16
|
-
label: t('Full name'),
|
|
17
|
-
required: true
|
|
18
|
-
}),
|
|
19
|
-
new FormInput({
|
|
20
|
-
name: 'email',
|
|
21
|
-
label: t('Email address'),
|
|
22
|
-
type: FormInput.TYPES.EMAIL,
|
|
23
|
-
required: true
|
|
24
|
-
}),
|
|
25
|
-
new FormInput({
|
|
26
|
-
name: 'phone',
|
|
27
|
-
label: t('Phone number'),
|
|
28
|
-
type: FormInput.TYPES.TEXT,
|
|
29
|
-
validator: (value) => {
|
|
30
|
-
return value.length >= 10 && value.length <= 15 ? null : t('Invalid phone number')
|
|
31
|
-
},
|
|
32
|
-
required: false
|
|
33
|
-
})
|
|
34
|
-
]
|
|
35
|
-
})
|
|
36
|
-
}
|
package/playground/main.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import Logger from '@nan0web/log'
|
|
4
|
-
import { CLIInputAdapter } from '../src/index.js'
|
|
5
|
-
import { createUserForm } from './forms/userForm.js'
|
|
6
|
-
import { createAgeForm } from './forms/ageForm.js'
|
|
7
|
-
import { createAddressForm } from './forms/addressForm.js'
|
|
8
|
-
import { createProfileForm } from './forms/profileForm.js'
|
|
9
|
-
import createT, { localesMap } from "./vocabs/index.js"
|
|
10
|
-
|
|
11
|
-
console = new Logger()
|
|
12
|
-
|
|
13
|
-
const adapter = new CLIInputAdapter()
|
|
14
|
-
|
|
15
|
-
console.info(Logger.style(Logger.LOGO, { color: "magenta" }))
|
|
16
|
-
console.warn('=== @nan0web/ui CLI Playground ===\n')
|
|
17
|
-
|
|
18
|
-
// Language selection
|
|
19
|
-
const langResult = await adapter.requestSelect({
|
|
20
|
-
title: "Language selection",
|
|
21
|
-
prompt: "Choose language (1-2): ",
|
|
22
|
-
options: localesMap,
|
|
23
|
-
elementId: "language-select"
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
if (langResult.action === 'select-cancel') {
|
|
27
|
-
console.warn('Language selection cancelled')
|
|
28
|
-
process.exit(0)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const selectedLang = langResult.value
|
|
32
|
-
const t = createT(selectedLang)
|
|
33
|
-
|
|
34
|
-
console.success(`${t('Language selection')}: ${t(selectedLang)}`)
|
|
35
|
-
console.info()
|
|
36
|
-
|
|
37
|
-
// User registration form
|
|
38
|
-
const userForm = createUserForm(t)
|
|
39
|
-
const userResult = await adapter.requestForm(userForm, { silent: false })
|
|
40
|
-
|
|
41
|
-
if (userResult.action === 'form-submit') {
|
|
42
|
-
console.success(t('Welcome to our platform!'))
|
|
43
|
-
console.info('User data:', userResult.data)
|
|
44
|
-
console.info()
|
|
45
|
-
} else {
|
|
46
|
-
console.warn('User registration cancelled')
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Age confirmation form
|
|
50
|
-
const ageForm = createAgeForm(t)
|
|
51
|
-
const ageResult = await adapter.requestForm(ageForm, { silent: false })
|
|
52
|
-
|
|
53
|
-
if (ageResult.action === 'form-submit') {
|
|
54
|
-
console.success(`Confirmed age: ${ageResult.data.age}`)
|
|
55
|
-
} else {
|
|
56
|
-
console.warn('Age confirmation cancelled')
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Address information form
|
|
60
|
-
const addressForm = createAddressForm(t)
|
|
61
|
-
const addressResult = await adapter.requestForm(addressForm, { silent: false })
|
|
62
|
-
|
|
63
|
-
if (addressResult.action === 'form-submit') {
|
|
64
|
-
console.success('Address information collected')
|
|
65
|
-
console.info('Address data:', addressResult.data)
|
|
66
|
-
console.info()
|
|
67
|
-
} else {
|
|
68
|
-
console.warn('Address form cancelled')
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Profile update form
|
|
72
|
-
const profileForm = createProfileForm(t)
|
|
73
|
-
const profileResult = await adapter.requestForm(profileForm, { silent: false })
|
|
74
|
-
|
|
75
|
-
if (profileResult.action === 'form-submit') {
|
|
76
|
-
console.success('Profile updated')
|
|
77
|
-
console.info('Profile data:', profileResult.data)
|
|
78
|
-
console.info()
|
|
79
|
-
} else {
|
|
80
|
-
console.warn('Profile update cancelled')
|
|
81
|
-
}
|
package/playground/vocabs/en.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
export default {
|
|
2
|
-
"User Registration Form": "User Registration Form",
|
|
3
|
-
"Full name": "Full name",
|
|
4
|
-
"Email address": "Email address",
|
|
5
|
-
"Phone number": "Phone number",
|
|
6
|
-
"Age confirmation form": "Age confirmation form",
|
|
7
|
-
"Please enter your age": "Please enter your age",
|
|
8
|
-
"Language selection": "Language selection",
|
|
9
|
-
"Choose language": "Choose language",
|
|
10
|
-
"English": "English",
|
|
11
|
-
"Ukrainian": "Ukrainian",
|
|
12
|
-
"You must be at least 18 years old": "You must be at least 18 years old",
|
|
13
|
-
"Invalid phone number": "Invalid phone number",
|
|
14
|
-
"Welcome to our platform!": "Welcome to our platform!",
|
|
15
|
-
"Address information": "Address information",
|
|
16
|
-
"Street": "Street",
|
|
17
|
-
"City": "City",
|
|
18
|
-
"Postal code": "Postal code",
|
|
19
|
-
"Country": "Country",
|
|
20
|
-
"Profile update form": "Profile update form",
|
|
21
|
-
"Username": "Username",
|
|
22
|
-
"Biography": "Biography",
|
|
23
|
-
"Newsletter subscription": "Newsletter subscription",
|
|
24
|
-
"Subscribe to newsletter": "Subscribe to newsletter"
|
|
25
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import i18n, { createT } from "@nan0web/i18n"
|
|
2
|
-
import en from "./en.js"
|
|
3
|
-
import uk from "./uk.js"
|
|
4
|
-
|
|
5
|
-
const getVocab = i18n({ en, uk })
|
|
6
|
-
|
|
7
|
-
export const localesMap = new Map([
|
|
8
|
-
["en", "English"],
|
|
9
|
-
["uk", "Українська"],
|
|
10
|
-
])
|
|
11
|
-
|
|
12
|
-
export default (locale) => createT(getVocab(locale))
|
package/playground/vocabs/uk.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
export default {
|
|
2
|
-
"User Registration Form": "Форма реєстрації користувача",
|
|
3
|
-
"Full name": "Повне ім'я",
|
|
4
|
-
"Email address": "Електронна пошта",
|
|
5
|
-
"Phone number": "Номер телефону",
|
|
6
|
-
"Age confirmation form": "Форма підтвердження віку",
|
|
7
|
-
"Please enter your age": "Будь ласка, введіть ваш вік",
|
|
8
|
-
"Language selection": "Вибір мови",
|
|
9
|
-
"Choose language": "Виберіть мову",
|
|
10
|
-
"English": "Англійська",
|
|
11
|
-
"Ukrainian": "Українська",
|
|
12
|
-
"You must be at least 18 years old": "Вам має бути не менше 18 років",
|
|
13
|
-
"Invalid phone number": "Невірний номер телефону",
|
|
14
|
-
"Welcome to our platform!": "Ласкаво просимо на нашу платформу!",
|
|
15
|
-
"Address information": "Інформація про адресу",
|
|
16
|
-
"Street": "Вулиця",
|
|
17
|
-
"City": "Місто",
|
|
18
|
-
"Postal code": "Поштовий код",
|
|
19
|
-
"Country": "Країна",
|
|
20
|
-
"Profile update form": "Форма оновлення профілю",
|
|
21
|
-
"Username": "Ім'я користувача",
|
|
22
|
-
"Biography": "Біографія",
|
|
23
|
-
"Newsletter subscription": "Підписка на розсилку",
|
|
24
|
-
"Subscribe to newsletter": "Підписатися на розсилку"
|
|
25
|
-
}
|
package/src/InputAdapter.test.js
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { describe, it } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
import { UIForm, FormInput, InputMessage } from '@nan0web/ui'
|
|
4
|
-
import { CancelError } from '@nan0web/ui/core'
|
|
5
|
-
import CLIInputAdapter from './InputAdapter.js'
|
|
6
|
-
|
|
7
|
-
// Awaits for the user input.
|
|
8
|
-
describe('CLIInputAdapter', () => {
|
|
9
|
-
it('should create instance', () => {
|
|
10
|
-
const adapter = new CLIInputAdapter()
|
|
11
|
-
assert.ok(adapter instanceof CLIInputAdapter)
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
it('should validate form fields', async () => {
|
|
15
|
-
const adapter = new CLIInputAdapter()
|
|
16
|
-
|
|
17
|
-
// Mock ask for testing
|
|
18
|
-
adapter.ask = () => Promise.resolve('test@example.com')
|
|
19
|
-
|
|
20
|
-
const form = new UIForm({
|
|
21
|
-
title: 'Test Form',
|
|
22
|
-
elementId: 'test-form',
|
|
23
|
-
fields: [
|
|
24
|
-
new FormInput({
|
|
25
|
-
name: 'email',
|
|
26
|
-
label: 'Email',
|
|
27
|
-
type: 'email',
|
|
28
|
-
required: true
|
|
29
|
-
})
|
|
30
|
-
]
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
const result = await adapter.requestForm(form, { silent: true })
|
|
34
|
-
assert.equal(result.form.state.email, 'test@example.com')
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
it('should handle form cancellation', async () => {
|
|
38
|
-
const adapter = new CLIInputAdapter()
|
|
39
|
-
|
|
40
|
-
// Mock ask for cancellation
|
|
41
|
-
adapter.ask = () => Promise.resolve(InputMessage.ESCAPE)
|
|
42
|
-
|
|
43
|
-
const form = new UIForm({
|
|
44
|
-
title: 'Test Form',
|
|
45
|
-
elementId: 'test-form',
|
|
46
|
-
fields: [
|
|
47
|
-
new FormInput({
|
|
48
|
-
name: 'name',
|
|
49
|
-
label: 'Name',
|
|
50
|
-
required: true
|
|
51
|
-
})
|
|
52
|
-
]
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
const result = await adapter.requestForm(form, { silent: true })
|
|
56
|
-
assert.equal(result.escaped, true)
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
it('should have CancelError static property', () => {
|
|
60
|
-
assert.ok(CLIInputAdapter.CancelError)
|
|
61
|
-
const error = new CLIInputAdapter.CancelError()
|
|
62
|
-
assert.equal(error.name, "CancelError")
|
|
63
|
-
assert.equal(error.message, "Operation cancelled by user")
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
it('should implement ask method', async () => {
|
|
67
|
-
const adapter = new CLIInputAdapter()
|
|
68
|
-
// Mock internal ask to avoid stdin interaction
|
|
69
|
-
const originalAsk = adapter.ask
|
|
70
|
-
adapter.ask = () => Promise.resolve('test answer')
|
|
71
|
-
|
|
72
|
-
const answer = await adapter.ask('Test question?')
|
|
73
|
-
assert.equal(answer, 'test answer')
|
|
74
|
-
|
|
75
|
-
// Restore original
|
|
76
|
-
adapter.ask = originalAsk
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
it('should implement select method', async () => {
|
|
80
|
-
const adapter = new CLIInputAdapter()
|
|
81
|
-
// Mock internal select to avoid stdin interaction
|
|
82
|
-
const originalSelect = adapter.select
|
|
83
|
-
adapter.select = () => Promise.resolve({ value: 'option1', index: 0 })
|
|
84
|
-
|
|
85
|
-
const result = await adapter.select({
|
|
86
|
-
title: 'Test Select',
|
|
87
|
-
prompt: 'Choose:',
|
|
88
|
-
options: ['option1', 'option2']
|
|
89
|
-
})
|
|
90
|
-
assert.equal(result.value, 'option1')
|
|
91
|
-
assert.equal(result.index, 0)
|
|
92
|
-
|
|
93
|
-
// Restore original
|
|
94
|
-
adapter.select = originalSelect
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
it('should handle select cancellation', async () => {
|
|
98
|
-
const adapter = new CLIInputAdapter()
|
|
99
|
-
|
|
100
|
-
// Mock select to throw CancelError
|
|
101
|
-
const originalSelect = adapter.select
|
|
102
|
-
adapter.select = () => Promise.reject(new CancelError())
|
|
103
|
-
|
|
104
|
-
const config = {
|
|
105
|
-
title: 'Test Select',
|
|
106
|
-
prompt: 'Choose:',
|
|
107
|
-
id: 'test-select',
|
|
108
|
-
options: ['option1', 'option2']
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const result = await adapter.requestSelect(config)
|
|
112
|
-
assert.deepStrictEqual(result.value, InputMessage.from({}).value)
|
|
113
|
-
|
|
114
|
-
// Restore original
|
|
115
|
-
adapter.select = originalSelect
|
|
116
|
-
})
|
|
117
|
-
})
|