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