@brunoluizdesiqueira/bbuilder-cli 1.0.16 → 1.0.18

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 CHANGED
@@ -1,206 +1,41 @@
1
1
  # bbuilder-cli
2
2
 
3
- CLI em Node.js/TypeScript que substitui o `build_local.bat` com interface interativa e suporte a flags diretas.
3
+ CLI para build local de projetos Delphi do Bimer.
4
4
 
5
- ---
5
+ Substitui o `build_local.bat` com:
6
+ - seleção interativa de projeto, modo e versão
7
+ - suporte a `FAST`, `DEBUG` e `RELEASE`
8
+ - configuração por arquivo `bbuilder.config.json`
9
+ - diagnóstico de ambiente com `doctor`
6
10
 
7
- ## Instalação
8
-
9
- ```bash
10
- # Desenvolvimento local
11
- npm install
12
- npm run build
13
- npm link # disponibiliza o comando 'bbuilder' globalmente
14
- ```
15
-
16
- ```bash
17
- # Instalação via npm
18
- npm install -g @brunoluizdesiqueira/bbuilder-cli
19
- ```
20
-
21
- ```bash
22
- # Publicação
23
- npm publish --access public
24
- ```
25
-
26
- ## Publicação
27
-
28
- ### Publicação manual inicial
29
-
30
- Use esse fluxo para a primeira publicação ou para publicar manualmente uma versão:
31
-
32
- 1. Faça login no npm:
33
-
34
- ```bash
35
- npm login
36
- ```
37
-
38
- 2. Valide o pacote localmente:
39
-
40
- ```bash
41
- npm run build
42
- npm pack --dry-run
43
- ```
44
-
45
- 3. Publique:
46
-
47
- ```bash
48
- npm publish --access public
49
- ```
50
-
51
- Se a versão atual do `package.json` já tiver sido publicada, gere uma nova versão antes:
52
-
53
- ```bash
54
- npm version patch --no-git-tag-version
55
- npm publish --access public
56
- ```
57
-
58
- ### Configurar publicação automática
59
-
60
- Depois da primeira publicação manual, configure o npm para confiar no workflow do GitHub Actions.
61
-
62
- No npm:
63
-
64
- 1. abra a página do pacote `@brunoluizdesiqueira/bbuilder-cli`
65
- 2. vá em `Settings`
66
- 3. abra `Trusted publishing`
67
- 4. adicione um publisher do tipo `GitHub Actions`
68
- 5. configure:
69
- - repositório: `brunoluizdesiqueira/b-cli`
70
- - workflow: `release.yml`
71
-
72
- Na opção **Publishing access**, use:
73
-
74
- - `Require two-factor authentication or a granular access token with bypass 2fa enabled`
75
-
76
- Evite para esse fluxo:
77
-
78
- - `Require two-factor authentication and disallow tokens`
79
-
80
- ### Publicação automática com Changesets
81
-
82
- Depois do Trusted Publisher configurado, o fluxo recomendado fica assim:
83
-
84
- 1. criar uma changeset para cada mudança publicada:
85
-
86
- ```bash
87
- npm run changeset
88
- ```
89
-
90
- 2. fazer commit da changeset junto com o código
91
- 3. abrir PR e fazer merge na `main`
92
- 4. o workflow `Release` abre ou atualiza uma PR de release
93
- 5. ao mergear a PR de release, o npm é publicado automaticamente
94
-
95
- Comandos locais úteis:
96
-
97
- ```bash
98
- npm run changeset
99
- npm run version-packages
100
- npm run release
101
- ```
102
-
103
- ### Troubleshooting do publish automático
104
-
105
- Se a PR de release for mergeada, a versão subir para o `package.json`, mas o publish no npm falhar com erro parecido com:
106
-
107
- ```text
108
- E404 Not Found - PUT https://registry.npmjs.org/@brunoluizdesiqueira%2fbbuilder-cli - Not found
109
- ```
110
-
111
- verifique estes pontos:
112
-
113
- 1. o Trusted Publisher do pacote está configurado para:
114
- - owner/user: `brunoluizdesiqueira`
115
- - repository: `b-cli`
116
- - workflow: `release.yml`
117
- 2. o repositório GitHub é público
118
- 3. o workflow `Release` tem `permissions.id-token: write`
119
- 4. o workflow roda com Node e npm atuais
120
-
121
- O ajuste que resolveu esse cenário neste projeto foi:
122
-
123
- - usar `actions/setup-node@v5`
124
- - executar o workflow com Node `24`
125
- - atualizar o npm antes do publish
126
- - definir no `package.json`:
127
-
128
- ```json
129
- "publishConfig": {
130
- "access": "public",
131
- "provenance": true
132
- }
133
- ```
11
+ ## Requisitos
134
12
 
