@hasna/connectors 0.5.7 → 0.5.9

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 (138) hide show
  1. package/README.md +48 -9
  2. package/bin/index.js +57 -1
  3. package/bin/mcp.js +57 -1
  4. package/bin/serve.js +56 -0
  5. package/connectors/connect-chargebee/.env.example +11 -0
  6. package/connectors/connect-chargebee/CLAUDE.md +272 -0
  7. package/connectors/connect-chargebee/README.md +193 -0
  8. package/connectors/connect-chargebee/package.json +51 -0
  9. package/connectors/connect-chargebee/scripts/release.ts +179 -0
  10. package/connectors/connect-chargebee/src/api/client.ts +213 -0
  11. package/connectors/connect-chargebee/src/api/example.ts +48 -0
  12. package/connectors/connect-chargebee/src/api/index.ts +51 -0
  13. package/connectors/connect-chargebee/src/cli/index.ts +254 -0
  14. package/connectors/connect-chargebee/src/index.ts +103 -0
  15. package/connectors/connect-chargebee/src/types/index.ts +237 -0
  16. package/connectors/connect-chargebee/src/utils/auth.ts +274 -0
  17. package/connectors/connect-chargebee/src/utils/bulk.ts +212 -0
  18. package/connectors/connect-chargebee/src/utils/config.ts +326 -0
  19. package/connectors/connect-chargebee/src/utils/output.ts +175 -0
  20. package/connectors/connect-chargebee/src/utils/settings.ts +114 -0
  21. package/connectors/connect-chargebee/src/utils/storage.ts +198 -0
  22. package/connectors/connect-chargebee/tsconfig.json +16 -0
  23. package/connectors/connect-databricks/.env.example +11 -0
  24. package/connectors/connect-databricks/CLAUDE.md +272 -0
  25. package/connectors/connect-databricks/README.md +193 -0
  26. package/connectors/connect-databricks/package.json +51 -0
  27. package/connectors/connect-databricks/scripts/release.ts +179 -0
  28. package/connectors/connect-databricks/src/api/client.ts +213 -0
  29. package/connectors/connect-databricks/src/api/example.ts +48 -0
  30. package/connectors/connect-databricks/src/api/index.ts +51 -0
  31. package/connectors/connect-databricks/src/cli/index.ts +254 -0
  32. package/connectors/connect-databricks/src/index.ts +103 -0
  33. package/connectors/connect-databricks/src/types/index.ts +237 -0
  34. package/connectors/connect-databricks/src/utils/auth.ts +274 -0
  35. package/connectors/connect-databricks/src/utils/bulk.ts +212 -0
  36. package/connectors/connect-databricks/src/utils/config.ts +326 -0
  37. package/connectors/connect-databricks/src/utils/output.ts +175 -0
  38. package/connectors/connect-databricks/src/utils/settings.ts +114 -0
  39. package/connectors/connect-databricks/src/utils/storage.ts +198 -0
  40. package/connectors/connect-databricks/tsconfig.json +16 -0
  41. package/connectors/connect-datadog/.env.example +11 -0
  42. package/connectors/connect-datadog/CLAUDE.md +170 -0
  43. package/connectors/connect-datadog/README.md +193 -0
  44. package/connectors/connect-datadog/package.json +53 -0
  45. package/connectors/connect-datadog/src/api/client.ts +150 -0
  46. package/connectors/connect-datadog/src/api/index.ts +537 -0
  47. package/connectors/connect-datadog/src/cli/index.ts +958 -0
  48. package/connectors/connect-datadog/src/index.ts +26 -0
  49. package/connectors/connect-datadog/src/types/index.ts +654 -0
  50. package/connectors/connect-datadog/src/utils/config.ts +219 -0
  51. package/connectors/connect-datadog/src/utils/output.ts +119 -0
  52. package/connectors/connect-datadog/tsconfig.json +16 -0
  53. package/connectors/connect-fathom/.env.example +11 -0
  54. package/connectors/connect-fathom/CLAUDE.md +272 -0
  55. package/connectors/connect-fathom/README.md +193 -0
  56. package/connectors/connect-fathom/package.json +51 -0
  57. package/connectors/connect-fathom/scripts/release.ts +179 -0
  58. package/connectors/connect-fathom/src/api/client.ts +213 -0
  59. package/connectors/connect-fathom/src/api/example.ts +48 -0
  60. package/connectors/connect-fathom/src/api/index.ts +51 -0
  61. package/connectors/connect-fathom/src/cli/index.ts +254 -0
  62. package/connectors/connect-fathom/src/index.ts +103 -0
  63. package/connectors/connect-fathom/src/types/index.ts +237 -0
  64. package/connectors/connect-fathom/src/utils/auth.ts +274 -0
  65. package/connectors/connect-fathom/src/utils/bulk.ts +212 -0
  66. package/connectors/connect-fathom/src/utils/config.ts +326 -0
  67. package/connectors/connect-fathom/src/utils/output.ts +175 -0
  68. package/connectors/connect-fathom/src/utils/settings.ts +114 -0
  69. package/connectors/connect-fathom/src/utils/storage.ts +198 -0
  70. package/connectors/connect-fathom/tsconfig.json +16 -0
  71. package/connectors/connect-grafana/.env.example +11 -0
  72. package/connectors/connect-grafana/CLAUDE.md +272 -0
  73. package/connectors/connect-grafana/README.md +193 -0
  74. package/connectors/connect-grafana/package.json +51 -0
  75. package/connectors/connect-grafana/scripts/release.ts +179 -0
  76. package/connectors/connect-grafana/src/api/client.ts +213 -0
  77. package/connectors/connect-grafana/src/api/example.ts +48 -0
  78. package/connectors/connect-grafana/src/api/index.ts +51 -0
  79. package/connectors/connect-grafana/src/cli/index.ts +254 -0
  80. package/connectors/connect-grafana/src/index.ts +103 -0
  81. package/connectors/connect-grafana/src/types/index.ts +237 -0
  82. package/connectors/connect-grafana/src/utils/auth.ts +274 -0
  83. package/connectors/connect-grafana/src/utils/bulk.ts +212 -0
  84. package/connectors/connect-grafana/src/utils/config.ts +326 -0
  85. package/connectors/connect-grafana/src/utils/output.ts +175 -0
  86. package/connectors/connect-grafana/src/utils/settings.ts +114 -0
  87. package/connectors/connect-grafana/src/utils/storage.ts +198 -0
  88. package/connectors/connect-grafana/tsconfig.json +16 -0
  89. package/connectors/connect-paddle/.env.example +11 -0
  90. package/connectors/connect-paddle/CLAUDE.md +272 -0
  91. package/connectors/connect-paddle/README.md +193 -0
  92. package/connectors/connect-paddle/package.json +51 -0
  93. package/connectors/connect-paddle/scripts/release.ts +179 -0
  94. package/connectors/connect-paddle/src/api/client.ts +213 -0
  95. package/connectors/connect-paddle/src/api/example.ts +48 -0
  96. package/connectors/connect-paddle/src/api/index.ts +51 -0
  97. package/connectors/connect-paddle/src/cli/index.ts +254 -0
  98. package/connectors/connect-paddle/src/index.ts +103 -0
  99. package/connectors/connect-paddle/src/types/index.ts +237 -0
  100. package/connectors/connect-paddle/src/utils/auth.ts +274 -0
  101. package/connectors/connect-paddle/src/utils/bulk.ts +212 -0
  102. package/connectors/connect-paddle/src/utils/config.ts +326 -0
  103. package/connectors/connect-paddle/src/utils/output.ts +175 -0
  104. package/connectors/connect-paddle/src/utils/settings.ts +114 -0
  105. package/connectors/connect-paddle/src/utils/storage.ts +198 -0
  106. package/connectors/connect-paddle/tsconfig.json +16 -0
  107. package/connectors/connect-snowflake/.env.example +11 -0
  108. package/connectors/connect-snowflake/CLAUDE.md +272 -0
  109. package/connectors/connect-snowflake/README.md +193 -0
  110. package/connectors/connect-snowflake/package.json +51 -0
  111. package/connectors/connect-snowflake/scripts/release.ts +179 -0
  112. package/connectors/connect-snowflake/src/api/client.ts +213 -0
  113. package/connectors/connect-snowflake/src/api/example.ts +48 -0
  114. package/connectors/connect-snowflake/src/api/index.ts +51 -0
  115. package/connectors/connect-snowflake/src/cli/index.ts +254 -0
  116. package/connectors/connect-snowflake/src/index.ts +103 -0
  117. package/connectors/connect-snowflake/src/types/index.ts +237 -0
  118. package/connectors/connect-snowflake/src/utils/auth.ts +274 -0
  119. package/connectors/connect-snowflake/src/utils/bulk.ts +212 -0
  120. package/connectors/connect-snowflake/src/utils/config.ts +326 -0
  121. package/connectors/connect-snowflake/src/utils/output.ts +175 -0
  122. package/connectors/connect-snowflake/src/utils/settings.ts +114 -0
  123. package/connectors/connect-snowflake/src/utils/storage.ts +198 -0
  124. package/connectors/connect-snowflake/tsconfig.json +16 -0
  125. package/connectors/connect-square/.env.example +11 -0
  126. package/connectors/connect-square/CLAUDE.md +128 -0
  127. package/connectors/connect-square/README.md +193 -0
  128. package/connectors/connect-square/package.json +52 -0
  129. package/connectors/connect-square/src/api/client.ts +152 -0
  130. package/connectors/connect-square/src/api/index.ts +343 -0
  131. package/connectors/connect-square/src/cli/index.ts +579 -0
  132. package/connectors/connect-square/src/index.ts +21 -0
  133. package/connectors/connect-square/src/types/index.ts +809 -0
  134. package/connectors/connect-square/src/utils/config.ts +209 -0
  135. package/connectors/connect-square/src/utils/output.ts +119 -0
  136. package/connectors/connect-square/tsconfig.json +16 -0
  137. package/dist/index.js +56 -0
  138. package/package.json +1 -1
