@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.
Files changed (117) hide show
  1. package/README.md +153 -203
  2. package/bin/cli.js +11 -0
  3. package/bin/nan0cli.js +86 -0
  4. package/package.json +27 -13
  5. package/src/CLI.js +22 -30
  6. package/src/CLiMessage.js +2 -3
  7. package/src/Command.js +26 -24
  8. package/src/CommandError.js +3 -5
  9. package/src/CommandHelp.js +40 -36
  10. package/src/CommandMessage.js +56 -40
  11. package/src/CommandParser.js +27 -25
  12. package/src/InputAdapter.js +630 -90
  13. package/src/OutputAdapter.js +7 -8
  14. package/src/README.md.js +241 -312
  15. package/src/components/Alert.js +3 -6
  16. package/src/components/prompt/Autocomplete.js +12 -0
  17. package/src/components/prompt/Confirm.js +29 -0
  18. package/src/components/prompt/DateTime.js +26 -0
  19. package/src/components/prompt/Input.js +15 -0
  20. package/src/components/prompt/Mask.js +12 -0
  21. package/src/components/prompt/Multiselect.js +26 -0
  22. package/src/components/prompt/Next.js +8 -0
  23. package/src/components/prompt/Password.js +13 -0
  24. package/src/components/prompt/Pause.js +9 -0
  25. package/src/components/prompt/ProgressBar.js +16 -0
  26. package/src/components/prompt/Select.js +29 -0
  27. package/src/components/prompt/Slider.js +16 -0
  28. package/src/components/prompt/Spinner.js +29 -0
  29. package/src/components/prompt/Toggle.js +13 -0
  30. package/src/components/prompt/Tree.js +17 -0
  31. package/src/components/view/Alert.js +78 -0
  32. package/src/components/view/Badge.js +11 -0
  33. package/src/components/view/Nav.js +23 -0
  34. package/src/components/view/Table.js +12 -0
  35. package/src/components/view/Toast.js +9 -0
  36. package/src/core/Component.js +79 -0
  37. package/src/core/PropValidation.js +138 -0
  38. package/src/core/render.js +37 -0
  39. package/src/index.js +85 -40
  40. package/src/test/PlaygroundTest.js +37 -25
  41. package/src/test/index.js +2 -4
  42. package/src/ui/alert.js +58 -0
  43. package/src/ui/autocomplete.js +86 -0
  44. package/src/ui/badge.js +35 -0
  45. package/src/ui/confirm.js +49 -0
  46. package/src/ui/date-time.js +45 -0
  47. package/src/ui/form.js +120 -55
  48. package/src/ui/index.js +18 -4
  49. package/src/ui/input.js +79 -152
  50. package/src/ui/mask.js +132 -0
  51. package/src/ui/multiselect.js +59 -0
  52. package/src/ui/nav.js +74 -0
  53. package/src/ui/next.js +18 -13
  54. package/src/ui/progress.js +88 -0
  55. package/src/ui/select.js +49 -72
  56. package/src/ui/slider.js +154 -0
  57. package/src/ui/spinner.js +65 -0
  58. package/src/ui/table.js +163 -0
  59. package/src/ui/toast.js +34 -0
  60. package/src/ui/toggle.js +34 -0
  61. package/src/ui/tree.js +393 -0
  62. package/src/utils/parse.js +1 -1
  63. package/types/CLI.d.ts +5 -5
  64. package/types/CLiMessage.d.ts +1 -1
  65. package/types/Command.d.ts +2 -2
  66. package/types/CommandHelp.d.ts +3 -3
  67. package/types/CommandMessage.d.ts +8 -8
  68. package/types/CommandParser.d.ts +3 -3
  69. package/types/InputAdapter.d.ts +149 -15
  70. package/types/OutputAdapter.d.ts +1 -1
  71. package/types/README.md.d.ts +1 -1
  72. package/types/UiMessage.d.ts +31 -29
  73. package/types/components/prompt/Autocomplete.d.ts +6 -0
  74. package/types/components/prompt/Confirm.d.ts +6 -0
  75. package/types/components/prompt/DateTime.d.ts +6 -0
  76. package/types/components/prompt/Input.d.ts +6 -0
  77. package/types/components/prompt/Mask.d.ts +6 -0
  78. package/types/components/prompt/Multiselect.d.ts +6 -0
  79. package/types/components/prompt/Next.d.ts +6 -0
  80. package/types/components/prompt/Password.d.ts +6 -0
  81. package/types/components/prompt/Pause.d.ts +6 -0
  82. package/types/components/prompt/ProgressBar.d.ts +12 -0
  83. package/types/components/prompt/Select.d.ts +18 -0
  84. package/types/components/prompt/Slider.d.ts +6 -0
  85. package/types/components/prompt/Spinner.d.ts +21 -0
  86. package/types/components/prompt/Toggle.d.ts +6 -0
  87. package/types/components/prompt/Tree.d.ts +6 -0
  88. package/types/components/view/Alert.d.ts +21 -0
  89. package/types/components/view/Badge.d.ts +5 -0
  90. package/types/components/view/Nav.d.ts +15 -0
  91. package/types/components/view/Table.d.ts +10 -0
  92. package/types/components/view/Toast.d.ts +5 -0
  93. package/types/core/Component.d.ts +34 -0
  94. package/types/core/PropValidation.d.ts +48 -0
  95. package/types/core/render.d.ts +6 -0
  96. package/types/index.d.ts +47 -15
  97. package/types/test/PlaygroundTest.d.ts +12 -8
  98. package/types/test/index.d.ts +1 -1
  99. package/types/ui/alert.d.ts +14 -0
  100. package/types/ui/autocomplete.d.ts +20 -0
  101. package/types/ui/badge.d.ts +8 -0
  102. package/types/ui/confirm.d.ts +21 -0
  103. package/types/ui/date-time.d.ts +19 -0
  104. package/types/ui/form.d.ts +43 -12
  105. package/types/ui/index.d.ts +17 -2
  106. package/types/ui/input.d.ts +31 -74
  107. package/types/ui/mask.d.ts +29 -0
  108. package/types/ui/multiselect.d.ts +25 -0
  109. package/types/ui/nav.d.ts +27 -0
  110. package/types/ui/progress.d.ts +43 -0
  111. package/types/ui/select.d.ts +25 -64
  112. package/types/ui/slider.d.ts +23 -0
  113. package/types/ui/spinner.d.ts +28 -0
  114. package/types/ui/table.d.ts +28 -0
  115. package/types/ui/toast.d.ts +8 -0
  116. package/types/ui/toggle.d.ts +17 -0
  117. package/types/ui/tree.d.ts +48 -0
@@ -4,10 +4,10 @@
4
4
  * @module CommandParser
5
5
  */
6
6
 
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"
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 === "string" ? str2argv(input) : input
35
- if (argv.length === 0) throw new Error("No command provided")
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("Unable to infer root command from options")
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 === "function"
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("-") && token.length > 1) {
139
+ } else if (token.startsWith('-') && token.length > 1) {
142
140
  const short = token.slice(1)
143
141
  if (short.length > 1) {
144
- short.split("").forEach(ch => {
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
- body[realKey] = this.#convertType(body[realKey], value)
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 === "boolean")
203
- return Boolean(value !== "false" && value !== false && value !== "")
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