135
- ## CI/CD
13
+ - Node.js 18+
14
+ - Windows
15
+ - Delphi instalado
16
+ - bibliotecas do projeto disponíveis na máquina
136
17
 
137
- O repositório agora está preparado com GitHub Actions:
138
-
139
- - `CI`: roda em `push` e `pull_request`, executando `npm ci`, `tsc`, `build` e `npm pack --dry-run`
140
- - `Release`: usa `changesets` para abrir uma PR de release com bump de versão e changelog; quando essa PR entra na `main`, o pacote é publicado no npm
18
+ ## Instalação
141
19
 
142
- Ou use direto sem instalar globalmente:
143
20
  ```bash
144
- npx ts-node src/index.ts build
21
+ npm install -g @brunoluizdesiqueira/bbuilder-cli
145
22
  ```
146
23
 
147
- ---
148
-
149
- ## Uso
150
-
151
- ### Modo interativo (sem argumentos)
152
- ```bash
153
- bbuilder
154
- ```
155
- Exibe menus para escolher: modo de build → projeto → versão.
24
+ Depois confirme:
156
25
 
157
- ### Comando `build` com flags opcionais
158
26
  ```bash
159
- bbuilder build # interativo completo
160
- bbuilder build --type DEBUG # escolhe projeto e versão interativamente
161
- bbuilder build --type FAST --project faturamento\BimerFaturamento
162
- bbuilder build --type RELEASE --project Bimer --version 11.3.1
27
+ bbuilder --version
163
28
  ```
164
29
 
165
- Durante o build, o CLI exibe feedback visual por etapas com spinner, barra indeterminada e tempo decorrido. Essa barra representa atividade do pipeline, não percentual real do `dcc64`.
166
-
167
- ### Atalhos diretos por modo
168
- ```bash
169
- bbuilder fast # interativo para projeto/versão
170
- bbuilder debug --project Bimer
171
- bbuilder release --project Bimer --version 11.3.1
172
- ```
30
+ ## Configuração
173
31
 
174
- ### Gerenciamento de projetos
175
- ```bash
176
- bbuilder project list # lista projetos configurados
177
- bbuilder project add # adiciona novo projeto (interativo)
178
- bbuilder project remove # remove projeto (interativo ou por --name)
179
- ```
32
+ Crie a configuração inicial:
180
33
 
181
- ### Configuração do ambiente
182
34
  ```bash
183
- bbuilder config init # assistente para criar bbuilder.config.json
184
- bbuilder config show # exibe configuração atual
185
- bbuilder config validate # valida a estrutura do arquivo de configuração
186
- bbuilder doctor # diagnostica ambiente, config e paths
35
+ bbuilder config init
187
36
  ```
188
37
 
