@neetru/cli 2.32.0 → 2.32.1
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/CHANGELOG.md +8 -0
- package/dist/commands/bug.js +4 -4
- package/dist/commands/db.js +3 -9
- package/dist/commands/deploy.js +9 -9
- package/dist/commands/init.js +2 -1
- package/dist/commands/products.js +2 -2
- package/dist/commands/servers.js +2 -1
- package/dist/lib/inquirer-sob-demanda.d.ts +14 -0
- package/dist/lib/inquirer-sob-demanda.js +18 -0
- package/dist/lib/pickers.js +5 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,14 @@ Convenção: [Keep a Changelog](https://keepachangelog.com/) + [SemVer](https://
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [2.32.1] — 2026-10-18 (comandos sem pergunta não carregam o `inquirer`)
|
|
8
|
+
|
|
9
|
+
> **Por que PATCH.** Só conserto de desempenho e testes, sem mudança de comportamento nem de saída documentada.
|
|
10
|
+
|
|
11
|
+
### Corrigido
|
|
12
|
+
|
|
13
|
+
- **`neetru deploy`, `neetru bug`, `neetru products` e os pickers (`tenants`, `servers`, `deployments`, `products db`…) não carregam mais o `inquirer` quando não vão perguntar nada** (P115). Os quatro módulos o importavam no topo, então todo `--json`, `--yes` e caminho não interativo pagava o import a frio dele: ~0,31 s sozinho e ~1 s com a máquina carregada, o mais caro do grafo da CLI. Agora o inquirer é carregado só no ponto da pergunta, por um carregador único (`src/lib/inquirer-sob-demanda.ts`), que `db`, `init` e `servers` também passam a usar no lugar das cópias próprias. Uma guarda nova reprova o módulo de `src/` que carregar o inquirer ou um `@inquirer/*` no topo, direto (import estático, `import()` ou `carregarInquirer()` no corpo do módulo, inclusive dentro de IIFE) ou por outro módulo que o carregue (transitivo), reprova `import('inquirer')` e `import('@inquirer/…')` fora do carregador e confere em runtime que importar os consumidores do carregador e do picker não o carrega. `ui`, `chat-menu`, `archive`, `auth`, `vm`, `new`, `ai` (por `auth`) e o `index.ts` (o menu do `neetru` sem argumentos, por `ui`) ainda o carregam: dívida declarada na guarda, com teto exato (entrada nova reprova). Nos testes: 27 arquivos cujo 1º teste carregava o comando a frio, dentro do corpo, ganharam aquecimento num `beforeAll` com `TIMEOUT_AQUECIMENTO_MS` (na suíte completa, o 1º teste passou de 0,6–2,1 s para 3–236 ms em 25 deles; em `build-standalone-packaging` e `build-env-local-exclusion` fica em 0,37–0,64 s, o nível dos demais testes de cada um, que rodam o `tar` de verdade), e outra guarda impede teste novo de importar comando no corpo sem aquecê-lo (dívida de 43 arquivos, também com teto exato). Sem mudança de comportamento.
|
|
14
|
+
|
|
7
15
|
## [2.32.0] — 2026-10-18 (`neetru secrets`, erro tipado e conselho que só cita o que existe)
|
|
8
16
|
|
|
9
17
|
> **Por que MINOR.** Entra comando novo (`neetru secrets set|list|archive`) e muda saída documentada: o `docs sync` com falha parcial passa a sair com o código do doc mais grave (antes era 1 fixo) e o `docs.sync.status` do JSON do `neetru deploy` de produção passa de `parcial` para `falha` quando nada deu certo. A 2.31.1 já tinha seção fechada aqui (11/10) e nunca foi publicada; publicar este código como 2.31.1 repetiria a colisão de número que a própria 2.31.1 corrigiu.
|
package/dist/commands/bug.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import chalk from 'chalk';
|
|
16
16
|
import ora from 'ora';
|
|
17
|
-
import
|
|
17
|
+
import { carregarInquirer } from '../lib/inquirer-sob-demanda.js';
|
|
18
18
|
import { apiRequest } from '../lib/api-client.js';
|
|
19
19
|
import { requireToken, handleApiError } from '../lib/cli-read.js';
|
|
20
20
|
import { printWriteResult } from '../lib/cli-write.js';
|
|
@@ -169,7 +169,7 @@ export async function runBugReport(opts) {
|
|
|
169
169
|
let severity = opts.severity?.trim() ?? '';
|
|
170
170
|
const interactive = !opts.json && (!title || !description);
|
|
171
171
|
if (interactive) {
|
|
172
|
-
const answers = await
|
|
172
|
+
const answers = await (await carregarInquirer()).prompt([
|
|
173
173
|
{
|
|
174
174
|
type: 'input',
|
|
175
175
|
name: 'title',
|
|
@@ -423,7 +423,7 @@ export async function runBugResolve(id, opts) {
|
|
|
423
423
|
let status = (opts.status ?? 'resolved').trim();
|
|
424
424
|
let duplicateOf = opts.duplicateOf?.trim() ?? '';
|
|
425
425
|
if (!opts.json && !summary) {
|
|
426
|
-
const ans = await
|
|
426
|
+
const ans = await (await carregarInquirer()).prompt([
|
|
427
427
|
{
|
|
428
428
|
type: 'editor',
|
|
429
429
|
name: 'summary',
|
|
@@ -497,7 +497,7 @@ export async function runBugComment(id, opts) {
|
|
|
497
497
|
}
|
|
498
498
|
let body = opts.body?.trim() ?? '';
|
|
499
499
|
if (!opts.json && !body) {
|
|
500
|
-
const ans = await
|
|
500
|
+
const ans = await (await carregarInquirer()).prompt([
|
|
501
501
|
{
|
|
502
502
|
type: 'editor',
|
|
503
503
|
name: 'body',
|
package/dist/commands/db.js
CHANGED
|
@@ -37,16 +37,10 @@ import { exitWithCliError } from '../lib/cli-error.js';
|
|
|
37
37
|
import { safeExit } from '../utils/safe-exit.js';
|
|
38
38
|
import { runApplyPipeline, runExecSqlPipeline, buildPipelineDeps, isPipelineError, } from '../lib/db-pipeline/index.js';
|
|
39
39
|
import { resolveStepUp } from '../lib/cli-write.js';
|
|
40
|
+
import { carregarInquirer } from '../lib/inquirer-sob-demanda.js';
|
|
40
41
|
import { loadProductConfig } from '../lib/product-config.js';
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
* interativos usam. Era o unico import estatico dele no grafo de `neetru db`
|
|
44
|
-
* — `db list`/`db status`/`db apply --json` (e os testes) pagavam a carga sem
|
|
45
|
-
* nunca perguntar nada.
|
|
46
|
-
*/
|
|
47
|
-
async function carregarInquirer() {
|
|
48
|
-
return (await import('inquirer')).default;
|
|
49
|
-
}
|
|
42
|
+
// `inquirer` sob demanda (bug_b1e9af59): só os prompts interativos o carregam,
|
|
43
|
+
// pelo `carregarInquirer()` único de `lib/inquirer-sob-demanda.ts` (P115).
|
|
50
44
|
// ---------------------------------------------------------------------------
|
|
51
45
|
// Constantes e tipos locais
|
|
52
46
|
// ---------------------------------------------------------------------------
|
package/dist/commands/deploy.js
CHANGED
|
@@ -21,7 +21,7 @@ import * as fs from 'node:fs';
|
|
|
21
21
|
import { promises as fsp } from 'node:fs';
|
|
22
22
|
import { spawnSync } from 'node:child_process';
|
|
23
23
|
import * as path from 'node:path';
|
|
24
|
-
import
|
|
24
|
+
import { carregarInquirer } from '../lib/inquirer-sob-demanda.js';
|
|
25
25
|
import chalk from 'chalk';
|
|
26
26
|
import ora from 'ora';
|
|
27
27
|
import { log } from '../utils/logger.js';
|
|
@@ -576,7 +576,7 @@ async function pickProduct(opts, nonInteractive, cwd) {
|
|
|
576
576
|
if (catalog.products.length === 0) {
|
|
577
577
|
deployFail(opts.json, 'no_products', 'Nenhum produto público encontrado. Crie um via `neetru publish` antes.');
|
|
578
578
|
}
|
|
579
|
-
const { slug } = await
|
|
579
|
+
const { slug } = await (await carregarInquirer()).prompt([
|
|
580
580
|
{
|
|
581
581
|
type: 'list',
|
|
582
582
|
name: 'slug',
|
|
@@ -601,7 +601,7 @@ export async function pickTarget(opts, nonInteractive, runtime) {
|
|
|
601
601
|
// handler .ts, não um app Next.js. Recomendar "Workspace" aqui levava quem
|
|
602
602
|
// aceita o padrão direto ao aviso do contrato (confirmação final do PR #74).
|
|
603
603
|
const ehNext = runtime === 'nextjs';
|
|
604
|
-
const { target } = await
|
|
604
|
+
const { target } = await (await carregarInquirer()).prompt([
|
|
605
605
|
{
|
|
606
606
|
type: 'list',
|
|
607
607
|
name: 'target',
|
|
@@ -674,7 +674,7 @@ async function pickServer(opts, nonInteractive) {
|
|
|
674
674
|
if (nonInteractive) {
|
|
675
675
|
deployFail(opts.json, 'server_required', '--server <id> é obrigatório em modo não interativo.');
|
|
676
676
|
}
|
|
677
|
-
const { serverId } = await
|
|
677
|
+
const { serverId } = await (await carregarInquirer()).prompt([
|
|
678
678
|
{
|
|
679
679
|
type: 'list',
|
|
680
680
|
name: 'serverId',
|
|
@@ -704,7 +704,7 @@ async function pickDomain(opts, nonInteractive, productSlug) {
|
|
|
704
704
|
if (nonInteractive)
|
|
705
705
|
return { domain };
|
|
706
706
|
if (!domain) {
|
|
707
|
-
const { d } = await
|
|
707
|
+
const { d } = await (await carregarInquirer()).prompt([
|
|
708
708
|
{
|
|
709
709
|
type: 'input',
|
|
710
710
|
name: 'd',
|
|
@@ -1264,7 +1264,7 @@ async function runWorkspaceDeploy(opts, productSlug, envName, cwd, nonInteractiv
|
|
|
1264
1264
|
if (sourceSizeBytes > WORKSPACE_SOURCE_GCS_THRESHOLD_BYTES) {
|
|
1265
1265
|
log.dim(` upload: via GCS (source grande — acima de ${Math.round(WORKSPACE_SOURCE_GCS_THRESHOLD_BYTES / 1024)} KB)`);
|
|
1266
1266
|
}
|
|
1267
|
-
const { ok } = await
|
|
1267
|
+
const { ok } = await (await carregarInquirer()).prompt([
|
|
1268
1268
|
{ type: 'confirm', name: 'ok', message: 'Confirmar deploy?', default: true },
|
|
1269
1269
|
]);
|
|
1270
1270
|
if (!ok) {
|
|
@@ -1730,7 +1730,7 @@ envFileTexto) {
|
|
|
1730
1730
|
log.dim(` ambiente: ${envName}`);
|
|
1731
1731
|
log.dim(' destino: cloud-run (serviço dedicado)');
|
|
1732
1732
|
log.dim(` imagem: ${imageUrl}`);
|
|
1733
|
-
const { ok } = await
|
|
1733
|
+
const { ok } = await (await carregarInquirer()).prompt([
|
|
1734
1734
|
{ type: 'confirm', name: 'ok', message: 'Confirmar deploy?', default: true },
|
|
1735
1735
|
]);
|
|
1736
1736
|
if (!ok) {
|
|
@@ -1886,7 +1886,7 @@ async function checkSchemaGate(cwd, opts) {
|
|
|
1886
1886
|
log.error(msg);
|
|
1887
1887
|
return false;
|
|
1888
1888
|
}
|
|
1889
|
-
const { continuar } = await
|
|
1889
|
+
const { continuar } = await (await carregarInquirer()).prompt([
|
|
1890
1890
|
{
|
|
1891
1891
|
type: 'confirm',
|
|
1892
1892
|
name: 'continuar',
|
|
@@ -2095,7 +2095,7 @@ export async function runDeploy(opts) {
|
|
|
2095
2095
|
log.dim(` sha256: ${artifact.artifactSha256.slice(0, 16)}…`);
|
|
2096
2096
|
// Em prod o default do confirm é FALSE — Enter não deploya produção sem
|
|
2097
2097
|
// uma decisão explícita (auditoria UX 2026-09).
|
|
2098
|
-
const { ok } = await
|
|
2098
|
+
const { ok } = await (await carregarInquirer()).prompt([
|
|
2099
2099
|
{ type: 'confirm', name: 'ok', message: 'Confirmar deploy?', default: envName !== 'prod' },
|
|
2100
2100
|
]);
|
|
2101
2101
|
if (!ok) {
|
package/dist/commands/init.js
CHANGED
|
@@ -7,6 +7,7 @@ import ora from 'ora';
|
|
|
7
7
|
// todo `neetru init --yes` (CI e scripts) e pelo 1º teste do init.test.ts,
|
|
8
8
|
// que estourava o timeout de 10 s com a máquina carregada.
|
|
9
9
|
import { log } from '../utils/logger.js';
|
|
10
|
+
import { carregarInquirer } from '../lib/inquirer-sob-demanda.js';
|
|
10
11
|
import { safeExit } from '../utils/safe-exit.js';
|
|
11
12
|
/**
|
|
12
13
|
* Inspeciona um diretório pra decidir se é projeto existente, vazio, ou
|
|
@@ -86,7 +87,7 @@ async function resolveTarget(name, cwd, opts) {
|
|
|
86
87
|
}
|
|
87
88
|
// ── Interactive ──────────────────────────────────────────────────────
|
|
88
89
|
// Só aqui há pergunta: o inquirer é carregado agora (ver o topo do arquivo).
|
|
89
|
-
const
|
|
90
|
+
const inquirer = await carregarInquirer();
|
|
90
91
|
console.log();
|
|
91
92
|
log.info(`Onde você quer inicializar o projeto "${name}"?`);
|
|
92
93
|
console.log();
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Saída: tabela (default) ou `--json`.
|
|
10
10
|
*/
|
|
11
11
|
import chalk from 'chalk';
|
|
12
|
-
import
|
|
12
|
+
import { carregarInquirer } from '../lib/inquirer-sob-demanda.js';
|
|
13
13
|
import ora from 'ora';
|
|
14
14
|
import { apiRequest, CliApiError } from '../lib/api-client.js';
|
|
15
15
|
import { config } from '../lib/config.js';
|
|
@@ -190,7 +190,7 @@ export async function runProductsCreate(opts) {
|
|
|
190
190
|
const environmentsRequested = parseEnvCsv(opts.env, [...AMBIENTES_PEDIDOS_POR_PADRAO]);
|
|
191
191
|
const interactive = !opts.yes && !opts.json && process.stdin.isTTY;
|
|
192
192
|
if (interactive) {
|
|
193
|
-
const answers = await
|
|
193
|
+
const answers = await (await carregarInquirer()).prompt([
|
|
194
194
|
{
|
|
195
195
|
type: 'input',
|
|
196
196
|
name: 'name',
|
package/dist/commands/servers.js
CHANGED
|
@@ -12,6 +12,7 @@ import { apiRequest, CliApiError } from '../lib/api-client.js';
|
|
|
12
12
|
import { requireToken, handleApiError } from '../lib/cli-read.js';
|
|
13
13
|
import { confirmDestructive, printWriteResult, resolveStepUp, } from '../lib/cli-write.js';
|
|
14
14
|
import { renderTable } from '../lib/render.js';
|
|
15
|
+
import { carregarInquirer } from '../lib/inquirer-sob-demanda.js';
|
|
15
16
|
import { pickServer, promptText, promptChoice } from '../lib/pickers.js';
|
|
16
17
|
import { AGENT_COMMAND_ALLOWLIST, AGENT_COMMAND_CHOICES, commandRequiresMfa, } from '../lib/agent-commands.js';
|
|
17
18
|
import { log } from '../utils/logger.js';
|
|
@@ -369,7 +370,7 @@ export async function runServersForceCleanup(id, opts) {
|
|
|
369
370
|
console.log(chalk.yellow.bold('\n⚠ FORCE-CLEANUP é IRREVERSÍVEL.'));
|
|
370
371
|
console.log(chalk.dim(' Server stuck em provisioning/timeout que está bloqueando o pipeline.'));
|
|
371
372
|
console.log(chalk.dim(' Audit pesado + notification all staff serão gerados.\n'));
|
|
372
|
-
const inquirer =
|
|
373
|
+
const inquirer = await carregarInquirer();
|
|
373
374
|
const ans = await inquirer.prompt([
|
|
374
375
|
{
|
|
375
376
|
type: 'input',
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `inquirer` sob demanda (P115, 2026-10-18; o `db.ts` já fazia o mesmo desde
|
|
3
|
+
* o bug_b1e9af59, e o `init.ts` desde o P112).
|
|
4
|
+
*
|
|
5
|
+
* O `inquirer` é o pacote mais caro de carregar a frio no grafo da CLI: ~0,31 s
|
|
6
|
+
* sozinho e ~1 s com a máquina carregada (medido no P115). Quem o importa no
|
|
7
|
+
* topo faz TODO caminho do comando pagar a carga — inclusive `--json`,
|
|
8
|
+
* `--yes` e os não interativos, que nunca perguntam nada. Os comandos carregam
|
|
9
|
+
* o inquirer por aqui, só no ponto em que vão perguntar.
|
|
10
|
+
*
|
|
11
|
+
* A guarda `guarda-inquirer-sob-demanda.test.ts` impede import estático novo
|
|
12
|
+
* do inquirer em `src/`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function carregarInquirer(): Promise<typeof import('inquirer').default>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `inquirer` sob demanda (P115, 2026-10-18; o `db.ts` já fazia o mesmo desde
|
|
3
|
+
* o bug_b1e9af59, e o `init.ts` desde o P112).
|
|
4
|
+
*
|
|
5
|
+
* O `inquirer` é o pacote mais caro de carregar a frio no grafo da CLI: ~0,31 s
|
|
6
|
+
* sozinho e ~1 s com a máquina carregada (medido no P115). Quem o importa no
|
|
7
|
+
* topo faz TODO caminho do comando pagar a carga — inclusive `--json`,
|
|
8
|
+
* `--yes` e os não interativos, que nunca perguntam nada. Os comandos carregam
|
|
9
|
+
* o inquirer por aqui, só no ponto em que vão perguntar.
|
|
10
|
+
*
|
|
11
|
+
* A guarda `guarda-inquirer-sob-demanda.test.ts` impede import estático novo
|
|
12
|
+
* do inquirer em `src/`.
|
|
13
|
+
*/
|
|
14
|
+
export async function carregarInquirer() {
|
|
15
|
+
const { default: inquirer } = await import('inquirer');
|
|
16
|
+
return inquirer;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=inquirer-sob-demanda.js.map
|
package/dist/lib/pickers.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import
|
|
2
|
+
import { carregarInquirer } from './inquirer-sob-demanda.js';
|
|
3
3
|
import { apiRequest } from './api-client.js';
|
|
4
4
|
import { handleApiError } from './api-error.js';
|
|
5
5
|
import { adviseCommand, declaredInputs } from '../cli-kit/command-context.js';
|
|
@@ -76,6 +76,8 @@ export async function resolveOrPick(opts) {
|
|
|
76
76
|
: `Múltiplos candidatos encontrados, e este comando não recebe ${sujeito} por argumento: ` +
|
|
77
77
|
`rode num terminal interativo para escolher.\nDisponiveis:\n${available}`, opts.json);
|
|
78
78
|
}
|
|
79
|
+
// Só aqui o picker pergunta: o inquirer é carregado agora (P115).
|
|
80
|
+
const inquirer = await carregarInquirer();
|
|
79
81
|
const choices = items.map((item) => ({
|
|
80
82
|
name: opts.format(item),
|
|
81
83
|
value: opts.getId(item),
|
|
@@ -107,7 +109,7 @@ export async function promptText(message, opts = {}) {
|
|
|
107
109
|
return '';
|
|
108
110
|
failInput(`Informe ${message}`, opts.json);
|
|
109
111
|
}
|
|
110
|
-
const answer = await
|
|
112
|
+
const answer = await (await carregarInquirer()).prompt([
|
|
111
113
|
{
|
|
112
114
|
type: 'input',
|
|
113
115
|
name: 'value',
|
|
@@ -131,7 +133,7 @@ export async function promptChoice(message, choices, opts = {}) {
|
|
|
131
133
|
return opts.default;
|
|
132
134
|
failInput(`Escolha ${message}`, opts.json);
|
|
133
135
|
}
|
|
134
|
-
const answer = await
|
|
136
|
+
const answer = await (await carregarInquirer()).prompt([
|
|
135
137
|
{
|
|
136
138
|
type: 'list',
|
|
137
139
|
name: 'picked',
|
package/package.json
CHANGED