@alertee/cli 0.3.1 → 0.5.0

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 (118) hide show
  1. package/dist/api.d.ts +180 -0
  2. package/dist/api.d.ts.map +1 -1
  3. package/dist/api.js +25 -2
  4. package/dist/api.js.map +1 -1
  5. package/dist/commands/alert-groups/add-email-group.d.ts +9 -0
  6. package/dist/commands/alert-groups/add-email-group.d.ts.map +1 -0
  7. package/dist/commands/alert-groups/add-email-group.js +33 -0
  8. package/dist/commands/alert-groups/add-email-group.js.map +1 -0
  9. package/dist/commands/alert-groups/add-webhook.d.ts +8 -0
  10. package/dist/commands/alert-groups/add-webhook.d.ts.map +1 -0
  11. package/dist/commands/alert-groups/add-webhook.js +64 -0
  12. package/dist/commands/alert-groups/add-webhook.js.map +1 -0
  13. package/dist/commands/alert-groups/create.d.ts +11 -0
  14. package/dist/commands/alert-groups/create.d.ts.map +1 -0
  15. package/dist/commands/alert-groups/create.js +31 -0
  16. package/dist/commands/alert-groups/create.js.map +1 -0
  17. package/dist/commands/alert-groups/delete.d.ts +5 -0
  18. package/dist/commands/alert-groups/delete.d.ts.map +1 -0
  19. package/dist/commands/alert-groups/delete.js +35 -0
  20. package/dist/commands/alert-groups/delete.js.map +1 -0
  21. package/dist/commands/alert-groups/list.d.ts +5 -0
  22. package/dist/commands/alert-groups/list.d.ts.map +1 -0
  23. package/dist/commands/alert-groups/list.js +35 -0
  24. package/dist/commands/alert-groups/list.js.map +1 -0
  25. package/dist/commands/alert-groups/recipients.d.ts +5 -0
  26. package/dist/commands/alert-groups/recipients.d.ts.map +1 -0
  27. package/dist/commands/alert-groups/recipients.js +62 -0
  28. package/dist/commands/alert-groups/recipients.js.map +1 -0
  29. package/dist/commands/alert-groups/remove-recipient.d.ts +8 -0
  30. package/dist/commands/alert-groups/remove-recipient.d.ts.map +1 -0
  31. package/dist/commands/alert-groups/remove-recipient.js +33 -0
  32. package/dist/commands/alert-groups/remove-recipient.js.map +1 -0
  33. package/dist/commands/alert-groups/resolve.d.ts +6 -0
  34. package/dist/commands/alert-groups/resolve.d.ts.map +1 -0
  35. package/dist/commands/alert-groups/resolve.js +27 -0
  36. package/dist/commands/alert-groups/resolve.js.map +1 -0
  37. package/dist/commands/alert-groups/test.d.ts +3 -0
  38. package/dist/commands/alert-groups/test.d.ts.map +1 -0
  39. package/dist/commands/alert-groups/test.js +24 -0
  40. package/dist/commands/alert-groups/test.js.map +1 -0
  41. package/dist/commands/alert-groups/update.d.ts +12 -0
  42. package/dist/commands/alert-groups/update.d.ts.map +1 -0
  43. package/dist/commands/alert-groups/update.js +46 -0
  44. package/dist/commands/alert-groups/update.js.map +1 -0
  45. package/dist/commands/checks/create.d.ts +25 -1
  46. package/dist/commands/checks/create.d.ts.map +1 -1
  47. package/dist/commands/checks/create.js +141 -88
  48. package/dist/commands/checks/create.js.map +1 -1
  49. package/dist/commands/checks/update.d.ts +3 -2
  50. package/dist/commands/checks/update.d.ts.map +1 -1
  51. package/dist/commands/checks/update.js +79 -19
  52. package/dist/commands/checks/update.js.map +1 -1
  53. package/dist/commands/connections/create.d.ts +14 -0
  54. package/dist/commands/connections/create.d.ts.map +1 -0
  55. package/dist/commands/connections/create.js +52 -0
  56. package/dist/commands/connections/create.js.map +1 -0
  57. package/dist/commands/connections/delete.d.ts +5 -0
  58. package/dist/commands/connections/delete.d.ts.map +1 -0
  59. package/dist/commands/connections/delete.js +35 -0
  60. package/dist/commands/connections/delete.js.map +1 -0
  61. package/dist/commands/connections/resolve.d.ts +9 -0
  62. package/dist/commands/connections/resolve.d.ts.map +1 -0
  63. package/dist/commands/connections/resolve.js +30 -0
  64. package/dist/commands/connections/resolve.js.map +1 -0
  65. package/dist/commands/connections/test.d.ts +3 -0
  66. package/dist/commands/connections/test.d.ts.map +1 -0
  67. package/dist/commands/connections/test.js +28 -0
  68. package/dist/commands/connections/test.js.map +1 -0
  69. package/dist/commands/email-groups/add.d.ts +3 -0
  70. package/dist/commands/email-groups/add.d.ts.map +1 -0
  71. package/dist/commands/email-groups/add.js +23 -0
  72. package/dist/commands/email-groups/add.js.map +1 -0
  73. package/dist/commands/email-groups/create.d.ts +8 -0
  74. package/dist/commands/email-groups/create.d.ts.map +1 -0
  75. package/dist/commands/email-groups/create.js +28 -0
  76. package/dist/commands/email-groups/create.js.map +1 -0
  77. package/dist/commands/email-groups/delete.d.ts +5 -0
  78. package/dist/commands/email-groups/delete.d.ts.map +1 -0
  79. package/dist/commands/email-groups/delete.js +35 -0
  80. package/dist/commands/email-groups/delete.js.map +1 -0
  81. package/dist/commands/email-groups/list.d.ts +5 -0
  82. package/dist/commands/email-groups/list.d.ts.map +1 -0
  83. package/dist/commands/email-groups/list.js +36 -0
  84. package/dist/commands/email-groups/list.js.map +1 -0
  85. package/dist/commands/email-groups/members.d.ts +5 -0
  86. package/dist/commands/email-groups/members.d.ts.map +1 -0
  87. package/dist/commands/email-groups/members.js +42 -0
  88. package/dist/commands/email-groups/members.js.map +1 -0
  89. package/dist/commands/email-groups/remove.d.ts +3 -0
  90. package/dist/commands/email-groups/remove.d.ts.map +1 -0
  91. package/dist/commands/email-groups/remove.js +19 -0
  92. package/dist/commands/email-groups/remove.js.map +1 -0
  93. package/dist/commands/email-groups/resolve.d.ts +6 -0
  94. package/dist/commands/email-groups/resolve.d.ts.map +1 -0
  95. package/dist/commands/email-groups/resolve.js +27 -0
  96. package/dist/commands/email-groups/resolve.js.map +1 -0
  97. package/dist/commands/org/create.d.ts +12 -0
  98. package/dist/commands/org/create.d.ts.map +1 -0
  99. package/dist/commands/org/create.js +33 -0
  100. package/dist/commands/org/create.js.map +1 -0
  101. package/dist/commands/org/list.d.ts +5 -0
  102. package/dist/commands/org/list.d.ts.map +1 -0
  103. package/dist/commands/org/list.js +35 -0
  104. package/dist/commands/org/list.js.map +1 -0
  105. package/dist/index.js +159 -3
  106. package/dist/index.js.map +1 -1
  107. package/dist/mcp.d.ts.map +1 -1
  108. package/dist/mcp.js +343 -2
  109. package/dist/mcp.js.map +1 -1
  110. package/dist/prompts.d.ts +15 -0
  111. package/dist/prompts.d.ts.map +1 -0
  112. package/dist/prompts.js +25 -0
  113. package/dist/prompts.js.map +1 -0
  114. package/dist/uuid.d.ts +13 -0
  115. package/dist/uuid.d.ts.map +1 -0
  116. package/dist/uuid.js +13 -0
  117. package/dist/uuid.js.map +1 -0
  118. package/package.json +1 -1