189
- ---
190
-
191
- ## Configuração (`bbuilder.config.json`)
192
-
193
- Prioridade de resolução da configuração:
194
-
195
- 1. `bbuilder --config <caminho>`
196
- 2. Variável de ambiente `BBUILDER_CONFIG`
197
- 3. `bbuilder.config.json` no diretório atual
198
- 4. `bimer.config.json` no diretório atual, por compatibilidade
199
- 5. Arquivo global do usuário
200
-
201
- No Windows, o arquivo global fica em `%APPDATA%\bbuilder-cli\bbuilder.config.json`.
202
-
203
- Crie com `bbuilder config init`, ou manualmente:
38
+ Ou use um arquivo manual como este:
204
39
 
205
40
  ```json
206
41
  {
@@ -218,181 +53,129 @@ Crie com `bbuilder config init`, ou manualmente:
218
53
  ],
219
54
  "projects": {
220
55
  "BimerFaturamento": "faturamento\\BimerFaturamento",
221
- "Bimer": "Bimer",
222
- "LiberadorEstoque": "geral\\gerenteeletronico.jobs.liberadorestoque\\LiberadorEstoque",
223
- "BimerEstoque": "estoque\\BimerEstoque"
56
+ "Bimer": "Bimer"
224
57
  }
225
58
  }
226
59
  ```
227
60
 
228
- `dependencyPaths` deve ser ajustado no `bbuilder.config.json`, porque esses caminhos podem variar entre usuários e máquinas.
229
-
230
- `projects` agora usa o formato `nome amigável: caminho real do projeto`, para a CLI exibir nomes humanizados sem perder a referência correta de compilação.
61
+ `dependencyPaths` varia por máquina e deve ser ajustado por usuário.
231
62
 
232
- Se o arquivo não existir, os valores padrão acima são usados automaticamente. Ao rodar `bbuilder config init`, a CLI gera um `dependencyPaths` inicial com base nos diretórios informados.
63
+ ## Resolução da Configuração
233
64
 
234
- ### Como usar configs locais
65
+ Ordem de prioridade:
235
66
 
236
- O pacote é instalado normalmente, e a configuração é informada na execução, não na instalação.
67
+ 1. `--config <caminho>`
68
+ 2. variável de ambiente `BBUILDER_CONFIG`
69
+ 3. `bbuilder.config.json` no diretório atual
70
+ 4. `bimer.config.json` no diretório atual, por compatibilidade
71
+ 5. arquivo global do usuário
237
72
 
238
- Instalação global:
73
+ No Windows, o arquivo global padrão fica em:
239
74
 
240
- ```bash
241
- npm install -g @brunoluizdesiqueira/bbuilder-cli
75
+ ```text
76
+ %APPDATA%\bbuilder-cli\bbuilder.config.json
242
77
  ```
243
78
 
244
- Usando um arquivo de config local explícito:
79
+ Exemplos:
245
80
 
246
81
  ```bash
247
82
  bbuilder --config C:\configs\bbuilder.config.json build
248
83
  ```
249
84
 
250
- Usando variável de ambiente no Windows CMD:
251
-
252
85
  ```bat
253
86
  set BBUILDER_CONFIG=C:\configs\bbuilder.config.json
254
87
  bbuilder build
255
88
  ```
256
89
 
257
- Usando variável de ambiente no PowerShell:
258
-
259
90
  ```powershell
260
91
  $env:BBUILDER_CONFIG="C:\configs\bbuilder.config.json"
261
92
  bbuilder build
262
93
  ```
263
94
 
264
- Usando config local no diretório atual:
95
+ ## Uso
96
+
97
+ Modo interativo:
265
98
 
266
- Se existir um `bbuilder.config.json` na pasta onde o comando é executado, a CLI usa esse arquivo automaticamente.
99
+ ```bash
100
+ bbuilder
101
+ ```
267
102
 
268
- Para verificar qual arquivo está sendo usado:
103
+ Build direto:
269
104
 
270
105
  ```bash