@@ -0,0 +1,958 @@
1
+ #!/usr/bin/env bun
2
+ import { Command } from 'commander';
3
+ import chalk from 'chalk';
4
+ import { Datadog } from '../api';
5
+ import {
6
+ getApiKey,
7
+ setApiKey,
8
+ getAppKey,
9
+ setAppKey,
10
+ getSite,
11
+ setSite,
12
+ clearConfig,
13
+ getConfigDir,
14
+ setProfileOverride,
15
+ getCurrentProfile,
16
+ setCurrentProfile,
17
+ listProfiles,
18
+ createProfile,
19
+ deleteProfile,
20
+ profileExists,
21
+ loadProfile,
22
+ } from '../utils/config';
23
+ import type { OutputFormat } from '../utils/output';
24
+ import { success, error, info, print } from '../utils/output';
25
+
26
+ const CONNECTOR_NAME = 'connect-datadog';
27
+ const VERSION = '0.0.1';
28
+
29
+ const program = new Command();
30
+
31
+ program
32
+ .name(CONNECTOR_NAME)
33
+ .description('Datadog connector - Manage metrics, monitors, dashboards, SLOs, and more')
34
+ .version(VERSION)
35
+ .option('-k, --api-key <key>', 'API key (overrides config)')
36
+ .option('-a, --app-key <key>', 'Application key (overrides config)')
37
+ .option('-s, --site <site>', 'Datadog site (e.g., datadoghq.com, datadoghq.eu)')
38
+ .option('-f, --format <format>', 'Output format (json, pretty)', 'pretty')
39
+ .option('-p, --profile <profile>', 'Use a specific profile')
40
+ .hook('preAction', (thisCommand) => {
41
+ const opts = thisCommand.opts();
42
+ if (opts.profile) {
43
+ if (!profileExists(opts.profile)) {
44
+ error(`Profile "${opts.profile}" does not exist. Create it with "${CONNECTOR_NAME} profile create ${opts.profile}"`);
45
+ process.exit(1);
46
+ }
47
+ setProfileOverride(opts.profile);
48
+ }
49
+ if (opts.apiKey) {
50
+ process.env.DATADOG_API_KEY = opts.apiKey;
51
+ }
52
+ if (opts.appKey) {
53
+ process.env.DATADOG_APP_KEY = opts.appKey;
54
+ }
55
+ if (opts.site) {
56
+ process.env.DATADOG_SITE = opts.site;
57
+ }
58
+ });
59
+
60
+ function getFormat(cmd: Command): OutputFormat {
61
+ const parent = cmd.parent;
62
+ return (parent?.opts().format || 'pretty') as OutputFormat;
63
+ }
64
+
65
+ function getClient(): Datadog {
66
+ const apiKey = getApiKey();
67
+ const appKey = getAppKey();
68
+ const site = getSite();
69
+
70
+ if (!apiKey) {
71
+ error(`No API key configured. Run "${CONNECTOR_NAME} config set-api-key <key>" or set DATADOG_API_KEY environment variable.`);
72
+ process.exit(1);
73
+ }
74
+ if (!appKey) {
75
+ error(`No Application key configured. Run "${CONNECTOR_NAME} config set-app-key <key>" or set DATADOG_APP_KEY environment variable.`);
76
+ process.exit(1);
77
+ }
78
+ return new Datadog({ apiKey, appKey, site });
79
+ }
80
+
81
+ // ============================================
82
+ // Profile Commands
83
+ // ============================================
84
+ const profileCmd = program
85
+ .command('profile')
86
+ .description('Manage configuration profiles');
87
+
88
+ profileCmd
89
+ .command('list')
90
+ .description('List all profiles')
91
+ .action(() => {
92
+ const profiles = listProfiles();
93
+ const current = getCurrentProfile();
94
+
95
+ if (profiles.length === 0) {
96
+ info('No profiles found. Use "profile create <name>" to create one.');
97
+ return;
98
+ }
99
+
100
+ success(`Profiles:`);
101
+ profiles.forEach(p => {
102
+ const isActive = p === current ? chalk.green(' (active)') : '';
103
+ console.log(` ${p}${isActive}`);
104
+ });
105
+ });
106
+
107
+ profileCmd
108
+ .command('use <name>')
109
+ .description('Switch to a profile')
110
+ .action((name: string) => {
111
+ if (!profileExists(name)) {
112
+ error(`Profile "${name}" does not exist. Create it with "profile create ${name}"`);
113
+ process.exit(1);
114
+ }
115
+ setCurrentProfile(name);
116
+ success(`Switched to profile: ${name}`);
117
+ });
118
+
119
+ profileCmd
120
+ .command('create <name>')
121
+ .description('Create a new profile')
122
+ .option('--api-key <key>', 'API key')
123
+ .option('--app-key <key>', 'Application key')
124
+ .option('--site <site>', 'Datadog site')
125
+ .option('--use', 'Switch to this profile after creation')
126
+ .action((name: string, opts) => {
127
+ if (profileExists(name)) {
128
+ error(`Profile "${name}" already exists`);
129
+ process.exit(1);
130
+ }
131
+
132
+ createProfile(name, {
133
+ apiKey: opts.apiKey,
134
+ appKey: opts.appKey,
135
+ site: opts.site,
136
+ });
137
+ success(`Profile "${name}" created`);
138
+
139
+ if (opts.use) {
140
+ setCurrentProfile(name);
141
+ info(`Switched to profile: ${name}`);
142
+ }
143
+ });
144
+
145
+ profileCmd
146
+ .command('delete <name>')
147
+ .description('Delete a profile')
148
+ .action((name: string) => {
149
+ if (name === 'default') {
150
+ error('Cannot delete the default profile');
151
+ process.exit(1);
152
+ }
153
+ if (deleteProfile(name)) {
154
+ success(`Profile "${name}" deleted`);
155
+ } else {
156
+ error(`Profile "${name}" not found`);
157
+ process.exit(1);
158
+ }
159
+ });
160
+
161
+ profileCmd
162
+ .command('show [name]')
163
+ .description('Show profile configuration')
164
+ .action((name?: string) => {
165
+ const profileName = name || getCurrentProfile();
166
+ const config = loadProfile(profileName);
167
+ const active = getCurrentProfile();
168
+
169
+ console.log(chalk.bold(`Profile: ${profileName}${profileName === active ? chalk.green(' (active)') : ''}`));
170
+ info(`API Key: ${config.apiKey ? `${config.apiKey.substring(0, 8)}...` : chalk.gray('not set')}`);
171
+ info(`App Key: ${config.appKey ? `${config.appKey.substring(0, 8)}...` : chalk.gray('not set')}`);
172
+ info(`Site: ${config.site || chalk.gray('datadoghq.com (default)')}`);
173
+ });
174
+
175
+ // ============================================
176
+ // Config Commands
177
+ // ============================================
178
+ const configCmd = program
179
+ .command('config')
180
+ .description('Manage CLI configuration');
181
+
182
+ configCmd
183
+ .command('set-api-key <apiKey>')
184
+ .description('Set API key')
185
+ .action((apiKey: string) => {
186
+ setApiKey(apiKey);
187
+ success(`API key saved to profile: ${getCurrentProfile()}`);
188
+ });
189
+
190
+ configCmd
191
+ .command('set-app-key <appKey>')
192
+ .description('Set Application key')
193
+ .action((appKey: string) => {
194
+ setAppKey(appKey);
195
+ success(`Application key saved to profile: ${getCurrentProfile()}`);
196
+ });
197
+
198
+ configCmd
199
+ .command('set-site <site>')
200
+ .description('Set Datadog site (e.g., datadoghq.com, datadoghq.eu)')
201
+ .action((site: string) => {
202
+ setSite(site);
203
+ success(`Site saved to profile: ${getCurrentProfile()}`);
204
+ });
205
+
206
+ configCmd
207
+ .command('show')
208
+ .description('Show current configuration')
209
+ .action(() => {
210
+ const profileName = getCurrentProfile();
211
+ const apiKey = getApiKey();
212
+ const appKey = getAppKey();
213
+ const site = getSite();
214
+
215
+ console.log(chalk.bold(`Active Profile: ${profileName}`));
216
+ info(`Config directory: ${getConfigDir()}`);
217
+ info(`API Key: ${apiKey ? `${apiKey.substring(0, 8)}...` : chalk.gray('not set')}`);
218
+ info(`App Key: ${appKey ? `${appKey.substring(0, 8)}...` : chalk.gray('not set')}`);
219
+ info(`Site: ${site || chalk.gray('datadoghq.com (default)')}`);
220
+ });
221
+
222
+ configCmd
223
+ .command('clear')
224
+ .description('Clear configuration')
225
+ .action(() => {
226
+ clearConfig();
227
+ success(`Configuration cleared for profile: ${getCurrentProfile()}`);
228
+ });
229
+
230
+ // ============================================
231
+ // Validate Command
232
+ // ============================================
233
+ program
234
+ .command('validate')
235
+ .description('Validate API credentials')
236
+ .action(async function(this: Command) {
237
+ try {
238
+ const client = getClient();
239
+ const result = await client.validate();
240
+ if (result.valid) {
241
+ success('API credentials are valid');
242
+ } else {
243
+ error('API credentials are invalid');
244
+ process.exit(1);
245
+ }
246
+ } catch (err) {
247
+ error(String(err));
248
+ process.exit(1);
249
+ }
250
+ });
251
+
252
+ // ============================================
253
+ // Organization Command
254
+ // ============================================
255
+ program
256
+ .command('org')
257
+ .description('Get organization info')
258
+ .action(async function(this: Command) {
259
+ try {
260
+ const client = getClient();
261
+ const result = await client.getOrganization();
262
+ print(result.org, getFormat(this));
263
+ } catch (err) {
264
+ error(String(err));
265
+ process.exit(1);
266
+ }
267
+ });
268
+
269
+ // ============================================
270
+ // Metrics Commands
271
+ // ============================================
272
+ const metricsCmd = program
273
+ .command('metrics')
274
+ .description('Manage metrics');
275
+
276
+ metricsCmd
277
+ .command('query')
278
+ .description('Query timeseries metrics')
279
+ .requiredOption('-q, --query <query>', 'Metrics query')
280
+ .option('--from <timestamp>', 'Start time (Unix timestamp)', String(Math.floor(Date.now() / 1000) - 3600))
281
+ .option('--to <timestamp>', 'End time (Unix timestamp)', String(Math.floor(Date.now() / 1000)))
282
+ .action(async function(this: Command, opts) {
283
+ try {
284
+ const client = getClient();
285
+ const result = await client.queryMetrics({
286
+ query: opts.query,
287
+ from: parseInt(opts.from),
288
+ to: parseInt(opts.to),
289
+ });
290
+ print(result, getFormat(this));
291
+ } catch (err) {
292
+ error(String(err));
293
+ process.exit(1);
294
+ }
295
+ });
296
+
297
+ metricsCmd
298
+ .command('list')
299
+ .description('List active metrics')
300
+ .requiredOption('--from <timestamp>', 'Start time (Unix timestamp)')
301
+ .option('--host <host>', 'Filter by host')
302
+ .option('--tag-filter <filter>', 'Filter by tag')
303
+ .action(async function(this: Command, opts) {
304
+ try {
305
+ const client = getClient();
306
+ const result = await client.listActiveMetrics({
307
+ from: parseInt(opts.from),
308
+ host: opts.host,
309
+ tag_filter: opts.tagFilter,
310
+ });
311
+ print(result, getFormat(this));
312
+ } catch (err) {
313
+ error(String(err));
314
+ process.exit(1);
315
+ }
316
+ });
317
+
318
+ metricsCmd
319
+ .command('metadata <name>')
320
+ .description('Get metric metadata')
321
+ .action(async function(this: Command, name: string) {
322
+ try {
323
+ const client = getClient();
324
+ const result = await client.getMetricMetadata(name);
325
+ print(result, getFormat(this));
326
+ } catch (err) {
327
+ error(String(err));
328
+ process.exit(1);
329
+ }
330
+ });
331
+
332
+ // ============================================
333
+ // Events Commands
334
+ // ============================================
335
+ const eventsCmd = program
336
+ .command('events')
337
+ .description('Manage events');
338
+
339
+ eventsCmd
340
+ .command('list')
341
+ .description('List events')
342
+ .requiredOption('--start <timestamp>', 'Start time (Unix timestamp)')
343
+ .requiredOption('--end <timestamp>', 'End time (Unix timestamp)')
344
+ .option('--priority <priority>', 'Priority (normal, low)')
345
+ .option('--sources <sources>', 'Comma-separated sources')
346
+ .option('--tags <tags>', 'Comma-separated tags')
347
+ .action(async function(this: Command, opts) {
348
+ try {
349
+ const client = getClient();
350
+ const result = await client.listEvents({
351
+ start: parseInt(opts.start),
352
+ end: parseInt(opts.end),
353
+ priority: opts.priority,
354
+ sources: opts.sources,
355
+ tags: opts.tags,
356
+ });
357
+ print(result.events, getFormat(this));
358
+ } catch (err) {
359
+ error(String(err));
360
+ process.exit(1);
361
+ }
362
+ });
363
+
364
+ eventsCmd
365
+ .command('get <id>')
366
+ .description('Get an event')
367
+ .action(async function(this: Command, id: string) {
368
+ try {
369
+ const client = getClient();
370
+ const result = await client.getEvent(parseInt(id));
371
+ print(result.event, getFormat(this));
372
+ } catch (err) {
373
+ error(String(err));
374
+ process.exit(1);
375
+ }
376
+ });
377
+
378
+ eventsCmd
379
+ .command('create')
380
+ .description('Create an event')
381
+ .requiredOption('--title <title>', 'Event title')
382
+ .requiredOption('--text <text>', 'Event text')
383
+ .option('--priority <priority>', 'Priority (normal, low)', 'normal')
384
+ .option('--alert-type <type>', 'Alert type (error, warning, info, success)')
385
+ .option('--host <host>', 'Host name')
386
+ .option('--tags <tags>', 'Comma-separated tags')
387
+ .action(async function(this: Command, opts) {
388
+ try {
389
+ const client = getClient();
390
+ const result = await client.createEvent({
391
+ title: opts.title,
392
+ text: opts.text,
393
+ priority: opts.priority,
394
+ alert_type: opts.alertType,
395
+ host: opts.host,
396
+ tags: opts.tags?.split(','),
397
+ });
398
+ print(result.event, getFormat(this));
399
+ success(`Event created: ${result.event.id}`);
400
+ } catch (err) {
401
+ error(String(err));
402
+ process.exit(1);
403
+ }
404
+ });
405
+
406
+ // ============================================
407
+ // Monitors Commands
408
+ // ============================================
409
+ const monitorsCmd = program
410
+ .command('monitors')
411
+ .description('Manage monitors');
412
+
413
+ monitorsCmd
414
+ .command('list')
415
+ .description('List monitors')
416
+ .option('--name <name>', 'Filter by name')
417
+ .option('--tags <tags>', 'Filter by tags')
418
+ .option('--page <page>', 'Page number', '0')
419
+ .option('--page-size <size>', 'Page size', '100')
420
+ .action(async function(this: Command, opts) {
421
+ try {
422
+ const client = getClient();
423
+ const result = await client.listMonitors({
424
+ name: opts.name,
425
+ tags: opts.tags,
426
+ page: parseInt(opts.page),
427
+ page_size: parseInt(opts.pageSize),
428
+ });
429
+ print(result, getFormat(this));
430
+ } catch (err) {
431
+ error(String(err));
432
+ process.exit(1);
433
+ }
434
+ });
435
+
436
+ monitorsCmd
437
+ .command('get <id>')
438
+ .description('Get a monitor')
439
+ .option('--with-downtimes', 'Include downtime info')
440
+ .action(async function(this: Command, id: string, opts) {
441
+ try {
442
+ const client = getClient();
443
+ const result = await client.getMonitor(parseInt(id), {
444
+ with_downtimes: opts.withDowntimes,
445
+ });
446
+ print(result, getFormat(this));
447
+ } catch (err) {
448
+ error(String(err));
449
+ process.exit(1);
450
+ }
451
+ });
452
+
453
+ monitorsCmd
454
+ .command('delete <id>')
455
+ .description('Delete a monitor')
456
+ .option('--force', 'Force deletion')
457
+ .action(async function(this: Command, id: string, opts) {
458
+ try {
459
+ const client = getClient();
460
+ await client.deleteMonitor(parseInt(id), { force: opts.force });
461
+ success(`Monitor ${id} deleted`);
462
+ } catch (err) {
463
+ error(String(err));
464
+ process.exit(1);
465
+ }
466
+ });
467
+
468
+ monitorsCmd
469
+ .command('mute <id>')
470
+ .description('Mute a monitor')
471
+ .option('--scope <scope>', 'Scope to mute')
472
+ .option('--end <timestamp>', 'End time (Unix timestamp)')
473
+ .action(async function(this: Command, id: string, opts) {
474
+ try {
475
+ const client = getClient();
476
+ await client.muteMonitor(parseInt(id), {
477
+ scope: opts.scope,
478
+ end: opts.end ? parseInt(opts.end) : undefined,
479
+ });
480
+ success(`Monitor ${id} muted`);
481
+ } catch (err) {
482
+ error(String(err));
483
+ process.exit(1);
484
+ }
485
+ });
486
+
487
+ monitorsCmd
488
+ .command('unmute <id>')
489
+ .description('Unmute a monitor')
490
+ .option('--scope <scope>', 'Scope to unmute')
491
+ .option('--all-scopes', 'Unmute all scopes')
492
+ .action(async function(this: Command, id: string, opts) {
493
+ try {
494
+ const client = getClient();
495
+ await client.unmuteMonitor(parseInt(id), {
496
+ scope: opts.scope,
497
+ all_scopes: opts.allScopes,
498
+ });
499
+ success(`Monitor ${id} unmuted`);
500
+ } catch (err) {
501
+ error(String(err));
502
+ process.exit(1);
503
+ }
504
+ });
505
+
506
+ // ============================================
507
+ // Dashboards Commands
508
+ // ============================================
509
+ const dashboardsCmd = program
510
+ .command('dashboards')
511
+ .description('Manage dashboards');
512
+
513
+ dashboardsCmd
514
+ .command('list')
515
+ .description('List dashboards')
516
+ .option('--count <count>', 'Number of dashboards', '100')
517
+ .option('--start <start>', 'Start index', '0')
518
+ .action(async function(this: Command, opts) {
519
+ try {
520
+ const client = getClient();
521
+ const result = await client.listDashboards({
522
+ count: parseInt(opts.count),
523
+ start: parseInt(opts.start),
524
+ });
525
+ print(result.dashboards, getFormat(this));
526
+ } catch (err) {
527
+ error(String(err));
528
+ process.exit(1);
529
+ }
530
+ });
531
+
532
+ dashboardsCmd
533
+ .command('get <id>')
534
+ .description('Get a dashboard')
535
+ .action(async function(this: Command, id: string) {
536
+ try {
537
+ const client = getClient();
538
+ const result = await client.getDashboard(id);
539
+ print(result, getFormat(this));
540
+ } catch (err) {
541
+ error(String(err));
542
+ process.exit(1);
543
+ }
544
+ });
545
+
546
+ dashboardsCmd
547
+ .command('delete <id>')
548
+ .description('Delete a dashboard')
549
+ .action(async function(this: Command, id: string) {
550
+ try {
551
+ const client = getClient();
552
+ await client.deleteDashboard(id);
553
+ success(`Dashboard ${id} deleted`);
554
+ } catch (err) {
555
+ error(String(err));
556
+ process.exit(1);
557
+ }
558
+ });
559
+
560
+ // ============================================
561
+ // SLOs Commands
562
+ // ============================================
563
+ const slosCmd = program
564
+ .command('slos')
565
+ .description('Manage SLOs (Service Level Objectives)');
566
+
567
+ slosCmd
568
+ .command('list')
569
+ .description('List SLOs')
570
+ .option('--query <query>', 'Search query')
571
+ .option('--tags <tags>', 'Filter by tags')
572
+ .option('--limit <limit>', 'Limit results', '100')
573
+ .option('--offset <offset>', 'Offset', '0')
574
+ .action(async function(this: Command, opts) {
575
+ try {
576
+ const client = getClient();
577
+ const result = await client.listSLOs({
578
+ query: opts.query,
579
+ tags_query: opts.tags,
580
+ limit: parseInt(opts.limit),
581
+ offset: parseInt(opts.offset),
582
+ });
583
+ print(result.data, getFormat(this));
584
+ } catch (err) {
585
+ error(String(err));
586
+ process.exit(1);
587
+ }
588
+ });
589
+
590
+ slosCmd
591
+ .command('get <id>')
592
+ .description('Get an SLO')
593
+ .action(async function(this: Command, id: string) {
594
+ try {
595
+ const client = getClient();
596
+ const result = await client.getSLO(id);
597
+ print(result.data, getFormat(this));
598
+ } catch (err) {
599
+ error(String(err));
600
+ process.exit(1);
601
+ }
602
+ });
603
+
604
+ slosCmd
605
+ .command('delete <id>')
606
+ .description('Delete an SLO')
607
+ .option('--force', 'Force deletion')
608
+ .action(async function(this: Command, id: string, opts) {
609
+ try {
610
+ const client = getClient();
611
+ await client.deleteSLO(id, { force: opts.force });
612
+ success(`SLO ${id} deleted`);
613
+ } catch (err) {
614
+ error(String(err));
615
+ process.exit(1);
616
+ }
617
+ });
618
+
619
+ slosCmd
620
+ .command('history <id>')
621
+ .description('Get SLO history')
622
+ .requiredOption('--from <timestamp>', 'Start time (Unix timestamp)')
623
+ .requiredOption('--to <timestamp>', 'End time (Unix timestamp)')
624
+ .action(async function(this: Command, id: string, opts) {
625
+ try {
626
+ const client = getClient();
627
+ const result = await client.getSLOHistory(id, {
628
+ from_ts: parseInt(opts.from),
629
+ to_ts: parseInt(opts.to),
630
+ });
631
+ print(result.data, getFormat(this));
632
+ } catch (err) {
633
+ error(String(err));
634
+ process.exit(1);
635
+ }
636
+ });
637
+
638
+ // ============================================
639
+ // Hosts Commands
640
+ // ============================================
641
+ const hostsCmd = program
642
+ .command('hosts')
643
+ .description('Manage hosts');
644
+
645
+ hostsCmd
646
+ .command('list')
647
+ .description('List hosts')
648
+ .option('--filter <filter>', 'Filter hosts')
649
+ .option('--sort-field <field>', 'Sort field')
650
+ .option('--sort-dir <dir>', 'Sort direction (asc, desc)')
651
+ .option('--count <count>', 'Number of hosts', '100')
652
+ .option('--start <start>', 'Start index', '0')
653
+ .action(async function(this: Command, opts) {
654
+ try {
655
+ const client = getClient();
656
+ const result = await client.listHosts({
657
+ filter: opts.filter,
658
+ sort_field: opts.sortField,
659
+ sort_dir: opts.sortDir,
660
+ count: parseInt(opts.count),
661
+ start: parseInt(opts.start),
662
+ });
663
+ print(result.host_list, getFormat(this));
664
+ } catch (err) {
665
+ error(String(err));
666
+ process.exit(1);
667
+ }
668
+ });
669
+
670
+ hostsCmd
671
+ .command('totals')
672
+ .description('Get host totals')
673
+ .action(async function(this: Command) {
674
+ try {
675
+ const client = getClient();
676
+ const result = await client.getHostTotals();
677
+ print(result, getFormat(this));
678
+ } catch (err) {
679
+ error(String(err));
680
+ process.exit(1);
681
+ }
682
+ });
683
+
684
+ hostsCmd
685
+ .command('mute <hostname>')
686
+ .description('Mute a host')
687
+ .option('--end <timestamp>', 'End time (Unix timestamp)')
688
+ .option('--message <message>', 'Mute message')
689
+ .action(async function(this: Command, hostname: string, opts) {
690
+ try {
691
+ const client = getClient();
692
+ await client.muteHost(hostname, {
693
+ end: opts.end ? parseInt(opts.end) : undefined,
694
+ message: opts.message,
695
+ });
696
+ success(`Host ${hostname} muted`);
697
+ } catch (err) {
698
+ error(String(err));
699
+ process.exit(1);
700
+ }
701
+ });
702
+
703
+ hostsCmd
704
+ .command('unmute <hostname>')
705
+ .description('Unmute a host')
706
+ .action(async function(this: Command, hostname: string) {
707
+ try {
708
+ const client = getClient();
709
+ await client.unmuteHost(hostname);
710
+ success(`Host ${hostname} unmuted`);
711
+ } catch (err) {
712
+ error(String(err));
713
+ process.exit(1);
714
+ }
715
+ });
716
+
717
+ // ============================================
718
+ // Downtimes Commands
719
+ // ============================================
720
+ const downtimesCmd = program
721
+ .command('downtimes')
722
+ .description('Manage downtimes');
723
+
724
+ downtimesCmd
725
+ .command('list')
726
+ .description('List downtimes')
727
+ .option('--current-only', 'Only current downtimes')
728
+ .action(async function(this: Command, opts) {
729
+ try {
730
+ const client = getClient();
731
+ const result = await client.listDowntimes({
732
+ current_only: opts.currentOnly,
733
+ });
734
+ print(result, getFormat(this));
735
+ } catch (err) {
736
+ error(String(err));
737
+ process.exit(1);
738
+ }
739
+ });
740
+
741
+ downtimesCmd
742
+ .command('get <id>')
743
+ .description('Get a downtime')
744
+ .action(async function(this: Command, id: string) {
745
+ try {
746
+ const client = getClient();
747
+ const result = await client.getDowntime(parseInt(id));
748
+ print(result, getFormat(this));
749
+ } catch (err) {
750
+ error(String(err));
751
+ process.exit(1);
752
+ }
753
+ });
754
+
755
+ downtimesCmd
756
+ .command('create')
757
+ .description('Create a downtime')
758
+ .requiredOption('--scope <scope>', 'Scope (e.g., "host:myhost")')
759
+ .option('--start <timestamp>', 'Start time (Unix timestamp)')
760
+ .option('--end <timestamp>', 'End time (Unix timestamp)')
761
+ .option('--message <message>', 'Downtime message')
762
+ .option('--timezone <timezone>', 'Timezone')
763
+ .action(async function(this: Command, opts) {
764
+ try {
765
+ const client = getClient();
766
+ const result = await client.createDowntime({
767
+ scope: opts.scope.split(','),
768
+ start: opts.start ? parseInt(opts.start) : undefined,
769
+ end: opts.end ? parseInt(opts.end) : undefined,
770
+ message: opts.message,
771
+ timezone: opts.timezone,
772
+ });
773
+ print(result, getFormat(this));
774
+ success(`Downtime created: ${result.id}`);
775
+ } catch (err) {
776
+ error(String(err));
777
+ process.exit(1);
778
+ }
779
+ });
780
+
781
+ downtimesCmd
782
+ .command('delete <id>')
783
+ .description('Delete a downtime')
784
+ .action(async function(this: Command, id: string) {
785
+ try {
786
+ const client = getClient();
787
+ await client.deleteDowntime(parseInt(id));
788
+ success(`Downtime ${id} deleted`);
789
+ } catch (err) {
790
+ error(String(err));
791
+ process.exit(1);
792
+ }
793
+ });
794
+
795
+ downtimesCmd
796
+ .command('cancel-by-scope')
797
+ .description('Cancel downtimes by scope')
798
+ .requiredOption('--scope <scope>', 'Scope to cancel')
799
+ .action(async function(this: Command, opts) {
800
+ try {
801
+ const client = getClient();
802
+ const result = await client.cancelDowntimesByScope(opts.scope);
803
+ print(result, getFormat(this));
804
+ success(`Cancelled ${result.cancelled_ids.length} downtime(s)`);
805
+ } catch (err) {
806
+ error(String(err));
807
+ process.exit(1);
808
+ }
809
+ });
810
+
811
+ // ============================================
812
+ // Synthetics Commands
813
+ // ============================================
814
+ const syntheticsCmd = program
815
+ .command('synthetics')
816
+ .description('Manage synthetic tests');
817
+
818
+ syntheticsCmd
819
+ .command('list')
820
+ .description('List synthetic tests')
821
+ .option('--page-size <size>', 'Page size', '100')
822
+ .option('--page-number <number>', 'Page number', '0')
823
+ .action(async function(this: Command, opts) {
824
+ try {
825
+ const client = getClient();
826
+ const result = await client.listSyntheticsTests({
827
+ page_size: parseInt(opts.pageSize),
828
+ page_number: parseInt(opts.pageNumber),
829
+ });
830
+ print(result.tests, getFormat(this));
831
+ } catch (err) {
832
+ error(String(err));
833
+ process.exit(1);
834
+ }
835
+ });
836
+
837
+ syntheticsCmd
838
+ .command('get <publicId>')
839
+ .description('Get a synthetic test')
840
+ .action(async function(this: Command, publicId: string) {
841
+ try {
842
+ const client = getClient();
843
+ const result = await client.getSyntheticsTest(publicId);
844
+ print(result, getFormat(this));
845
+ } catch (err) {
846
+ error(String(err));
847
+ process.exit(1);
848
+ }
849
+ });
850
+
851
+ syntheticsCmd
852
+ .command('delete <publicIds>')
853
+ .description('Delete synthetic tests (comma-separated IDs)')
854
+ .action(async function(this: Command, publicIds: string) {
855
+ try {
856
+ const client = getClient();
857
+ const result = await client.deleteSyntheticsTest(publicIds.split(','));
858
+ print(result, getFormat(this));
859
+ success(`Deleted ${result.deleted_tests.length} test(s)`);
860
+ } catch (err) {
861
+ error(String(err));
862
+ process.exit(1);
863
+ }
864
+ });
865
+
866
+ syntheticsCmd
867
+ .command('trigger <publicIds>')
868
+ .description('Trigger synthetic tests (comma-separated IDs)')
869
+ .action(async function(this: Command, publicIds: string) {
870
+ try {
871
+ const client = getClient();
872
+ const result = await client.triggerSyntheticsTests(publicIds.split(','));
873
+ print(result, getFormat(this));
874
+ success(`Triggered tests, batch ID: ${result.batch_id}`);
875
+ } catch (err) {
876
+ error(String(err));
877
+ process.exit(1);
878
+ }
879
+ });
880
+
881
+ syntheticsCmd
882
+ .command('results <publicId>')
883
+ .description('Get synthetic test results')
884
+ .option('--from <timestamp>', 'Start time (Unix timestamp)')
885
+ .option('--to <timestamp>', 'End time (Unix timestamp)')
886
+ .action(async function(this: Command, publicId: string, opts) {
887
+ try {
888
+ const client = getClient();
889
+ const result = await client.getSyntheticsTestResults(publicId, {
890
+ from_ts: opts.from ? parseInt(opts.from) : undefined,
891
+ to_ts: opts.to ? parseInt(opts.to) : undefined,
892
+ });
893
+ print(result.results, getFormat(this));
894
+ } catch (err) {
895
+ error(String(err));
896
+ process.exit(1);
897
+ }
898
+ });
899
+
900
+ // ============================================
901
+ // Users Commands
902
+ // ============================================
903
+ const usersCmd = program
904
+ .command('users')
905
+ .description('Manage users');
906
+
907
+ usersCmd
908
+ .command('list')
909
+ .description('List users')
910
+ .option('--page-size <size>', 'Page size', '100')
911
+ .option('--page-number <number>', 'Page number', '0')
912
+ .option('--filter <filter>', 'Filter users')
913
+ .option('--filter-status <status>', 'Filter by status')
914
+ .action(async function(this: Command, opts) {
915
+ try {
916
+ const client = getClient();
917
+ const result = await client.listUsers({
918
+ page_size: parseInt(opts.pageSize),
919
+ page_number: parseInt(opts.pageNumber),
920
+ filter: opts.filter,
921
+ filter_status: opts.filterStatus,
922
+ });
923
+ print(result.data, getFormat(this));
924
+ } catch (err) {
925
+ error(String(err));
926
+ process.exit(1);
927
+ }
928
+ });
929
+
930
+ usersCmd
931
+ .command('get <id>')
932
+ .description('Get a user')
933
+ .action(async function(this: Command, id: string) {
934
+ try {
935
+ const client = getClient();
936
+ const result = await client.getUser(id);
937
+ print(result.data, getFormat(this));
938
+ } catch (err) {
939
+ error(String(err));
940
+ process.exit(1);
941
+ }
942
+ });
943
+
944
+ usersCmd
945
+ .command('me')
946
+ .description('Get current user')
947
+ .action(async function(this: Command) {
948
+ try {
949
+ const client = getClient();
950
+ const result = await client.getCurrentUser();
951
+ print(result.data, getFormat(this));
952
+ } catch (err) {
953
+ error(String(err));
954
+ process.exit(1);
955
+ }
956
+ });
957
+
958
+ program.parse();