@neetru/cli 2.2.0 → 2.4.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/dist/commands/ai.js +82 -10
- package/dist/commands/ai.js.map +1 -1
- package/dist/commands/auth.d.ts +19 -0
- package/dist/commands/auth.js +203 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/deploy.js +8 -8
- package/dist/commands/deployments.d.ts +5 -5
- package/dist/commands/deployments.js +32 -6
- package/dist/commands/deployments.js.map +1 -1
- package/dist/commands/products-db.d.ts +9 -9
- package/dist/commands/products-db.js +84 -19
- package/dist/commands/products-db.js.map +1 -1
- package/dist/commands/products.d.ts +2 -2
- package/dist/commands/products.js +8 -6
- package/dist/commands/products.js.map +1 -1
- package/dist/commands/schema.d.ts +25 -0
- package/dist/commands/schema.js +321 -0
- package/dist/commands/schema.js.map +1 -0
- package/dist/commands/servers.d.ts +5 -5
- package/dist/commands/servers.js +25 -17
- package/dist/commands/servers.js.map +1 -1
- package/dist/commands/status.js +3 -2
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/tenants.d.ts +14 -14
- package/dist/commands/tenants.js +62 -30
- package/dist/commands/tenants.js.map +1 -1
- package/dist/commands/ui.d.ts +1 -0
- package/dist/commands/ui.js +454 -0
- package/dist/commands/ui.js.map +1 -0
- package/dist/commands/workspaces.d.ts +9 -9
- package/dist/commands/workspaces.js +66 -31
- package/dist/commands/workspaces.js.map +1 -1
- package/dist/index.js +226 -165
- package/dist/index.js.map +1 -1
- package/dist/lib/ai/auth-discovery.d.ts +26 -0
- package/dist/lib/ai/auth-discovery.js +256 -0
- package/dist/lib/ai/auth-discovery.js.map +1 -0
- package/dist/lib/ai/orchestrator.d.ts +25 -0
- package/dist/lib/ai/orchestrator.js +190 -28
- package/dist/lib/ai/orchestrator.js.map +1 -1
- package/dist/lib/config-schema.d.ts +18 -18
- package/dist/lib/pickers.d.ts +123 -0
- package/dist/lib/pickers.js +336 -0
- package/dist/lib/pickers.js.map +1 -0
- package/dist/lib/schema-cache.d.ts +87 -0
- package/dist/lib/schema-cache.js +134 -0
- package/dist/lib/schema-cache.js.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,22 +5,30 @@ import { CLI_VERSION } from './version.js';
|
|
|
5
5
|
const program = new Command();
|
|
6
6
|
program
|
|
7
7
|
.name('neetru')
|
|
8
|
-
.description('Neetru Developer Kit
|
|
8
|
+
.description('Operar o Neetru Developer Kit (scaffold, AI, deploy)')
|
|
9
9
|
.version(CLI_VERSION);
|
|
10
10
|
// ── neetru ai ─────────────────────────────────────────────────────────
|
|
11
11
|
program
|
|
12
12
|
.command('ai')
|
|
13
|
-
.description('REPL
|
|
13
|
+
.description('Abrir REPL de IA Neetru-aware (Claude/OpenAI/Gemini)')
|
|
14
14
|
.option('-m, --model <model>', 'modelo: claude | openai | gemini | auto', 'auto')
|
|
15
15
|
.action(async (opts) => {
|
|
16
16
|
const { runAiRepl } = await import('./commands/ai.js');
|
|
17
17
|
await runAiRepl({ model: opts.model });
|
|
18
18
|
});
|
|
19
|
+
program
|
|
20
|
+
.command('ui')
|
|
21
|
+
.alias('menu')
|
|
22
|
+
.description('Abrir a interface interativa do Neetru CLI')
|
|
23
|
+
.action(async () => {
|
|
24
|
+
const { runTerminalUi } = await import('./commands/ui.js');
|
|
25
|
+
await runTerminalUi();
|
|
26
|
+
});
|
|
19
27
|
// ── neetru init ───────────────────────────────────────────────────────
|
|
20
28
|
// v2.1.1 — prompt interativo de caminho + merge mode + preserva arquivos
|
|
21
29
|
program
|
|
22
30
|
.command('init <name>')
|
|
23
|
-
.description('
|
|
31
|
+
.description('Inicializar scaffold de produto SaaS Neetru')
|
|
24
32
|
.option('--type <type>', 'nextjs | node-api', 'nextjs')
|
|
25
33
|
.option('--here', 'init no cwd atual (modo merge — preserva existentes)')
|
|
26
34
|
.option('--path <path>', 'custom path target')
|
|
@@ -41,7 +49,7 @@ program
|
|
|
41
49
|
// Cria produto + workspace + scaffold local + abre painel — single command.
|
|
42
50
|
program
|
|
43
51
|
.command('new <name>')
|
|
44
|
-
.description('
|
|
52
|
+
.description('Criar produto, workspace, scaffold e abrir painel')
|
|
45
53
|
.option('--product-slug <slug>', 'slug do produto (default: derivado de <name>)')
|
|
46
54
|
.option('--env <env>', 'dev (default) | staging | prod', 'dev')
|
|
47
55
|
.option('--tier <tier>', 'standard (default) | dev | enterprise', 'standard')
|
|
@@ -61,27 +69,56 @@ program
|
|
|
61
69
|
json: !!opts.json,
|
|
62
70
|
});
|
|
63
71
|
});
|
|
72
|
+
// ── neetru auth ───────────────────────────────────────────────────────
|
|
73
|
+
// Wave D — detecta Claude Code/Codex/Gemini instalados e reaproveita creds.
|
|
74
|
+
const authCmd = program
|
|
75
|
+
.command('auth')
|
|
76
|
+
.description('Gerenciar credenciais de IA (Claude, Codex, Gemini)');
|
|
77
|
+
authCmd
|
|
78
|
+
.command('status')
|
|
79
|
+
.description('Listar provedores detectados e estado das credenciais')
|
|
80
|
+
.option('--json', 'saída JSON')
|
|
81
|
+
.action(async (opts) => {
|
|
82
|
+
const { runAuthStatus } = await import('./commands/auth.js');
|
|
83
|
+
await runAuthStatus({ json: !!opts.json });
|
|
84
|
+
});
|
|
85
|
+
authCmd
|
|
86
|
+
.command('setup')
|
|
87
|
+
.description('Wizard interativo: detectar, instalar, configurar')
|
|
88
|
+
.option('--json', 'modo não-interativo (equivalente a pull)')
|
|
89
|
+
.action(async (opts) => {
|
|
90
|
+
const { runAuthSetup } = await import('./commands/auth.js');
|
|
91
|
+
await runAuthSetup({ json: !!opts.json });
|
|
92
|
+
});
|
|
93
|
+
authCmd
|
|
94
|
+
.command('pull')
|
|
95
|
+
.description('Copiar creds dos CLIs detectados pra config do Neetru')
|
|
96
|
+
.option('--json', 'saída JSON')
|
|
97
|
+
.action(async (opts) => {
|
|
98
|
+
const { runAuthPull } = await import('./commands/auth.js');
|
|
99
|
+
await runAuthPull({ json: !!opts.json });
|
|
100
|
+
});
|
|
64
101
|
// ── neetru config ─────────────────────────────────────────────────────
|
|
65
102
|
const configCmd = program
|
|
66
103
|
.command('config')
|
|
67
|
-
.description('Gerenciar configurações do CLI
|
|
104
|
+
.description('Gerenciar configurações do CLI');
|
|
68
105
|
configCmd
|
|
69
106
|
.command('set <key> <value>')
|
|
70
|
-
.description('
|
|
107
|
+
.description('Definir valor de configuração')
|
|
71
108
|
.action(async (key, value) => {
|
|
72
109
|
const { configSet } = await import('./commands/config.js');
|
|
73
110
|
configSet(key, value);
|
|
74
111
|
});
|
|
75
112
|
configCmd
|
|
76
113
|
.command('get [key]')
|
|
77
|
-
.description('
|
|
114
|
+
.description('Ler configuração por chave (ou todas)')
|
|
78
115
|
.action(async (key) => {
|
|
79
116
|
const { configGet } = await import('./commands/config.js');
|
|
80
117
|
configGet(key);
|
|
81
118
|
});
|
|
82
119
|
configCmd
|
|
83
120
|
.command('path')
|
|
84
|
-
.description('
|
|
121
|
+
.description('Mostrar caminho do arquivo de configuração')
|
|
85
122
|
.action(async () => {
|
|
86
123
|
const { configPath } = await import('./commands/config.js');
|
|
87
124
|
configPath();
|
|
@@ -89,7 +126,7 @@ configCmd
|
|
|
89
126
|
// ── neetru login ──────────────────────────────────────────────────────
|
|
90
127
|
program
|
|
91
128
|
.command('login')
|
|
92
|
-
.description('
|
|
129
|
+
.description('Autenticar CLI via Device Code OAuth (RFC 8628)')
|
|
93
130
|
.option('--token <token>', 'token nrt_<keyId>_<secret> (modo CI/legado, pula browser)')
|
|
94
131
|
.option('--json', 'saída em JSON (machine-readable)')
|
|
95
132
|
.action(async (opts) => {
|
|
@@ -99,7 +136,7 @@ program
|
|
|
99
136
|
// ── neetru logout ─────────────────────────────────────────────────────
|
|
100
137
|
program
|
|
101
138
|
.command('logout')
|
|
102
|
-
.description('
|
|
139
|
+
.description('Remover credenciais locais do CLI')
|
|
103
140
|
.action(async () => {
|
|
104
141
|
const { runLogout } = await import('./commands/logout.js');
|
|
105
142
|
await runLogout();
|
|
@@ -107,7 +144,7 @@ program
|
|
|
107
144
|
// ── neetru whoami ─────────────────────────────────────────────────────
|
|
108
145
|
program
|
|
109
146
|
.command('whoami')
|
|
110
|
-
.description('
|
|
147
|
+
.description('Mostrar identidade da chave CLI corrente')
|
|
111
148
|
.option('--json', 'saída em JSON')
|
|
112
149
|
.action(async (opts) => {
|
|
113
150
|
const { runWhoami } = await import('./commands/whoami.js');
|
|
@@ -116,7 +153,7 @@ program
|
|
|
116
153
|
// ── neetru build ──────────────────────────────────────────────────────
|
|
117
154
|
program
|
|
118
155
|
.command('build')
|
|
119
|
-
.description('
|
|
156
|
+
.description('Construir tarball do produto pronto para deploy')
|
|
120
157
|
.option('--product <slug>', 'override do slug (default: lê neetru.config.json)')
|
|
121
158
|
.option('--stack <stack>', 'node | docker | php-apache | static (default: detectado)')
|
|
122
159
|
.option('--output <dir>', 'diretório de saída', '.neetru-build')
|
|
@@ -135,7 +172,7 @@ program
|
|
|
135
172
|
// ── neetru deploy ─────────────────────────────────────────────────────
|
|
136
173
|
program
|
|
137
174
|
.command('deploy')
|
|
138
|
-
.description('
|
|
175
|
+
.description('Deployar produto via pipeline do Neetru Core')
|
|
139
176
|
.option('--product <slug>', 'slug do produto')
|
|
140
177
|
.option('--version <version>', 'versão a deployar')
|
|
141
178
|
.option('--stack <stack>', 'node | docker | php-apache | static')
|
|
@@ -174,7 +211,7 @@ program
|
|
|
174
211
|
// delega ao status de workspace legado (backward-compat).
|
|
175
212
|
program
|
|
176
213
|
.command('status')
|
|
177
|
-
.description('
|
|
214
|
+
.description('Verificar saúde das superfícies públicas do Core')
|
|
178
215
|
.option('--client-id <id>', 'oauthClientId do workspace (status de workspace legado)')
|
|
179
216
|
.option('--json', 'saída em JSON')
|
|
180
217
|
.action(async (opts) => {
|
|
@@ -184,10 +221,10 @@ program
|
|
|
184
221
|
// ── neetru tenants ────────────────────────────────────────────────────
|
|
185
222
|
const tenantsCmd = program
|
|
186
223
|
.command('tenants')
|
|
187
|
-
.description('
|
|
224
|
+
.description('Gerenciar tenants (read-only)');
|
|
188
225
|
tenantsCmd
|
|
189
226
|
.command('list')
|
|
190
|
-
.description('
|
|
227
|
+
.description('Listar tenants')
|
|
191
228
|
.option('--status <status>', 'ativo | em provisionamento | suspenso | arquivado')
|
|
192
229
|
.option('--product <productId>', 'filtra por productId')
|
|
193
230
|
.option('--limit <n>', 'máximo de resultados (default 100, max 500)')
|
|
@@ -202,8 +239,8 @@ tenantsCmd
|
|
|
202
239
|
});
|
|
203
240
|
});
|
|
204
241
|
tenantsCmd
|
|
205
|
-
.command('get
|
|
206
|
-
.description('
|
|
242
|
+
.command('get [id]')
|
|
243
|
+
.description('Mostrar detalhes de um tenant')
|
|
207
244
|
.option('--json', 'saída em JSON')
|
|
208
245
|
.action(async (id, opts) => {
|
|
209
246
|
const { runTenantsGet } = await import('./commands/tenants.js');
|
|
@@ -211,12 +248,12 @@ tenantsCmd
|
|
|
211
248
|
});
|
|
212
249
|
tenantsCmd
|
|
213
250
|
.command('create')
|
|
214
|
-
.description('
|
|
215
|
-
.
|
|
216
|
-
.
|
|
217
|
-
.
|
|
218
|
-
.
|
|
219
|
-
.
|
|
251
|
+
.description('Criar tenant (status inicial: em provisionamento)')
|
|
252
|
+
.option('--name <name>', 'nome do tenant')
|
|
253
|
+
.option('--slug <slug>', 'slug do tenant')
|
|
254
|
+
.option('--customer <customerId>', 'id do customer')
|
|
255
|
+
.option('--product <productId>', 'id do produto (interativo se ausente)')
|
|
256
|
+
.option('--env <env>', 'dev | staging | prod (default: dev)')
|
|
220
257
|
.option('--domain <domain>', 'domínio primário')
|
|
221
258
|
.option('--json', 'saída em JSON')
|
|
222
259
|
.action(async (opts) => {
|
|
@@ -232,13 +269,13 @@ tenantsCmd
|
|
|
232
269
|
});
|
|
233
270
|
});
|
|
234
271
|
tenantsCmd
|
|
235
|
-
.command('update
|
|
236
|
-
.description('
|
|
237
|
-
.
|
|
238
|
-
.
|
|
239
|
-
.
|
|
240
|
-
.
|
|
241
|
-
.
|
|
272
|
+
.command('update [id]')
|
|
273
|
+
.description('Atualizar dados de um tenant')
|
|
274
|
+
.option('--name <name>', 'nome do tenant')
|
|
275
|
+
.option('--slug <slug>', 'slug do tenant')
|
|
276
|
+
.option('--customer <customerId>', 'id do customer')
|
|
277
|
+
.option('--product <productId>', 'id do produto (interativo se ausente)')
|
|
278
|
+
.option('--env <env>', 'dev | staging | prod (default: dev)')
|
|
242
279
|
.option('--domain <domain>', 'domínio primário')
|
|
243
280
|
.option('--json', 'saída em JSON')
|
|
244
281
|
.action(async (id, opts) => {
|
|
@@ -254,8 +291,8 @@ tenantsCmd
|
|
|
254
291
|
});
|
|
255
292
|
});
|
|
256
293
|
tenantsCmd
|
|
257
|
-
.command('suspend
|
|
258
|
-
.description('
|
|
294
|
+
.command('suspend [id]')
|
|
295
|
+
.description('Suspender tenant (destrutivo — exige confirmação)')
|
|
259
296
|
.option('--yes', 'pula a confirmação interativa (modo script)')
|
|
260
297
|
.option('--force', 'alias de --yes')
|
|
261
298
|
.option('--json', 'saída em JSON')
|
|
@@ -264,8 +301,8 @@ tenantsCmd
|
|
|
264
301
|
await runTenantsSuspend(id, { yes: !!opts.yes, force: !!opts.force, json: !!opts.json });
|
|
265
302
|
});
|
|
266
303
|
tenantsCmd
|
|
267
|
-
.command('reactivate
|
|
268
|
-
.description('
|
|
304
|
+
.command('reactivate [id]')
|
|
305
|
+
.description('Reativar tenant suspenso')
|
|
269
306
|
.option('--json', 'saída em JSON')
|
|
270
307
|
.action(async (id, opts) => {
|
|
271
308
|
const { runTenantsReactivate } = await import('./commands/tenants.js');
|
|
@@ -274,10 +311,10 @@ tenantsCmd
|
|
|
274
311
|
// ── neetru audit ──────────────────────────────────────────────────────
|
|
275
312
|
const auditCmd = program
|
|
276
313
|
.command('audit')
|
|
277
|
-
.description('
|
|
314
|
+
.description('Consultar trilha de auditoria do Core (read-only)');
|
|
278
315
|
auditCmd
|
|
279
316
|
.command('tail')
|
|
280
|
-
.description('
|
|
317
|
+
.description('Listar últimos eventos de audit_logs')
|
|
281
318
|
.option('-n, --limit <n>', 'número de eventos (default 50, max 200)')
|
|
282
319
|
.option('--action <substring>', 'filtra por substring da ação (ex: billing, tenant.create)')
|
|
283
320
|
.option('--severity <level>', 'info | warning | critical')
|
|
@@ -296,10 +333,10 @@ auditCmd
|
|
|
296
333
|
// ── neetru billing ────────────────────────────────────────────────────
|
|
297
334
|
const billingCmd = program
|
|
298
335
|
.command('billing')
|
|
299
|
-
.description('
|
|
336
|
+
.description('Consultar billing e contabilidade (read-only)');
|
|
300
337
|
billingCmd
|
|
301
338
|
.command('summary')
|
|
302
|
-
.description('
|
|
339
|
+
.description('Mostrar sumário contábil do mês (MRR, invoices, subs)')
|
|
303
340
|
.option('--year <YYYY>', 'ano (default: corrente)')
|
|
304
341
|
.option('--month <1-12>', 'mês (default: corrente)')
|
|
305
342
|
.option('--json', 'saída em JSON')
|
|
@@ -310,18 +347,24 @@ billingCmd
|
|
|
310
347
|
// ── neetru servers ────────────────────────────────────────────────────
|
|
311
348
|
const serversCmd = program
|
|
312
349
|
.command('servers')
|
|
313
|
-
.description('
|
|
350
|
+
.description('Gerenciar servers e inventário de VMs');
|
|
314
351
|
serversCmd
|
|
315
352
|
.command('list')
|
|
316
|
-
.description('
|
|
317
|
-
.option('--status <status>', 'online
|
|
353
|
+
.description('Listar servers')
|
|
354
|
+
.option('--status <status>', 'online | operacional (ativo) ou offline | desconectado (inativo)')
|
|
318
355
|
.option('--provider <provider>', 'hetzner | digitalocean | aws | ...')
|
|
319
356
|
.option('--capacity', 'inclui colunas de RAM/CPU/disco')
|
|
320
357
|
.option('--json', 'saída em JSON')
|
|
321
358
|
.action(async (opts) => {
|
|
359
|
+
const STATUS_ALIASES = {
|
|
360
|
+
operacional: 'online',
|
|
361
|
+
desconectado: 'offline',
|
|
362
|
+
};
|
|
363
|
+
const rawStatus = opts.status;
|
|
364
|
+
const resolvedStatus = rawStatus ? (STATUS_ALIASES[rawStatus] ?? rawStatus) : undefined;
|
|
322
365
|
const { runServersList } = await import('./commands/servers.js');
|
|
323
366
|
await runServersList({
|
|
324
|
-
status:
|
|
367
|
+
status: resolvedStatus,
|
|
325
368
|
provider: opts.provider,
|
|
326
369
|
capacity: !!opts.capacity,
|
|
327
370
|
json: !!opts.json,
|
|
@@ -329,10 +372,10 @@ serversCmd
|
|
|
329
372
|
});
|
|
330
373
|
serversCmd
|
|
331
374
|
.command('provision')
|
|
332
|
-
.description('
|
|
333
|
-
.
|
|
334
|
-
.
|
|
335
|
-
.
|
|
375
|
+
.description('Provisionar VM GCP e gerar registration token (admin)')
|
|
376
|
+
.option('--name <name>', 'nome do servidor')
|
|
377
|
+
.option('--zone <zone>', 'zona GCP (ex: us-central1-a)')
|
|
378
|
+
.option('--machine-type <type>', 'machine type GCP (ex: e2-small)')
|
|
336
379
|
.option('--tenant <tenantId>', 'tenant associado')
|
|
337
380
|
.option('--customer <customerId>', 'customer associado')
|
|
338
381
|
.option('--json', 'saída em JSON')
|
|
@@ -348,8 +391,8 @@ serversCmd
|
|
|
348
391
|
});
|
|
349
392
|
});
|
|
350
393
|
serversCmd
|
|
351
|
-
.command('deactivate
|
|
352
|
-
.description('
|
|
394
|
+
.command('deactivate [serverId]')
|
|
395
|
+
.description('Desativar server (destrutivo top-tier — exige MFA)')
|
|
353
396
|
.option('--yes', 'pula a confirmação interativa (modo script)')
|
|
354
397
|
.option('--force', 'alias de --yes')
|
|
355
398
|
.option('--dry-run', 'valida e mostra o efeito sem aplicar')
|
|
@@ -366,8 +409,8 @@ serversCmd
|
|
|
366
409
|
});
|
|
367
410
|
});
|
|
368
411
|
serversCmd
|
|
369
|
-
.command('dispatch
|
|
370
|
-
.description('
|
|
412
|
+
.command('dispatch [serverId] [commandType]')
|
|
413
|
+
.description('Enfileirar comando para o agente Linux do server')
|
|
371
414
|
.option('--params <json>', 'objeto JSON de params do comando')
|
|
372
415
|
.option('--json', 'saída em JSON')
|
|
373
416
|
.action(async (id, commandType, opts) => {
|
|
@@ -377,14 +420,14 @@ serversCmd
|
|
|
377
420
|
// ── neetru workspaces ─────────────────────────────────────────────────
|
|
378
421
|
const workspacesCmd = program
|
|
379
422
|
.command('workspaces')
|
|
380
|
-
.description('
|
|
423
|
+
.description('Gerenciar workspaces compartilhados');
|
|
381
424
|
workspacesCmd
|
|
382
425
|
.command('create')
|
|
383
|
-
.description('
|
|
384
|
-
.
|
|
385
|
-
.
|
|
386
|
-
.
|
|
387
|
-
.
|
|
426
|
+
.description('Criar workspace (retorna OAuth secret one-time)')
|
|
427
|
+
.option('--product <productId>', 'id do produto (interativo se ausente)')
|
|
428
|
+
.option('--customer <customerId>', 'id do customer (default: self/Neetru)')
|
|
429
|
+
.option('--env <env>', 'dev | staging | prod (default: dev)')
|
|
430
|
+
.option('--tier <tier>', 'dev | standard | enterprise (default: standard)')
|
|
388
431
|
.option('--name <name>', 'label do workspace')
|
|
389
432
|
.option('--json', 'saída em JSON')
|
|
390
433
|
.action(async (opts) => {
|
|
@@ -399,10 +442,10 @@ workspacesCmd
|
|
|
399
442
|
});
|
|
400
443
|
});
|
|
401
444
|
workspacesCmd
|
|
402
|
-
.command('advance
|
|
403
|
-
.description('
|
|
404
|
-
.
|
|
405
|
-
.
|
|
445
|
+
.command('advance [workspaceId]')
|
|
446
|
+
.description('Promover versão de bundle para running no workspace')
|
|
447
|
+
.option('--product <slug>', 'productSlug do bundle (interativo se ausente)')
|
|
448
|
+
.option('--version <version>', 'versão do bundle a ativar')
|
|
406
449
|
.option('--json', 'saída em JSON')
|
|
407
450
|
.action(async (id, opts) => {
|
|
408
451
|
const { runWorkspacesAdvance } = await import('./commands/workspaces.js');
|
|
@@ -414,7 +457,7 @@ workspacesCmd
|
|
|
414
457
|
});
|
|
415
458
|
workspacesCmd
|
|
416
459
|
.command('list')
|
|
417
|
-
.description('
|
|
460
|
+
.description('Listar workspaces')
|
|
418
461
|
.option('--product <productId>', 'filtra por productId')
|
|
419
462
|
.option('--env <env>', 'dev | staging | prod')
|
|
420
463
|
.option('--status <status>', 'active | paused | provisioning | …')
|
|
@@ -429,16 +472,16 @@ workspacesCmd
|
|
|
429
472
|
});
|
|
430
473
|
});
|
|
431
474
|
workspacesCmd
|
|
432
|
-
.command('get
|
|
433
|
-
.description('
|
|
475
|
+
.command('get [workspaceId]')
|
|
476
|
+
.description('Mostrar detalhes de um workspace')
|
|
434
477
|
.option('--json', 'saída em JSON')
|
|
435
478
|
.action(async (id, opts) => {
|
|
436
479
|
const { runWorkspacesGet } = await import('./commands/workspaces.js');
|
|
437
480
|
await runWorkspacesGet(id, { json: !!opts.json });
|
|
438
481
|
});
|
|
439
482
|
workspacesCmd
|
|
440
|
-
.command('open
|
|
441
|
-
.description('
|
|
483
|
+
.command('open [workspaceId]')
|
|
484
|
+
.description('Abrir painel do workspace no browser')
|
|
442
485
|
.action(async (id) => {
|
|
443
486
|
const { runWorkspacesOpen } = await import('./commands/workspaces.js');
|
|
444
487
|
await runWorkspacesOpen(id);
|
|
@@ -446,15 +489,15 @@ workspacesCmd
|
|
|
446
489
|
// ── neetru deployments ────────────────────────────────────────────────
|
|
447
490
|
const deploymentsCmd = program
|
|
448
491
|
.command('deployments')
|
|
449
|
-
.description('
|
|
492
|
+
.description('Gerenciar deployments do Core');
|
|
450
493
|
deploymentsCmd
|
|
451
494
|
.command('create')
|
|
452
|
-
.description('
|
|
453
|
-
.
|
|
454
|
-
.
|
|
455
|
-
.
|
|
456
|
-
.
|
|
457
|
-
.
|
|
495
|
+
.description('Criar deployment (dispara comando para o agente)')
|
|
496
|
+
.option('--product <productId>', 'id do produto (interativo se ausente)')
|
|
497
|
+
.option('--tenant <tenantId>', 'id do tenant alvo (interativo se ausente)')
|
|
498
|
+
.option('--version <version>', 'versao a deployar')
|
|
499
|
+
.option('--env <env>', 'dev | staging | prod (default: dev)')
|
|
500
|
+
.option('--server <serverId>', 'id do server alvo (interativo se ausente)')
|
|
458
501
|
.option('--json', 'saída em JSON')
|
|
459
502
|
.action(async (opts) => {
|
|
460
503
|
const { runDeploymentsCreate } = await import('./commands/deployments.js');
|
|
@@ -469,7 +512,7 @@ deploymentsCmd
|
|
|
469
512
|
});
|
|
470
513
|
deploymentsCmd
|
|
471
514
|
.command('rollback <deploymentId>')
|
|
472
|
-
.description('
|
|
515
|
+
.description('Reverter deployment (destrutivo top-tier — exige MFA)')
|
|
473
516
|
.option('--yes', 'pula a confirmação interativa (modo script)')
|
|
474
517
|
.option('--force', 'alias de --yes')
|
|
475
518
|
.option('--dry-run', 'valida e mostra o efeito sem aplicar')
|
|
@@ -488,10 +531,10 @@ deploymentsCmd
|
|
|
488
531
|
// ── neetru cloud-run ──────────────────────────────────────────────────
|
|
489
532
|
const cloudRunCmd = program
|
|
490
533
|
.command('cloud-run')
|
|
491
|
-
.description('
|
|
534
|
+
.description('Gerenciar serviços Cloud Run (admin)');
|
|
492
535
|
cloudRunCmd
|
|
493
536
|
.command('pause <service>')
|
|
494
|
-
.description('
|
|
537
|
+
.description('Pausar serviço Cloud Run (scale-to-zero)')
|
|
495
538
|
.option('--json', 'saída em JSON')
|
|
496
539
|
.action(async (service, opts) => {
|
|
497
540
|
const { runCloudRunPause } = await import('./commands/cloud-run.js');
|
|
@@ -499,7 +542,7 @@ cloudRunCmd
|
|
|
499
542
|
});
|
|
500
543
|
cloudRunCmd
|
|
501
544
|
.command('resume <service>')
|
|
502
|
-
.description('
|
|
545
|
+
.description('Retomar serviço Cloud Run pausado')
|
|
503
546
|
.option('--min-instances <n>', 'minInstanceCount')
|
|
504
547
|
.option('--max-instances <n>', 'maxInstanceCount')
|
|
505
548
|
.option('--json', 'saída em JSON')
|
|
@@ -513,7 +556,7 @@ cloudRunCmd
|
|
|
513
556
|
});
|
|
514
557
|
cloudRunCmd
|
|
515
558
|
.command('delete <service>')
|
|
516
|
-
.description('
|
|
559
|
+
.description('Remover serviço Cloud Run (IRREVERSÍVEL — exige MFA)')
|
|
517
560
|
.option('--yes', 'pula a confirmação interativa (modo script)')
|
|
518
561
|
.option('--force', 'alias de --yes')
|
|
519
562
|
.option('--dry-run', 'valida e mostra o efeito sem aplicar')
|
|
@@ -532,10 +575,10 @@ cloudRunCmd
|
|
|
532
575
|
// ── neetru api-catalog ────────────────────────────────────────────────
|
|
533
576
|
const apiCatalogCmd = program
|
|
534
577
|
.command('api-catalog')
|
|
535
|
-
.description('
|
|
578
|
+
.description('Gerenciar catálogo de APIs versionadas');
|
|
536
579
|
apiCatalogCmd
|
|
537
580
|
.command('create <slug>')
|
|
538
|
-
.description('
|
|
581
|
+
.description('Registrar nova API no catálogo')
|
|
539
582
|
.requiredOption('--name <name>', 'nome da API')
|
|
540
583
|
.requiredOption('--base-url <url>', 'base URL')
|
|
541
584
|
.requiredOption('--version <version>', 'versão')
|
|
@@ -565,7 +608,7 @@ apiCatalogCmd
|
|
|
565
608
|
});
|
|
566
609
|
apiCatalogCmd
|
|
567
610
|
.command('update <slug>')
|
|
568
|
-
.description('
|
|
611
|
+
.description('Atualizar entrada do catálogo (slug imutável)')
|
|
569
612
|
.requiredOption('--name <name>', 'nome da API')
|
|
570
613
|
.requiredOption('--base-url <url>', 'base URL')
|
|
571
614
|
.requiredOption('--version <version>', 'versão')
|
|
@@ -595,7 +638,7 @@ apiCatalogCmd
|
|
|
595
638
|
});
|
|
596
639
|
apiCatalogCmd
|
|
597
640
|
.command('archive <slug>')
|
|
598
|
-
.description('
|
|
641
|
+
.description('Arquivar API por soft-delete (--unarchive reverte)')
|
|
599
642
|
.option('--unarchive', 'reativa em vez de arquivar')
|
|
600
643
|
.option('--yes', 'pula a confirmação interativa (modo script)')
|
|
601
644
|
.option('--force', 'alias de --yes')
|
|
@@ -611,7 +654,7 @@ apiCatalogCmd
|
|
|
611
654
|
});
|
|
612
655
|
apiCatalogCmd
|
|
613
656
|
.command('delete <slug>')
|
|
614
|
-
.description('
|
|
657
|
+
.description('Remover API fisicamente (IRREVERSÍVEL — exige MFA)')
|
|
615
658
|
.option('--yes', 'pula a confirmação interativa (modo script)')
|
|
616
659
|
.option('--force', 'alias de --yes')
|
|
617
660
|
.option('--dry-run', 'valida e mostra o efeito sem aplicar')
|
|
@@ -630,10 +673,10 @@ apiCatalogCmd
|
|
|
630
673
|
// ── neetru products ───────────────────────────────────────────────────
|
|
631
674
|
const productsCmd = program
|
|
632
675
|
.command('products')
|
|
633
|
-
.description('
|
|
676
|
+
.description('Gerenciar registry de produtos SaaS internos');
|
|
634
677
|
productsCmd
|
|
635
678
|
.command('list')
|
|
636
|
-
.description('
|
|
679
|
+
.description('Listar produtos internos')
|
|
637
680
|
.option('--status <status>', 'ativo | beta | descontinuado')
|
|
638
681
|
.option('--limit <n>', 'máximo de resultados (default 100, max 500)')
|
|
639
682
|
.option('--json', 'saída em JSON')
|
|
@@ -643,7 +686,7 @@ productsCmd
|
|
|
643
686
|
});
|
|
644
687
|
productsCmd
|
|
645
688
|
.command('create')
|
|
646
|
-
.description('
|
|
689
|
+
.description('Criar produto SaaS interno (interativo por default)')
|
|
647
690
|
.option('--name <name>', 'nome do produto (interativo se ausente)')
|
|
648
691
|
.option('--slug <slug>', 'slug (auto-derivado de --name se ausente)')
|
|
649
692
|
.option('--description <text>', 'descrição (opcional)')
|
|
@@ -666,16 +709,16 @@ productsCmd
|
|
|
666
709
|
});
|
|
667
710
|
});
|
|
668
711
|
productsCmd
|
|
669
|
-
.command('publish
|
|
670
|
-
.description('
|
|
712
|
+
.command('publish [slug]')
|
|
713
|
+
.description('Publicar produto no catálogo público')
|
|
671
714
|
.option('--json', 'saída em JSON')
|
|
672
715
|
.action(async (slug, opts) => {
|
|
673
716
|
const { runProductsPublish } = await import('./commands/products.js');
|
|
674
717
|
await runProductsPublish(slug, { json: !!opts.json });
|
|
675
718
|
});
|
|
676
719
|
productsCmd
|
|
677
|
-
.command('unpublish
|
|
678
|
-
.description('
|
|
720
|
+
.command('unpublish [slug]')
|
|
721
|
+
.description('Remover produto do catálogo público')
|
|
679
722
|
.option('--json', 'saída em JSON')
|
|
680
723
|
.action(async (slug, opts) => {
|
|
681
724
|
const { runProductsUnpublish } = await import('./commands/products.js');
|
|
@@ -684,14 +727,14 @@ productsCmd
|
|
|
684
727
|
// ── neetru products db (Phase A — per-product DB isolation) ────────────
|
|
685
728
|
const productsDbCmd = productsCmd
|
|
686
729
|
.command('db')
|
|
687
|
-
.description('
|
|
730
|
+
.description('Gerenciar bancos isolados por produto');
|
|
688
731
|
productsDbCmd
|
|
689
732
|
.command('list')
|
|
690
|
-
.description('
|
|
691
|
-
.option('--product-id <id>')
|
|
692
|
-
.option('--engine <engine>')
|
|
693
|
-
.option('--status <status>')
|
|
694
|
-
.option('--json')
|
|
733
|
+
.description('Listar bancos de produtos')
|
|
734
|
+
.option('--product-id <id>', 'ID do produto')
|
|
735
|
+
.option('--engine <engine>', 'firestore-instance | cloud-sql-postgres | cloud-sql-mysql | vm-postgres-single | vm-postgres-cluster | vm-mysql-single | vm-mysql-cluster')
|
|
736
|
+
.option('--status <status>', 'Filtrar por status (ativo, provisionando, falha, arquivado)')
|
|
737
|
+
.option('--json', 'Saída em JSON estruturado')
|
|
695
738
|
.action(async (opts) => {
|
|
696
739
|
const { runDbList } = await import('./commands/products-db.js');
|
|
697
740
|
await runDbList({
|
|
@@ -703,7 +746,7 @@ productsDbCmd
|
|
|
703
746
|
});
|
|
704
747
|
productsDbCmd
|
|
705
748
|
.command('engines')
|
|
706
|
-
.description('
|
|
749
|
+
.description('Listar engines de banco suportados')
|
|
707
750
|
.option('--json')
|
|
708
751
|
.action(async (opts) => {
|
|
709
752
|
const { runDbEngines } = await import('./commands/products-db.js');
|
|
@@ -711,22 +754,22 @@ productsDbCmd
|
|
|
711
754
|
});
|
|
712
755
|
productsDbCmd
|
|
713
756
|
.command('create')
|
|
714
|
-
.description('
|
|
715
|
-
.
|
|
716
|
-
.
|
|
717
|
-
.
|
|
718
|
-
.
|
|
719
|
-
.option('--region <region>', '
|
|
720
|
-
.option('--server-id <serverId>', '
|
|
721
|
-
.option('--replica-count <n>', '
|
|
722
|
-
.option('--json')
|
|
757
|
+
.description('Criar banco de produto (Phase A: registra + audit)')
|
|
758
|
+
.option('--product-id <id>', 'ID do produto')
|
|
759
|
+
.option('--label <label>', 'Nome descritivo do banco')
|
|
760
|
+
.option('--engine <engine>', 'firestore-instance | cloud-sql-postgres | cloud-sql-mysql | vm-postgres-single | vm-postgres-cluster | vm-mysql-single | vm-mysql-cluster')
|
|
761
|
+
.option('--env <env>', 'Ambiente: dev | staging | production')
|
|
762
|
+
.option('--region <region>', 'Região GCP', 'us-central1')
|
|
763
|
+
.option('--server-id <serverId>', 'ID da VM alvo (obrigatório para engines vm-*)')
|
|
764
|
+
.option('--replica-count <n>', 'Número de réplicas para engines *-cluster (padrão 2)')
|
|
765
|
+
.option('--json', 'Saída em JSON estruturado')
|
|
723
766
|
.action(async (opts) => {
|
|
724
767
|
const { runDbCreate } = await import('./commands/products-db.js');
|
|
725
768
|
await runDbCreate({
|
|
726
769
|
productId: opts.productId,
|
|
727
770
|
label: opts.label,
|
|
728
771
|
engine: opts.engine,
|
|
729
|
-
|
|
772
|
+
env: opts.env,
|
|
730
773
|
region: opts.region,
|
|
731
774
|
serverId: opts.serverId,
|
|
732
775
|
replicaCount: opts.replicaCount,
|
|
@@ -734,16 +777,16 @@ productsDbCmd
|
|
|
734
777
|
});
|
|
735
778
|
});
|
|
736
779
|
productsDbCmd
|
|
737
|
-
.command('get
|
|
738
|
-
.description('
|
|
780
|
+
.command('get [id]')
|
|
781
|
+
.description('Mostrar detalhes de um banco')
|
|
739
782
|
.option('--json')
|
|
740
783
|
.action(async (id, opts) => {
|
|
741
784
|
const { runDbGet } = await import('./commands/products-db.js');
|
|
742
785
|
await runDbGet(id, { json: !!opts.json });
|
|
743
786
|
});
|
|
744
787
|
productsDbCmd
|
|
745
|
-
.command('status
|
|
746
|
-
.description('
|
|
788
|
+
.command('status [id] [status]')
|
|
789
|
+
.description('Atualizar status de um banco de produto')
|
|
747
790
|
.option('--reason <text>')
|
|
748
791
|
.option('--json')
|
|
749
792
|
.action(async (id, status, opts) => {
|
|
@@ -751,24 +794,24 @@ productsDbCmd
|
|
|
751
794
|
await runDbStatus(id, status, { reason: opts.reason, json: !!opts.json });
|
|
752
795
|
});
|
|
753
796
|
productsDbCmd
|
|
754
|
-
.command('retry
|
|
755
|
-
.description('
|
|
797
|
+
.command('retry [id]')
|
|
798
|
+
.description('Reenfileirar provisionamento de banco')
|
|
756
799
|
.option('--json')
|
|
757
800
|
.action(async (id, opts) => {
|
|
758
801
|
const { runDbRetry } = await import('./commands/products-db.js');
|
|
759
802
|
await runDbRetry(id, { json: !!opts.json });
|
|
760
803
|
});
|
|
761
804
|
productsDbCmd
|
|
762
|
-
.command('rotate
|
|
763
|
-
.description('
|
|
805
|
+
.command('rotate [id]')
|
|
806
|
+
.description('Rotacionar credenciais do banco (admin)')
|
|
764
807
|
.option('--json')
|
|
765
808
|
.action(async (id, opts) => {
|
|
766
809
|
const { runDbRotate } = await import('./commands/products-db.js');
|
|
767
810
|
await runDbRotate(id, { json: !!opts.json });
|
|
768
811
|
});
|
|
769
812
|
productsDbCmd
|
|
770
|
-
.command('delete
|
|
771
|
-
.description('
|
|
813
|
+
.command('delete [id]')
|
|
814
|
+
.description('Arquivar banco por soft-delete (admin)')
|
|
772
815
|
.option('--json')
|
|
773
816
|
.action(async (id, opts) => {
|
|
774
817
|
const { runDbDelete } = await import('./commands/products-db.js');
|
|
@@ -777,7 +820,7 @@ productsDbCmd
|
|
|
777
820
|
// ── neetru logs ───────────────────────────────────────────────────────
|
|
778
821
|
program
|
|
779
822
|
.command('logs')
|
|
780
|
-
.description('
|
|
823
|
+
.description('Visualizar logs do workspace (suporta tail contínuo)')
|
|
781
824
|
.option('--client-id <id>', 'oauthClientId do workspace')
|
|
782
825
|
.option('-f, --follow', 'tail contínuo (poll a cada 5s)')
|
|
783
826
|
.option('-n, --lines <count>', 'número de linhas a buscar', '50')
|
|
@@ -802,7 +845,7 @@ program
|
|
|
802
845
|
// ── neetru validate ───────────────────────────────────────────────────
|
|
803
846
|
program
|
|
804
847
|
.command('validate')
|
|
805
|
-
.description('
|
|
848
|
+
.description('Validar config local e conexão com o Core')
|
|
806
849
|
.action(async () => {
|
|
807
850
|
const { runValidate } = await import('./commands/validate.js');
|
|
808
851
|
await runValidate();
|
|
@@ -810,7 +853,7 @@ program
|
|
|
810
853
|
// ── neetru open ───────────────────────────────────────────────────────
|
|
811
854
|
program
|
|
812
855
|
.command('open [target]')
|
|
813
|
-
.description('
|
|
856
|
+
.description('Abrir página do painel Neetru no browser')
|
|
814
857
|
.option('--client-id <id>', 'oauthClientId do workspace (anexa em targets workspace-scoped)')
|
|
815
858
|
.action(async (target, opts) => {
|
|
816
859
|
const { runOpen } = await import('./commands/open.js');
|
|
@@ -819,7 +862,7 @@ program
|
|
|
819
862
|
// ── neetru publish ────────────────────────────────────────────────────
|
|
820
863
|
program
|
|
821
864
|
.command('publish')
|
|
822
|
-
.description('
|
|
865
|
+
.description('Publicar produto no catálogo público da landing')
|
|
823
866
|
.option('--draft', 'salva como rascunho (published=false)')
|
|
824
867
|
.option('--unpublish', 'remove o produto da landing (mantém o doc)')
|
|
825
868
|
.option('--slug <slug>', 'override do slug do neetru.config.json')
|
|
@@ -850,7 +893,7 @@ program
|
|
|
850
893
|
// ── neetru add ────────────────────────────────────────────────────────
|
|
851
894
|
program
|
|
852
895
|
.command('add <feature>')
|
|
853
|
-
.description('
|
|
896
|
+
.description('Adicionar template de feature (auth/billing/usage/...)')
|
|
854
897
|
.option('--force', 'sobrescrever arquivos existentes')
|
|
855
898
|
.action(async (feature, opts) => {
|
|
856
899
|
const { runAdd } = await import('./commands/add.js');
|
|
@@ -859,10 +902,10 @@ program
|
|
|
859
902
|
// ── neetru mocks ──────────────────────────────────────────────────────
|
|
860
903
|
const mocksCmd = program
|
|
861
904
|
.command('mocks')
|
|
862
|
-
.description('
|
|
905
|
+
.description('Gerenciar fixtures de dev (NEETRU_ENV=dev)');
|
|
863
906
|
mocksCmd
|
|
864
907
|
.command('reset')
|
|
865
|
-
.description('
|
|
908
|
+
.description('Resetar fixtures de dev para vazio')
|
|
866
909
|
.action(async () => {
|
|
867
910
|
const { runMocksReset } = await import('./commands/mocks.js');
|
|
868
911
|
await runMocksReset();
|
|
@@ -870,10 +913,10 @@ mocksCmd
|
|
|
870
913
|
// ── neetru env ────────────────────────────────────────────────────────
|
|
871
914
|
const envCmd = program
|
|
872
915
|
.command('env')
|
|
873
|
-
.description('
|
|
916
|
+
.description('Gerenciar NEETRU_ENV no .env.local');
|
|
874
917
|
envCmd
|
|
875
918
|
.command('switch <target>')
|
|
876
|
-
.description('
|
|
919
|
+
.description('Alternar NEETRU_ENV (dev/workspace/production)')
|
|
877
920
|
.action(async (target) => {
|
|
878
921
|
const { runEnvSwitch } = await import('./commands/env.js');
|
|
879
922
|
await runEnvSwitch({ target });
|
|
@@ -881,10 +924,10 @@ envCmd
|
|
|
881
924
|
// ── neetru db ─────────────────────────────────────────────────────────
|
|
882
925
|
const dbCmd = program
|
|
883
926
|
.command('db')
|
|
884
|
-
.description('
|
|
927
|
+
.description('Gerenciar schema, migrations e seed do produto');
|
|
885
928
|
dbCmd
|
|
886
929
|
.command('init')
|
|
887
|
-
.description('
|
|
930
|
+
.description('Criar manifest de schema a partir do config')
|
|
888
931
|
.option('--out <path>', 'caminho do manifest (default db/schema.manifest.json)')
|
|
889
932
|
.option('--force', 'sobrescreve se já existir')
|
|
890
933
|
.action(async (opts) => {
|
|
@@ -893,7 +936,7 @@ dbCmd
|
|
|
893
936
|
});
|
|
894
937
|
dbCmd
|
|
895
938
|
.command('migrate <toVersion>')
|
|
896
|
-
.description('
|
|
939
|
+
.description('Aplicar migration de schema via Core')
|
|
897
940
|
.option('--from <fromVersion>', 'versão atual (default: schemaVersion do config)')
|
|
898
941
|
.action(async (toVersion, opts) => {
|
|
899
942
|
const { runDbMigrate } = await import('./commands/db.js');
|
|
@@ -901,7 +944,7 @@ dbCmd
|
|
|
901
944
|
});
|
|
902
945
|
dbCmd
|
|
903
946
|
.command('seed')
|
|
904
|
-
.description('
|
|
947
|
+
.description('Executar script de seed do produto')
|
|
905
948
|
.option('--script <path>', 'caminho custom do script de seed')
|
|
906
949
|
.action(async (opts) => {
|
|
907
950
|
const { runDbSeed } = await import('./commands/db.js');
|
|
@@ -910,10 +953,10 @@ dbCmd
|
|
|
910
953
|
// ── neetru fn ─────────────────────────────────────────────────────────
|
|
911
954
|
const fnCmd = program
|
|
912
955
|
.command('fn')
|
|
913
|
-
.description('
|
|
956
|
+
.description('Gerenciar Functions e APIs do produto');
|
|
914
957
|
fnCmd
|
|
915
958
|
.command('deploy')
|
|
916
|
-
.description('
|
|
959
|
+
.description('Registrar nova versão da API no catálogo')
|
|
917
960
|
.option('--version <v>', 'versão da API (default: apiVersion do config ou v1)')
|
|
918
961
|
.option('--channel <channel>', 'stable | beta | alpha', 'stable')
|
|
919
962
|
.option('--spec <path>', 'caminho de OpenAPI/JSON schema')
|
|
@@ -924,7 +967,7 @@ fnCmd
|
|
|
924
967
|
// ── neetru promote ────────────────────────────────────────────────────
|
|
925
968
|
program
|
|
926
969
|
.command('promote')
|
|
927
|
-
.description('
|
|
970
|
+
.description('Solicitar promotion entre ambientes (staff-gated)')
|
|
928
971
|
.requiredOption('--from <env>', 'dev | workspace | beta | prod')
|
|
929
972
|
.requiredOption('--to <env>', 'dev | workspace | beta | prod')
|
|
930
973
|
.option('--product <slug>', 'override do slug do neetru.config.json')
|
|
@@ -945,7 +988,7 @@ program
|
|
|
945
988
|
// ── neetru doctor ─────────────────────────────────────────────────────
|
|
946
989
|
program
|
|
947
990
|
.command('doctor')
|
|
948
|
-
.description('
|
|
991
|
+
.description('Diagnosticar saúde do CLI (token, core, schema, env)')
|
|
949
992
|
.option('--json', 'saída em JSON (machine-readable)')
|
|
950
993
|
.action(async (opts) => {
|
|
951
994
|
const { runDoctor } = await import('./commands/doctor.js');
|
|
@@ -954,7 +997,7 @@ program
|
|
|
954
997
|
// ── neetru upgrade ────────────────────────────────────────────────────
|
|
955
998
|
program
|
|
956
999
|
.command('upgrade')
|
|
957
|
-
.description('
|
|
1000
|
+
.description('Verificar versão mais recente do CLI no npm')
|
|
958
1001
|
.option('--json', 'saída em JSON')
|
|
959
1002
|
.action(async (opts) => {
|
|
960
1003
|
const { runUpgrade } = await import('./commands/upgrade.js');
|
|
@@ -963,7 +1006,7 @@ program
|
|
|
963
1006
|
// ── neetru autocomplete ───────────────────────────────────────────────
|
|
964
1007
|
program
|
|
965
1008
|
.command('autocomplete <shell>')
|
|
966
|
-
.description('
|
|
1009
|
+
.description('Gerar script de shell completion (bash/zsh/pwsh)')
|
|
967
1010
|
.action(async (shell) => {
|
|
968
1011
|
const { runAutocomplete } = await import('./commands/autocomplete.js');
|
|
969
1012
|
await runAutocomplete(shell);
|
|
@@ -971,10 +1014,10 @@ program
|
|
|
971
1014
|
// ── neetru agent release ──────────────────────────────────────────────
|
|
972
1015
|
const agentCmd = program
|
|
973
1016
|
.command('agent')
|
|
974
|
-
.description('
|
|
1017
|
+
.description('Gerenciar binário do Neetru Agent (Linux daemon)');
|
|
975
1018
|
agentCmd
|
|
976
1019
|
.command('release')
|
|
977
|
-
.description('
|
|
1020
|
+
.description('Registrar nova release do agente em agent_releases')
|
|
978
1021
|
.requiredOption('--version <semver>', 'versão (ex: 1.2.0 ou 1.2.0-beta.1)')
|
|
979
1022
|
.option('--channel <channel>', 'stable | beta | canary (default: beta)', 'beta')
|
|
980
1023
|
.option('--changelog <text|@file>', 'changelog markdown inline ou "@path" pra ler de arquivo')
|
|
@@ -996,7 +1039,7 @@ agentCmd
|
|
|
996
1039
|
});
|
|
997
1040
|
agentCmd
|
|
998
1041
|
.command('yank <version>')
|
|
999
|
-
.description('
|
|
1042
|
+
.description('Revogar release do agente (destrutivo — exige MFA)')
|
|
1000
1043
|
.requiredOption('--reason <text>', 'motivo do yank (mínimo 5 caracteres)')
|
|
1001
1044
|
.option('--yes', 'pula a confirmação interativa (modo script)')
|
|
1002
1045
|
.option('--force', 'alias de --yes')
|
|
@@ -1016,10 +1059,10 @@ agentCmd
|
|
|
1016
1059
|
});
|
|
1017
1060
|
const agentCanaryCmd = agentCmd
|
|
1018
1061
|
.command('canary')
|
|
1019
|
-
.description('
|
|
1062
|
+
.description('Controlar canary rollout de releases do agente');
|
|
1020
1063
|
agentCanaryCmd
|
|
1021
1064
|
.command('start <version>')
|
|
1022
|
-
.description('
|
|
1065
|
+
.description('Iniciar canary rollout de uma release (phase1 5%)')
|
|
1023
1066
|
.option('--json', 'saída em JSON')
|
|
1024
1067
|
.action(async (version, opts) => {
|
|
1025
1068
|
const { runAgentCanaryStart } = await import('./commands/agent-write.js');
|
|
@@ -1027,7 +1070,7 @@ agentCanaryCmd
|
|
|
1027
1070
|
});
|
|
1028
1071
|
agentCanaryCmd
|
|
1029
1072
|
.command('rollback <version>')
|
|
1030
|
-
.description('
|
|
1073
|
+
.description('Reverter canary de uma release (destrutivo — exige MFA)')
|
|
1031
1074
|
.requiredOption('--reason <text>', 'motivo do rollback (mínimo 5 caracteres)')
|
|
1032
1075
|
.option('--yes', 'pula a confirmação interativa (modo script)')
|
|
1033
1076
|
.option('--force', 'alias de --yes')
|
|
@@ -1048,13 +1091,13 @@ agentCanaryCmd
|
|
|
1048
1091
|
// ── neetru support ───────────────────────────────────────────────────
|
|
1049
1092
|
const supportCmd = program
|
|
1050
1093
|
.command('support')
|
|
1051
|
-
.description('
|
|
1094
|
+
.description('Gerenciar suporte ao cliente via CLI');
|
|
1052
1095
|
const supportTicketsCmd = supportCmd
|
|
1053
1096
|
.command('tickets')
|
|
1054
|
-
.description('
|
|
1097
|
+
.description('Operar tickets de suporte');
|
|
1055
1098
|
supportTicketsCmd
|
|
1056
1099
|
.command('list')
|
|
1057
|
-
.description('
|
|
1100
|
+
.description('Listar tickets de suporte')
|
|
1058
1101
|
.option('--status <s>', 'open | in_progress | resolved | closed')
|
|
1059
1102
|
.option('--severity <s>', 'sev1 | sev2 | sev3 | sev4')
|
|
1060
1103
|
.option('--product <id>', 'filtra por productId')
|
|
@@ -1076,7 +1119,7 @@ supportTicketsCmd
|
|
|
1076
1119
|
});
|
|
1077
1120
|
supportTicketsCmd
|
|
1078
1121
|
.command('describe <id>')
|
|
1079
|
-
.description('
|
|
1122
|
+
.description('Mostrar ticket com thread de mensagens')
|
|
1080
1123
|
.option('--json', 'saída em JSON')
|
|
1081
1124
|
.action(async (id, opts) => {
|
|
1082
1125
|
const { runSupportTicketsDescribe } = await import('./commands/support.js');
|
|
@@ -1084,7 +1127,7 @@ supportTicketsCmd
|
|
|
1084
1127
|
});
|
|
1085
1128
|
supportTicketsCmd
|
|
1086
1129
|
.command('reply <id>')
|
|
1087
|
-
.description('
|
|
1130
|
+
.description('Responder ticket com mensagem staff')
|
|
1088
1131
|
.requiredOption('--message <text>', 'corpo da mensagem')
|
|
1089
1132
|
.option('--json', 'saída em JSON')
|
|
1090
1133
|
.action(async (id, opts) => {
|
|
@@ -1093,7 +1136,7 @@ supportTicketsCmd
|
|
|
1093
1136
|
});
|
|
1094
1137
|
supportTicketsCmd
|
|
1095
1138
|
.command('assign <id>')
|
|
1096
|
-
.description('
|
|
1139
|
+
.description('Atribuir ticket a um staff')
|
|
1097
1140
|
.requiredOption('--to <staffUid>', 'uid do staff destino')
|
|
1098
1141
|
.option('--json', 'saída em JSON')
|
|
1099
1142
|
.action(async (id, opts) => {
|
|
@@ -1102,7 +1145,7 @@ supportTicketsCmd
|
|
|
1102
1145
|
});
|
|
1103
1146
|
supportTicketsCmd
|
|
1104
1147
|
.command('status <id>')
|
|
1105
|
-
.description('
|
|
1148
|
+
.description('Transicionar status do ticket')
|
|
1106
1149
|
.requiredOption('--to <status>', 'open | in_progress | resolved | closed')
|
|
1107
1150
|
.option('--json', 'saída em JSON')
|
|
1108
1151
|
.action(async (id, opts) => {
|
|
@@ -1110,23 +1153,27 @@ supportTicketsCmd
|
|
|
1110
1153
|
await runSupportTicketsStatus(id, { to: opts.to, json: !!opts.json });
|
|
1111
1154
|
});
|
|
1112
1155
|
// ── neetru dns ───────────────────────────────────────────────────────
|
|
1113
|
-
const dnsCmd = program
|
|
1114
|
-
|
|
1156
|
+
const dnsCmd = program
|
|
1157
|
+
.command('dns')
|
|
1158
|
+
.description('Gerenciar Cloud DNS managed zones');
|
|
1159
|
+
const dnsZonesCmd = dnsCmd
|
|
1115
1160
|
.command('zones')
|
|
1116
|
-
.description('
|
|
1161
|
+
.description('Operar managed zones do Cloud DNS');
|
|
1162
|
+
dnsZonesCmd
|
|
1117
1163
|
.command('list')
|
|
1118
|
-
.description('
|
|
1164
|
+
.description('Listar managed zones do projeto')
|
|
1119
1165
|
.option('--json', 'saída em JSON')
|
|
1120
1166
|
.action(async (opts) => {
|
|
1121
1167
|
const { runDnsZonesList } = await import('./commands/infra-read.js');
|
|
1122
1168
|
await runDnsZonesList({ json: !!opts.json });
|
|
1123
1169
|
});
|
|
1124
1170
|
// ── neetru hosting ───────────────────────────────────────────────────
|
|
1125
|
-
program
|
|
1171
|
+
const hostingCmd = program
|
|
1126
1172
|
.command('hosting')
|
|
1127
|
-
.description('
|
|
1173
|
+
.description('Gerenciar customer domains e hosting setup');
|
|
1174
|
+
hostingCmd
|
|
1128
1175
|
.command('list')
|
|
1129
|
-
.description('
|
|
1176
|
+
.description('Listar customer domains com scope de tenant')
|
|
1130
1177
|
.option('--json', 'saída em JSON')
|
|
1131
1178
|
.action(async (opts) => {
|
|
1132
1179
|
const { runHostingList } = await import('./commands/infra-read.js');
|
|
@@ -1135,9 +1182,9 @@ program
|
|
|
1135
1182
|
// ── neetru builds ────────────────────────────────────────────────────
|
|
1136
1183
|
program
|
|
1137
1184
|
.command('builds')
|
|
1138
|
-
.description('Cloud Build
|
|
1185
|
+
.description('Consultar Cloud Build (status e duração)')
|
|
1139
1186
|
.command('list')
|
|
1140
|
-
.description('
|
|
1187
|
+
.description('Listar Cloud Builds recentes (global e regional)')
|
|
1141
1188
|
.option('--json', 'saída em JSON')
|
|
1142
1189
|
.action(async (opts) => {
|
|
1143
1190
|
const { runBuildsList } = await import('./commands/infra-read.js');
|
|
@@ -1147,13 +1194,13 @@ program
|
|
|
1147
1194
|
// Disaster Recovery — listar exports + restore assistido (admin + step-up MFA).
|
|
1148
1195
|
const drCmd = program
|
|
1149
1196
|
.command('dr')
|
|
1150
|
-
.description('Disaster Recovery
|
|
1197
|
+
.description('Operar Disaster Recovery (admin only)');
|
|
1151
1198
|
const drExportsCmd = drCmd
|
|
1152
1199
|
.command('exports')
|
|
1153
|
-
.description('
|
|
1200
|
+
.description('Operar exports de Firestore em gs://neetru-backups');
|
|
1154
1201
|
drExportsCmd
|
|
1155
1202
|
.command('list')
|
|
1156
|
-
.description('
|
|
1203
|
+
.description('Listar exports de DR disponíveis')
|
|
1157
1204
|
.option('--json', 'saída em JSON')
|
|
1158
1205
|
.action(async (opts) => {
|
|
1159
1206
|
const { runDrExportsList } = await import('./commands/dr.js');
|
|
@@ -1161,7 +1208,7 @@ drExportsCmd
|
|
|
1161
1208
|
});
|
|
1162
1209
|
drCmd
|
|
1163
1210
|
.command('restore')
|
|
1164
|
-
.description('
|
|
1211
|
+
.description('Restaurar Firestore de export (IRREVERSÍVEL — exige MFA)')
|
|
1165
1212
|
.requiredOption('--gcs-path <path>', 'gs://neetru-backups/firestore-exports/<stamp>/')
|
|
1166
1213
|
.requiredOption('--target-project <project>', 'projeto GCP de destino (deve ser STAGING)')
|
|
1167
1214
|
.option('--yes', 'pula a confirmação interativa (modo script)')
|
|
@@ -1181,10 +1228,24 @@ drCmd
|
|
|
1181
1228
|
json: !!opts.json,
|
|
1182
1229
|
});
|
|
1183
1230
|
});
|
|
1231
|
+
// ── neetru schema ─────────────────────────────────────────────────────
|
|
1232
|
+
// Inspecionar spec OpenAPI do Core — usado pela IA e devs pra entender endpoints.
|
|
1233
|
+
{
|
|
1234
|
+
const { registerSchemaCommand } = await import('./commands/schema.js');
|
|
1235
|
+
registerSchemaCommand(program);
|
|
1236
|
+
}
|
|
1184
1237
|
// ── parse ─────────────────────────────────────────────────────────────
|
|
1185
|
-
program.parse(process.argv);
|
|
1186
1238
|
if (!process.argv.slice(2).length) {
|
|
1187
|
-
|
|
1188
|
-
|
|
1239
|
+
if (process.stdin.isTTY && process.stdout.isTTY && process.env.CI !== 'true') {
|
|
1240
|
+
const { runTerminalUi } = await import('./commands/ui.js');
|
|
1241
|
+
await runTerminalUi();
|
|
1242
|
+
}
|
|
1243
|
+
else {
|
|
1244
|
+
log.banner();
|
|
1245
|
+
program.outputHelp();
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
else {
|
|
1249
|
+
program.parse(process.argv);
|
|
1189
1250
|
}
|
|
1190
1251
|
//# sourceMappingURL=index.js.map
|