@qodalis/cli 2.0.0-beta.11 → 2.0.0-beta.12

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/public-api.mjs CHANGED
@@ -410,7 +410,7 @@ var CliBackgroundServiceRegistry_TOKEN = "cli-background-service-registry";
410
410
  var CliPackageManagerService_TOKEN = "cli-package-manager-service";
411
411
 
412
412
  // src/lib/version.ts
413
- var LIBRARY_VERSION = "2.0.0-beta.11";
413
+ var LIBRARY_VERSION = "2.0.0-beta.12";
414
414
  var API_VERSION = 2;
415
415
  var CliAliasCommandProcessor = class {
416
416
  constructor() {
@@ -4773,6 +4773,7 @@ var CliPackagesCommandProcessor = class {
4773
4773
  const { progressBar, writer } = context2;
4774
4774
  const { signal, cleanup } = scope.createAbortSignal(context2);
4775
4775
  progressBar.show();
4776
+ context2.setStatusText("Browsing packages");
4776
4777
  const prefix = packagesManager.QODALIS_COMMAND_PREFIX;
4777
4778
  const knownShortNames = [
4778
4779
  "browser-storage",
@@ -4965,6 +4966,7 @@ var CliPackagesCommandProcessor = class {
4965
4966
  const packages = command2.value.split(" ");
4966
4967
  for (const pkg of packages) {
4967
4968
  if (signal.aborted) break;
4969
+ context2.setStatusText(`Installing ${pkg}`);
4968
4970
  await scope.addPackage(pkg, context2, signal);
4969
4971
  }
4970
4972
  cleanup();
@@ -5005,6 +5007,7 @@ var CliPackagesCommandProcessor = class {
5005
5007
  const packages = command2.value.split(" ");
5006
5008
  for (const pkg of packages) {
5007
5009
  if (signal.aborted) break;
5010
+ context2.setStatusText(`Removing ${pkg}`);
5008
5011
  await scope.removePackage(pkg, context2);
5009
5012
  }
5010
5013
  cleanup();
@@ -5040,6 +5043,7 @@ var CliPackagesCommandProcessor = class {
5040
5043
  const fullName = name.startsWith(prefix) ? name : `${prefix}${name}`;
5041
5044
  progressBar.show();
5042
5045
  progressBar.setText(`Fetching versions for ${name}`);
5046
+ context2.setStatusText(`Fetching versions for ${name}`);
5043
5047
  try {
5044
5048
  const response = await scriptsLoader.getScript(
5045
5049
  `https://registry.npmjs.org/${encodeURIComponent(fullName)}`,
@@ -6246,6 +6250,8 @@ async function executeOnServer(connection, serverName, descriptor, command2, con
6246
6250
  command: commandPath && commandPath.length > 0 ? commandPath[0] : descriptor.command,
6247
6251
  chainCommands: commandPath && commandPath.length > 1 ? commandPath.slice(1) : []
6248
6252
  };
6253
+ const cmdLabel = commandPath && commandPath.length > 0 ? commandPath.join(" ") : descriptor.command;
6254
+ context2.setStatusText(`executing command: ${cmdLabel} on server ${serverName}`);
6249
6255
  try {
6250
6256
  if (connection.capabilities?.streaming) {
6251
6257
  const result = await connection.executeStream(
@@ -10404,6 +10410,7 @@ var CliPingCommandProcessor = class {
10404
10410
  context2.writer.writeln(
10405
10411
  `PING ${host} (${url}):`
10406
10412
  );
10413
+ context2.setStatusText(`ping ${host}`);
10407
10414
  const times = [];
10408
10415
  let transmitted = 0;
10409
10416
  let received = 0;
@@ -10429,6 +10436,7 @@ var CliPingCommandProcessor = class {
10429
10436
  received++;
10430
10437
  times.push(elapsed);
10431
10438
  const status = response.type === "opaque" ? "ok" : `status=${response.status}`;
10439
+ context2.setStatusText(`ping ${host}: seq=${seq} time=${ms}ms`);
10432
10440
  context2.writer.writeln(
10433
10441
  `${url}: seq=${seq} ${status} time=${ms} ms`
10434
10442
  );
@@ -10894,11 +10902,21 @@ var CliCommandExecutionContext = class {
10894
10902
  this.reader = context2.reader;
10895
10903
  this.enterFullScreenMode = (p, o) => context2.enterFullScreenMode(p, o);
10896
10904
  this.exitFullScreenMode = () => context2.exitFullScreenMode();
10905
+ this.submitCommand = (command2) => context2.submitCommand(command2);
10897
10906
  this.createInterval = (cb, ms) => context2.createInterval(cb, ms);
10898
10907
  this.createTimeout = (cb, ms) => context2.createTimeout(cb, ms);
10899
10908
  this.backgroundServices = context2.backgroundServices;
10900
10909
  this.state = context2.services.get(CliStateStoreManager_TOKEN).getProcessorStateStore(processor);
10901
10910
  }
10911
+ setStatusText(text) {
10912
+ this.context.setStatusText(text);
10913
+ }
10914
+ clearStatusText() {
10915
+ this.context.clearStatusText();
10916
+ }
10917
+ getStatusText() {
10918
+ return this.context.getStatusText();
10919
+ }
10902
10920
  get promptLength() {
10903
10921
  return this.context.promptLength;
10904
10922
  }
@@ -14075,18 +14093,15 @@ var CommandLineMode = class {
14075
14093
  if (data === "\r") {
14076
14094
  this.clearGhostText();
14077
14095
  this.host.terminal.write("\r\n");
14078
- if (buffer.text) {
14079
- await this.host.commandHistory.addCommand(buffer.text);
14096
+ const text = buffer.text;
14097
+ if (text) {
14080
14098
  this.historyIndex = this.host.commandHistory.getLastIndex();
14081
14099
  this.bufferSetByHistory = false;
14082
- this.isExecutingCommand = true;
14083
- const ctx = this.host.getExecutionContext();
14084
- await ctx.executor.executeCommand(buffer.text, ctx);
14085
- this.isExecutingCommand = false;
14086
- }
14087
- if (!this.host.isRawModeActive()) {
14088
- this.host.showPrompt();
14089
14100
  }
14101
+ this.isExecutingCommand = true;
14102
+ const ctx = this.host.getExecutionContext();
14103
+ await ctx.submitCommand(text);
14104
+ this.isExecutingCommand = false;
14090
14105
  } else if (data === "\x1B[A") {
14091
14106
  this.showPreviousCommand();
14092
14107
  } else if (data === "\x1B[B") {
@@ -14468,6 +14483,12 @@ var CliExecutionContext = class {
14468
14483
  this.onAbort = new Subject();
14469
14484
  this.completionEngine = new CliCompletionEngine();
14470
14485
  this.promptLength = 0;
14486
+ /**
14487
+ * Whether a command is currently being executed.
14488
+ * Set by the command executor at start/end of executeCommand().
14489
+ */
14490
+ this.isExecuting = false;
14491
+ this.statusTextChange$ = new Subject();
14471
14492
  this.lineBuffer = new CliLineBuffer();
14472
14493
  this.modeStack = [];
14473
14494
  this.timerManager = new CliTimerManager();
@@ -14522,6 +14543,17 @@ var CliExecutionContext = class {
14522
14543
  this.backgroundServices
14523
14544
  );
14524
14545
  }
14546
+ setStatusText(text) {
14547
+ this._statusText = text;
14548
+ this.statusTextChange$.next(text);
14549
+ }
14550
+ clearStatusText() {
14551
+ this._statusText = void 0;
14552
+ this.statusTextChange$.next(void 0);
14553
+ }
14554
+ getStatusText() {
14555
+ return this._statusText;
14556
+ }
14525
14557
  // -- Public API (ICliExecutionContext) --
14526
14558
  writeToTerminal(text) {
14527
14559
  this.terminal.write(text);
@@ -14601,6 +14633,20 @@ var CliExecutionContext = class {
14601
14633
  this.getPromptOptions()
14602
14634
  );
14603
14635
  }
14636
+ /**
14637
+ * Submit and execute a command — shared by interactive Enter key
14638
+ * and programmatic engine.execute(). Adds to history, runs the
14639
+ * command, and shows a new prompt afterwards.
14640
+ */
14641
+ async submitCommand(command2) {
14642
+ if (command2.trim()) {
14643
+ await this.commandHistory.addCommand(command2);
14644
+ await this.executor.executeCommand(command2, this);
14645
+ }
14646
+ if (!this.isRawModeActive()) {
14647
+ this.showPrompt();
14648
+ }
14649
+ }
14604
14650
  clearCurrentLine() {
14605
14651
  this.clearLine();
14606
14652
  this.showPrompt();
@@ -15186,92 +15232,106 @@ var CliCommandExecutor = class {
15186
15232
  } else {
15187
15233
  rootContext = context2;
15188
15234
  }
15189
- let lastExitSuccess = true;
15190
- let shouldRunNext = true;
15191
- let pipelineData = void 0;
15192
- let lastCapturingWriter;
15193
- for (let i = 0; i < parts.length; i++) {
15194
- const part = parts[i];
15195
- if (part.type === "&&") {
15196
- shouldRunNext = lastExitSuccess;
15197
- continue;
15198
- } else if (part.type === "||") {
15199
- shouldRunNext = !lastExitSuccess;
15200
- continue;
15201
- } else if (part.type === "|") {
15202
- shouldRunNext = true;
15203
- continue;
15204
- } else if (part.type === ";") {
15205
- shouldRunNext = true;
15206
- pipelineData = void 0;
15207
- continue;
15208
- } else if (part.type === ">>") {
15209
- const nextPart = parts[i + 1];
15210
- i++;
15211
- if (!nextPart || nextPart.type !== "command") {
15212
- context2.writer.writeError("Missing file path after >>");
15213
- lastExitSuccess = false;
15235
+ rootContext.isExecuting = true;
15236
+ try {
15237
+ let lastExitSuccess = true;
15238
+ let shouldRunNext = true;
15239
+ let pipelineData = void 0;
15240
+ let lastCapturingWriter;
15241
+ for (let i = 0; i < parts.length; i++) {
15242
+ const part = parts[i];
15243
+ if (part.type === "&&") {
15244
+ shouldRunNext = lastExitSuccess;
15214
15245
  continue;
15215
- }
15216
- if (shouldRunNext) {
15217
- await appendOutputToFile(nextPart.value, context2);
15218
- pipelineData = void 0;
15219
- }
15220
- continue;
15221
- } else if (part.type === ">") {
15222
- const nextPart = parts[i + 1];
15223
- i++;
15224
- if (!nextPart || nextPart.type !== "command") {
15225
- context2.writer.writeError("Missing file path after >");
15226
- lastExitSuccess = false;
15246
+ } else if (part.type === "||") {
15247
+ shouldRunNext = !lastExitSuccess;
15227
15248
  continue;
15228
- }
15229
- if (shouldRunNext) {
15230
- await writeOutputToFile(nextPart.value, context2);
15249
+ } else if (part.type === "|") {
15250
+ shouldRunNext = true;
15251
+ continue;
15252
+ } else if (part.type === ";") {
15253
+ shouldRunNext = true;
15231
15254
  pipelineData = void 0;
15232
- }
15233
- continue;
15234
- } else if (part.type === "2>>") {
15235
- const nextPart = parts[i + 1];
15236
- i++;
15237
- if (!nextPart || nextPart.type !== "command") {
15238
- context2.writer.writeError("Missing file path after 2>>");
15239
- lastExitSuccess = false;
15255
+ continue;
15256
+ } else if (part.type === ">>") {
15257
+ const nextPart = parts[i + 1];
15258
+ i++;
15259
+ if (!nextPart || nextPart.type !== "command") {
15260
+ context2.writer.writeError("Missing file path after >>");
15261
+ lastExitSuccess = false;
15262
+ continue;
15263
+ }
15264
+ if (shouldRunNext) {
15265
+ await appendOutputToFile(nextPart.value, context2);
15266
+ pipelineData = void 0;
15267
+ }
15268
+ continue;
15269
+ } else if (part.type === ">") {
15270
+ const nextPart = parts[i + 1];
15271
+ i++;
15272
+ if (!nextPart || nextPart.type !== "command") {
15273
+ context2.writer.writeError("Missing file path after >");
15274
+ lastExitSuccess = false;
15275
+ continue;
15276
+ }
15277
+ if (shouldRunNext) {
15278
+ await writeOutputToFile(nextPart.value, context2);
15279
+ pipelineData = void 0;
15280
+ }
15281
+ continue;
15282
+ } else if (part.type === "2>>") {
15283
+ const nextPart = parts[i + 1];
15284
+ i++;
15285
+ if (!nextPart || nextPart.type !== "command") {
15286
+ context2.writer.writeError("Missing file path after 2>>");
15287
+ lastExitSuccess = false;
15288
+ continue;
15289
+ }
15290
+ if (shouldRunNext) {
15291
+ await appendStderrToFile(nextPart.value, context2, lastCapturingWriter);
15292
+ }
15293
+ continue;
15294
+ } else if (part.type === "2>") {
15295
+ const nextPart = parts[i + 1];
15296
+ i++;
15297
+ if (!nextPart || nextPart.type !== "command") {
15298
+ context2.writer.writeError("Missing file path after 2>");
15299
+ lastExitSuccess = false;
15300
+ continue;
15301
+ }
15302
+ if (shouldRunNext) {
15303
+ await writeStderrToFile(nextPart.value, context2, lastCapturingWriter);
15304
+ }
15240
15305
  continue;
15241
15306
  }
15242
- if (shouldRunNext) {
15243
- await appendStderrToFile(nextPart.value, context2, lastCapturingWriter);
15244
- }
15245
- continue;
15246
- } else if (part.type === "2>") {
15247
- const nextPart = parts[i + 1];
15248
- i++;
15249
- if (!nextPart || nextPart.type !== "command") {
15250
- context2.writer.writeError("Missing file path after 2>");
15251
- lastExitSuccess = false;
15307
+ if (!shouldRunNext) {
15252
15308
  continue;
15253
15309
  }
15254
- if (shouldRunNext) {
15255
- await writeStderrToFile(nextPart.value, context2, lastCapturingWriter);
15310
+ try {
15311
+ lastCapturingWriter = await this.executeSingleCommand(
15312
+ part.value,
15313
+ pipelineData,
15314
+ rootContext
15315
+ );
15316
+ lastExitSuccess = context2.process.exitCode === void 0 || context2.process.exitCode === 0;
15317
+ rootContext.lastCommandResult = {
15318
+ command: part.value,
15319
+ success: lastExitSuccess
15320
+ };
15321
+ pipelineData = context2.process.data;
15322
+ } catch (e) {
15323
+ lastExitSuccess = false;
15324
+ rootContext.lastCommandResult = {
15325
+ command: part.value,
15326
+ success: false
15327
+ };
15328
+ context2.writer.writeError(`Command ${part.value} failed: ${e}`);
15256
15329
  }
15257
- continue;
15258
- }
15259
- if (!shouldRunNext) {
15260
- continue;
15261
- }
15262
- try {
15263
- lastCapturingWriter = await this.executeSingleCommand(
15264
- part.value,
15265
- pipelineData,
15266
- rootContext
15267
- );
15268
- lastExitSuccess = context2.process.exitCode === void 0 || context2.process.exitCode === 0;
15269
- pipelineData = context2.process.data;
15270
- } catch (e) {
15271
- lastExitSuccess = false;
15272
- context2.writer.writeError(`Command ${part.value} failed: ${e}`);
15330
+ shouldRunNext = true;
15273
15331
  }
15274
- shouldRunNext = true;
15332
+ } finally {
15333
+ rootContext.isExecuting = false;
15334
+ rootContext.clearStatusText?.();
15275
15335
  }
15276
15336
  }
15277
15337
  async executeSingleCommand(command2, data, context2) {
@@ -16856,6 +16916,7 @@ var ServerStatusProcessor = class {
16856
16916
  return;
16857
16917
  }
16858
16918
  context2.spinner?.show(`Pinging ${serverName}...`);
16919
+ context2.setStatusText(`Pinging ${serverName}`);
16859
16920
  const reachable = await connection.ping();
16860
16921
  context2.spinner?.hide();
16861
16922
  if (reachable) {
@@ -16895,6 +16956,7 @@ var ServerReconnectProcessor = class {
16895
16956
  return;
16896
16957
  }
16897
16958
  context2.spinner?.show(`Reconnecting to ${serverName}...`);
16959
+ context2.setStatusText(`Reconnecting to ${serverName}`);
16898
16960
  const result = await manager.reconnect(serverName);
16899
16961
  context2.spinner?.hide();
16900
16962
  if (result.success) {
@@ -17778,6 +17840,8 @@ var CliEngine = class {
17778
17840
  if (this.options?.snapshot) {
17779
17841
  await this.restoreSnapshot(this.options.snapshot);
17780
17842
  }
17843
+ this._startedAt = Date.now();
17844
+ this.safeFit();
17781
17845
  }
17782
17846
  /**
17783
17847
  * Clean up terminal and event listeners.
@@ -17836,15 +17900,22 @@ var CliEngine = class {
17836
17900
  return this.registry;
17837
17901
  }
17838
17902
  /**
17839
- * Execute a command programmatically.
17903
+ * Timestamp (ms since epoch) when the engine finished starting.
17904
+ */
17905
+ get startedAt() {
17906
+ return this._startedAt;
17907
+ }
17908
+ /**
17909
+ * Execute a command programmatically, behaving the same as if the user
17910
+ * typed it and pressed Enter: echoes the command, adds it to history,
17911
+ * executes it, and shows a new prompt afterwards.
17840
17912
  */
17841
17913
  async execute(command2) {
17842
- if (this.executionContext) {
17843
- await this.executionContext.executor.executeCommand(
17844
- command2,
17845
- this.executionContext
17846
- );
17847
- }
17914
+ if (!this.executionContext) return;
17915
+ const ctx = this.executionContext;
17916
+ ctx.showPrompt({ reset: true });
17917
+ this.terminal.write(command2 + "\r\n");
17918
+ await ctx.submitCommand(command2);
17848
17919
  }
17849
17920
  /**
17850
17921
  * Capture a snapshot of the current engine state.
@@ -18070,6 +18141,14 @@ var CliTestHarness = class {
18070
18141
  },
18071
18142
  exitFullScreenMode: () => {
18072
18143
  },
18144
+ submitCommand: async (command2) => {
18145
+ await this.executor.executeCommand(command2, context2);
18146
+ },
18147
+ setStatusText: () => {
18148
+ },
18149
+ clearStatusText: () => {
18150
+ },
18151
+ getStatusText: () => void 0,
18073
18152
  createInterval: (cb, ms) => {
18074
18153
  const id = setInterval(cb, ms);
18075
18154
  return {