@nan0web/ui-cli 1.1.1 → 2.1.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/README.md +153 -203
- package/bin/cli.js +11 -0
- package/bin/nan0cli.js +86 -0
- package/package.json +27 -13
- package/src/CLI.js +22 -30
- package/src/CLiMessage.js +2 -3
- package/src/Command.js +26 -24
- package/src/CommandError.js +3 -5
- package/src/CommandHelp.js +40 -36
- package/src/CommandMessage.js +56 -40
- package/src/CommandParser.js +27 -25
- package/src/InputAdapter.js +630 -90
- package/src/OutputAdapter.js +7 -8
- package/src/README.md.js +241 -312
- package/src/components/Alert.js +3 -6
- package/src/components/prompt/Autocomplete.js +12 -0
- package/src/components/prompt/Confirm.js +29 -0
- package/src/components/prompt/DateTime.js +26 -0
- package/src/components/prompt/Input.js +15 -0
- package/src/components/prompt/Mask.js +12 -0
- package/src/components/prompt/Multiselect.js +26 -0
- package/src/components/prompt/Next.js +8 -0
- package/src/components/prompt/Password.js +13 -0
- package/src/components/prompt/Pause.js +9 -0
- package/src/components/prompt/ProgressBar.js +16 -0
- package/src/components/prompt/Select.js +29 -0
- package/src/components/prompt/Slider.js +16 -0
- package/src/components/prompt/Spinner.js +29 -0
- package/src/components/prompt/Toggle.js +13 -0
- package/src/components/prompt/Tree.js +17 -0
- package/src/components/view/Alert.js +78 -0
- package/src/components/view/Badge.js +11 -0
- package/src/components/view/Nav.js +23 -0
- package/src/components/view/Table.js +12 -0
- package/src/components/view/Toast.js +9 -0
- package/src/core/Component.js +79 -0
- package/src/core/PropValidation.js +138 -0
- package/src/core/render.js +37 -0
- package/src/index.js +85 -40
- package/src/test/PlaygroundTest.js +37 -25
- package/src/test/index.js +2 -4
- package/src/ui/alert.js +58 -0
- package/src/ui/autocomplete.js +86 -0
- package/src/ui/badge.js +35 -0
- package/src/ui/confirm.js +49 -0
- package/src/ui/date-time.js +45 -0
- package/src/ui/form.js +120 -55
- package/src/ui/index.js +18 -4
- package/src/ui/input.js +79 -152
- package/src/ui/mask.js +132 -0
- package/src/ui/multiselect.js +59 -0
- package/src/ui/nav.js +74 -0
- package/src/ui/next.js +18 -13
- package/src/ui/progress.js +88 -0
- package/src/ui/select.js +49 -72
- package/src/ui/slider.js +154 -0
- package/src/ui/spinner.js +65 -0
- package/src/ui/table.js +163 -0
- package/src/ui/toast.js +34 -0
- package/src/ui/toggle.js +34 -0
- package/src/ui/tree.js +393 -0
- package/src/utils/parse.js +1 -1
- package/types/CLI.d.ts +5 -5
- package/types/CLiMessage.d.ts +1 -1
- package/types/Command.d.ts +2 -2
- package/types/CommandHelp.d.ts +3 -3
- package/types/CommandMessage.d.ts +8 -8
- package/types/CommandParser.d.ts +3 -3
- package/types/InputAdapter.d.ts +149 -15
- package/types/OutputAdapter.d.ts +1 -1
- package/types/README.md.d.ts +1 -1
- package/types/UiMessage.d.ts +31 -29
- package/types/components/prompt/Autocomplete.d.ts +6 -0
- package/types/components/prompt/Confirm.d.ts +6 -0
- package/types/components/prompt/DateTime.d.ts +6 -0
- package/types/components/prompt/Input.d.ts +6 -0
- package/types/components/prompt/Mask.d.ts +6 -0
- package/types/components/prompt/Multiselect.d.ts +6 -0
- package/types/components/prompt/Next.d.ts +6 -0
- package/types/components/prompt/Password.d.ts +6 -0
- package/types/components/prompt/Pause.d.ts +6 -0
- package/types/components/prompt/ProgressBar.d.ts +12 -0
- package/types/components/prompt/Select.d.ts +18 -0
- package/types/components/prompt/Slider.d.ts +6 -0
- package/types/components/prompt/Spinner.d.ts +21 -0
- package/types/components/prompt/Toggle.d.ts +6 -0
- package/types/components/prompt/Tree.d.ts +6 -0
- package/types/components/view/Alert.d.ts +21 -0
- package/types/components/view/Badge.d.ts +5 -0
- package/types/components/view/Nav.d.ts +15 -0
- package/types/components/view/Table.d.ts +10 -0
- package/types/components/view/Toast.d.ts +5 -0
- package/types/core/Component.d.ts +34 -0
- package/types/core/PropValidation.d.ts +48 -0
- package/types/core/render.d.ts +6 -0
- package/types/index.d.ts +47 -15
- package/types/test/PlaygroundTest.d.ts +12 -8
- package/types/test/index.d.ts +1 -1
- package/types/ui/alert.d.ts +14 -0
- package/types/ui/autocomplete.d.ts +20 -0
- package/types/ui/badge.d.ts +8 -0
- package/types/ui/confirm.d.ts +21 -0
- package/types/ui/date-time.d.ts +19 -0
- package/types/ui/form.d.ts +43 -12
- package/types/ui/index.d.ts +17 -2
- package/types/ui/input.d.ts +31 -74
- package/types/ui/mask.d.ts +29 -0
- package/types/ui/multiselect.d.ts +25 -0
- package/types/ui/nav.d.ts +27 -0
- package/types/ui/progress.d.ts +43 -0
- package/types/ui/select.d.ts +25 -64
- package/types/ui/slider.d.ts +23 -0
- package/types/ui/spinner.d.ts +28 -0
- package/types/ui/table.d.ts +28 -0
- package/types/ui/toast.d.ts +8 -0
- package/types/ui/toggle.d.ts +17 -0
- package/types/ui/tree.d.ts +48 -0
package/src/CommandParser.js
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* @module CommandParser
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { Message } from
|
|
8
|
-
import CommandHelp from
|
|
9
|
-
import CommandError from
|
|
10
|
-
import { str2argv } from
|
|
7
|
+
import { Message } from '@nan0web/co'
|
|
8
|
+
import CommandHelp from './CommandHelp.js'
|
|
9
|
+
import CommandError from './CommandError.js'
|
|
10
|
+
import { str2argv } from './utils/parse.js'
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* @class
|
|
@@ -31,18 +31,16 @@ export default class CommandParser {
|
|
|
31
31
|
* @throws {Error} If no command is supplied or unknown root command.
|
|
32
32
|
*/
|
|
33
33
|
parse(input = process.argv.slice(2)) {
|
|
34
|
-
const argv = typeof input ===
|
|
35
|
-
if (argv.length === 0) throw new Error(
|
|
34
|
+
const argv = typeof input === 'string' ? str2argv(input) : input
|
|
35
|
+
if (argv.length === 0) throw new Error('No command provided')
|
|
36
36
|
let rootName = null
|
|
37
37
|
let remaining = argv
|
|
38
38
|
|
|
39
|
-
if (!argv[0].startsWith(
|
|
39
|
+
if (!argv[0].startsWith('-')) {
|
|
40
40
|
rootName = argv[0]
|
|
41
41
|
remaining = argv.slice(1)
|
|
42
42
|
|
|
43
|
-
let RootClass = this.Messages.find(
|
|
44
|
-
cls => cls.name.toLowerCase() === rootName.toLowerCase(),
|
|
45
|
-
)
|
|
43
|
+
let RootClass = this.Messages.find((cls) => cls.name.toLowerCase() === rootName.toLowerCase())
|
|
46
44
|
if (!RootClass) {
|
|
47
45
|
if (this.Messages.length === 1) RootClass = this.Messages[0]
|
|
48
46
|
else throw new Error(`Unknown root command: ${rootName}`)
|
|
@@ -56,7 +54,7 @@ export default class CommandParser {
|
|
|
56
54
|
return this.#processMessageTree(rootMessage, remaining)
|
|
57
55
|
}
|
|
58
56
|
|
|
59
|
-
if (this.Messages.length !== 1) throw new Error(
|
|
57
|
+
if (this.Messages.length !== 1) throw new Error('Unable to infer root command from options')
|
|
60
58
|
// @ts-ignore – see comment above
|
|
61
59
|
const RootClass = this.Messages[0]
|
|
62
60
|
// @ts-ignore
|
|
@@ -81,7 +79,7 @@ export default class CommandParser {
|
|
|
81
79
|
const subName = remaining[0]
|
|
82
80
|
// @ts-ignore
|
|
83
81
|
const SubClass = currentMessage.constructor.Children.find(
|
|
84
|
-
cls => cls.name.toLowerCase() === subName.toLowerCase()
|
|
82
|
+
(cls) => cls.name.toLowerCase() === subName.toLowerCase()
|
|
85
83
|
)
|
|
86
84
|
if (!SubClass) break
|
|
87
85
|
|
|
@@ -97,14 +95,14 @@ export default class CommandParser {
|
|
|
97
95
|
const parsedBody = this.#parseLeafBody(
|
|
98
96
|
remaining,
|
|
99
97
|
// @ts-ignore – `Body` may be undefined on some classes
|
|
100
|
-
currentMessage.constructor.Body
|
|
98
|
+
currentMessage.constructor.Body
|
|
101
99
|
)
|
|
102
100
|
currentMessage.body = { ...currentMessage.body, ...parsedBody }
|
|
103
101
|
}
|
|
104
102
|
|
|
105
103
|
if (
|
|
106
104
|
rootMessage.body.subCommand &&
|
|
107
|
-
typeof rootMessage.body.subCommand.assertValid ===
|
|
105
|
+
typeof rootMessage.body.subCommand.assertValid === 'function'
|
|
108
106
|
) {
|
|
109
107
|
rootMessage.body.subCommand.assertValid()
|
|
110
108
|
}
|
|
@@ -125,23 +123,23 @@ export default class CommandParser {
|
|
|
125
123
|
for (let i = 0; i < tokens.length; i++) {
|
|
126
124
|
const token = tokens[i]
|
|
127
125
|
|
|
128
|
-
if (token.startsWith(
|
|
126
|
+
if (token.startsWith('--')) {
|
|
129
127
|
let key = token.slice(2)
|
|
130
128
|
/** @type {boolean | string} */
|
|
131
129
|
let value = true
|
|
132
|
-
const eqIdx = key.indexOf(
|
|
130
|
+
const eqIdx = key.indexOf('=')
|
|
133
131
|
if (eqIdx > -1) {
|
|
134
132
|
value = key.slice(eqIdx + 1)
|
|
135
133
|
key = key.slice(0, eqIdx)
|
|
136
|
-
} else if (i + 1 < tokens.length && !tokens[i + 1].startsWith(
|
|
134
|
+
} else if (i + 1 < tokens.length && !tokens[i + 1].startsWith('-')) {
|
|
137
135
|
value = tokens[++i]
|
|
138
136
|
}
|
|
139
137
|
const realKey = this.#resolveAlias(key, BodyClass) || key
|
|
140
138
|
if (props.includes(realKey)) body[realKey] = this.#convertType(body[realKey], value)
|
|
141
|
-
} else if (token.startsWith(
|
|
139
|
+
} else if (token.startsWith('-') && token.length > 1) {
|
|
142
140
|
const short = token.slice(1)
|
|
143
141
|
if (short.length > 1) {
|
|
144
|
-
short.split(
|
|
142
|
+
short.split('').forEach((ch) => {
|
|
145
143
|
const realKey = this.#resolveAlias(ch, BodyClass)
|
|
146
144
|
if (realKey && props.includes(realKey)) body[realKey] = true
|
|
147
145
|
})
|
|
@@ -150,10 +148,15 @@ export default class CommandParser {
|
|
|
150
148
|
if (props.includes(realKey)) {
|
|
151
149
|
/** @type {boolean | string} */
|
|
152
150
|
let value = true
|
|
153
|
-
if (i + 1 < tokens.length && !tokens[i + 1].startsWith(
|
|
151
|
+
if (i + 1 < tokens.length && !tokens[i + 1].startsWith('-')) {
|
|
154
152
|
value = tokens[++i]
|
|
155
153
|
}
|
|
156
|
-
|
|
154
|
+
const type = typeof body[realKey]
|
|
155
|
+
if ('object' === type && Array.isArray(body[realKey])) {
|
|
156
|
+
body[realKey].push(this.#convertType(body[realKey], value))
|
|
157
|
+
} else {
|
|
158
|
+
body[realKey] = this.#convertType(body[realKey], value)
|
|
159
|
+
}
|
|
157
160
|
}
|
|
158
161
|
}
|
|
159
162
|
} else {
|
|
@@ -162,7 +165,7 @@ export default class CommandParser {
|
|
|
162
165
|
}
|
|
163
166
|
}
|
|
164
167
|
|
|
165
|
-
props.forEach(prop => {
|
|
168
|
+
props.forEach((prop) => {
|
|
166
169
|
const schema = BodyClass[prop]
|
|
167
170
|
if (schema?.default !== undefined && body[prop] === undefined) {
|
|
168
171
|
body[prop] = schema.default
|
|
@@ -199,9 +202,8 @@ export default class CommandParser {
|
|
|
199
202
|
*/
|
|
200
203
|
#convertType(defaultVal, value) {
|
|
201
204
|
const type = typeof defaultVal
|
|
202
|
-
if (type ===
|
|
203
|
-
|
|
204
|
-
if (type === "number") return Number(value) || 0
|
|
205
|
+
if (type === 'boolean') return Boolean(value !== 'false' && value !== false && value !== '')
|
|
206
|
+
if (type === 'number') return Number(value) || 0
|
|
205
207
|
return String(value)
|
|
206
208
|
}
|
|
207
209
|
|