@hasna/connectors 0.5.8 → 0.6.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 (137) hide show
  1. package/bin/index.js +108 -128
  2. package/bin/mcp.js +57 -1
  3. package/bin/serve.js +56 -0
  4. package/connectors/connect-chargebee/.env.example +11 -0
  5. package/connectors/connect-chargebee/CLAUDE.md +272 -0
  6. package/connectors/connect-chargebee/README.md +193 -0
  7. package/connectors/connect-chargebee/package.json +51 -0
  8. package/connectors/connect-chargebee/scripts/release.ts +179 -0
  9. package/connectors/connect-chargebee/src/api/client.ts +213 -0
  10. package/connectors/connect-chargebee/src/api/example.ts +48 -0
  11. package/connectors/connect-chargebee/src/api/index.ts +51 -0
  12. package/connectors/connect-chargebee/src/cli/index.ts +254 -0
  13. package/connectors/connect-chargebee/src/index.ts +103 -0
  14. package/connectors/connect-chargebee/src/types/index.ts +237 -0
  15. package/connectors/connect-chargebee/src/utils/auth.ts +274 -0
  16. package/connectors/connect-chargebee/src/utils/bulk.ts +212 -0
  17. package/connectors/connect-chargebee/src/utils/config.ts +326 -0
  18. package/connectors/connect-chargebee/src/utils/output.ts +175 -0
  19. package/connectors/connect-chargebee/src/utils/settings.ts +114 -0
  20. package/connectors/connect-chargebee/src/utils/storage.ts +198 -0
  21. package/connectors/connect-chargebee/tsconfig.json +16 -0
  22. package/connectors/connect-databricks/.env.example +11 -0
  23. package/connectors/connect-databricks/CLAUDE.md +272 -0
  24. package/connectors/connect-databricks/README.md +193 -0
  25. package/connectors/connect-databricks/package.json +51 -0
  26. package/connectors/connect-databricks/scripts/release.ts +179 -0
  27. package/connectors/connect-databricks/src/api/client.ts +213 -0
  28. package/connectors/connect-databricks/src/api/example.ts +48 -0
  29. package/connectors/connect-databricks/src/api/index.ts +51 -0
  30. package/connectors/connect-databricks/src/cli/index.ts +254 -0
  31. package/connectors/connect-databricks/src/index.ts +103 -0
  32. package/connectors/connect-databricks/src/types/index.ts +237 -0
  33. package/connectors/connect-databricks/src/utils/auth.ts +274 -0
  34. package/connectors/connect-databricks/src/utils/bulk.ts +212 -0
  35. package/connectors/connect-databricks/src/utils/config.ts +326 -0
  36. package/connectors/connect-databricks/src/utils/output.ts +175 -0
  37. package/connectors/connect-databricks/src/utils/settings.ts +114 -0
  38. package/connectors/connect-databricks/src/utils/storage.ts +198 -0
  39. package/connectors/connect-databricks/tsconfig.json +16 -0
  40. package/connectors/connect-datadog/.env.example +11 -0
  41. package/connectors/connect-datadog/CLAUDE.md +170 -0
  42. package/connectors/connect-datadog/README.md +193 -0
  43. package/connectors/connect-datadog/package.json +53 -0
  44. package/connectors/connect-datadog/src/api/client.ts +150 -0
  45. package/connectors/connect-datadog/src/api/index.ts +537 -0
  46. package/connectors/connect-datadog/src/cli/index.ts +958 -0
  47. package/connectors/connect-datadog/src/index.ts +26 -0
  48. package/connectors/connect-datadog/src/types/index.ts +654 -0
  49. package/connectors/connect-datadog/src/utils/config.ts +219 -0
  50. package/connectors/connect-datadog/src/utils/output.ts +119 -0
  51. package/connectors/connect-datadog/tsconfig.json +16 -0
  52. package/connectors/connect-fathom/.env.example +11 -0
  53. package/connectors/connect-fathom/CLAUDE.md +272 -0
  54. package/connectors/connect-fathom/README.md +193 -0
  55. package/connectors/connect-fathom/package.json +51 -0
  56. package/connectors/connect-fathom/scripts/release.ts +179 -0
  57. package/connectors/connect-fathom/src/api/client.ts +213 -0
  58. package/connectors/connect-fathom/src/api/example.ts +48 -0
  59. package/connectors/connect-fathom/src/api/index.ts +51 -0
  60. package/connectors/connect-fathom/src/cli/index.ts +254 -0
  61. package/connectors/connect-fathom/src/index.ts +103 -0
  62. package/connectors/connect-fathom/src/types/index.ts +237 -0
  63. package/connectors/connect-fathom/src/utils/auth.ts +274 -0
  64. package/connectors/connect-fathom/src/utils/bulk.ts +212 -0
  65. package/connectors/connect-fathom/src/utils/config.ts +326 -0
  66. package/connectors/connect-fathom/src/utils/output.ts +175 -0
  67. package/connectors/connect-fathom/src/utils/settings.ts +114 -0
  68. package/connectors/connect-fathom/src/utils/storage.ts +198 -0
  69. package/connectors/connect-fathom/tsconfig.json +16 -0
  70. package/connectors/connect-grafana/.env.example +11 -0
  71. package/connectors/connect-grafana/CLAUDE.md +272 -0
  72. package/connectors/connect-grafana/README.md +193 -0
  73. package/connectors/connect-grafana/package.json +51 -0
  74. package/connectors/connect-grafana/scripts/release.ts +179 -0
  75. package/connectors/connect-grafana/src/api/client.ts +213 -0
  76. package/connectors/connect-grafana/src/api/example.ts +48 -0
  77. package/connectors/connect-grafana/src/api/index.ts +51 -0
  78. package/connectors/connect-grafana/src/cli/index.ts +254 -0
  79. package/connectors/connect-grafana/src/index.ts +103 -0
  80. package/connectors/connect-grafana/src/types/index.ts +237 -0
  81. package/connectors/connect-grafana/src/utils/auth.ts +274 -0
  82. package/connectors/connect-grafana/src/utils/bulk.ts +212 -0
  83. package/connectors/connect-grafana/src/utils/config.ts +326 -0
  84. package/connectors/connect-grafana/src/utils/output.ts +175 -0
  85. package/connectors/connect-grafana/src/utils/settings.ts +114 -0
  86. package/connectors/connect-grafana/src/utils/storage.ts +198 -0
  87. package/connectors/connect-grafana/tsconfig.json +16 -0
  88. package/connectors/connect-paddle/.env.example +11 -0
  89. package/connectors/connect-paddle/CLAUDE.md +272 -0
  90. package/connectors/connect-paddle/README.md +193 -0
  91. package/connectors/connect-paddle/package.json +51 -0
  92. package/connectors/connect-paddle/scripts/release.ts +179 -0
  93. package/connectors/connect-paddle/src/api/client.ts +213 -0
  94. package/connectors/connect-paddle/src/api/example.ts +48 -0
  95. package/connectors/connect-paddle/src/api/index.ts +51 -0
  96. package/connectors/connect-paddle/src/cli/index.ts +254 -0
  97. package/connectors/connect-paddle/src/index.ts +103 -0
  98. package/connectors/connect-paddle/src/types/index.ts +237 -0
  99. package/connectors/connect-paddle/src/utils/auth.ts +274 -0
  100. package/connectors/connect-paddle/src/utils/bulk.ts +212 -0
  101. package/connectors/connect-paddle/src/utils/config.ts +326 -0
  102. package/connectors/connect-paddle/src/utils/output.ts +175 -0
  103. package/connectors/connect-paddle/src/utils/settings.ts +114 -0
  104. package/connectors/connect-paddle/src/utils/storage.ts +198 -0
  105. package/connectors/connect-paddle/tsconfig.json +16 -0
  106. package/connectors/connect-snowflake/.env.example +11 -0
  107. package/connectors/connect-snowflake/CLAUDE.md +272 -0
  108. package/connectors/connect-snowflake/README.md +193 -0
  109. package/connectors/connect-snowflake/package.json +51 -0
  110. package/connectors/connect-snowflake/scripts/release.ts +179 -0
  111. package/connectors/connect-snowflake/src/api/client.ts +213 -0
  112. package/connectors/connect-snowflake/src/api/example.ts +48 -0
  113. package/connectors/connect-snowflake/src/api/index.ts +51 -0
  114. package/connectors/connect-snowflake/src/cli/index.ts +254 -0
  115. package/connectors/connect-snowflake/src/index.ts +103 -0
  116. package/connectors/connect-snowflake/src/types/index.ts +237 -0
  117. package/connectors/connect-snowflake/src/utils/auth.ts +274 -0
  118. package/connectors/connect-snowflake/src/utils/bulk.ts +212 -0
  119. package/connectors/connect-snowflake/src/utils/config.ts +326 -0
  120. package/connectors/connect-snowflake/src/utils/output.ts +175 -0
  121. package/connectors/connect-snowflake/src/utils/settings.ts +114 -0
  122. package/connectors/connect-snowflake/src/utils/storage.ts +198 -0
  123. package/connectors/connect-snowflake/tsconfig.json +16 -0
  124. package/connectors/connect-square/.env.example +11 -0
  125. package/connectors/connect-square/CLAUDE.md +128 -0
  126. package/connectors/connect-square/README.md +193 -0
  127. package/connectors/connect-square/package.json +52 -0
  128. package/connectors/connect-square/src/api/client.ts +152 -0
  129. package/connectors/connect-square/src/api/index.ts +343 -0
  130. package/connectors/connect-square/src/cli/index.ts +579 -0
  131. package/connectors/connect-square/src/index.ts +21 -0
  132. package/connectors/connect-square/src/types/index.ts +809 -0
  133. package/connectors/connect-square/src/utils/config.ts +209 -0
  134. package/connectors/connect-square/src/utils/output.ts +119 -0
  135. package/connectors/connect-square/tsconfig.json +16 -0
  136. package/dist/index.js +56 -0
  137. package/package.json +1 -1
