@cat-indev/catops-cli 0.0.1-alpha.10

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.
Files changed (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1254 -0
  3. package/dist/bin/devops-cli.d.ts +2 -0
  4. package/dist/bin/devops-cli.js +132 -0
  5. package/dist/bin/devops-cli.js.map +1 -0
  6. package/dist/core/Context.d.ts +56 -0
  7. package/dist/core/Context.js +197 -0
  8. package/dist/core/Context.js.map +1 -0
  9. package/dist/core/Menu.d.ts +23 -0
  10. package/dist/core/Menu.js +160 -0
  11. package/dist/core/Menu.js.map +1 -0
  12. package/dist/core/Notifier.d.ts +42 -0
  13. package/dist/core/Notifier.js +128 -0
  14. package/dist/core/Notifier.js.map +1 -0
  15. package/dist/core/classifiers.d.ts +45 -0
  16. package/dist/core/classifiers.js +90 -0
  17. package/dist/core/classifiers.js.map +1 -0
  18. package/dist/core/logger.d.ts +8 -0
  19. package/dist/core/logger.js +37 -0
  20. package/dist/core/logger.js.map +1 -0
  21. package/dist/core/messages.d.ts +102 -0
  22. package/dist/core/messages.js +163 -0
  23. package/dist/core/messages.js.map +1 -0
  24. package/dist/core/prompt.d.ts +10 -0
  25. package/dist/core/prompt.js +87 -0
  26. package/dist/core/prompt.js.map +1 -0
  27. package/dist/core/senders.d.ts +27 -0
  28. package/dist/core/senders.js +109 -0
  29. package/dist/core/senders.js.map +1 -0
  30. package/dist/core/types.d.ts +135 -0
  31. package/dist/core/types.js +33 -0
  32. package/dist/core/types.js.map +1 -0
  33. package/dist/index.d.ts +20 -0
  34. package/dist/index.js +66 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/services/ansible.d.ts +12 -0
  37. package/dist/services/ansible.js +35 -0
  38. package/dist/services/ansible.js.map +1 -0
  39. package/dist/services/archive.d.ts +4 -0
  40. package/dist/services/archive.js +16 -0
  41. package/dist/services/archive.js.map +1 -0
  42. package/dist/services/argocd.d.ts +23 -0
  43. package/dist/services/argocd.js +48 -0
  44. package/dist/services/argocd.js.map +1 -0
  45. package/dist/services/az.d.ts +38 -0
  46. package/dist/services/az.js +51 -0
  47. package/dist/services/az.js.map +1 -0
  48. package/dist/services/azdo-api.d.ts +213 -0
  49. package/dist/services/azdo-api.js +247 -0
  50. package/dist/services/azdo-api.js.map +1 -0
  51. package/dist/services/azdo.d.ts +13 -0
  52. package/dist/services/azdo.js +57 -0
  53. package/dist/services/azdo.js.map +1 -0
  54. package/dist/services/docker.d.ts +21 -0
  55. package/dist/services/docker.js +36 -0
  56. package/dist/services/docker.js.map +1 -0
  57. package/dist/services/git.d.ts +9 -0
  58. package/dist/services/git.js +36 -0
  59. package/dist/services/git.js.map +1 -0
  60. package/dist/services/helm.d.ts +4 -0
  61. package/dist/services/helm.js +24 -0
  62. package/dist/services/helm.js.map +1 -0
  63. package/dist/services/http-types.d.ts +57 -0
  64. package/dist/services/http-types.js +3 -0
  65. package/dist/services/http-types.js.map +1 -0
  66. package/dist/services/http.d.ts +64 -0
  67. package/dist/services/http.js +288 -0
  68. package/dist/services/http.js.map +1 -0
  69. package/dist/services/index.d.ts +37 -0
  70. package/dist/services/index.js +88 -0
  71. package/dist/services/index.js.map +1 -0
  72. package/dist/services/kubectl.d.ts +137 -0
  73. package/dist/services/kubectl.js +271 -0
  74. package/dist/services/kubectl.js.map +1 -0
  75. package/dist/services/npm.d.ts +5 -0
  76. package/dist/services/npm.js +20 -0
  77. package/dist/services/npm.js.map +1 -0
  78. package/dist/services/oc.d.ts +156 -0
  79. package/dist/services/oc.js +309 -0
  80. package/dist/services/oc.js.map +1 -0
  81. package/dist/services/pipeline.d.ts +116 -0
  82. package/dist/services/pipeline.js +474 -0
  83. package/dist/services/pipeline.js.map +1 -0
  84. package/dist/services/shell.d.ts +28 -0
  85. package/dist/services/shell.js +206 -0
  86. package/dist/services/shell.js.map +1 -0
  87. package/dist/services/tekton.d.ts +16 -0
  88. package/dist/services/tekton.js +46 -0
  89. package/dist/services/tekton.js.map +1 -0
  90. package/dist/services/terraform.d.ts +31 -0
  91. package/dist/services/terraform.js +63 -0
  92. package/dist/services/terraform.js.map +1 -0
  93. package/package.json +58 -0
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Notifier = void 0;
4
+ const types_1 = require("./types");
5
+ const WILDCARD = "*";
6
+ function toMessage(error) {
7
+ if (error instanceof types_1.ServiceError) {
8
+ return error.message;
9
+ }
10
+ if (error instanceof Error) {
11
+ return error.message;
12
+ }
13
+ const maybeExecError = error;
14
+ const lastLine = (text) => {
15
+ return text ? text.trim().split("\n").pop() || text : undefined;
16
+ };
17
+ return lastLine(maybeExecError?.stderr)
18
+ || lastLine(maybeExecError?.stdout)
19
+ || maybeExecError?.message
20
+ || String(error);
21
+ }
22
+ class Notifier {
23
+ constructor() {
24
+ this.classifiers = [];
25
+ this.messageFormatters = [];
26
+ this.channels = new Map();
27
+ this.successSenders = [];
28
+ this.defaultArea = "unclassified";
29
+ }
30
+ /**
31
+ * Registra una función que decide a qué área de TI corresponde un
32
+ * error. Se prueban en el orden en que se registraron; gana la primera
33
+ * que devuelva un string. Si ninguna matchea, se usa el área "unclassified"
34
+ * (configurable con `setDefaultArea`).
35
+ */
36
+ classify(classifier) {
37
+ this.classifiers.push(classifier);
38
+ return this;
39
+ }
40
+ /**
41
+ * Registra una función que, dado el error, devuelve el mensaje
42
+ * personalizado a reportar (reemplaza el stderr/mensaje crudo). Se
43
+ * prueban en orden; gana la primera que devuelva un string. Si ninguna
44
+ * matchea, se usa el mensaje crudo del error (stderr/Error.message).
45
+ *
46
+ * Ejemplo:
47
+ * notifier.describeError(messages.byPattern([
48
+ * [/500 Internal Server Error/, "Se reportó a infraestructura: falta de espacio en el registry"],
49
+ * [/unauthorized|403/, "Credenciales inválidas contra el registry, revisa el secret"]
50
+ * ]));
51
+ */
52
+ describeError(formatter) {
53
+ this.messageFormatters.push(formatter);
54
+ return this;
55
+ }
56
+ setDefaultArea(area) {
57
+ this.defaultArea = area;
58
+ return this;
59
+ }
60
+ /**
61
+ * Asocia uno o más senders a un área. Puedes registrar el mismo sender
62
+ * en varias áreas, o usar el área especial "*" para que reciba TODOS
63
+ * los errores sin importar la clasificación.
64
+ */
65
+ channel(area, ...senders) {
66
+ const existing = this.channels.get(area) ?? [];
67
+ this.channels.set(area, [...existing, ...senders]);
68
+ return this;
69
+ }
70
+ /** Senders que se disparan en cada tarea exitosa, sin clasificación. */
71
+ onSuccess(...senders) {
72
+ this.successSenders.push(...senders);
73
+ return this;
74
+ }
75
+ resolveArea(error, ctx) {
76
+ for (const classifier of this.classifiers) {
77
+ const area = classifier(error, ctx);
78
+ if (area)
79
+ return area;
80
+ }
81
+ return this.defaultArea;
82
+ }
83
+ resolveMessage(error, ctx) {
84
+ for (const formatter of this.messageFormatters) {
85
+ const message = formatter(error, ctx);
86
+ if (message)
87
+ return message;
88
+ }
89
+ return toMessage(error);
90
+ }
91
+ async reportSuccess(taskId, result, ctx) {
92
+ if (!this.successSenders.length)
93
+ return;
94
+ const event = {
95
+ type: "success",
96
+ taskId,
97
+ result,
98
+ message: `Tarea "${taskId}" finalizó correctamente`,
99
+ timestamp: new Date().toISOString()
100
+ };
101
+ await Promise.allSettled(this.successSenders.map(sender => sender(event)));
102
+ }
103
+ async reportError(taskId, error, ctx) {
104
+ const area = this.resolveArea(error, ctx);
105
+ const senders = [
106
+ ...(this.channels.get(area) ?? []),
107
+ ...(area !== WILDCARD ? this.channels.get(WILDCARD) ?? [] : [])
108
+ ];
109
+ const serviceError = error instanceof types_1.ServiceError ? error : undefined;
110
+ const event = {
111
+ type: "error",
112
+ taskId,
113
+ area,
114
+ error,
115
+ message: this.resolveMessage(error, ctx),
116
+ timestamp: new Date().toISOString(),
117
+ ...(serviceError ? {
118
+ service: serviceError.service,
119
+ method: serviceError.method,
120
+ args: serviceError.args
121
+ } : {})
122
+ };
123
+ await Promise.allSettled(senders.map(sender => sender(event)));
124
+ return area;
125
+ }
126
+ }
127
+ exports.Notifier = Notifier;
128
+ //# sourceMappingURL=Notifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Notifier.js","sourceRoot":"","sources":["../../src/core/Notifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import type { ErrorClassifier } from "./types";
2
+ /**
3
+ * Clasificador de fábrica: mapea el comando que falló (el primer argumento
4
+ * que le pasaste a shell.exec / docker.*, git.*, etc.) a un área de TI.
5
+ *
6
+ * Ejemplo:
7
+ * notifier.classify(classifiers.byCommand({
8
+ * docker: "containers",
9
+ * kubectl: "kubernetes",
10
+ * oc: "kubernetes",
11
+ * terraform: "infra",
12
+ * ansible: "infra",
13
+ * git: "scm",
14
+ * argocd: "cd-pipeline",
15
+ * tkn: "cd-pipeline",
16
+ * az: "cloud-azure"
17
+ * }));
18
+ */
19
+ export declare function byCommand(map: Record<string, string>): ErrorClassifier;
20
+ /**
21
+ * Clasificador de fábrica: prueba una lista de [regex, área] contra el
22
+ * stderr (o stdout si stderr viene vacío) /mensaje del error y devuelve el
23
+ * área del primer patrón que matchee.
24
+ *
25
+ * Ejemplo:
26
+ * notifier.classify(classifiers.byPattern([
27
+ * [/permission denied|unauthorized/i, "security"],
28
+ * [/timeout|ETIMEDOUT|ECONNREFUSED/i, "networking"],
29
+ * [/no space left|ENOSPC/i, "infra"]
30
+ * ]));
31
+ */
32
+ export declare function byPattern(rules: Array<[RegExp, string]>): ErrorClassifier;
33
+ /**
34
+ * Clasificador de fábrica: mapea el nombre del servicio que falló a un área
35
+ * de TI. Funciona con errores envueltos por `ctx.wrap()` (ServiceError) y
36
+ * también con errores raw de `shell.exec` (via `byCommand` como fallback).
37
+ *
38
+ * Ejemplo:
39
+ * notifier.classify(classifiers.byService({
40
+ * docker: "containers",
41
+ * kubectl: "kubernetes",
42
+ * http: "networking"
43
+ * }));
44
+ */
45
+ export declare function byService(map: Record<string, string>): ErrorClassifier;
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.byCommand = byCommand;
4
+ exports.byPattern = byPattern;
5
+ exports.byService = byService;
6
+ const types_1 = require("./types");
7
+ function unwrapExecLike(error) {
8
+ if (error instanceof types_1.ServiceError && error.cause) {
9
+ return error.cause;
10
+ }
11
+ return error;
12
+ }
13
+ function unwrapText(error) {
14
+ if (error instanceof types_1.ServiceError && error.cause) {
15
+ const cause = error.cause;
16
+ return cause.stderr || cause.stdout || cause.message || String(error.cause);
17
+ }
18
+ const execError = error;
19
+ return execError?.stderr || execError?.stdout || execError?.message || String(error);
20
+ }
21
+ /**
22
+ * Clasificador de fábrica: mapea el comando que falló (el primer argumento
23
+ * que le pasaste a shell.exec / docker.*, git.*, etc.) a un área de TI.
24
+ *
25
+ * Ejemplo:
26
+ * notifier.classify(classifiers.byCommand({
27
+ * docker: "containers",
28
+ * kubectl: "kubernetes",
29
+ * oc: "kubernetes",
30
+ * terraform: "infra",
31
+ * ansible: "infra",
32
+ * git: "scm",
33
+ * argocd: "cd-pipeline",
34
+ * tkn: "cd-pipeline",
35
+ * az: "cloud-azure"
36
+ * }));
37
+ */
38
+ function byCommand(map) {
39
+ return (error) => {
40
+ const execError = unwrapExecLike(error);
41
+ const command = execError?.command;
42
+ if (!command)
43
+ return undefined;
44
+ return map[command];
45
+ };
46
+ }
47
+ /**
48
+ * Clasificador de fábrica: prueba una lista de [regex, área] contra el
49
+ * stderr (o stdout si stderr viene vacío) /mensaje del error y devuelve el
50
+ * área del primer patrón que matchee.
51
+ *
52
+ * Ejemplo:
53
+ * notifier.classify(classifiers.byPattern([
54
+ * [/permission denied|unauthorized/i, "security"],
55
+ * [/timeout|ETIMEDOUT|ECONNREFUSED/i, "networking"],
56
+ * [/no space left|ENOSPC/i, "infra"]
57
+ * ]));
58
+ */
59
+ function byPattern(rules) {
60
+ return (error) => {
61
+ const text = unwrapText(error);
62
+ for (const [pattern, area] of rules) {
63
+ if (pattern.test(text)) {
64
+ return area;
65
+ }
66
+ }
67
+ return undefined;
68
+ };
69
+ }
70
+ /**
71
+ * Clasificador de fábrica: mapea el nombre del servicio que falló a un área
72
+ * de TI. Funciona con errores envueltos por `ctx.wrap()` (ServiceError) y
73
+ * también con errores raw de `shell.exec` (via `byCommand` como fallback).
74
+ *
75
+ * Ejemplo:
76
+ * notifier.classify(classifiers.byService({
77
+ * docker: "containers",
78
+ * kubectl: "kubernetes",
79
+ * http: "networking"
80
+ * }));
81
+ */
82
+ function byService(map) {
83
+ return (error) => {
84
+ if (error instanceof types_1.ServiceError) {
85
+ return map[error.service];
86
+ }
87
+ return undefined;
88
+ };
89
+ }
90
+ //# sourceMappingURL=classifiers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classifiers.js","sourceRoot":"","sources":["../../src/core/classifiers.ts"],"names":[],"mappings":";;AA2CA,8BAaC;AAcD,8BAgBC;AAcD,8BAYC;AA/GD,mCAAuC;AASvC,SAAS,cAAc,CAAC,KAAc;IAClC,IAAI,KAAK,YAAY,oBAAY,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/C,OAAO,KAAK,CAAC,KAAsB,CAAC;IACxC,CAAC;IACD,OAAO,KAAsB,CAAC;AAClC,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAC9B,IAAI,KAAK,YAAY,oBAAY,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAsB,CAAC;QAC3C,OAAO,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAChF,CAAC;IACD,MAAM,SAAS,GAAG,KAAsB,CAAC;IACzC,OAAO,SAAS,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,IAAI,SAAS,EAAE,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;AACzF,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,SAAgB,SAAS,CAAC,GAA2B;IAEjD,OAAO,CAAC,KAAc,EAAE,EAAE;QAEtB,MAAM,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,SAAS,EAAE,OAAO,CAAC;QAEnC,IAAI,CAAC,OAAO;YAAE,OAAO,SAAS,CAAC;QAE/B,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC;IAExB,CAAC,CAAC;AAEN,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,SAAS,CAAC,KAA8B;IAEpD,OAAO,CAAC,KAAc,EAAE,EAAE;QAEtB,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QAE/B,KAAK,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC;YAClC,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrB,OAAO,IAAI,CAAC;YAChB,CAAC;QACL,CAAC;QAED,OAAO,SAAS,CAAC;IAErB,CAAC,CAAC;AAEN,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,SAAS,CAAC,GAA2B;IAEjD,OAAO,CAAC,KAAc,EAAE,EAAE;QAEtB,IAAI,KAAK,YAAY,oBAAY,EAAE,CAAC;YAChC,OAAO,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;QAED,OAAO,SAAS,CAAC;IAErB,CAAC,CAAC;AAEN,CAAC"}
@@ -0,0 +1,8 @@
1
+ export interface Logger {
2
+ debug(message: string): void;
3
+ info(message: string): void;
4
+ success(message: string): void;
5
+ warn(message: string): void;
6
+ error(message: string): void;
7
+ }
8
+ export declare const logger: Logger;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.logger = void 0;
4
+ const COLORS = {
5
+ reset: "\x1b[0m",
6
+ gray: "\x1b[90m",
7
+ cyan: "\x1b[36m",
8
+ green: "\x1b[32m",
9
+ yellow: "\x1b[33m",
10
+ red: "\x1b[31m"
11
+ };
12
+ function timestamp() {
13
+ return new Date().toISOString().split("T")[1].replace("Z", "");
14
+ }
15
+ function paint(color, label, message) {
16
+ return `${COLORS.gray}[${timestamp()}]${COLORS.reset} ${color}${label}${COLORS.reset} ${message}`;
17
+ }
18
+ exports.logger = {
19
+ debug(message) {
20
+ if (!process.env.DEBUG)
21
+ return;
22
+ console.log(paint(COLORS.gray, "DEBUG", message));
23
+ },
24
+ info(message) {
25
+ console.log(paint(COLORS.cyan, "INFO ", message));
26
+ },
27
+ success(message) {
28
+ console.log(paint(COLORS.green, "OK ", message));
29
+ },
30
+ warn(message) {
31
+ console.warn(paint(COLORS.yellow, "WARN ", message));
32
+ },
33
+ error(message) {
34
+ console.error(paint(COLORS.red, "ERROR", message));
35
+ }
36
+ };
37
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":";;;AAAA,MAAM,MAAM,GAAG;IACX,KAAK,EAAE,SAAS;IAChB,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,UAAU;IACjB,MAAM,EAAE,UAAU;IAClB,GAAG,EAAE,UAAU;CACT,CAAC;AAEX,SAAS,SAAS;IACd,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,KAAK,CAAC,KAAa,EAAE,KAAa,EAAE,OAAe;IACxD,OAAO,GAAG,MAAM,CAAC,IAAI,IAAI,SAAS,EAAE,IAAI,MAAM,CAAC,KAAK,IAAI,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,OAAO,EAAE,CAAC;AACtG,CAAC;AAUY,QAAA,MAAM,GAAW;IAE1B,KAAK,CAAC,OAAe;QACjB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK;YAAE,OAAO;QAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,CAAC,OAAe;QAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,CAAC,OAAe;QACnB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IACvD,CAAC;IAED,IAAI,CAAC,OAAe;QAChB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,OAAe;QACjB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IACvD,CAAC;CAEJ,CAAC"}
@@ -0,0 +1,102 @@
1
+ import type { Context } from "./Context";
2
+ import type { ErrorMessageFormatter } from "./types";
3
+ /**
4
+ * Formateador de fábrica: prueba una lista de [regex, mensaje] contra el
5
+ * stderr (o stdout si stderr viene vacío, p. ej. errores de `oc` que se
6
+ * imprimen en stdout) /mensaje del error y devuelve el mensaje personalizado
7
+ * del primer patrón que matchee, en vez del stderr crudo.
8
+ *
9
+ * Ojo: esto NO distingue por comando — un mismo patrón (ej. "500 Internal
10
+ * Server Error") aplica igual venga de `docker`, `kubectl` o `terraform`.
11
+ * Si necesitas distinguir por comando (y opcionalmente por sub-comando),
12
+ * usa `byRule` más abajo.
13
+ *
14
+ * Ejemplo:
15
+ * notifier.describeError(messages.byPattern([
16
+ * [/500 Internal Server Error/, "Se reportó a infraestructura: falta de espacio en el registry"],
17
+ * [/unauthorized|403/i, "Credenciales inválidas contra el registry, revisa el secret"],
18
+ * [/no space left|ENOSPC/i, "El nodo se quedó sin espacio en disco"]
19
+ * ]));
20
+ */
21
+ export declare function byPattern(rules: Array<[RegExp, string]>): ErrorMessageFormatter;
22
+ /**
23
+ * Formateador de fábrica: mapea el comando que falló (docker, kubectl,
24
+ * terraform, etc.) a un mensaje genérico fijo, sin importar el detalle del
25
+ * error. Útil como mensaje "catch-all" por comando cuando no necesitas
26
+ * distinguir por patrón.
27
+ *
28
+ * Ejemplo:
29
+ * notifier.describeError(messages.byCommand({
30
+ * docker: "Falló un paso de Docker, revisa el build/push del registry"
31
+ * }));
32
+ */
33
+ export declare function byCommand(map: Record<string, string>): ErrorMessageFormatter;
34
+ /**
35
+ * Una regla de `byRule`: TODAS las condiciones que definas deben cumplirse
36
+ * (AND) para que aplique. Omitir una condición equivale a "no filtrar por
37
+ * eso" (matchea cualquier valor).
38
+ */
39
+ export interface MessageRule {
40
+ /**
41
+ * Comando exacto (o lista de comandos) que debe haber fallado, tal como
42
+ * lo ve `shell.exec` (el primer argumento: "docker", "kubectl", "oc",
43
+ * "terraform", "git", etc.). Sin esto, la regla no filtra por comando.
44
+ */
45
+ command?: string | string[];
46
+ /**
47
+ * Sub-comando / argumento que debe estar presente, por ejemplo "push"
48
+ * para distinguir `docker push` de `docker build`. Puede ser un string
49
+ * exacto (se busca entre los args, o como substring de los args unidos)
50
+ * o un RegExp contra los args unidos con espacios.
51
+ */
52
+ args?: string | RegExp;
53
+ /** Patrón contra el stderr/mensaje del error. Sin esto, no filtra por texto. */
54
+ pattern?: RegExp;
55
+ /** Mensaje final. Puede ser un string fijo o una función que lo arma dinámicamente. */
56
+ message: string | ((error: unknown, ctx: Context) => string);
57
+ }
58
+ /**
59
+ * Formateador de fábrica avanzado: combina comando + sub-comando/args +
60
+ * patrón de texto (todo opcional, en modo AND) para distinguir el MISMO
61
+ * error de red/HTTP según de dónde vino. Resuelve justo el caso de "un 500
62
+ * puede venir de docker push, de kubectl, o de terraform, y cada uno
63
+ * necesita su propio mensaje".
64
+ *
65
+ * Se prueban las reglas en orden; gana la primera que matchee todas sus
66
+ * condiciones. Una regla sin `command` ni `args` ni `pattern` matchea
67
+ * cualquier error (útil como catch-all al final de la lista).
68
+ *
69
+ * Ejemplo — el caso concreto de varios comandos devolviendo el mismo 500:
70
+ *
71
+ * notifier.describeError(messages.byRule([
72
+ * {
73
+ * command: "docker", args: "push", pattern: /500 Internal Server Error/,
74
+ * message: "Se ha reportado a infraestructura: falta de espacio en el registry"
75
+ * },
76
+ * {
77
+ * command: "kubectl", pattern: /500/,
78
+ * message: "El API server de Kubernetes devolvió 500, reintenta en unos minutos"
79
+ * },
80
+ * {
81
+ * command: "terraform", pattern: /500/,
82
+ * message: (error, ctx) => `El backend remoto de Terraform State no respondió (env: ${ctx.params.env ?? "?"})`
83
+ * },
84
+ * {
85
+ * pattern: /500 Internal Server Error/,
86
+ * message: "Error 500 no clasificado por comando, revisar logs crudos"
87
+ * }
88
+ * ]));
89
+ */
90
+ export declare function byRule(rules: MessageRule[]): ErrorMessageFormatter;
91
+ /**
92
+ * Formateador de fábrica: mapea el nombre del servicio que falló a un
93
+ * mensaje genérico fijo. Funciona con errores envueltos por `ctx.wrap()`
94
+ * (ServiceError).
95
+ *
96
+ * Ejemplo:
97
+ * notifier.describeError(messages.byService({
98
+ * docker: "Falló una operación de Docker, revisa el build/push del registry",
99
+ * http: "Falló una petición HTTP, revisa la conectividad"
100
+ * }));
101
+ */
102
+ export declare function byService(map: Record<string, string>): ErrorMessageFormatter;
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.byPattern = byPattern;
4
+ exports.byCommand = byCommand;
5
+ exports.byRule = byRule;
6
+ exports.byService = byService;
7
+ const types_1 = require("./types");
8
+ function unwrapExecLike(error) {
9
+ if (error instanceof types_1.ServiceError && error.cause) {
10
+ return error.cause;
11
+ }
12
+ return error;
13
+ }
14
+ function textOf(error) {
15
+ if (error instanceof types_1.ServiceError && error.cause) {
16
+ const cause = error.cause;
17
+ return cause.stderr || cause.stdout || cause.message || String(error.cause);
18
+ }
19
+ const execError = error;
20
+ return execError?.stderr || execError?.stdout || execError?.message || String(error);
21
+ }
22
+ /**
23
+ * Formateador de fábrica: prueba una lista de [regex, mensaje] contra el
24
+ * stderr (o stdout si stderr viene vacío, p. ej. errores de `oc` que se
25
+ * imprimen en stdout) /mensaje del error y devuelve el mensaje personalizado
26
+ * del primer patrón que matchee, en vez del stderr crudo.
27
+ *
28
+ * Ojo: esto NO distingue por comando — un mismo patrón (ej. "500 Internal
29
+ * Server Error") aplica igual venga de `docker`, `kubectl` o `terraform`.
30
+ * Si necesitas distinguir por comando (y opcionalmente por sub-comando),
31
+ * usa `byRule` más abajo.
32
+ *
33
+ * Ejemplo:
34
+ * notifier.describeError(messages.byPattern([
35
+ * [/500 Internal Server Error/, "Se reportó a infraestructura: falta de espacio en el registry"],
36
+ * [/unauthorized|403/i, "Credenciales inválidas contra el registry, revisa el secret"],
37
+ * [/no space left|ENOSPC/i, "El nodo se quedó sin espacio en disco"]
38
+ * ]));
39
+ */
40
+ function byPattern(rules) {
41
+ return (error) => {
42
+ const text = textOf(error);
43
+ for (const [pattern, message] of rules) {
44
+ if (pattern.test(text)) {
45
+ return message;
46
+ }
47
+ }
48
+ return undefined;
49
+ };
50
+ }
51
+ /**
52
+ * Formateador de fábrica: mapea el comando que falló (docker, kubectl,
53
+ * terraform, etc.) a un mensaje genérico fijo, sin importar el detalle del
54
+ * error. Útil como mensaje "catch-all" por comando cuando no necesitas
55
+ * distinguir por patrón.
56
+ *
57
+ * Ejemplo:
58
+ * notifier.describeError(messages.byCommand({
59
+ * docker: "Falló un paso de Docker, revisa el build/push del registry"
60
+ * }));
61
+ */
62
+ function byCommand(map) {
63
+ return (error) => {
64
+ const execError = unwrapExecLike(error);
65
+ const command = execError?.command;
66
+ if (!command)
67
+ return undefined;
68
+ return map[command];
69
+ };
70
+ }
71
+ function commandMatches(rule, command) {
72
+ if (!rule.command)
73
+ return true;
74
+ if (!command)
75
+ return false;
76
+ const candidates = Array.isArray(rule.command) ? rule.command : [rule.command];
77
+ return candidates.includes(command);
78
+ }
79
+ function argsMatch(rule, args) {
80
+ if (!rule.args)
81
+ return true;
82
+ if (!args || !args.length)
83
+ return false;
84
+ const joined = args.join(" ");
85
+ if (rule.args instanceof RegExp) {
86
+ return rule.args.test(joined);
87
+ }
88
+ return args.includes(rule.args) || joined.includes(rule.args);
89
+ }
90
+ function patternMatches(rule, text) {
91
+ if (!rule.pattern)
92
+ return true;
93
+ return rule.pattern.test(text);
94
+ }
95
+ /**
96
+ * Formateador de fábrica avanzado: combina comando + sub-comando/args +
97
+ * patrón de texto (todo opcional, en modo AND) para distinguir el MISMO
98
+ * error de red/HTTP según de dónde vino. Resuelve justo el caso de "un 500
99
+ * puede venir de docker push, de kubectl, o de terraform, y cada uno
100
+ * necesita su propio mensaje".
101
+ *
102
+ * Se prueban las reglas en orden; gana la primera que matchee todas sus
103
+ * condiciones. Una regla sin `command` ni `args` ni `pattern` matchea
104
+ * cualquier error (útil como catch-all al final de la lista).
105
+ *
106
+ * Ejemplo — el caso concreto de varios comandos devolviendo el mismo 500:
107
+ *
108
+ * notifier.describeError(messages.byRule([
109
+ * {
110
+ * command: "docker", args: "push", pattern: /500 Internal Server Error/,
111
+ * message: "Se ha reportado a infraestructura: falta de espacio en el registry"
112
+ * },
113
+ * {
114
+ * command: "kubectl", pattern: /500/,
115
+ * message: "El API server de Kubernetes devolvió 500, reintenta en unos minutos"
116
+ * },
117
+ * {
118
+ * command: "terraform", pattern: /500/,
119
+ * message: (error, ctx) => `El backend remoto de Terraform State no respondió (env: ${ctx.params.env ?? "?"})`
120
+ * },
121
+ * {
122
+ * pattern: /500 Internal Server Error/,
123
+ * message: "Error 500 no clasificado por comando, revisar logs crudos"
124
+ * }
125
+ * ]));
126
+ */
127
+ function byRule(rules) {
128
+ return (error, ctx) => {
129
+ const execError = unwrapExecLike(error);
130
+ const text = textOf(error);
131
+ for (const rule of rules) {
132
+ const matches = commandMatches(rule, execError?.command)
133
+ && argsMatch(rule, execError?.args)
134
+ && patternMatches(rule, text);
135
+ if (matches) {
136
+ return typeof rule.message === "function"
137
+ ? rule.message(error, ctx)
138
+ : rule.message;
139
+ }
140
+ }
141
+ return undefined;
142
+ };
143
+ }
144
+ /**
145
+ * Formateador de fábrica: mapea el nombre del servicio que falló a un
146
+ * mensaje genérico fijo. Funciona con errores envueltos por `ctx.wrap()`
147
+ * (ServiceError).
148
+ *
149
+ * Ejemplo:
150
+ * notifier.describeError(messages.byService({
151
+ * docker: "Falló una operación de Docker, revisa el build/push del registry",
152
+ * http: "Falló una petición HTTP, revisa la conectividad"
153
+ * }));
154
+ */
155
+ function byService(map) {
156
+ return (error) => {
157
+ if (error instanceof types_1.ServiceError) {
158
+ return map[error.service];
159
+ }
160
+ return undefined;
161
+ };
162
+ }
163
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/core/messages.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export interface AskOptions {
2
+ defaultValue?: string;
3
+ }
4
+ export declare function ask(question: string, options?: AskOptions): Promise<string | undefined>;
5
+ export interface ConfirmOptions {
6
+ defaultValue?: boolean;
7
+ }
8
+ export declare function confirm(question: string, options?: ConfirmOptions): Promise<boolean>;
9
+ export type SelectChoices = string[] | Record<string, string>;
10
+ export declare function select(title: string, choices: SelectChoices): Promise<string>;