devvami 1.4.2 → 1.5.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 +7 -0
- package/oclif.manifest.json +129 -89
- package/package.json +2 -1
- package/src/commands/auth/login.js +20 -16
- package/src/commands/changelog.js +12 -12
- package/src/commands/costs/get.js +14 -24
- package/src/commands/costs/trend.js +13 -24
- package/src/commands/create/repo.js +72 -54
- package/src/commands/docs/list.js +29 -25
- package/src/commands/docs/projects.js +58 -24
- package/src/commands/docs/read.js +56 -39
- package/src/commands/docs/search.js +37 -25
- package/src/commands/doctor.js +37 -35
- package/src/commands/dotfiles/add.js +51 -39
- package/src/commands/dotfiles/setup.js +62 -33
- package/src/commands/dotfiles/status.js +18 -18
- package/src/commands/dotfiles/sync.js +62 -46
- package/src/commands/init.js +143 -132
- package/src/commands/logs/index.js +10 -16
- package/src/commands/open.js +12 -12
- package/src/commands/pipeline/logs.js +8 -11
- package/src/commands/pipeline/rerun.js +21 -16
- package/src/commands/pipeline/status.js +28 -24
- package/src/commands/pr/create.js +40 -27
- package/src/commands/pr/detail.js +9 -7
- package/src/commands/pr/review.js +18 -19
- package/src/commands/pr/status.js +27 -21
- package/src/commands/prompts/browse.js +15 -15
- package/src/commands/prompts/download.js +15 -16
- package/src/commands/prompts/install-speckit.js +11 -12
- package/src/commands/prompts/list.js +12 -12
- package/src/commands/prompts/run.js +16 -19
- package/src/commands/repo/list.js +57 -41
- package/src/commands/search.js +20 -18
- package/src/commands/security/setup.js +38 -34
- package/src/commands/sync-config-ai/index.js +143 -0
- package/src/commands/tasks/assigned.js +43 -33
- package/src/commands/tasks/list.js +43 -33
- package/src/commands/tasks/today.js +32 -30
- package/src/commands/upgrade.js +18 -17
- package/src/commands/vuln/detail.js +8 -8
- package/src/commands/vuln/scan.js +39 -20
- package/src/commands/vuln/search.js +23 -18
- package/src/commands/welcome.js +2 -2
- package/src/commands/whoami.js +19 -23
- package/src/formatters/ai-config.js +127 -0
- package/src/formatters/charts.js +6 -23
- package/src/formatters/cost.js +1 -7
- package/src/formatters/dotfiles.js +48 -19
- package/src/formatters/markdown.js +11 -6
- package/src/formatters/openapi.js +7 -9
- package/src/formatters/prompts.js +69 -78
- package/src/formatters/security.js +2 -2
- package/src/formatters/status.js +1 -1
- package/src/formatters/table.js +1 -3
- package/src/formatters/vuln.js +33 -20
- package/src/help.js +162 -164
- package/src/hooks/init.js +1 -3
- package/src/hooks/postrun.js +5 -7
- package/src/index.js +1 -1
- package/src/services/ai-config-store.js +318 -0
- package/src/services/ai-env-deployer.js +444 -0
- package/src/services/ai-env-scanner.js +242 -0
- package/src/services/audit-detector.js +2 -2
- package/src/services/audit-runner.js +40 -31
- package/src/services/auth.js +9 -9
- package/src/services/awesome-copilot.js +7 -4
- package/src/services/aws-costs.js +22 -22
- package/src/services/clickup.js +26 -26
- package/src/services/cloudwatch-logs.js +5 -9
- package/src/services/config.js +13 -13
- package/src/services/docs.js +19 -20
- package/src/services/dotfiles.js +149 -51
- package/src/services/github.js +22 -24
- package/src/services/nvd.js +21 -31
- package/src/services/platform.js +2 -2
- package/src/services/prompts.js +23 -35
- package/src/services/security.js +135 -61
- package/src/services/shell.js +4 -4
- package/src/services/skills-sh.js +3 -9
- package/src/services/speckit.js +4 -7
- package/src/services/version-check.js +10 -10
- package/src/types.js +85 -0
- package/src/utils/aws-vault.js +18 -41
- package/src/utils/banner.js +5 -7
- package/src/utils/errors.js +42 -46
- package/src/utils/frontmatter.js +4 -4
- package/src/utils/gradient.js +18 -16
- package/src/utils/open-browser.js +3 -3
- package/src/utils/tui/form.js +1006 -0
- package/src/utils/tui/modal.js +15 -14
- package/src/utils/tui/navigable-table.js +16 -16
- package/src/utils/tui/tab-tui.js +800 -0
- package/src/utils/typewriter.js +3 -3
- package/src/utils/welcome.js +18 -21
- package/src/validators/repo-name.js +2 -2
package/src/help.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {Help} from '@oclif/core'
|
|
2
2
|
import chalk from 'chalk'
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import {isColorEnabled} from './utils/gradient.js'
|
|
4
|
+
import {printBanner} from './utils/banner.js'
|
|
5
5
|
|
|
6
6
|
// ─── Brand palette (flat — no gradient on help rows) ────────────────────────
|
|
7
|
-
const ORANGE
|
|
7
|
+
const ORANGE = '#FF6B2B'
|
|
8
8
|
const LIGHT_ORANGE = '#FF9A5C'
|
|
9
|
-
const DIM_BLUE
|
|
10
|
-
const DIM_GRAY
|
|
9
|
+
const DIM_BLUE = '#4A9EFF'
|
|
10
|
+
const DIM_GRAY = '#888888'
|
|
11
11
|
|
|
12
12
|
// Strip ANSI escape codes
|
|
13
13
|
const ANSI_RE = /\x1B\[[0-?]*[ -/]*[@-~]/g
|
|
@@ -27,92 +27,91 @@ const CATEGORIES = [
|
|
|
27
27
|
{
|
|
28
28
|
title: 'GitHub & Documentazione',
|
|
29
29
|
cmds: [
|
|
30
|
-
{
|
|
31
|
-
{
|
|
32
|
-
{
|
|
33
|
-
{
|
|
34
|
-
{
|
|
35
|
-
{
|
|
36
|
-
{
|
|
37
|
-
{
|
|
30
|
+
{id: 'repo:list', hint: '[--language] [--search]'},
|
|
31
|
+
{id: 'docs:read', hint: '[FILE] [--repo] [--raw] [--render]'},
|
|
32
|
+
{id: 'docs:list', hint: '[--repo] [--search]'},
|
|
33
|
+
{id: 'docs:search', hint: '<TERM> [--repo]'},
|
|
34
|
+
{id: 'docs:projects', hint: '[--search]'},
|
|
35
|
+
{id: 'create:repo', hint: '[TEMPLATE] [--list] [--name]'},
|
|
36
|
+
{id: 'search', hint: '<QUERY>'},
|
|
37
|
+
{id: 'open', hint: '<TARGET>'},
|
|
38
38
|
],
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
title: 'Pull Request',
|
|
42
42
|
cmds: [
|
|
43
|
-
{
|
|
44
|
-
{
|
|
45
|
-
{
|
|
46
|
-
{
|
|
43
|
+
{id: 'pr:create', hint: ''},
|
|
44
|
+
{id: 'pr:status', hint: ''},
|
|
45
|
+
{id: 'pr:detail', hint: '<PR_NUMBER> --repo <owner/repo>'},
|
|
46
|
+
{id: 'pr:review', hint: ''},
|
|
47
47
|
],
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
title: 'Pipeline & DevOps',
|
|
51
51
|
cmds: [
|
|
52
|
-
{
|
|
53
|
-
{
|
|
54
|
-
{
|
|
55
|
-
{
|
|
52
|
+
{id: 'pipeline:status', hint: '[--repo] [--branch]'},
|
|
53
|
+
{id: 'pipeline:rerun', hint: '<RUN_ID> --repo <repo>'},
|
|
54
|
+
{id: 'pipeline:logs', hint: '<RUN_ID> --repo <repo>'},
|
|
55
|
+
{id: 'changelog', hint: ''},
|
|
56
56
|
],
|
|
57
57
|
},
|
|
58
58
|
{
|
|
59
59
|
title: 'Tasks (ClickUp)',
|
|
60
60
|
cmds: [
|
|
61
|
-
{
|
|
62
|
-
{
|
|
63
|
-
{
|
|
61
|
+
{id: 'tasks:list', hint: '[--status] [--search]'},
|
|
62
|
+
{id: 'tasks:today', hint: ''},
|
|
63
|
+
{id: 'tasks:assigned', hint: '[--status] [--search]'},
|
|
64
64
|
],
|
|
65
65
|
},
|
|
66
66
|
{
|
|
67
67
|
title: 'Cloud & Costi',
|
|
68
68
|
cmds: [
|
|
69
|
-
{
|
|
70
|
-
{
|
|
71
|
-
{
|
|
69
|
+
{id: 'costs:get', hint: '[SERVICE] [--period] [--group-by] [--tag-key]'},
|
|
70
|
+
{id: 'costs:trend', hint: '[--group-by] [--tag-key] [--line]'},
|
|
71
|
+
{id: 'logs', hint: '[--group] [--filter] [--since] [--limit] [--region]'},
|
|
72
72
|
],
|
|
73
73
|
},
|
|
74
74
|
{
|
|
75
75
|
title: 'AI Prompts',
|
|
76
76
|
cmds: [
|
|
77
|
-
{
|
|
78
|
-
{
|
|
79
|
-
{
|
|
80
|
-
{
|
|
81
|
-
{
|
|
77
|
+
{id: 'prompts:list', hint: '[--filter]'},
|
|
78
|
+
{id: 'prompts:download', hint: '<PATH> [--overwrite]'},
|
|
79
|
+
{id: 'prompts:browse', hint: '[--source] [--query] [--category]'},
|
|
80
|
+
{id: 'prompts:install-speckit', hint: '[--force]'},
|
|
81
|
+
{id: 'prompts:run', hint: '[PATH] [--tool]'},
|
|
82
|
+
{id: 'sync-config-ai', hint: '[--json]'},
|
|
82
83
|
],
|
|
83
84
|
},
|
|
84
85
|
{
|
|
85
86
|
title: 'Sicurezza & Credenziali',
|
|
86
|
-
cmds: [
|
|
87
|
-
{ id: 'security:setup', hint: '[--json]' },
|
|
88
|
-
],
|
|
87
|
+
cmds: [{id: 'security:setup', hint: '[--json]'}],
|
|
89
88
|
},
|
|
90
89
|
{
|
|
91
90
|
title: 'CVE & Vulnerabilità',
|
|
92
91
|
cmds: [
|
|
93
|
-
{
|
|
94
|
-
{
|
|
95
|
-
{
|
|
92
|
+
{id: 'vuln:search', hint: '[KEYWORD] [--days] [--severity] [--limit]'},
|
|
93
|
+
{id: 'vuln:detail', hint: '<CVE-ID> [--open]'},
|
|
94
|
+
{id: 'vuln:scan', hint: '[--severity] [--no-fail] [--report]'},
|
|
96
95
|
],
|
|
97
96
|
},
|
|
98
97
|
{
|
|
99
98
|
title: 'Dotfiles & Cifratura',
|
|
100
99
|
cmds: [
|
|
101
|
-
{
|
|
102
|
-
{
|
|
103
|
-
{
|
|
104
|
-
{
|
|
100
|
+
{id: 'dotfiles:setup', hint: '[--json]'},
|
|
101
|
+
{id: 'dotfiles:add', hint: '[FILES...] [--encrypt]'},
|
|
102
|
+
{id: 'dotfiles:status', hint: '[--json]'},
|
|
103
|
+
{id: 'dotfiles:sync', hint: '[--push] [--pull] [--dry-run]'},
|
|
105
104
|
],
|
|
106
105
|
},
|
|
107
106
|
{
|
|
108
107
|
title: 'Setup & Ambiente',
|
|
109
108
|
cmds: [
|
|
110
|
-
{
|
|
111
|
-
{
|
|
112
|
-
{
|
|
113
|
-
{
|
|
114
|
-
{
|
|
115
|
-
{
|
|
109
|
+
{id: 'init', hint: '[--dry-run]'},
|
|
110
|
+
{id: 'doctor', hint: ''},
|
|
111
|
+
{id: 'auth:login', hint: ''},
|
|
112
|
+
{id: 'whoami', hint: ''},
|
|
113
|
+
{id: 'welcome', hint: ''},
|
|
114
|
+
{id: 'upgrade', hint: ''},
|
|
116
115
|
],
|
|
117
116
|
},
|
|
118
117
|
]
|
|
@@ -126,31 +125,30 @@ const CATEGORIES = [
|
|
|
126
125
|
* - Gradient solo sul logo; tutto il resto usa colori flat chalk
|
|
127
126
|
*/
|
|
128
127
|
export default class CustomHelp extends Help {
|
|
128
|
+
/**
|
|
129
|
+
* Root help override: banner animato → layout categorizzato.
|
|
130
|
+
* Override di showRootHelp() (async) per evitare che formatRoot() (sync)
|
|
131
|
+
* debba attendere la Promise del banner.
|
|
132
|
+
* @returns {Promise<void>}
|
|
133
|
+
*/
|
|
134
|
+
async showRootHelp() {
|
|
135
|
+
// Animated logo — identical to `dvmi init` (no-ops in CI/non-TTY)
|
|
136
|
+
await printBanner()
|
|
137
|
+
|
|
138
|
+
// Version check: uses cached result (populated by init hook) — 800 ms timeout
|
|
139
|
+
let versionInfo = null
|
|
140
|
+
try {
|
|
141
|
+
const {checkForUpdate} = await import('./services/version-check.js')
|
|
142
|
+
versionInfo = await Promise.race([
|
|
143
|
+
checkForUpdate(),
|
|
144
|
+
new Promise((resolve) => setTimeout(() => resolve(null), 800)),
|
|
145
|
+
])
|
|
146
|
+
} catch {
|
|
147
|
+
// never block help output
|
|
148
|
+
}
|
|
129
149
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
* Override di showRootHelp() (async) per evitare che formatRoot() (sync)
|
|
133
|
-
* debba attendere la Promise del banner.
|
|
134
|
-
* @returns {Promise<void>}
|
|
135
|
-
*/
|
|
136
|
-
async showRootHelp() {
|
|
137
|
-
// Animated logo — identical to `dvmi init` (no-ops in CI/non-TTY)
|
|
138
|
-
await printBanner()
|
|
139
|
-
|
|
140
|
-
// Version check: uses cached result (populated by init hook) — 800 ms timeout
|
|
141
|
-
let versionInfo = null
|
|
142
|
-
try {
|
|
143
|
-
const { checkForUpdate } = await import('./services/version-check.js')
|
|
144
|
-
versionInfo = await Promise.race([
|
|
145
|
-
checkForUpdate(),
|
|
146
|
-
new Promise((resolve) => setTimeout(() => resolve(null), 800)),
|
|
147
|
-
])
|
|
148
|
-
} catch {
|
|
149
|
-
// never block help output
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
this.log(this.#buildRootLayout(versionInfo))
|
|
153
|
-
}
|
|
150
|
+
this.log(this.#buildRootLayout(versionInfo))
|
|
151
|
+
}
|
|
154
152
|
|
|
155
153
|
/**
|
|
156
154
|
* @param {import('@oclif/core').Interfaces.Topic[]} topics
|
|
@@ -179,69 +177,64 @@ export default class CustomHelp extends Help {
|
|
|
179
177
|
|
|
180
178
|
// ─── Private helpers ──────────────────────────────────────────────────────
|
|
181
179
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
180
|
+
/**
|
|
181
|
+
* Build the full categorized root help layout.
|
|
182
|
+
* @param {{ hasUpdate: boolean, current: string, latest: string|null }|null} [versionInfo]
|
|
183
|
+
* @returns {string}
|
|
184
|
+
*/
|
|
187
185
|
#buildRootLayout(versionInfo = null) {
|
|
188
186
|
/** @type {Map<string, import('@oclif/core').Command.Cached>} */
|
|
189
187
|
const cmdMap = new Map(this.config.commands.map((c) => [c.id, c]))
|
|
190
188
|
|
|
191
189
|
/** @type {Array<{cmd: string, note: string}>} */
|
|
192
190
|
const EXAMPLES = [
|
|
193
|
-
{
|
|
194
|
-
{
|
|
195
|
-
{
|
|
196
|
-
{
|
|
197
|
-
{
|
|
198
|
-
{
|
|
199
|
-
{
|
|
200
|
-
{
|
|
201
|
-
{
|
|
202
|
-
{
|
|
203
|
-
{
|
|
204
|
-
{
|
|
205
|
-
{
|
|
206
|
-
{
|
|
207
|
-
{
|
|
208
|
-
{
|
|
209
|
-
{
|
|
210
|
-
{
|
|
211
|
-
{
|
|
212
|
-
{
|
|
213
|
-
{
|
|
214
|
-
{
|
|
215
|
-
{
|
|
216
|
-
{
|
|
217
|
-
{
|
|
218
|
-
{
|
|
219
|
-
{
|
|
220
|
-
{
|
|
221
|
-
{
|
|
222
|
-
{
|
|
223
|
-
{
|
|
224
|
-
{
|
|
225
|
-
{
|
|
226
|
-
{
|
|
191
|
+
{cmd: 'dvmi prompts list', note: 'Sfoglia prompt AI dal tuo repository'},
|
|
192
|
+
{cmd: 'dvmi prompts list --filter refactor', note: 'Filtra prompt per parola chiave'},
|
|
193
|
+
{cmd: 'dvmi prompts download coding/refactor-prompt.md', note: 'Scarica un prompt localmente'},
|
|
194
|
+
{cmd: 'dvmi prompts browse skills --query refactor', note: 'Cerca skill su skills.sh'},
|
|
195
|
+
{cmd: 'dvmi prompts browse awesome --category agents', note: 'Sfoglia awesome-copilot agents'},
|
|
196
|
+
{cmd: 'dvmi prompts run coding/refactor-prompt.md --tool opencode', note: 'Esegui un prompt con opencode'},
|
|
197
|
+
{cmd: 'dvmi docs read', note: 'Leggi il README del repo corrente'},
|
|
198
|
+
{cmd: 'dvmi docs search "authentication"', note: 'Cerca nei docs del repo corrente'},
|
|
199
|
+
{cmd: 'dvmi repo list --search "api"', note: 'Filtra repository per nome'},
|
|
200
|
+
{cmd: 'dvmi pr status', note: 'PR aperte e review in attesa'},
|
|
201
|
+
{cmd: 'dvmi pipeline status', note: 'Ultimi workflow CI/CD'},
|
|
202
|
+
{cmd: 'dvmi tasks list --search "bug"', note: 'Cerca task ClickUp'},
|
|
203
|
+
{cmd: 'dvmi tasks today', note: 'Task in lavorazione oggi'},
|
|
204
|
+
{cmd: 'dvmi costs get --period mtd', note: 'Costi AWS mese corrente per servizio'},
|
|
205
|
+
{cmd: 'dvmi costs get --group-by tag --tag-key env', note: 'Costi raggruppati per tag env'},
|
|
206
|
+
{cmd: 'dvmi costs trend --line', note: 'Trend costi 2 mesi (grafico lineare)'},
|
|
207
|
+
{cmd: 'dvmi costs get --json', note: 'Costi AWS in formato JSON'},
|
|
208
|
+
{cmd: 'dvmi logs', note: 'Sfoglia log CloudWatch in modo interattivo'},
|
|
209
|
+
{cmd: 'dvmi logs --group /aws/lambda/my-fn --since 24h', note: 'Log Lambda ultimi 24h'},
|
|
210
|
+
{cmd: 'dvmi logs --group /aws/lambda/my-fn --filter "ERROR"', note: 'Filtra eventi ERROR su un log group'},
|
|
211
|
+
{cmd: 'dvmi security setup --json', note: 'Controlla lo stato degli strumenti di sicurezza'},
|
|
212
|
+
{cmd: 'dvmi security setup', note: 'Wizard interattivo: installa aws-vault e GCM'},
|
|
213
|
+
{cmd: 'dvmi dotfiles setup', note: 'Configura chezmoi con cifratura age'},
|
|
214
|
+
{cmd: 'dvmi dotfiles add ~/.zshrc ~/.gitconfig', note: 'Aggiungi dotfile a chezmoi'},
|
|
215
|
+
{cmd: 'dvmi dotfiles status --json', note: 'Stato dotfile gestiti (JSON)'},
|
|
216
|
+
{cmd: 'dvmi dotfiles sync --push', note: 'Push dotfile al repository remoto'},
|
|
217
|
+
{cmd: 'dvmi welcome', note: 'Dashboard missione dvmi con intro animata'},
|
|
218
|
+
{cmd: 'dvmi vuln search openssl', note: 'Cerca CVE recenti per keyword'},
|
|
219
|
+
{cmd: 'dvmi vuln search log4j --days 30 --severity critical', note: 'CVE critiche Log4j negli ultimi 30 giorni'},
|
|
220
|
+
{cmd: 'dvmi vuln detail CVE-2021-44228', note: 'Dettaglio completo di una CVE'},
|
|
221
|
+
{cmd: 'dvmi vuln detail CVE-2021-44228 --open', note: 'Apri la prima referenza nel browser'},
|
|
222
|
+
{cmd: 'dvmi vuln scan', note: 'Scansiona dipendenze del progetto corrente'},
|
|
223
|
+
{cmd: 'dvmi vuln scan --severity high --no-fail', note: 'Scansione senza bloccare CI (solo high+)'},
|
|
224
|
+
{cmd: 'dvmi vuln scan --report ./vuln-report.md', note: 'Esporta report Markdown delle vulnerabilità'},
|
|
227
225
|
]
|
|
228
226
|
|
|
229
227
|
const lines = []
|
|
230
228
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
' ' + (isColorEnabled ? chalk.hex(ORANGE).bold('dvmi') : 'dvmi') +
|
|
235
|
-
chalk.dim(' <COMANDO> [FLAGS]\n'),
|
|
236
|
-
)
|
|
229
|
+
// ── Usage ──────────────────────────────────────────────────────────────
|
|
230
|
+
lines.push(this.#sectionHeader('USAGE'))
|
|
231
|
+
lines.push(' ' + (isColorEnabled ? chalk.hex(ORANGE).bold('dvmi') : 'dvmi') + chalk.dim(' <COMANDO> [FLAGS]\n'))
|
|
237
232
|
|
|
238
233
|
// ── Comandi per categoria ──────────────────────────────────────────────
|
|
239
234
|
lines.push(this.#sectionHeader('COMMANDS'))
|
|
240
235
|
|
|
241
236
|
for (const cat of CATEGORIES) {
|
|
242
|
-
lines.push(
|
|
243
|
-
' ' + (isColorEnabled ? chalk.hex(ORANGE).bold(cat.title) : cat.title),
|
|
244
|
-
)
|
|
237
|
+
lines.push(' ' + (isColorEnabled ? chalk.hex(ORANGE).bold(cat.title) : cat.title))
|
|
245
238
|
|
|
246
239
|
for (const entry of cat.cmds) {
|
|
247
240
|
const cmd = cmdMap.get(entry.id)
|
|
@@ -249,17 +242,14 @@ export default class CustomHelp extends Help {
|
|
|
249
242
|
|
|
250
243
|
const displayId = entry.id.replaceAll(':', ' ')
|
|
251
244
|
const hint = entry.hint || ''
|
|
252
|
-
const desc = cmd.summary ?? (typeof cmd.description === 'string'
|
|
253
|
-
? cmd.description.split('\n')[0]
|
|
254
|
-
: '')
|
|
245
|
+
const desc = cmd.summary ?? (typeof cmd.description === 'string' ? cmd.description.split('\n')[0] : '')
|
|
255
246
|
|
|
256
247
|
// Left column (name + flags hint), right-padded to align descriptions
|
|
257
248
|
const rawLeft = ' ' + displayId + (hint ? ' ' + hint : '')
|
|
258
249
|
const pad = ' '.repeat(Math.max(2, 50 - rawLeft.length))
|
|
259
250
|
|
|
260
251
|
const leftPart = isColorEnabled
|
|
261
|
-
? ' ' + chalk.hex(LIGHT_ORANGE).bold(displayId) +
|
|
262
|
-
(hint ? ' ' + chalk.dim(hint) : '')
|
|
252
|
+
? ' ' + chalk.hex(LIGHT_ORANGE).bold(displayId) + (hint ? ' ' + chalk.dim(hint) : '')
|
|
263
253
|
: rawLeft
|
|
264
254
|
|
|
265
255
|
lines.push(leftPart + pad + chalk.dim(desc))
|
|
@@ -270,8 +260,8 @@ export default class CustomHelp extends Help {
|
|
|
270
260
|
|
|
271
261
|
// ── Flag globali ───────────────────────────────────────────────────────
|
|
272
262
|
lines.push(this.#sectionHeader('GLOBAL FLAGS'))
|
|
273
|
-
lines.push(this.#flagLine('-h, --help',
|
|
274
|
-
lines.push(this.#flagLine(' --json',
|
|
263
|
+
lines.push(this.#flagLine('-h, --help', 'Mostra aiuto per un comando'))
|
|
264
|
+
lines.push(this.#flagLine(' --json', 'Output in formato JSON strutturato'))
|
|
275
265
|
lines.push(this.#flagLine('-v, --version', 'Versione installata'))
|
|
276
266
|
lines.push('')
|
|
277
267
|
|
|
@@ -281,39 +271,49 @@ export default class CustomHelp extends Help {
|
|
|
281
271
|
const maxCmdLen = Math.max(...EXAMPLES.map((e) => e.cmd.length))
|
|
282
272
|
for (const ex of EXAMPLES) {
|
|
283
273
|
const pad = ' '.repeat(maxCmdLen - ex.cmd.length + 4)
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
274
|
+
const sub = ex.cmd.replace(/^dvmi /, '')
|
|
275
|
+
const formatted = isColorEnabled
|
|
276
|
+
? chalk.dim('$') +
|
|
277
|
+
' ' +
|
|
278
|
+
chalk.hex(ORANGE).bold('dvmi') +
|
|
279
|
+
' ' +
|
|
280
|
+
chalk.white(sub) +
|
|
281
|
+
pad +
|
|
282
|
+
chalk.hex(DIM_GRAY)(ex.note)
|
|
283
|
+
: '$ ' + ex.cmd + pad + ex.note
|
|
289
284
|
lines.push(' ' + formatted)
|
|
290
285
|
}
|
|
291
286
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
287
|
+
lines.push('')
|
|
288
|
+
|
|
289
|
+
// ── Versione + update notice ───────────────────────────────────────────
|
|
290
|
+
const current = versionInfo?.current ?? this.config.version
|
|
291
|
+
const versionStr = isColorEnabled ? chalk.dim('version ') + chalk.hex(DIM_BLUE)(current) : `version ${current}`
|
|
292
|
+
|
|
293
|
+
if (versionInfo?.hasUpdate && versionInfo.latest) {
|
|
294
|
+
const updateStr = isColorEnabled
|
|
295
|
+
? chalk.yellow('update disponibile: ') +
|
|
296
|
+
chalk.dim(current) +
|
|
297
|
+
chalk.yellow(' → ') +
|
|
298
|
+
chalk.green(versionInfo.latest) +
|
|
299
|
+
chalk.dim(' (esegui ') +
|
|
300
|
+
chalk.hex(LIGHT_ORANGE)('dvmi upgrade') +
|
|
301
|
+
chalk.dim(')')
|
|
302
|
+
: `update disponibile: ${current} → ${versionInfo.latest} (esegui dvmi upgrade)`
|
|
303
|
+
lines.push(' ' + versionStr + chalk.dim(' · ') + updateStr)
|
|
304
|
+
} else {
|
|
305
|
+
lines.push(' ' + versionStr)
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
lines.push(
|
|
309
|
+
' ' +
|
|
310
|
+
chalk.dim('Approfondisci:') +
|
|
311
|
+
' ' +
|
|
312
|
+
chalk.hex(DIM_BLUE)('dvmi <COMANDO> --help') +
|
|
313
|
+
chalk.dim(' · ') +
|
|
314
|
+
chalk.hex(DIM_BLUE)('dvmi <TOPIC> --help') +
|
|
315
|
+
'\n',
|
|
316
|
+
)
|
|
317
317
|
|
|
318
318
|
return lines.join('\n')
|
|
319
319
|
}
|
|
@@ -379,12 +379,10 @@ export default class CustomHelp extends Help {
|
|
|
379
379
|
const plain = strip(line)
|
|
380
380
|
if (!plain.trim()) return line
|
|
381
381
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
)
|
|
387
|
-
}
|
|
382
|
+
// Example lines: "$ dvmi …"
|
|
383
|
+
if (plain.includes('$ dvmi') || plain.trim().startsWith('$ dvmi')) {
|
|
384
|
+
return plain.replace(/\$ (dvmi\S*)/g, (_, cmd) => '$ ' + chalk.hex(ORANGE).bold(cmd))
|
|
385
|
+
}
|
|
388
386
|
|
|
389
387
|
// Flag rows: "--flag desc" or "-f, --flag desc"
|
|
390
388
|
const flagMatch = plain.match(/^(\s{2,})((?:-\w,\s*)?--[\w-]+)(\s+)(.*)$/)
|
package/src/hooks/init.js
CHANGED
|
@@ -3,7 +3,5 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const init = async () => {
|
|
5
5
|
// Fire-and-forget version check — result used by postrun hook
|
|
6
|
-
import('../services/version-check.js')
|
|
7
|
-
.then(({ checkForUpdate }) => checkForUpdate())
|
|
8
|
-
.catch(() => null) // never block command execution
|
|
6
|
+
import('../services/version-check.js').then(({checkForUpdate}) => checkForUpdate()).catch(() => null) // never block command execution
|
|
9
7
|
}
|
package/src/hooks/postrun.js
CHANGED
|
@@ -5,13 +5,11 @@ import chalk from 'chalk'
|
|
|
5
5
|
*/
|
|
6
6
|
export const postrun = async () => {
|
|
7
7
|
try {
|
|
8
|
-
const {
|
|
9
|
-
const {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
)
|
|
14
|
-
}
|
|
8
|
+
const {checkForUpdate} = await import('../services/version-check.js')
|
|
9
|
+
const {hasUpdate, current, latest} = await checkForUpdate()
|
|
10
|
+
if (hasUpdate && latest) {
|
|
11
|
+
process.stderr.write(chalk.dim(`\nUpdate available: ${current} → ${chalk.green(latest)}. Run \`dvmi upgrade\`\n`))
|
|
12
|
+
}
|
|
15
13
|
} catch {
|
|
16
14
|
// Never interrupt user flow
|
|
17
15
|
}
|
package/src/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {run} from '@oclif/core'
|