@@ -0,0 +1,62 @@
1
+ import { createClient } from '../../api.js';
2
+ import { requireConfig, requireOrg } from '../../config.js';
3
+ import { printJson, resolveFormat } from '../../output.js';
4
+ import { uuidValue } from '../../uuid.js';
5
+ import { resolveAlertGroupId } from './resolve.js';
6
+ /** List the recipients (channels) in an alert group. */
7
+ export async function listRecipients(nameOrId, opts = {}) {
8
+ const format = resolveFormat(opts.format);
9
+ const config = requireConfig();
10
+ requireOrg(config);
11
+ const client = createClient(config);
12
+ const groupId = await resolveAlertGroupId(client, nameOrId);
13
+ let channels;
14
+ try {
15
+ channels = (await client.listAlertChannels(groupId)).channels;
16
+ }
17
+ catch (err) {
18
+ console.error('Failed to list recipients:', err.message);
19
+ process.exit(1);
20
+ }
21
+ if (format === 'json') {
22
+ printJson(channels);
23
+ return;
24
+ }
25
+ if (channels.length === 0) {
26
+ console.log('No recipients. Add one: alertee alert-groups add-webhook <group> --url …');
27
+ return;
28
+ }
29
+ // Resolve email-group ids to names for a friendlier summary (best-effort).
30
+ const emailGroupNames = new Map();
31
+ if (channels.some((c) => c.channel_type === 'email_group')) {
32
+ try {
33
+ for (const g of (await client.listEmailGroups()).groups)
34
+ emailGroupNames.set(g.id, g.name);
35
+ }
36
+ catch {
37
+ // non-fatal — fall back to showing the id
38
+ }
39
+ }
40
+ const header = `TYPE ENABLED SUMMARY${' '.repeat(33)}ID`;
41
+ console.log(header);
42
+ console.log('─'.repeat(header.length));
43
+ for (const c of channels) {
44
+ const summary = summarize(c, emailGroupNames);
45
+ console.log(`${c.channel_type.padEnd(12)} ${(c.enabled ? 'yes' : 'no').padEnd(7)} ${summary.padEnd(38)} ${c.id}`);
46
+ }
47
+ }
48
+ function summarize(c, emailGroupNames) {
49
+ if (c.channel_type === 'email_group') {
50
+ const id = uuidValue(c.email_group_id);
51
+ return (id ? emailGroupNames.get(id) ?? id : undefined) ?? '—';
52
+ }
53
+ const config = (c.config ?? {});
54
+ if (c.channel_type === 'webhook')
55
+ return String(config.url ?? '—');
56
+ if (c.channel_type === 'slack')
57
+ return String(config.channel ?? '—');
58
+ if (c.channel_type === 'email')
59
+ return String(config.address ?? config.email ?? '—');
60
+ return '—';
61
+ }
62
+ //# sourceMappingURL=recipients.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recipients.js","sourceRoot":"","sources":["../../../src/commands/alert-groups/recipients.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Remove a recipient (channel) from an alert group by its channel ID — get IDs
3
+ * from `alertee alert-groups recipients <group>`.
4
+ */
5
+ export declare function removeRecipient(channelId: string, opts?: {
6
+ yes?: boolean;
7
+ }): Promise<void>;
8
+ //# sourceMappingURL=remove-recipient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove-recipient.d.ts","sourceRoot":"","sources":["../../../src/commands/alert-groups/remove-recipient.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAO,GAC3B,OAAO,CAAC,IAAI,CAAC,CAwBf"}
@@ -0,0 +1,33 @@
1
+ import { confirm } from '@inquirer/prompts';
2
+ import { createClient } from '../../api.js';
3
+ import { requireConfig, requireOrg } from '../../config.js';
4
+ import { isInteractive } from '../../prompts.js';
5
+ /**
6
+ * Remove a recipient (channel) from an alert group by its channel ID — get IDs
7
+ * from `alertee alert-groups recipients <group>`.
8
+ */
9
+ export async function removeRecipient(channelId, opts = {}) {
10
+ const config = requireConfig();
11
+ requireOrg(config);
12
+ const client = createClient(config);
13
+ if (!opts.yes) {
14
+ if (!isInteractive()) {
15
+ console.error('Refusing to remove without confirmation. Pass --yes.');
16
+ process.exit(1);
17
+ }
18
+ const ok = await confirm({ message: `Remove recipient ${channelId}?`, default: false });
19
+ if (!ok) {
20
+ console.log('Aborted.');
21
+ return;
22
+ }
23
+ }
24
+ try {
25
+ await client.deleteAlertChannel(channelId);
26
+ }
27
+ catch (err) {
28
+ console.error('Failed to remove recipient:', err.message);
29
+ process.exit(1);
30
+ }
31
+ console.log(`Removed recipient ${channelId}.`);
32
+ }
33
+ //# sourceMappingURL=remove-recipient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove-recipient.js","sourceRoot":"","sources":["../../../src/commands/alert-groups/remove-recipient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAEhD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,SAAiB,EACjB,OAA0B,EAAE;IAE5B,MAAM,MAAM,GAAG,aAAa,EAAE,CAAA;IAC9B,UAAU,CAAC,MAAM,CAAC,CAAA;IAClB,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;IAEnC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QACd,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;YACrB,OAAO,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAA;YACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QACD,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,EAAE,OAAO,EAAE,oBAAoB,SAAS,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAA;QACvF,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;YACvB,OAAM;QACR,CAAC;IACH,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAA;IAC5C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAG,GAAa,CAAC,OAAO,CAAC,CAAA;QACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,qBAAqB,SAAS,GAAG,CAAC,CAAA;AAChD,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { createClient } from '../../api.js';
2
+ type Client = ReturnType<typeof createClient>;
3
+ /** Resolve an alert group argument (UUID or case-insensitive name) to its ID. */
4
+ export declare function resolveAlertGroupId(client: Client, nameOrId: string): Promise<string>;
5
+ export {};
6
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/commands/alert-groups/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAEhD,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAA;AAK7C,iFAAiF;AACjF,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CAyBjB"}
@@ -0,0 +1,27 @@
1
+ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
2
+ /** Resolve an alert group argument (UUID or case-insensitive name) to its ID. */
3
+ export async function resolveAlertGroupId(client, nameOrId) {
4
+ if (UUID_RE.test(nameOrId.trim())) {
5
+ return nameOrId.trim();
6
+ }
7
+ let groups;
8
+ try {
9
+ groups = (await client.listAlertGroups()).alert_groups;
10
+ }
11
+ catch (err) {
12
+ console.error('Failed to list alert groups:', err.message);
13
+ process.exit(1);
14
+ }
15
+ const needle = nameOrId.trim().toLowerCase();
16
+ const matches = groups.filter((g) => g.Name.toLowerCase() === needle);
17
+ if (matches.length === 0) {
18
+ console.error(`No alert group named "${nameOrId}". Run \`alertee alert-groups list\`.`);
19
+ process.exit(1);
20
+ }
21
+ if (matches.length > 1) {
22
+ console.error(`"${nameOrId}" matches ${matches.length} alert groups; pass the ID instead.`);
23
+ process.exit(1);
24
+ }
25
+ return matches[0].ID;
26
+ }
27
+ //# sourceMappingURL=resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../../src/commands/alert-groups/resolve.ts"],"names":[],"mappings":"AAIA,MAAM,OAAO,GACX,iEAAiE,CAAA;AAEnE,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAc,EACd,QAAgB;IAEhB,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QAClC,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAA;IACxB,CAAC;IAED,IAAI,MAA0E,CAAA;IAC9E,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC,YAAY,CAAA;IACxD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAG,GAAa,CAAC,OAAO,CAAC,CAAA;QACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,CAAA;IAErE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,KAAK,CAAC,yBAAyB,QAAQ,uCAAuC,CAAC,CAAA;QACvF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CAAC,IAAI,QAAQ,aAAa,OAAO,CAAC,MAAM,qCAAqC,CAAC,CAAA;QAC3F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;AACtB,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Send a test alert through every recipient in a group (by name or ID). */
2
+ export declare function testAlertGroup(nameOrId: string): Promise<void>;
3
+ //# sourceMappingURL=test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../../src/commands/alert-groups/test.ts"],"names":[],"mappings":"AAIA,4EAA4E;AAC5E,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBpE"}
@@ -0,0 +1,24 @@
1
+ import { createClient } from '../../api.js';
2
+ import { requireConfig, requireOrg } from '../../config.js';
3
+ import { resolveAlertGroupId } from './resolve.js';
4
+ /** Send a test alert through every recipient in a group (by name or ID). */
5
+ export async function testAlertGroup(nameOrId) {
6
+ const config = requireConfig();
7
+ requireOrg(config);
8
+ const client = createClient(config);
9
+ const id = await resolveAlertGroupId(client, nameOrId);
10
+ let res;
11
+ try {
12
+ res = await client.sendTestAlert(id, { alert_group_id: id });
13
+ }
14
+ catch (err) {
15
+ console.error('Failed to send test alert:', err.message);
16
+ process.exit(1);
17
+ }
18
+ if (!res.success) {
19
+ console.error(`✗ ${res.message || 'Test alert failed.'}`);
20
+ process.exit(1);
21
+ }
22
+ console.log(`✓ ${res.message || 'Test alert sent.'}`);
23
+ }
24
+ //# sourceMappingURL=test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.js","sourceRoot":"","sources":["../../../src/commands/alert-groups/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAElD,4EAA4E;AAC5E,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAgB;IACnD,MAAM,MAAM,GAAG,aAAa,EAAE,CAAA;IAC9B,UAAU,CAAC,MAAM,CAAC,CAAA;IAClB,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;IACnC,MAAM,EAAE,GAAG,MAAM,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;IAEtD,IAAI,GAAqD,CAAA;IACzD,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,CAAA;IAC9D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAG,GAAa,CAAC,OAAO,CAAC,CAAA;QACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,OAAO,IAAI,oBAAoB,EAAE,CAAC,CAAA;QACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,OAAO,IAAI,kBAAkB,EAAE,CAAC,CAAA;AACvD,CAAC"}
@@ -0,0 +1,12 @@
1
+ export interface UpdateAlertGroupOptions {
2
+ name?: string;
3
+ description?: string;
4
+ default?: boolean;
5
+ }
6
+ /**
7
+ * Rename / re-describe an alert group, or set it as the default. The PUT
8
+ * endpoint replaces all fields, so we read the current group first and apply
9
+ * only the flags you pass.
10
+ */
11
+ export declare function updateAlertGroup(nameOrId: string, opts: UpdateAlertGroupOptions): Promise<void>;
12
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/commands/alert-groups/update.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAKD;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAuCf"}
@@ -0,0 +1,46 @@
1
+ import { createClient } from '../../api.js';
2
+ import { requireConfig, requireOrg } from '../../config.js';
3
+ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
4
+ /**
5
+ * Rename / re-describe an alert group, or set it as the default. The PUT
6
+ * endpoint replaces all fields, so we read the current group first and apply
7
+ * only the flags you pass.
8
+ */
9
+ export async function updateAlertGroup(nameOrId, opts) {
10
+ if (opts.name === undefined && opts.description === undefined && opts.default === undefined) {
11
+ console.error('Nothing to update. Pass --name, --description, or --default.');
12
+ process.exit(1);
13
+ }
14
+ const config = requireConfig();
15
+ requireOrg(config);
16
+ const client = createClient(config);
17
+ let groups;
18
+ try {
19
+ groups = (await client.listAlertGroups()).alert_groups;
20
+ }
21
+ catch (err) {
22
+ console.error('Failed to list alert groups:', err.message);
23
+ process.exit(1);
24
+ }
25
+ const needle = nameOrId.trim().toLowerCase();
26
+ const current = UUID_RE.test(nameOrId.trim())
27
+ ? groups.find((g) => g.ID === nameOrId.trim())
28
+ : groups.find((g) => g.Name.toLowerCase() === needle);
29
+ if (!current) {
30
+ console.error(`No alert group "${nameOrId}". Run \`alertee alert-groups list\`.`);
31
+ process.exit(1);
32
+ }
33
+ try {
34
+ await client.updateAlertGroup(current.ID, {
35
+ name: opts.name ?? current.Name,
36
+ description: opts.description ?? current.Description?.String ?? '',
37
+ is_default: opts.default ?? current.IsDefault?.Bool ?? false,
38
+ });
39
+ }
40
+ catch (err) {
41
+ console.error('Failed to update alert group:', err.message);
42
+ process.exit(1);
43
+ }
44
+ console.log(`Updated alert group ${current.ID}.`);
45
+ }
46
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../../src/commands/alert-groups/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAQ3D,MAAM,OAAO,GACX,iEAAiE,CAAA;AAEnE;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,QAAgB,EAChB,IAA6B;IAE7B,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC5F,OAAO,CAAC,KAAK,CAAC,8DAA8D,CAAC,CAAA;QAC7E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,MAAM,MAAM,GAAG,aAAa,EAAE,CAAA;IAC9B,UAAU,CAAC,MAAM,CAAC,CAAA;IAClB,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;IAEnC,IAAI,MAA0E,CAAA;IAC9E,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC,YAAY,CAAA;IACxD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAG,GAAa,CAAC,OAAO,CAAC,CAAA;QACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IAC5C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC3C,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC9C,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,CAAA;IAEvD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,mBAAmB,QAAQ,uCAAuC,CAAC,CAAA;QACjF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,EAAE;YACxC,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI;YAC/B,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,OAAO,CAAC,WAAW,EAAE,MAAM,IAAI,EAAE;YAClE,UAAU,EAAE,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,IAAI,IAAI,KAAK;SAC7D,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAG,GAAa,CAAC,OAAO,CAAC,CAAA;QACtE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,uBAAuB,OAAO,CAAC,EAAE,GAAG,CAAC,CAAA;AACnD,CAAC"}
@@ -1,2 +1,26 @@
1
- export declare function createCheck(): Promise<void>;
1
+ export interface CreateCheckOptions {
2
+ name?: string;
3
+ /** Connection name or ID. */
4
+ connection?: string;
5
+ query?: string;
6
+ /** Force a grid (multi-dimensional) check. */
7
+ grid?: boolean;
8
+ evaluationType?: string;
9
+ /** Comparison for single-value / per-cell conditions. */
10
+ condition?: string;
11
+ threshold?: number;
12
+ severity?: string;
13
+ labelQuery?: string;
14
+ interval?: string;
15
+ alertLevel?: string;
16
+ /** Route this check's alerts to a specific alert group (name or ID). */
17
+ alertGroup?: string;
18
+ }
19
+ /**
20
+ * Create a check, psql-style: pass everything as flags for non-interactive use
21
+ * (CI, or Claude driving the CLI), or omit flags to be prompted for each field
22
+ * at a terminal. The check type is single-value unless --grid or
23
+ * --evaluation-type is given.
24
+ */
25
+ export declare function createCheck(opts?: CreateCheckOptions): Promise<void>;
2
26
  //# sourceMappingURL=create.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/checks/create.ts"],"names":[],"mappings":"AAcA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CA0IjD"}
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/checks/create.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,6BAA6B;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,8CAA8C;IAC9C,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,IAAI,GAAE,kBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2D9E"}
@@ -1,7 +1,10 @@
1
1
  import { confirm, input, number, select } from '@inquirer/prompts';