@@ -0,0 +1,150 @@
1
+ import type { DatadogConfig, OutputFormat } from '../types';
2
+ import { DatadogApiError } from '../types';
3
+
4
+ // Default to US site, can be overridden
5
+ const SITES: Record<string, string> = {
6
+ 'datadoghq.com': 'https://api.datadoghq.com',
7
+ 'us3.datadoghq.com': 'https://api.us3.datadoghq.com',
8
+ 'us5.datadoghq.com': 'https://api.us5.datadoghq.com',
9
+ 'datadoghq.eu': 'https://api.datadoghq.eu',
10
+ 'ap1.datadoghq.com': 'https://api.ap1.datadoghq.com',
11
+ 'ddog-gov.com': 'https://api.ddog-gov.com',
12
+ };
13
+
14
+ const DEFAULT_SITE = 'datadoghq.com';
15
+
16
+ export interface RequestOptions {
17
+ method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
18
+ params?: Record<string, string | number | boolean | undefined>;
19
+ body?: Record<string, unknown> | unknown[] | string;
20
+ headers?: Record<string, string>;
21
+ format?: OutputFormat;
22
+ apiVersion?: 'v1' | 'v2';
23
+ }
24
+
25
+ export class DatadogClient {
26
+ private readonly apiKey: string;
27
+ private readonly appKey: string;
28
+ private readonly baseUrl: string;
29
+
30
+ constructor(config: DatadogConfig) {
31
+ if (!config.apiKey) {
32
+ throw new Error('API key is required');
33
+ }
34
+ if (!config.appKey) {
35
+ throw new Error('Application key is required');
36
+ }
37
+ this.apiKey = config.apiKey;
38
+ this.appKey = config.appKey;
39
+ const site = config.site || DEFAULT_SITE;
40
+ this.baseUrl = SITES[site] || `https://api.${site}`;
41
+ }
42
+
43
+ private buildUrl(path: string, params?: Record<string, string | number | boolean | undefined>, apiVersion: 'v1' | 'v2' = 'v1'): string {
44
+ const url = new URL(`${this.baseUrl}/api/${apiVersion}${path}`);
45
+
46
+ if (params) {
47
+ Object.entries(params).forEach(([key, value]) => {
48
+ if (value !== undefined && value !== null && value !== '') {
49
+ url.searchParams.append(key, String(value));
50
+ }
51
+ });
52
+ }
53
+
54
+ return url.toString();
55
+ }
56
+
57
+ /**
58
+ * Make an authenticated request to Datadog API
59
+ * Uses DD-API-KEY and DD-APPLICATION-KEY headers
60
+ */
61
+ async request<T>(path: string, options: RequestOptions = {}): Promise<T> {
62
+ const { method = 'GET', params, body, headers = {}, apiVersion = 'v1' } = options;
63
+
64
+ const url = this.buildUrl(path, params, apiVersion);
65
+
66
+ const requestHeaders: Record<string, string> = {
67
+ 'DD-API-KEY': this.apiKey,
68
+ 'DD-APPLICATION-KEY': this.appKey,
69
+ 'Accept': 'application/json',
70
+ ...headers,
71
+ };
72
+
73
+ if (body && ['POST', 'PUT', 'PATCH'].includes(method)) {
74
+ requestHeaders['Content-Type'] = 'application/json';
75
+ }
76
+
77
+ const fetchOptions: RequestInit = {
78
+ method,
79
+ headers: requestHeaders,
80
+ };
81
+
82
+ if (body && ['POST', 'PUT', 'PATCH'].includes(method)) {
83
+ fetchOptions.body = typeof body === 'string' ? body : JSON.stringify(body);
84
+ }
85
+
86
+ const response = await fetch(url, fetchOptions);
87
+
88
+ // Handle 204 No Content
89
+ if (response.status === 204) {
90
+ return {} as T;
91
+ }
92
+
93
+ // Parse response
94
+ let data: unknown;
95
+ const contentType = response.headers.get('content-type') || '';
96
+
97
+ if (contentType.includes('application/json')) {
98
+ const text = await response.text();
99
+ if (text) {
100
+ try {
101
+ data = JSON.parse(text);
102
+ } catch {
103
+ data = text;
104
+ }
105
+ }
106
+ } else {
107
+ data = await response.text();
108
+ }
109
+
110
+ // Handle errors - Datadog returns { errors: string[] }
111
+ if (!response.ok) {
112
+ const errorData = data as { errors?: string[] } | undefined;
113
+ const errors = errorData?.errors;
114
+ const message = errors?.join(', ') || response.statusText;
115
+ throw new DatadogApiError(message, response.status, errors);
116
+ }
117
+
118
+ return data as T;
119
+ }
120
+
121
+ async get<T>(path: string, params?: Record<string, string | number | boolean | undefined>, apiVersion?: 'v1' | 'v2'): Promise<T> {
122
+ return this.request<T>(path, { method: 'GET', params, apiVersion });
123
+ }
124
+
125
+ async post<T>(path: string, body?: Record<string, unknown> | unknown[] | string | object, params?: Record<string, string | number | boolean | undefined>, apiVersion?: 'v1' | 'v2'): Promise<T> {
126
+ return this.request<T>(path, { method: 'POST', body: body as Record<string, unknown>, params, apiVersion });
127
+ }
128
+
129
+ async put<T>(path: string, body?: Record<string, unknown> | object, params?: Record<string, string | number | boolean | undefined>, apiVersion?: 'v1' | 'v2'): Promise<T> {
130
+ return this.request<T>(path, { method: 'PUT', body: body as Record<string, unknown>, params, apiVersion });
131
+ }
132
+
133
+ async patch<T>(path: string, body?: Record<string, unknown> | object, params?: Record<string, string | number | boolean | undefined>, apiVersion?: 'v1' | 'v2'): Promise<T> {
134
+ return this.request<T>(path, { method: 'PATCH', body: body as Record<string, unknown>, params, apiVersion });
135
+ }
136
+
137
+ async delete<T>(path: string, params?: Record<string, string | number | boolean | undefined>, apiVersion?: 'v1' | 'v2'): Promise<T> {
138
+ return this.request<T>(path, { method: 'DELETE', params, apiVersion });
139
+ }
140
+
141
+ /**
142
+ * Get a preview of the API key (for display/debugging)
143
+ */
144
+ getApiKeyPreview(): string {
145
+ if (this.apiKey.length > 10) {
146
+ return `${this.apiKey.substring(0, 6)}...${this.apiKey.substring(this.apiKey.length - 4)}`;
147
+ }
148
+ return '***';
149
+ }
150
+ }
@@ -0,0 +1,537 @@
1
+ import type {
2
+ DatadogConfig,
3
+ MetricMetadata,
4
+ MetricSeries,
5
+ MetricQueryResult,
6
+ Event,
7
+ EventCreateParams,
8
+ Monitor,
9
+ MonitorCreateParams,
10
+ Dashboard,
11
+ DashboardSummary,
12
+ SLO,
13
+ SLOCreateParams,
14
+ Host,
15
+ HostTotals,
16
+ Downtime,
17
+ DowntimeCreateParams,
18
+ SyntheticsTest,
19
+ User,
20
+ Organization,
21
+ } from '../types';
22
+ import { DatadogClient } from './client';
23
+
24
+ /**
25
+ * Datadog API wrapper
26
+ */
27
+ export class Datadog {
28
+ private readonly client: DatadogClient;
29
+
30
+ constructor(config: DatadogConfig) {
31
+ this.client = new DatadogClient(config);
32
+ }
33
+
34
+ /**
35
+ * Create a client from environment variables
36
+ */
37
+ static fromEnv(): Datadog {
38
+ const apiKey = process.env.DATADOG_API_KEY;
39
+ const appKey = process.env.DATADOG_APP_KEY;
40
+ const site = process.env.DATADOG_SITE;
41
+
42
+ if (!apiKey) {
43
+ throw new Error('DATADOG_API_KEY environment variable is required');
44
+ }
45
+ if (!appKey) {
46
+ throw new Error('DATADOG_APP_KEY environment variable is required');
47
+ }
48
+ return new Datadog({ apiKey, appKey, site });
49
+ }
50
+
51
+ /**
52
+ * Get a preview of the API key (for debugging)
53
+ */
54
+ getApiKeyPreview(): string {
55
+ return this.client.getApiKeyPreview();
56
+ }
57
+
58
+ /**
59
+ * Get the underlying client for direct API access
60
+ */
61
+ getClient(): DatadogClient {
62
+ return this.client;
63
+ }
64
+
65
+ // ============================================
66
+ // Metrics API
67
+ // ============================================
68
+
69
+ /**
70
+ * Query timeseries metrics
71
+ */
72
+ async queryMetrics(params: {
73
+ from: number;
74
+ to: number;
75
+ query: string;
76
+ }): Promise<MetricQueryResult> {
77
+ return this.client.get<MetricQueryResult>('/query', params);
78
+ }
79
+
80
+ /**
81
+ * Get metric metadata
82
+ */
83
+ async getMetricMetadata(metricName: string): Promise<MetricMetadata> {
84
+ return this.client.get<MetricMetadata>(`/metrics/${encodeURIComponent(metricName)}`);
85
+ }
86
+
87
+ /**
88
+ * Update metric metadata
89
+ */
90
+ async updateMetricMetadata(metricName: string, metadata: MetricMetadata): Promise<MetricMetadata> {
91
+ return this.client.put<MetricMetadata>(`/metrics/${encodeURIComponent(metricName)}`, metadata);
92
+ }
93
+
94
+ /**
95
+ * List active metrics
96
+ */
97
+ async listActiveMetrics(params: {
98
+ from: number;
99
+ host?: string;
100
+ tag_filter?: string;
101
+ }): Promise<{ metrics: string[]; from: number }> {
102
+ return this.client.get('/metrics', params);
103
+ }
104
+
105
+ /**
106
+ * Submit metrics (timeseries data)
107
+ */
108
+ async submitMetrics(series: MetricSeries[]): Promise<{ status: string }> {
109
+ return this.client.post('/series', { series });
110
+ }
111
+
112
+ // ============================================
113
+ // Events API
114
+ // ============================================
115
+
116
+ /**
117
+ * List events
118
+ */
119
+ async listEvents(params: {
120
+ start: number;
121
+ end: number;
122
+ priority?: 'normal' | 'low';
123
+ sources?: string;
124
+ tags?: string;
125
+ unaggregated?: boolean;
126
+ exclude_aggregate?: boolean;
127
+ page?: number;
128
+ }): Promise<{ events: Event[] }> {
129
+ return this.client.get('/events', params);
130
+ }
131
+
132
+ /**
133
+ * Get an event
134
+ */
135
+ async getEvent(eventId: number): Promise<{ event: Event }> {
136
+ return this.client.get(`/events/${eventId}`);
137
+ }
138
+
139
+ /**
140
+ * Create an event
141
+ */
142
+ async createEvent(event: EventCreateParams): Promise<{ event: Event }> {
143
+ return this.client.post('/events', event);
144
+ }
145
+
146
+ // ============================================
147
+ // Monitors API
148
+ // ============================================
149
+
150
+ /**
151
+ * List monitors
152
+ */
153
+ async listMonitors(params?: {
154
+ group_states?: string;
155
+ name?: string;
156
+ tags?: string;
157
+ monitor_tags?: string;
158
+ with_downtimes?: boolean;
159
+ id_offset?: number;
160
+ page?: number;
161
+ page_size?: number;
162
+ }): Promise<Monitor[]> {
163
+ return this.client.get('/monitor', params);
164
+ }
165
+
166
+ /**
167
+ * Get a monitor
168
+ */
169
+ async getMonitor(monitorId: number, params?: {
170
+ group_states?: string;
171
+ with_downtimes?: boolean;
172
+ }): Promise<Monitor> {
173
+ return this.client.get(`/monitor/${monitorId}`, params);
174
+ }
175
+
176
+ /**
177
+ * Create a monitor
178
+ */
179
+ async createMonitor(monitor: MonitorCreateParams): Promise<Monitor> {
180
+ return this.client.post('/monitor', monitor);
181
+ }
182
+
183
+ /**
184
+ * Update a monitor
185
+ */
186
+ async updateMonitor(monitorId: number, monitor: Partial<MonitorCreateParams>): Promise<Monitor> {
187
+ return this.client.put(`/monitor/${monitorId}`, monitor);
188
+ }
189
+
190
+ /**
191
+ * Delete a monitor
192
+ */
193
+ async deleteMonitor(monitorId: number, params?: {
194
+ force?: boolean;
195
+ }): Promise<{ deleted_monitor_id: number }> {
196
+ return this.client.delete(`/monitor/${monitorId}`, params);
197
+ }
198
+
199
+ /**
200
+ * Mute a monitor
201
+ */
202
+ async muteMonitor(monitorId: number, params?: {
203
+ scope?: string;
204
+ end?: number;
205
+ }): Promise<Monitor> {
206
+ return this.client.post(`/monitor/${monitorId}/mute`, params);
207
+ }
208
+
209
+ /**
210
+ * Unmute a monitor
211
+ */
212
+ async unmuteMonitor(monitorId: number, params?: {
213
+ scope?: string;
214
+ all_scopes?: boolean;
215
+ }): Promise<Monitor> {
216
+ return this.client.post(`/monitor/${monitorId}/unmute`, params);
217
+ }
218
+
219
+ // ============================================
220
+ // Dashboards API
221
+ // ============================================
222
+
223
+ /**
224
+ * List dashboards
225
+ */
226
+ async listDashboards(params?: {
227
+ filter_shared?: boolean;
228
+ filter_deleted?: boolean;
229
+ count?: number;
230
+ start?: number;
231
+ }): Promise<{ dashboards: DashboardSummary[] }> {
232
+ return this.client.get('/dashboard', params);
233
+ }
234
+
235
+ /**
236
+ * Get a dashboard
237
+ */
238
+ async getDashboard(dashboardId: string): Promise<Dashboard> {
239
+ return this.client.get(`/dashboard/${dashboardId}`);
240
+ }
241
+
242
+ /**
243
+ * Create a dashboard
244
+ */
245
+ async createDashboard(dashboard: Omit<Dashboard, 'id'>): Promise<Dashboard> {
246
+ return this.client.post('/dashboard', dashboard);
247
+ }
248
+
249
+ /**
250
+ * Update a dashboard
251
+ */
252
+ async updateDashboard(dashboardId: string, dashboard: Omit<Dashboard, 'id'>): Promise<Dashboard> {
253
+ return this.client.put(`/dashboard/${dashboardId}`, dashboard);
254
+ }
255
+
256
+ /**
257
+ * Delete a dashboard
258
+ */
259
+ async deleteDashboard(dashboardId: string): Promise<{ deleted_dashboard_id: string }> {
260
+ return this.client.delete(`/dashboard/${dashboardId}`);
261
+ }
262
+
263
+ // ============================================
264
+ // SLOs API
265
+ // ============================================
266
+
267
+ /**
268
+ * List SLOs
269
+ */
270
+ async listSLOs(params?: {
271
+ ids?: string;
272
+ query?: string;
273
+ tags_query?: string;
274
+ metrics_query?: string;
275
+ limit?: number;
276
+ offset?: number;
277
+ }): Promise<{ data: SLO[] }> {
278
+ return this.client.get('/slo', params);
279
+ }
280
+
281
+ /**
282
+ * Get an SLO
283
+ */
284
+ async getSLO(sloId: string, params?: {
285
+ with_configured_alert_ids?: boolean;
286
+ }): Promise<{ data: SLO }> {
287
+ return this.client.get(`/slo/${sloId}`, params);
288
+ }
289
+
290
+ /**
291
+ * Create an SLO
292
+ */
293
+ async createSLO(slo: SLOCreateParams): Promise<{ data: SLO[] }> {
294
+ return this.client.post('/slo', slo);
295
+ }
296
+
297
+ /**
298
+ * Update an SLO
299
+ */
300
+ async updateSLO(sloId: string, slo: Partial<SLOCreateParams>): Promise<{ data: SLO[] }> {
301
+ return this.client.put(`/slo/${sloId}`, slo);
302
+ }
303
+
304
+ /**
305
+ * Delete an SLO
306
+ */
307
+ async deleteSLO(sloId: string, params?: {
308
+ force?: boolean;
309
+ }): Promise<{ data: string[] }> {
310
+ return this.client.delete(`/slo/${sloId}`, params);
311
+ }
312
+
313
+ /**
314
+ * Get SLO history
315
+ */
316
+ async getSLOHistory(sloId: string, params: {
317
+ from_ts: number;
318
+ to_ts: number;
319
+ target?: number;
320
+ apply_correction?: boolean;
321
+ }): Promise<{ data: unknown }> {
322
+ return this.client.get(`/slo/${sloId}/history`, params);
323
+ }
324
+
325
+ // ============================================
326
+ // Hosts API
327
+ // ============================================
328
+
329
+ /**
330
+ * List hosts
331
+ */
332
+ async listHosts(params?: {
333
+ filter?: string;
334
+ sort_field?: string;
335
+ sort_dir?: 'asc' | 'desc';
336
+ start?: number;
337
+ count?: number;
338
+ from?: number;
339
+ include_muted_hosts_data?: boolean;
340
+ include_hosts_metadata?: boolean;
341
+ }): Promise<{ host_list: Host[]; total_matching?: number; total_returned?: number }> {
342
+ return this.client.get('/hosts', params);
343
+ }
344
+
345
+ /**
346
+ * Get host totals
347
+ */
348
+ async getHostTotals(params?: {
349
+ from?: number;
350
+ }): Promise<HostTotals> {
351
+ return this.client.get('/hosts/totals', params);
352
+ }
353
+
354
+ /**
355
+ * Mute a host
356
+ */
357
+ async muteHost(hostName: string, params?: {
358
+ end?: number;
359
+ message?: string;
360
+ override?: boolean;
361
+ }): Promise<{ action: string; hostname: string; message?: string }> {
362
+ return this.client.post(`/host/${encodeURIComponent(hostName)}/mute`, params);
363
+ }
364
+
365
+ /**
366
+ * Unmute a host
367
+ */
368
+ async unmuteHost(hostName: string): Promise<{ action: string; hostname: string }> {
369
+ return this.client.post(`/host/${encodeURIComponent(hostName)}/unmute`);
370
+ }
371
+
372
+ // ============================================
373
+ // Downtimes API
374
+ // ============================================
375
+
376
+ /**
377
+ * List downtimes
378
+ */
379
+ async listDowntimes(params?: {
380
+ current_only?: boolean;
381
+ with_creator?: boolean;
382
+ }): Promise<Downtime[]> {
383
+ return this.client.get('/downtime', params);
384
+ }
385
+
386
+ /**
387
+ * Get a downtime
388
+ */
389
+ async getDowntime(downtimeId: number): Promise<Downtime> {
390
+ return this.client.get(`/downtime/${downtimeId}`);
391
+ }
392
+
393
+ /**
394
+ * Create a downtime
395
+ */
396
+ async createDowntime(downtime: DowntimeCreateParams): Promise<Downtime> {
397
+ return this.client.post('/downtime', downtime);
398
+ }
399
+
400
+ /**
401
+ * Update a downtime
402
+ */
403
+ async updateDowntime(downtimeId: number, downtime: Partial<DowntimeCreateParams>): Promise<Downtime> {
404
+ return this.client.put(`/downtime/${downtimeId}`, downtime);
405
+ }
406
+
407
+ /**
408
+ * Delete a downtime
409
+ */
410
+ async deleteDowntime(downtimeId: number): Promise<void> {
411
+ await this.client.delete(`/downtime/${downtimeId}`);
412
+ }
413
+
414
+ /**
415
+ * Cancel downtimes by scope
416
+ */
417
+ async cancelDowntimesByScope(scope: string): Promise<{ cancelled_ids: number[] }> {
418
+ return this.client.post('/downtime/cancel/by_scope', { scope });
419
+ }
420
+
421
+ // ============================================
422
+ // Synthetics API
423
+ // ============================================
424
+
425
+ /**
426
+ * List synthetics tests
427
+ */
428
+ async listSyntheticsTests(params?: {
429
+ page_size?: number;
430
+ page_number?: number;
431
+ locations?: string;
432
+ }): Promise<{ tests: SyntheticsTest[] }> {
433
+ return this.client.get('/synthetics/tests', params);
434
+ }
435
+
436
+ /**
437
+ * Get a synthetics test
438
+ */
439
+ async getSyntheticsTest(publicId: string): Promise<SyntheticsTest> {
440
+ return this.client.get(`/synthetics/tests/${publicId}`);
441
+ }
442
+
443
+ /**
444
+ * Create a synthetics test
445
+ */
446
+ async createSyntheticsTest(test: Omit<SyntheticsTest, 'public_id'>): Promise<SyntheticsTest> {
447
+ return this.client.post('/synthetics/tests', test);
448
+ }
449
+
450
+ /**
451
+ * Update a synthetics test
452
+ */
453
+ async updateSyntheticsTest(publicId: string, test: Partial<SyntheticsTest>): Promise<SyntheticsTest> {
454
+ return this.client.put(`/synthetics/tests/${publicId}`, test);
455
+ }
456
+
457
+ /**
458
+ * Delete a synthetics test
459
+ */
460
+ async deleteSyntheticsTest(publicIds: string[]): Promise<{ deleted_tests: Array<{ public_id: string }> }> {
461
+ return this.client.post('/synthetics/tests/delete', { public_ids: publicIds });
462
+ }
463
+
464
+ /**
465
+ * Trigger synthetics tests
466
+ */
467
+ async triggerSyntheticsTests(publicIds: string[]): Promise<{ batch_id: string; results: unknown[] }> {
468
+ return this.client.post('/synthetics/tests/trigger', { tests: publicIds.map(id => ({ public_id: id })) });
469
+ }
470
+
471
+ /**
472
+ * Get synthetics test results
473
+ */
474
+ async getSyntheticsTestResults(publicId: string, params?: {
475
+ from_ts?: number;
476
+ to_ts?: number;
477
+ probe_dc?: string[];
478
+ }): Promise<{ results: unknown[] }> {
479
+ return this.client.get(`/synthetics/tests/${publicId}/results`, params);
480
+ }
481
+
482
+ // ============================================
483
+ // Users API (v2)
484
+ // ============================================
485
+
486
+ /**
487
+ * List users
488
+ */
489
+ async listUsers(params?: {
490
+ page_size?: number;
491
+ page_number?: number;
492
+ sort?: string;
493
+ sort_dir?: 'asc' | 'desc';
494
+ filter?: string;
495
+ filter_status?: string;
496
+ }): Promise<{ data: User[]; meta?: { page?: { total_count?: number } } }> {
497
+ return this.client.get('/users', params, 'v2');
498
+ }
499
+
500
+ /**
501
+ * Get a user
502
+ */
503
+ async getUser(userId: string): Promise<{ data: User }> {
504
+ return this.client.get(`/users/${userId}`, undefined, 'v2');
505
+ }
506
+
507
+ /**
508
+ * Get current user
509
+ */
510
+ async getCurrentUser(): Promise<{ data: User }> {
511
+ return this.client.get('/current_user', undefined, 'v2');
512
+ }
513
+
514
+ // ============================================
515
+ // Organization API
516
+ // ============================================
517
+
518
+ /**
519
+ * Get organization
520
+ */
521
+ async getOrganization(): Promise<{ org: Organization }> {
522
+ return this.client.get('/org');
523
+ }
524
+
525
+ // ============================================
526
+ // Validate API
527
+ // ============================================
528
+
529
+ /**
530
+ * Validate API credentials
531
+ */
532
+ async validate(): Promise<{ valid: boolean }> {
533
+ return this.client.get('/validate');
534
+ }
535
+ }
536
+
537
+ export { DatadogClient } from './client';