@nan0web/ui-cli 2.0.0 → 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 +43 -0
- package/bin/cli.js +11 -0
- package/bin/nan0cli.js +86 -0
- package/package.json +10 -6
- package/src/README.md.js +56 -1
- package/src/index.js +6 -0
package/README.md
CHANGED
|
@@ -25,6 +25,49 @@ npm install @nan0web/ui-cli
|
|
|
25
25
|
|
|
26
26
|
How to install the package?
|
|
27
27
|
|
|
28
|
+
## nan0cli — Universal CLI Runner
|
|
29
|
+
|
|
30
|
+
The `nan0cli` binary provides a universal entry point for any nan0web application.
|
|
31
|
+
It reads the app's `package.json`, resolves the CLI entry point, and runs commands.
|
|
32
|
+
|
|
33
|
+
### App Contract
|
|
34
|
+
|
|
35
|
+
Your app must export Messages from its entry point:
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
// E1: Messages Array (recommended)
|
|
39
|
+
export default [Serve, Dump]
|
|
40
|
+
|
|
41
|
+
// E2: Single Message class (auto-wrapped to array)
|
|
42
|
+
export default class MyApp { }
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Entry Point Resolution
|
|
46
|
+
|
|
47
|
+
`nan0cli` looks for the entry point in this order:
|
|
48
|
+
1. `nan0web.cli.entry` field in `package.json`
|
|
49
|
+
2. `src/cli.js` (convention)
|
|
50
|
+
3. `src/messages/index.js` (legacy)
|
|
51
|
+
|
|
52
|
+
### Configuration
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"nan0web": {
|
|
57
|
+
"cli": { "entry": "src/cli.js" }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
nan0cli binary is registered
|
|
63
|
+
|
|
64
|
+
### Error Handling
|
|
65
|
+
|
|
66
|
+
When no entry point is found, `nan0cli` displays a styled `Alert` error and exits with code 1.
|
|
67
|
+
All errors are displayed via `Logger` + `Alert` components — never raw `console.log`.
|
|
68
|
+
|
|
69
|
+
nan0cli is included in package files
|
|
70
|
+
|
|
28
71
|
## Usage (V2 Architecture)
|
|
29
72
|
|
|
30
73
|
Starting from v2.0, we recommend using the `render()` function with Composable Components.
|
package/bin/cli.js
ADDED
package/bin/nan0cli.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Universal NaN•Web CLI Runner
|
|
5
|
+
*
|
|
6
|
+
* Takes configuration from current working directory's package.json
|
|
7
|
+
* and executes command using @nan0web/ui-cli core logic.
|
|
8
|
+
*
|
|
9
|
+
* App contract:
|
|
10
|
+
* E1: export default [Serve, Dump] — Messages Array
|
|
11
|
+
* E2: export default class MyApp { } — Single Message class (auto-wrapped)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { pathToFileURL } from 'node:url'
|
|
15
|
+
|
|
16
|
+
import DBFS from '@nan0web/db-fs'
|
|
17
|
+
import Logger from '@nan0web/log'
|
|
18
|
+
|
|
19
|
+
import { CLI, Alert, render } from '../src/index.js'
|
|
20
|
+
|
|
21
|
+
const console = new Logger({ level: Logger.detectLevel(process.argv) })
|
|
22
|
+
const fs = new DBFS()
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Display error via Alert component + Logger
|
|
26
|
+
* @param {string} title
|
|
27
|
+
* @param {string} text
|
|
28
|
+
*/
|
|
29
|
+
const showError = (title, text) => {
|
|
30
|
+
try {
|
|
31
|
+
console.error(render(new Alert({ type: 'error', title, description: text })))
|
|
32
|
+
} catch {
|
|
33
|
+
console.error(`[CRITICAL] ${title}: ${text}`)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
;(async () => {
|
|
38
|
+
try {
|
|
39
|
+
// 1. Load package.json via DBFS (A4)
|
|
40
|
+
const pkg = await fs.loadDocument('package.json', {})
|
|
41
|
+
const entry = pkg?.nan0web?.cli?.entry
|
|
42
|
+
|
|
43
|
+
// 2. Resolve entry point via statDocument (B3)
|
|
44
|
+
const candidates = [entry, 'src/cli.js', 'src/messages/index.js'].filter(Boolean)
|
|
45
|
+
let appPath = null
|
|
46
|
+
|
|
47
|
+
for (const candidate of candidates) {
|
|
48
|
+
const stat = await fs.statDocument(candidate)
|
|
49
|
+
if (!stat.error) {
|
|
50
|
+
appPath = fs.location(candidate)
|
|
51
|
+
break
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!appPath) {
|
|
56
|
+
showError(
|
|
57
|
+
'Config Error',
|
|
58
|
+
'No CLI entry point found.\nPlease add "nan0web.cli.entry" to package.json\nOR create src/cli.js / src/messages/index.js'
|
|
59
|
+
)
|
|
60
|
+
process.exit(1)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 3. Import App Module (D1)
|
|
64
|
+
const appModule = await import(pathToFileURL(appPath))
|
|
65
|
+
|
|
66
|
+
// 4. Resolve Messages (E1 + E2)
|
|
67
|
+
const App = appModule.default || appModule.Messages || appModule.App
|
|
68
|
+
if (!App) {
|
|
69
|
+
showError('Config Error', `Module at ${appPath} must export default, Messages, or App`)
|
|
70
|
+
process.exit(1)
|
|
71
|
+
}
|
|
72
|
+
const Messages = Array.isArray(App) ? App : [App]
|
|
73
|
+
|
|
74
|
+
// 5. Run CLI
|
|
75
|
+
const cli = new CLI({ Messages, argv: process.argv.slice(2) })
|
|
76
|
+
for await (const output of cli.run()) {
|
|
77
|
+
if (output?.content) {
|
|
78
|
+
output.content.forEach((line) => console.info(line))
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
} catch (error) {
|
|
82
|
+
showError('Runtime Error', error.message || String(error))
|
|
83
|
+
if (process.env.DEBUG) console.error(error.stack)
|
|
84
|
+
process.exit(1)
|
|
85
|
+
}
|
|
86
|
+
})()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nan0web/ui-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "NaN•Web UI CLI. Command line interface for One application logic (algorithm) and many UI.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "types/index.d.ts",
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
"src/**/*.js",
|
|
10
10
|
"!src/**/*.test.js",
|
|
11
|
-
"types/**/*.d.ts"
|
|
11
|
+
"types/**/*.d.ts",
|
|
12
|
+
"bin/**/*.js"
|
|
12
13
|
],
|
|
13
14
|
"exports": {
|
|
14
15
|
".": {
|
|
@@ -57,17 +58,20 @@
|
|
|
57
58
|
"author": "ЯRаСлав (YaRaSLove) <support@yaro.page>",
|
|
58
59
|
"license": "ISC",
|
|
59
60
|
"devDependencies": {
|
|
60
|
-
"@nan0web/db-fs": "1.0.0",
|
|
61
61
|
"@nan0web/i18n": "^1.0.1",
|
|
62
|
-
"@nan0web/log": "1.1.1",
|
|
63
62
|
"@nan0web/test": "1.1.0",
|
|
64
63
|
"@types/node": "^24.10.1",
|
|
65
64
|
"knip": "^5.83.0",
|
|
66
65
|
"prettier": "^3.8.1"
|
|
67
66
|
},
|
|
67
|
+
"bin": {
|
|
68
|
+
"nan0cli": "./bin/nan0cli.js"
|
|
69
|
+
},
|
|
68
70
|
"dependencies": {
|
|
71
|
+
"@nan0web/db-fs": "1.0.0",
|
|
69
72
|
"@nan0web/event": "^1.0.0",
|
|
70
|
-
"@nan0web/
|
|
73
|
+
"@nan0web/log": "1.1.1",
|
|
74
|
+
"@nan0web/ui": "^1.1.0",
|
|
71
75
|
"prompts": "^2.4.2"
|
|
72
76
|
}
|
|
73
|
-
}
|
|
77
|
+
}
|
package/src/README.md.js
CHANGED
|
@@ -110,6 +110,59 @@ function testRender() {
|
|
|
110
110
|
assert.equal(pkg.name, '@nan0web/ui-cli')
|
|
111
111
|
})
|
|
112
112
|
|
|
113
|
+
/**
|
|
114
|
+
* @docs
|
|
115
|
+
* ## nan0cli — Universal CLI Runner
|
|
116
|
+
*
|
|
117
|
+
* The `nan0cli` binary provides a universal entry point for any nan0web application.
|
|
118
|
+
* It reads the app's `package.json`, resolves the CLI entry point, and runs commands.
|
|
119
|
+
*
|
|
120
|
+
* ### App Contract
|
|
121
|
+
*
|
|
122
|
+
* Your app must export Messages from its entry point:
|
|
123
|
+
*
|
|
124
|
+
* ```js
|
|
125
|
+
* // E1: Messages Array (recommended)
|
|
126
|
+
* export default [Serve, Dump]
|
|
127
|
+
*
|
|
128
|
+
* // E2: Single Message class (auto-wrapped to array)
|
|
129
|
+
* export default class MyApp { }
|
|
130
|
+
* ```
|
|
131
|
+
*
|
|
132
|
+
* ### Entry Point Resolution
|
|
133
|
+
*
|
|
134
|
+
* `nan0cli` looks for the entry point in this order:
|
|
135
|
+
* 1. `nan0web.cli.entry` field in `package.json`
|
|
136
|
+
* 2. `src/cli.js` (convention)
|
|
137
|
+
* 3. `src/messages/index.js` (legacy)
|
|
138
|
+
*
|
|
139
|
+
* ### Configuration
|
|
140
|
+
*
|
|
141
|
+
* ```json
|
|
142
|
+
* {
|
|
143
|
+
* "nan0web": {
|
|
144
|
+
* "cli": { "entry": "src/cli.js" }
|
|
145
|
+
* }
|
|
146
|
+
* }
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
it('nan0cli binary is registered', () => {
|
|
150
|
+
assert.ok(pkg.bin?.nan0cli, 'bin.nan0cli must be defined')
|
|
151
|
+
assert.equal(pkg.bin.nan0cli, './bin/nan0cli.js')
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @docs
|
|
156
|
+
*
|
|
157
|
+
* ### Error Handling
|
|
158
|
+
*
|
|
159
|
+
* When no entry point is found, `nan0cli` displays a styled `Alert` error and exits with code 1.
|
|
160
|
+
* All errors are displayed via `Logger` + `Alert` components — never raw `console.log`.
|
|
161
|
+
*/
|
|
162
|
+
it('nan0cli is included in package files', () => {
|
|
163
|
+
assert.ok(pkg.files?.includes('bin/**/*.js'), 'bin/**/*.js must be in files array')
|
|
164
|
+
})
|
|
165
|
+
|
|
113
166
|
/**
|
|
114
167
|
* @docs
|
|
115
168
|
* ## Usage (V2 Architecture)
|
|
@@ -324,7 +377,9 @@ describe('README.md testing', testRender)
|
|
|
324
377
|
|
|
325
378
|
describe('Rendering README.md', async () => {
|
|
326
379
|
const parser = new DocsParser()
|
|
327
|
-
|
|
380
|
+
// Read source as string — Bun strips comments from Function.toString()
|
|
381
|
+
const source = await fs.loadDocument('src/README.md.js', '')
|
|
382
|
+
const text = String(parser.decode(source))
|
|
328
383
|
await fs.saveDocument('README.md', text)
|
|
329
384
|
|
|
330
385
|
it('document is rendered', async () => {
|
package/src/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import OutputAdapter from './OutputAdapter.js'
|
|
|
3
3
|
import { CancelError } from '@nan0web/ui/core'
|
|
4
4
|
import CLI from './CLI.js'
|
|
5
5
|
import CommandParser from './CommandParser.js'
|
|
6
|
+
import Form, { generateForm } from './ui/form.js'
|
|
6
7
|
|
|
7
8
|
// V2 Component Exports
|
|
8
9
|
import { render } from './core/render.js'
|
|
@@ -87,6 +88,11 @@ export {
|
|
|
87
88
|
CLI,
|
|
88
89
|
CommandParser,
|
|
89
90
|
OutputAdapter,
|
|
91
|
+
Form,
|
|
92
|
+
generateForm,
|
|
90
93
|
}
|
|
91
94
|
|
|
95
|
+
export { default as Command } from './Command.js'
|
|
96
|
+
export { str2argv } from './utils/parse.js'
|
|
97
|
+
|
|
92
98
|
export default CLiInputAdapter
|