271
- bbuilder config show
106
+ bbuilder build --type DEBUG --project BimerFaturamento --version 11.3.1
107
+ bbuilder build --type FAST --project Bimer
108
+ bbuilder build --type RELEASE --project Bimer
272
109
  ```
273
110
 
274
- Exemplos:
111
+ Atalhos:
275
112
 
276
113
  ```bash
277
- bbuilder --config C:\configs\bbuilder.config.json build
114
+ bbuilder fast
115
+ bbuilder debug --project Bimer
116
+ bbuilder release --project Bimer --version 11.3.1
278
117
  ```
279
118
 
119
+ Projetos:
120
+
280
121
  ```bash
281
- set BBUILDER_CONFIG=C:\configs\bbuilder.config.json
122
+ bbuilder project list
123
+ bbuilder project add
124
+ bbuilder project remove
125
+ bbuilder project remove --name Bimer
126
+ ```
127
+
128
+ Configuração:
129
+
130
+ ```bash
131
+ bbuilder config init
282
132
  bbuilder config show
133
+ bbuilder config validate
134
+ bbuilder doctor
283
135
  ```
284
136
 
285
- ---
137
+ ## Observações de Uso
286
138
 
287
- ## Integração com VSCode (`tasks.json`)
139
+ - o build mostra etapas com tempo decorrido
140
+ - `cgrc` e `dcc64` escrevem diretamente no terminal durante a compilação
141
+ - no PowerShell, a saída do compilador pode ser menos verbosa que no `cmd`, mesmo com o build funcionando corretamente
288
142
 
289
- Substitua o `tasks.json` atual por este (sem mais menus do VSCode, a CLI cuida de tudo):
143
+ Se o PowerShell bloquear `npm` ou `bbuilder`, ajuste a policy do usuário:
290
144
 
291
- ```json
292
- {
293
- "version": "2.0.0",
294
- "tasks": [
295
- {
296
- "label": "Bimer: FAST + Run",
297
- "type": "shell",
298
- "command": "bbuilder fast",
299
- "group": "build",
300
- "presentation": { "reveal": "always", "focus": true, "panel": "dedicated", "clear": true },
301
- "problemMatcher": {
302
- "owner": "delphi",
303
- "fileLocation": ["autoDetect", "${workspaceFolder}"],
304
- "pattern": {
305
- "regexp": "^(.*?)\\s*\\((\\d+)\\)(?:\\s+|:\\s*)(Fatal|Error|Warning|Hint|error|fatal):\\s+(.*)$",
306
- "file": 1, "line": 2, "severity": 3, "message": 4
307
- }
308
- }
309
- },
310
- {
311
- "label": "Bimer: DEBUG + Run",
312
- "type": "shell",
313
- "command": "bbuilder debug",
314
- "group": "build",
315
- "presentation": { "reveal": "always", "focus": true, "panel": "dedicated", "clear": true },
316
- "problemMatcher": {
317
- "owner": "delphi",
318
- "fileLocation": ["autoDetect", "${workspaceFolder}"],
319
- "pattern": {
320
- "regexp": "^(.*?)\\s*\\((\\d+)\\)(?:\\s+|:\\s*)(Fatal|Error|Warning|Hint|error|fatal):\\s+(.*)$",
321
- "file": 1, "line": 2, "severity": 3, "message": 4
322
- }
323
- }
324
- },
325
- {
326
- "label": "Bimer: RELEASE",
327
- "type": "shell",
328
- "command": "bbuilder release",
329
- "group": "build",
330
- "presentation": { "reveal": "always", "focus": true, "panel": "dedicated", "clear": true },
331
- "problemMatcher": {
332
- "owner": "delphi",
333
- "fileLocation": ["autoDetect", "${workspaceFolder}"],
334
- "pattern": {
335
- "regexp": "^(.*?)\\s*\\((\\d+)\\)(?:\\s+|:\\s*)(Fatal|Error|Warning|Hint|error|fatal):\\s+(.*)$",
336
- "file": 1, "line": 2, "severity": 3, "message": 4
337
- }
338
- }
339
- }
340
- ]
341
- }
145
+ ```powershell
146
+ Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
342
147
  ```