2
2
  import { createClient } from '../../api.js';
3
- import { requireConfig, resolveOrgId, resolveWebUrl, usingEnvToken } from '../../config.js';
3
+ import { requireConfig, requireOrg, resolveWebUrl } from '../../config.js';
4
4
  import { INTERVAL_CHOICES } from '../../intervals.js';
5
+ import { isInteractive, requireValue } from '../../prompts.js';
6
+ import { resolveAlertGroupId } from '../alert-groups/resolve.js';
7
+ import { resolveConnectionId } from '../connections/resolve.js';
5
8
  const CELL_COMPARISONS = [
6
9
  { name: 'Greater than', value: 'greater_than' },
7
10
  { name: 'Less than', value: 'less_than' },
@@ -10,32 +13,69 @@ const CELL_COMPARISONS = [
10
13
  { name: 'Equal to', value: 'equals' },
11
14
  { name: 'Not equal to', value: 'not_equals' },
12
15
  ];
13
- export async function createCheck() {
16
+ const VALID_COMPARISONS = CELL_COMPARISONS.map((c) => c.value);
17
+ const EVALUATION_TYPES = ['all_cells', 'any_cell', 'dimension_missing', 'dimension_added'];
18
+ const VALID_INTERVALS = INTERVAL_CHOICES.map((c) => c.value);
19
+ const VALID_SEVERITIES = ['info', 'warning', 'critical'];
20
+ /**
21
+ * Create a check, psql-style: pass everything as flags for non-interactive use
22
+ * (CI, or Claude driving the CLI), or omit flags to be prompted for each field
23
+ * at a terminal. The check type is single-value unless --grid or
24
+ * --evaluation-type is given.
25
+ */
26
+ export async function createCheck(opts = {}) {
14
27
  const config = requireConfig();
15
- if (!resolveOrgId(config) && !usingEnvToken()) {
16
- console.error('No organization linked. Run: alertee link (or set ALERTEE_ORG)');
28
+ requireOrg(config);
29
+ const client = createClient(config);
30
+ const isGrid = await resolveMode(opts);
31
+ const name = await requireValue(opts.name, () => input({ message: 'Check name:', validate: (v) => v.trim().length > 0 || 'Required' }), 'Check name required. Pass --name.');
32
+ const connectionId = await resolveConnection(client, opts.connection);
33
+ const query = await requireValue(opts.query, () => input({
34
+ message: isGrid
35
+ ? 'SQL query (must return `name` and `value` columns, one row per dimension):'
36
+ : 'SQL query (must return a single numeric value):',
37
+ validate: (v) => v.trim().length > 0 || 'Query is required',
38
+ }), 'SQL query required. Pass --query.');
39
+ const { condition, labelQuery } = isGrid
40
+ ? await buildGridCondition(opts)
41
+ : { condition: await buildSingleCondition(opts), labelQuery: undefined };
42
+ const interval = await requireValue(opts.interval, () => select({ message: 'Check interval:', choices: INTERVAL_CHOICES }), 'Interval required. Pass --interval (e.g. five_minutes).');
43
+ if (!VALID_INTERVALS.includes(interval)) {
44
+ console.error(`Invalid --interval "${interval}". One of: ${VALID_INTERVALS.join(', ')}.`);
17
45
  process.exit(1);
18
46
  }
19
- const client = createClient(config);
20
- // Fetch connections to let user choose
21
- let connections;
47
+ const alertGroupId = opts.alertGroup
48
+ ? await resolveAlertGroupId(client, opts.alertGroup)
49
+ : undefined;
22
50
  try {
23
- const resp = await client.listConnections();
24
- connections = resp.connections;
51
+ const resp = await client.createCheck({
52
+ name,
53
+ connection_id: connectionId,
54
+ query,
55
+ condition,
56
+ interval,
57
+ alert_level: opts.alertLevel,
58
+ alert_group_id: alertGroupId,
59
+ label_query: labelQuery,
60
+ });
61
+ console.log(`\nCheck created: ${resp.check.ID}`);
62
+ console.log(`View at: ${resolveWebUrl()}/checks/${resp.check.ID}`);
25
63
  }
26
64
  catch (err) {
27
- console.error('Failed to fetch connections:', err.message);
65
+ console.error('Failed to create check:', err.message);
28
66
  process.exit(1);
29
67
  }
30
- if (connections.length === 0) {
31
- console.error('No database connections found. Add one at app.alertee.app/settings?tab=connections');
68
+ }
69
+ /** Decide single vs grid from flags, prompting only when ambiguous + interactive. */
70
+ async function resolveMode(opts) {
71
+ if (opts.grid || opts.evaluationType)
72
+ return true;
73
+ if (opts.condition || opts.threshold !== undefined)
74
+ return false;
75
+ if (!isInteractive()) {
76
+ console.error('Specify the check type: --condition + --threshold (single-value), or --grid / --evaluation-type (grid).');
32
77
  process.exit(1);
33
78
  }
34
- const name = await input({ message: 'Check name:' });
35
- const connectionId = await select({
36
- message: 'Database connection:',
37
- choices: connections.map((c) => ({ name: `${c.name} (${c.type})`, value: c.id })),
38
- });
39
79
  const mode = await select({
40
80
  message: 'Evaluation:',
41
81
  choices: [
@@ -43,51 +83,86 @@ export async function createCheck() {
43
83
  { name: 'Multi-dimensional / grid (query returns name + value rows)', value: 'grid' },
44
84
  ],
45
85
  });
46
- const query = await input({
47
- message: mode === 'grid'
48
- ? 'SQL query (must return `name` and `value` columns, one row per dimension):'
49
- : 'SQL query (must return a single numeric value):',
50
- validate: (v) => v.trim().length > 0 || 'Query is required',
86
+ return mode === 'grid';
87
+ }
88
+ async function resolveConnection(client, connection) {
89
+ if (connection)
90
+ return resolveConnectionId(client, connection);
91
+ if (!isInteractive()) {
92
+ console.error('Connection required. Pass --connection <name|id> (see: alertee connections list).');
93
+ process.exit(1);
94
+ }
95
+ const connections = (await client.listConnections()).connections;
96
+ if (connections.length === 0) {
97
+ console.error('No database connections found. Create one: alertee connections create');
98
+ process.exit(1);
99
+ }
100
+ return select({
101
+ message: 'Database connection:',
102
+ choices: connections.map((c) => ({ name: `${c.name} (${c.type})`, value: c.id })),
51
103
  });
52
- let condition;
53
- let labelQuery;
54
- if (mode === 'grid') {
55
- const evaluationType = await select({
56
- message: 'Grid evaluation type:',
57
- choices: [
58
- {
59
- name: 'Every cell must satisfy a condition (alert if any fails)',
60
- value: 'all_cells',
61
- },
62
- {
63
- name: 'At least one cell must satisfy a condition (alert if none do)',
64
- value: 'any_cell',
65
- },
66
- { name: 'A dimension goes missing', value: 'dimension_missing' },
67
- { name: 'A new dimension appears', value: 'dimension_added' },
68
- ],
69
- });
70
- condition = { evaluation_type: evaluationType };
71
- if (evaluationType === 'any_cell' || evaluationType === 'all_cells') {
72
- const comparison = await select({
73
- message: "Each cell's value should be (healthy state; alert on cells that don't match):",
74
- choices: CELL_COMPARISONS,
75
- });
76
- const threshold = await number({
77
- message: 'Threshold value:',
78
- validate: (v) => v !== undefined || 'Required',
79
- });
80
- condition.type = comparison;
81
- condition.value = String(threshold);
104
+ }
105
+ async function buildSingleCondition(opts) {
106
+ const comparison = await requireValue(opts.condition, () => select({
107
+ message: 'Condition type:',
108
+ choices: CELL_COMPARISONS,
109
+ }), 'Condition required. Pass --condition (e.g. less_than).');
110
+ if (!VALID_COMPARISONS.includes(comparison)) {
111
+ console.error(`Invalid --condition "${comparison}". One of: ${VALID_COMPARISONS.join(', ')}.`);
112
+ process.exit(1);
113
+ }
114
+ const threshold = await requireThreshold(opts);
115
+ return { type: comparison, value: String(threshold) };
116
+ }
117
+ async function buildGridCondition(opts) {
118
+ const evaluationType = await requireValue(opts.evaluationType, () => select({
119
+ message: 'Grid evaluation type:',
120
+ choices: [
121
+ { name: 'Every cell must satisfy a condition (alert if any fails)', value: 'all_cells' },
122
+ { name: 'At least one cell must satisfy a condition (alert if none do)', value: 'any_cell' },
123
+ { name: 'A dimension goes missing', value: 'dimension_missing' },
124
+ { name: 'A new dimension appears', value: 'dimension_added' },
125
+ ],
126
+ }), 'Grid evaluation type required. Pass --evaluation-type (e.g. any_cell).');
127
+ if (!EVALUATION_TYPES.includes(evaluationType)) {
128
+ console.error(`Invalid --evaluation-type "${evaluationType}". One of: ${EVALUATION_TYPES.join(', ')}.`);
129
+ process.exit(1);
130
+ }
131
+ const condition = {
132
+ evaluation_type: evaluationType,
133
+ };
134
+ if (evaluationType === 'any_cell' || evaluationType === 'all_cells') {
135
+ const comparison = await requireValue(opts.condition, () => select({
136
+ message: "Each cell's value should be (healthy state; alert on cells that don't match):",
137
+ choices: CELL_COMPARISONS,
138
+ }), 'Per-cell condition required. Pass --condition (e.g. greater_or_equal).');
139
+ if (!VALID_COMPARISONS.includes(comparison)) {
140
+ console.error(`Invalid --condition "${comparison}". One of: ${VALID_COMPARISONS.join(', ')}.`);
141
+ process.exit(1);
82
142
  }
83
- condition.severity = await select({
143
+ condition.type = comparison;
144
+ condition.value = String(await requireThreshold(opts));
145
+ }
146
+ // Severity defaults to the backend default (warning) when omitted non-interactively.
147
+ if (opts.severity) {
148
+ if (!VALID_SEVERITIES.includes(opts.severity)) {
149
+ console.error(`Invalid --severity "${opts.severity}". One of: ${VALID_SEVERITIES.join(', ')}.`);
150
+ process.exit(1);
151
+ }
152
+ condition.severity = opts.severity;
153
+ }
154
+ else if (isInteractive()) {
155
+ condition.severity = (await select({
84
156
  message: 'Cell severity when matched:',
85
157
  choices: [
86
158
  { name: 'Warning', value: 'warning' },
87
159
  { name: 'Critical', value: 'critical' },
88
160
  { name: 'Info', value: 'info' },
89
161
  ],
90
- });
162
+ }));
163
+ }
164
+ let labelQuery = opts.labelQuery;
165
+ if (!labelQuery && isInteractive()) {
91
166
  const wantsLabels = await confirm({
92
167
  message: 'Add a label query (map dimension keys to display names)?',
93
168
  default: false,
@@ -99,41 +174,19 @@ export async function createCheck() {
99
174
  });
100
175
  }
101
176
  }
102
- else {
103
- const conditionType = await select({
104
- message: 'Condition type:',
105
- choices: [
106
- { name: 'Greater than', value: 'greater_than' },
107
- { name: 'Less than', value: 'less_than' },
108
- { name: 'Equal to', value: 'equals' },
109
- { name: 'Not equal to', value: 'not_equals' },
110
- ],
111
- });
112
- const threshold = await number({
113
- message: 'Threshold value:',
114
- validate: (v) => v !== undefined || 'Required',
115
- });
116
- condition = { type: conditionType, value: String(threshold) };
117
- }
118
- const interval = await select({
119
- message: 'Check interval:',
120
- choices: INTERVAL_CHOICES,
121
- });
122
- try {
123
- const resp = await client.createCheck({
124
- name,
125
- connection_id: connectionId,
126
- query,
127
- condition,
128
- interval,
129
- label_query: labelQuery,
130
- });
131
- console.log(`\nCheck created: ${resp.check.ID}`);
132
- console.log(`View at: ${resolveWebUrl()}/checks/${resp.check.ID}`);
133
- }
134
- catch (err) {
135
- console.error('Failed to create check:', err.message);
177
+ return { condition, labelQuery };
178
+ }
179
+ async function requireThreshold(opts) {
180
+ if (opts.threshold !== undefined)
181
+ return opts.threshold;
182
+ if (!isInteractive()) {
183
+ console.error('Threshold required. Pass --threshold <number>.');
136
184
  process.exit(1);
137
185
  }
186
+ const value = await number({
187
+ message: 'Threshold value:',
188
+ validate: (v) => v !== undefined || 'Required',
189
+ });
190
+ return value;
138
191
  }
139
192
  //# sourceMappingURL=create.js.map