@bussolabs/closeyourit-cli 0.25.0 → 0.25.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/dist/base.js CHANGED
@@ -36,6 +36,13 @@ function paginationError(opts) {
36
36
  return `Invalid --per ${opts.per}: ask for at least 1 row.`;
37
37
  return undefined;
38
38
  }
39
+ /**
40
+ * `this.exit(n)` di oclif lancia un ExitError: si riconosce dal codice `EEXIT`, non dalla classe —
41
+ * importarla legherebbe la base a un percorso interno di oclif che cambia fra le versioni.
42
+ */
43
+ function isExitError(error) {
44
+ return typeof error === 'object' && error !== null && error.code === 'EEXIT';
45
+ }
39
46
  class BaseCommand extends core_1.Command {
40
47
  static enableJsonFlag = true;
41
48
  /**
@@ -205,6 +212,12 @@ class BaseCommand extends core_1.Command {
205
212
  * swallowed (empty stdout, exit looks like a silent success) for machine consumers (CYCL-1).
206
213
  */
207
214
  async catch(error) {
215
+ // CYCL-52 — `this.exit(n)` è una decisione presa dal comando, non un guasto da raccontare: chi
216
+ // l'ha chiamata ha già detto la sua sull'uscita. Senza questa riga l'ExitError arriva quaggiù e
217
+ // il ramo generico emette un SECONDO envelope, così chi legge in modalità dati si trova due
218
+ // oggetti JSON sulla stessa uscita e non sa quale dei due sia la risposta.
219
+ if (isExitError(error))
220
+ throw error;
208
221
  if (error instanceof api_1.ApiRequestError) {
209
222
  if (this.jsonEnabled()) {
210
223
  this.logJson({ error: { code: error.code, message: error.message, ...(error.details === undefined ? {} : { details: error.details }) } });
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@oclif/core");
4
4
  const base_1 = require("../../base");
5
+ const error_codes_1 = require("../../errors/error-codes");
5
6
  const limits_1 = require("../../lib/limits");
6
7
  const output_1 = require("../../lib/output");
7
8
  const ticket_body_1 = require("../../lib/ticket-body");
@@ -42,9 +43,29 @@ class TicketsCreate extends base_1.BaseCommand {
42
43
  body.status_id = statusId;
43
44
  body.priority_id = priorityId;
44
45
  const res = await this.api.post(`/cli/v1/projects/${projectId}/tickets`, body);
45
- if (!this.jsonEnabled()) {
46
- this.log('Ticket created:');
47
- this.log((0, output_1.renderRecord)(res.data ?? {}));
46
+ // CYCL-52 — da qui in poi il ticket ESISTE sul server, e qualunque cosa vada storta mentre lo si
47
+ // racconta non lo cancella. Se il comando esce non-zero senza dire niente, chi legge conclude che
48
+ // non è stato creato e lo ricrea: è così che sono nati CYRA-755/756, due volte lo stesso ticket.
49
+ // Perciò il codice e l'id vengono emessi comunque, e solo dopo l'errore vero risale.
50
+ try {
51
+ if (!this.jsonEnabled()) {
52
+ this.log('Ticket created:');
53
+ this.log((0, output_1.renderRecord)(res.data ?? {}));
54
+ }
55
+ }
56
+ catch (error) {
57
+ const creato = res.data ?? {};
58
+ const identita = { code: creato.code, id: creato.id };
59
+ const motivo = error instanceof Error ? error.message : String(error);
60
+ // In modalità dati l'envelope è UNO: se si lasciasse risalire l'errore, la base ne emetterebbe
61
+ // un secondo e chi legge si troverebbe due oggetti sulla stessa uscita. Qui data ed error
62
+ // stanno insieme — il ticket c'è, e c'è anche cosa è andato storto — e si esce non-zero.
63
+ if (this.jsonEnabled()) {
64
+ this.logJson({ data: identita, error: { code: error_codes_1.ErrorCodes.System.unexpected, message: motivo } });
65
+ return this.exit(1);
66
+ }
67
+ this.logToStderr(`Ticket creato (${String(identita.code ?? identita.id ?? 'senza codice')}), ma la resa è fallita: ${motivo}`);
68
+ throw error;
48
69
  }
49
70
  return res;
50
71
  }