343
148
 
344
- E nos keybindings, nada muda — os atalhos continuam os mesmos.
345
-
346
- ---
149
+ ## Troubleshooting
347
150
 
348
- ## Estrutura do Projeto
151
+ Validar ambiente:
349
152
 
153
+ ```bash
154
+ bbuilder doctor
350
155
  ```
351
- bbuilder-cli/
352
- ├── .changeset/
353
- │ ├── config.json
354
- │ └── *.md
355
- ├── .github/
356
- │ └── workflows/
357
- │ ├── ci.yml
358
- │ └── release.yml
359
- ├── src/
360
- │ ├── build/
361
- │ │ ├── compiler.ts
362
- │ │ ├── execute.ts
363
- │ │ ├── project.ts
364
- │ │ └── resources.ts
365
- │ ├── cli/
366
- │ │ └── program.ts
367
- │ ├── config/
368
- │ │ ├── config.ts
369
- │ │ └── validate.ts
370
- │ ├── diagnostics/
371
- │ │ └── doctor.ts
372
- │ ├── ui/
373
- │ │ ├── output.ts
374
- │ │ └── prompts.ts
375
- │ ├── index.ts
376
- │ └── types.ts
377
- ├── files/
378
- │ ├── build_local.bat
379
- │ ├── tasks.json
380
- │ └── ...
381
- ├── bbuilder.config.json
382
- ├── package.json
383
- ├── package-lock.json
384
- ├── tsconfig.json
385
- ├── .gitignore
386
- ├── LICENSE
387
- └── README.md
156
+
157
+ Validar configuração:
158
+
159
+ ```bash
160
+ bbuilder config validate
388
161
  ```
389
162
 
390
- ## Stack
163
+ Erro `Unit not found: 'System'` normalmente indica problema em:
164
+ - `delphiDir`
165
+ - `dependencyPaths`
166
+ - path `...\lib\Win64\release` ausente na configuração
167
+
168
+ ## Publicação
169
+
170
+ Para usuários, nada além de instalar o pacote é necessário.
171
+
172
+ Para mantenedores, o fluxo é:
173
+ - criar changeset
174
+ - abrir PR
175
+ - mergear na `main`
176
+ - mergear a PR automática de release
177
+ - publicação no npm ocorre via GitHub Actions
178
+
179
+ ## Licença
391
180
 
392
- | Lib | Por quê |
393
- |---|---|
394
- | **commander** | Parsing de comandos e flags |
395
- | **inquirer** | Menus interativos com setas |
396
- | **chalk** | Cores ANSI no terminal |
397
- | **execa** | Spawn de processos externos (CGRC, DCC64) |
398
- | **typescript** | Tipagem, autocomplete, menos bugs |
181
+ ISC
@@ -37,6 +37,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.buildCompilerFlags = buildCompilerFlags;
40
+ exports.ensureDelphiEnvironment = ensureDelphiEnvironment;
40
41
  exports.runCgrc = runCgrc;
41
42
  exports.runDcc64 = runDcc64;
42
43
  exports.runBuiltExecutable = runBuiltExecutable;
@@ -117,6 +118,9 @@ async function getDelphiEnvironment(delphiDir) {
117
118
  (0, output_1.fatal)(`Falha ao carregar o ambiente do Delphi via rsvars.bat (${rsvarsPath}). Detalhe: ${message}`);
118
119
  }
119
120
  }
121
+ async function ensureDelphiEnvironment(delphiDir) {
122
+ await getDelphiEnvironment(delphiDir);
123
+ }
120
124
  async function runCgrc(opts, projectName) {
121
125
  const tempDir = path.join(os.tmpdir(), `BimerBuild_${projectName}`);
122
126
  const vrcFile = path.join(tempDir, `${projectName}.vrc`);
@@ -41,21 +41,22 @@ const compiler_1 = require("./compiler");
41
41
  const project_1 = require("./project");
42
42
  const resources_1 = require("./resources");
43
43
  async function executeBuild(opts) {
44
- const totalStages = 4;
44
+ const totalStages = 5;
45
45
  (0, output_1.banner)();
46
46
  const { workspaceDir, projectName } = (0, project_1.resolveProject)(opts.project, opts.repoBase);
47
47
  (0, output_1.printBuildHeader)(opts, projectName, workspaceDir);
48
- await (0, output_1.withProgress)(1, totalStages, 'Preparando versao, manifesto e recursos', () => {
48
+ await (0, output_1.withStep)(1, totalStages, 'Carregando ambiente do Delphi', () => (0, compiler_1.ensureDelphiEnvironment)(opts.delphiDir));
49
+ await (0, output_1.withStep)(2, totalStages, 'Preparando versao, manifesto e recursos', () => {
49
50
  (0, resources_1.prepareProjectResources)(opts, projectName, workspaceDir);
50
51
  });
51
52
  const oldRes = path.win32.join(workspaceDir, `${projectName}.res`);
52
53
  if (fs.existsSync(oldRes))
53
54
  fs.unlinkSync(oldRes);
54
- const resFile = await (0, output_1.withProgress)(2, totalStages, 'Compilando recursos nativos', () => (0, compiler_1.runCgrc)(opts, projectName), { streamingOutput: true });
55
- await (0, output_1.withProgress)(3, totalStages, 'Sincronizando recurso final no projeto', () => {
55
+ const resFile = await (0, output_1.withStep)(3, totalStages, 'Compilando recursos nativos', () => (0, compiler_1.runCgrc)(opts, projectName));
56
+ await (0, output_1.withStep)(4, totalStages, 'Sincronizando recurso final no projeto', () => {
56
57
  fs.copyFileSync(resFile, path.win32.join(workspaceDir, `${projectName}.res`));
57
58
  });
58
- await (0, output_1.withProgress)(4, totalStages, `Compilando projeto Delphi (${opts.type})`, () => (0, compiler_1.runDcc64)(opts, projectName, workspaceDir), { streamingOutput: true });
59
+ await (0, output_1.withStep)(5, totalStages, `Compilando projeto Delphi (${opts.type})`, () => (0, compiler_1.runDcc64)(opts, projectName, workspaceDir));
59
60
  (0, output_1.printSuccess)(opts.type);
60
61
  const { runAfter } = (0, compiler_1.buildCompilerFlags)(opts.type);
61
62
  if (runAfter) {
@@ -98,7 +98,7 @@ async function runCli(argv) {
98
98
  .description('Compila um projeto Delphi (interativo se flags omitidas)')
99
99
  .option('-t, --type <FAST|DEBUG|RELEASE>', 'Modo de build')
100
100
  .option('-p, --project <path>', 'Caminho do projeto (ex: faturamento\\BimerFaturamento)')
101
- .option('-v, --version <version>', 'Versão a injetar (ex: 11.2.4)'), HELP_EXAMPLES.build)
101
+ .option('-v, --version <version>', 'Versão a injetar (ex: 11.3.0)'), HELP_EXAMPLES.build)
102
102
  .action(async (opts) => {
103
103
  const buildType = opts.type?.toUpperCase();
104
104
  if (buildType && !['FAST', 'DEBUG', 'RELEASE'].includes(buildType)) {
package/dist/ui/output.js CHANGED
@@ -1,37 +1,4 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
36
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
4
  };
@@ -40,13 +7,11 @@ exports.banner = banner;
40
7
  exports.printBuildHeader = printBuildHeader;
41
8
  exports.printSuccess = printSuccess;
42
9
  exports.step = step;
10
+ exports.formatElapsedMs = formatElapsedMs;
11
+ exports.withStep = withStep;
43
12
  exports.withProgress = withProgress;
44
13
  exports.fatal = fatal;
45
14
  const chalk_1 = __importDefault(require("chalk"));
46
- const readline = __importStar(require("readline"));
47
- const SPINNER_FRAMES = ['|', '/', '-', '\\'];
48
- const BAR_WIDTH = 18;
49
- const BAR_SEGMENT = 6;
50
15
  function banner() {
51
16
  console.log('');
52
17
  console.log(chalk_1.default.blue(' ══════════════════════════════════════════════════════════════'));
@@ -95,105 +60,31 @@ function printSuccess(buildType) {
95
60
  function step(msg) {
96
61
  console.log(chalk_1.default.cyan(' [*]') + ' ' + chalk_1.default.white(msg));
97
62
  }
98
- function formatElapsed(startTime) {
99
- const totalSeconds = Math.max(0, Math.floor((Date.now() - startTime) / 1000));
63
+ function formatElapsedMs(elapsedMs) {
64
+ const totalSeconds = Math.max(0, Math.floor(elapsedMs / 1000));
100
65
  const minutes = Math.floor(totalSeconds / 60)
101
66
  .toString()
102
67
  .padStart(2, '0');
103
68
  const seconds = (totalSeconds % 60).toString().padStart(2, '0');
104
69
  return `${minutes}:${seconds}`;
105
70
  }
106
- function buildIndeterminateBar(frameIndex) {
107
- const chars = new Array(BAR_WIDTH).fill('░');
108
- const start = frameIndex % (BAR_WIDTH + BAR_SEGMENT);
109
- for (let offset = 0; offset < BAR_SEGMENT; offset++) {
110
- const position = start - offset;
111
- if (position >= 0 && position < BAR_WIDTH) {
112
- chars[position] = '█';
113
- }
114
- }
115
- return chars.join('');
116
- }
117
- function truncateLabel(label, maxLength) {
118
- if (maxLength <= 0)
119
- return '';
120
- if (label.length <= maxLength)
121
- return label;
122
- if (maxLength <= 1)
123
- return label.slice(0, maxLength);
124
- return `${label.slice(0, maxLength - 1)}…`;
125
- }
126
- function renderProgressLine(stage, total, label, startTime, frameIndex) {
127
- const spinner = SPINNER_FRAMES[frameIndex % SPINNER_FRAMES.length];
128
- const bar = buildIndeterminateBar(frameIndex);
129
- const elapsed = formatElapsed(startTime);
130
- const columns = process.stdout.columns || 100;
131
- const reservedLength = 2 + `[${stage}/${total}]`.length + 1 + 1 + 1 + 1 + 1 + (BAR_WIDTH + 2) + 1 + elapsed.length;
132
- const maxLabelLength = Math.max(12, columns - reservedLength);
133
- const safeLabel = truncateLabel(label, maxLabelLength);
134
- return ` ${chalk_1.default.cyan(`[${stage}/${total}]`)} ${chalk_1.default.yellow(spinner)} ${chalk_1.default.white(safeLabel)} ${chalk_1.default.blue(`[${bar}]`)} ${chalk_1.default.gray(elapsed)}`;
135
- }
136
- function drawProgressLine(line) {
137
- readline.clearLine(process.stdout, 0);
138
- readline.cursorTo(process.stdout, 0);
139
- process.stdout.write(line);
140
- }
141
- function clearProgressLine() {
142
- readline.clearLine(process.stdout, 0);
143
- readline.cursorTo(process.stdout, 0);
144
- }
145
- async function withProgress(stage, total, label, task, options) {
71
+ async function withStep(stage, total, label, task, options) {
146
72
  const startTime = Date.now();
147
- const streamingOutput = options?.streamingOutput ?? false;
148
- if (!process.stdout.isTTY) {
149
- step(`[${stage}/${total}] ${label}`);
150
- const result = await task();
151
- console.log(` ${chalk_1.default.green('OK')} ${chalk_1.default.white(label)} ${chalk_1.default.gray(`(${formatElapsed(startTime)})`)}`);
152
- return result;
153
- }
154
- if (streamingOutput) {
155
- step(`[${stage}/${total}] ${label}`);
156
- try {
157
- const result = await task();
158
- console.log(` ${chalk_1.default.green('OK')} ${chalk_1.default.white(label)} ${chalk_1.default.gray(`(${formatElapsed(startTime)})`)}`);
159
- return result;
160
- }
161
- catch (error) {
162
- console.log(` ${chalk_1.default.red('FAIL')} ${chalk_1.default.white(label)} ${chalk_1.default.gray(`(${formatElapsed(startTime)})`)}`);
163
- throw error;
164
- }
165
- }
166
- let frameIndex = 0;
167
- let rendered = false;
168
- let timer;
169
- const render = () => {
170
- clearProgressLine();
171
- drawProgressLine(renderProgressLine(stage, total, label, startTime, frameIndex));
172
- rendered = true;
173
- };
174
- render();
175
- timer = setInterval(() => {
176
- frameIndex += 1;
177
- render();
178
- }, 120);
73
+ const prefix = `[${stage}/${total}] ${label}`;
74
+ step(prefix);
179
75
  try {
180
76
  const result = await task();
181
- if (timer)
182
- clearInterval(timer);
183
- if (rendered)
184
- clearProgressLine();
185
- console.log(` ${chalk_1.default.green('OK')} ${chalk_1.default.white(label)} ${chalk_1.default.gray(`(${formatElapsed(startTime)})`)}`);
77
+ console.log(` ${chalk_1.default.green('OK')} ${chalk_1.default.white(label)} ${chalk_1.default.gray(`(${formatElapsedMs(Date.now() - startTime)})`)}`);
186
78
  return result;
187
79
  }
188
80
  catch (error) {
189
- if (timer)
190
- clearInterval(timer);
191
- if (rendered)
192
- clearProgressLine();
193
- console.log(` ${chalk_1.default.red('FAIL')} ${chalk_1.default.white(label)} ${chalk_1.default.gray(`(${formatElapsed(startTime)})`)}`);
81
+ console.log(` ${chalk_1.default.red('FAIL')} ${chalk_1.default.white(label)} ${chalk_1.default.gray(`(${formatElapsedMs(Date.now() - startTime)})`)}`);
194
82
  throw error;
195
83
  }
196
84
  }
85
+ async function withProgress(stage, total, label, task, options) {
86
+ return withStep(stage, total, label, task, options);
87
+ }
197
88
  function fatal(msg) {
198
89
  console.error('');
199
90
  console.error(chalk_1.default.red(' [ERRO FATAL] ') + msg);
@@ -43,7 +43,7 @@ async function promptBuild(config, cliType, cliProject, cliVersion) {
43
43
  type: 'input',
44
44
  name: 'version',
45
45
  message: 'Versão do EXE? (deixe em branco para manter atual):',
46
- default: '',
46
+ default: '11.3.0',
47
47
  });
48
48
  }
49
49
  const answers = await inquirer_1.default.prompt(questions);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brunoluizdesiqueira/bbuilder-cli",
3
- "version": "1.0.16",
3
+ "version": "1.0.18",
4
4
  "description": "CLI de build local para projetos Delphi do Bimer",
5
5
  "license": "ISC",
6
6
  "repository": {
@@ -33,6 +33,7 @@
33
33
  "scripts": {
34
34
  "build": "tsc",
35
35
  "dev": "ts-node src/index.ts",
36
+ "test": "npm run build && node --test test/**/*.test.js",
36
37
  "prepack": "npm run build",
37
38
  "changeset": "changeset",
38
39
  "version-packages": "changeset version",