@rustrak/client 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,766 @@
1
+ import { z } from 'zod';
2
+ import ky, { isHTTPError } from 'ky';
3
+
4
+ // src/resources/alert-channels.ts
5
+ var paginatedResponseSchema = (itemSchema) => z.object({
6
+ items: z.array(itemSchema),
7
+ next_cursor: z.string().optional(),
8
+ has_more: z.boolean()
9
+ });
10
+ var offsetPaginatedResponseSchema = (itemSchema) => z.object({
11
+ items: z.array(itemSchema),
12
+ total_count: z.number().int(),
13
+ page: z.number().int(),
14
+ per_page: z.number().int(),
15
+ total_pages: z.number().int()
16
+ });
17
+ z.enum(["asc", "desc"]);
18
+ z.enum(["digest_order", "last_seen"]);
19
+ z.enum(["open", "resolved", "muted", "all"]);
20
+ var dateTimeSchema = z.string().datetime();
21
+ var uuidSchema = z.string().uuid();
22
+ z.object({
23
+ error: z.string(),
24
+ message: z.string().optional()
25
+ });
26
+
27
+ // src/schemas/alert.ts
28
+ var channelTypeSchema = z.enum(["webhook", "email", "slack"]);
29
+ var alertTypeSchema = z.enum(["new_issue", "regression", "unmute"]);
30
+ var alertStatusSchema = z.enum([
31
+ "pending",
32
+ "sent",
33
+ "failed",
34
+ "skipped"
35
+ ]);
36
+ var notificationChannelSchema = z.object({
37
+ id: z.number().int(),
38
+ name: z.string(),
39
+ channel_type: channelTypeSchema,
40
+ config: z.record(z.string(), z.unknown()),
41
+ is_enabled: z.boolean(),
42
+ failure_count: z.number().int(),
43
+ last_failure_at: dateTimeSchema.nullable(),
44
+ last_failure_message: z.string().nullable(),
45
+ last_success_at: dateTimeSchema.nullable(),
46
+ created_at: dateTimeSchema,
47
+ updated_at: dateTimeSchema
48
+ });
49
+ var createNotificationChannelSchema = z.object({
50
+ name: z.string().min(1),
51
+ channel_type: channelTypeSchema,
52
+ config: z.record(z.string(), z.unknown()),
53
+ is_enabled: z.boolean().optional()
54
+ });
55
+ var updateNotificationChannelSchema = z.object({
56
+ name: z.string().min(1).optional(),
57
+ config: z.record(z.string(), z.unknown()).optional(),
58
+ is_enabled: z.boolean().optional()
59
+ });
60
+ var alertRuleSchema = z.object({
61
+ id: z.number().int(),
62
+ project_id: z.number().int(),
63
+ name: z.string(),
64
+ alert_type: alertTypeSchema,
65
+ is_enabled: z.boolean(),
66
+ conditions: z.record(z.string(), z.unknown()),
67
+ cooldown_minutes: z.number().int(),
68
+ last_triggered_at: dateTimeSchema.nullable(),
69
+ created_at: dateTimeSchema,
70
+ updated_at: dateTimeSchema,
71
+ channel_ids: z.array(z.number().int())
72
+ });
73
+ var createAlertRuleSchema = z.object({
74
+ name: z.string().min(1),
75
+ alert_type: alertTypeSchema,
76
+ channel_ids: z.array(z.number().int()).min(1),
77
+ is_enabled: z.boolean().optional(),
78
+ conditions: z.record(z.string(), z.unknown()).optional(),
79
+ cooldown_minutes: z.number().int().min(0).optional()
80
+ });
81
+ var updateAlertRuleSchema = z.object({
82
+ name: z.string().min(1).optional(),
83
+ is_enabled: z.boolean().optional(),
84
+ conditions: z.record(z.string(), z.unknown()).optional(),
85
+ cooldown_minutes: z.number().int().min(0).optional(),
86
+ channel_ids: z.array(z.number().int()).optional()
87
+ });
88
+ var alertHistorySchema = z.object({
89
+ id: z.number().int(),
90
+ alert_rule_id: z.number().int().nullable(),
91
+ channel_id: z.number().int().nullable(),
92
+ issue_id: z.string().uuid().nullable(),
93
+ project_id: z.number().int().nullable(),
94
+ alert_type: z.string(),
95
+ channel_type: z.string(),
96
+ channel_name: z.string(),
97
+ status: alertStatusSchema,
98
+ attempt_count: z.number().int(),
99
+ next_retry_at: dateTimeSchema.nullable(),
100
+ error_message: z.string().nullable(),
101
+ http_status_code: z.number().int().nullable(),
102
+ idempotency_key: z.string(),
103
+ created_at: dateTimeSchema,
104
+ sent_at: dateTimeSchema.nullable()
105
+ });
106
+ var testChannelResponseSchema = z.object({
107
+ success: z.boolean(),
108
+ message: z.string()
109
+ });
110
+
111
+ // src/errors/base.ts
112
+ var RustrakError = class extends Error {
113
+ /**
114
+ * Whether this error is safe to retry
115
+ */
116
+ retryable;
117
+ /**
118
+ * HTTP status code if applicable
119
+ */
120
+ statusCode;
121
+ /**
122
+ * Original error cause
123
+ */
124
+ cause;
125
+ constructor(message, options) {
126
+ super(message);
127
+ this.name = this.constructor.name;
128
+ this.retryable = options?.retryable ?? false;
129
+ this.statusCode = options?.statusCode;
130
+ this.cause = options?.cause;
131
+ if (Error.captureStackTrace) {
132
+ Error.captureStackTrace(this, this.constructor);
133
+ }
134
+ }
135
+ };
136
+
137
+ // src/errors/http.ts
138
+ var NetworkError = class extends RustrakError {
139
+ constructor(message, cause) {
140
+ super(message, { retryable: true, cause });
141
+ }
142
+ };
143
+ var AuthenticationError = class extends RustrakError {
144
+ constructor(message = "Authentication failed") {
145
+ super(message, { retryable: false, statusCode: 401 });
146
+ }
147
+ };
148
+ var AuthorizationError = class extends RustrakError {
149
+ constructor(message = "Insufficient permissions") {
150
+ super(message, { retryable: false, statusCode: 403 });
151
+ }
152
+ };
153
+ var NotFoundError = class extends RustrakError {
154
+ constructor(resource) {
155
+ super(`Resource not found: ${resource}`, {
156
+ retryable: false,
157
+ statusCode: 404
158
+ });
159
+ }
160
+ };
161
+ var RateLimitError = class extends RustrakError {
162
+ /**
163
+ * Number of seconds to wait before retrying (from Retry-After header)
164
+ */
165
+ retryAfter;
166
+ constructor(message = "Rate limit exceeded", retryAfter) {
167
+ super(message, { retryable: true, statusCode: 429 });
168
+ if (retryAfter !== void 0) {
169
+ this.retryAfter = typeof retryAfter === "string" ? parseInt(retryAfter, 10) : retryAfter;
170
+ }
171
+ }
172
+ };
173
+ var ServerError = class extends RustrakError {
174
+ constructor(message, statusCode = 500) {
175
+ super(message, { retryable: true, statusCode });
176
+ }
177
+ };
178
+ var BadRequestError = class extends RustrakError {
179
+ constructor(message) {
180
+ super(message, { retryable: false, statusCode: 400 });
181
+ }
182
+ };
183
+
184
+ // src/errors/validation.ts
185
+ var ValidationError = class extends RustrakError {
186
+ /**
187
+ * Zod validation errors
188
+ */
189
+ validationErrors;
190
+ constructor(message, validationErrors) {
191
+ super(message, { retryable: false });
192
+ this.validationErrors = validationErrors;
193
+ }
194
+ /**
195
+ * Get a formatted string of validation errors
196
+ */
197
+ getValidationDetails() {
198
+ if (!this.validationErrors) {
199
+ return this.message;
200
+ }
201
+ const errors = this.validationErrors.issues.map((err) => `${err.path.map(String).join(".")}: ${err.message}`).join(", ");
202
+ return `${this.message} - ${errors}`;
203
+ }
204
+ };
205
+
206
+ // src/resources/base.ts
207
+ var BaseResource = class {
208
+ http;
209
+ constructor(http) {
210
+ this.http = http;
211
+ }
212
+ /**
213
+ * Validate API response against Zod schema
214
+ * @throws {ValidationError} if validation fails
215
+ */
216
+ validate(data, schema) {
217
+ const result = schema.safeParse(data);
218
+ if (!result.success) {
219
+ throw new ValidationError("API response validation failed", result.error);
220
+ }
221
+ return result.data;
222
+ }
223
+ };
224
+
225
+ // src/resources/alert-channels.ts
226
+ var AlertChannelsResource = class extends BaseResource {
227
+ /**
228
+ * List all notification channels
229
+ */
230
+ async list() {
231
+ const data = await this.http.get("api/alert-channels").json();
232
+ return this.validate(data, z.array(notificationChannelSchema));
233
+ }
234
+ /**
235
+ * Get a single notification channel by ID
236
+ */
237
+ async get(id) {
238
+ const data = await this.http.get(`api/alert-channels/${id}`).json();
239
+ return this.validate(data, notificationChannelSchema);
240
+ }
241
+ /**
242
+ * Create a new notification channel
243
+ */
244
+ async create(input) {
245
+ const validatedInput = this.validate(
246
+ input,
247
+ createNotificationChannelSchema
248
+ );
249
+ const data = await this.http.post("api/alert-channels", { json: validatedInput }).json();
250
+ return this.validate(data, notificationChannelSchema);
251
+ }
252
+ /**
253
+ * Update an existing notification channel
254
+ */
255
+ async update(id, input) {
256
+ const validatedInput = this.validate(
257
+ input,
258
+ updateNotificationChannelSchema
259
+ );
260
+ const data = await this.http.patch(`api/alert-channels/${id}`, { json: validatedInput }).json();
261
+ return this.validate(data, notificationChannelSchema);
262
+ }
263
+ /**
264
+ * Delete a notification channel
265
+ */
266
+ async delete(id) {
267
+ await this.http.delete(`api/alert-channels/${id}`);
268
+ }
269
+ /**
270
+ * Send a test notification to verify channel configuration
271
+ */
272
+ async test(id) {
273
+ const data = await this.http.post(`api/alert-channels/${id}/test`).json();
274
+ return this.validate(data, testChannelResponseSchema);
275
+ }
276
+ };
277
+ var AlertRulesResource = class extends BaseResource {
278
+ /**
279
+ * List all alert rules for a project
280
+ */
281
+ async list(projectId) {
282
+ const data = await this.http.get(`api/projects/${projectId}/alert-rules`).json();
283
+ return this.validate(data, z.array(alertRuleSchema));
284
+ }
285
+ /**
286
+ * Get a single alert rule by ID
287
+ */
288
+ async get(projectId, ruleId) {
289
+ const data = await this.http.get(`api/projects/${projectId}/alert-rules/${ruleId}`).json();
290
+ return this.validate(data, alertRuleSchema);
291
+ }
292
+ /**
293
+ * Create a new alert rule for a project
294
+ */
295
+ async create(projectId, input) {
296
+ const validatedInput = this.validate(input, createAlertRuleSchema);
297
+ const data = await this.http.post(`api/projects/${projectId}/alert-rules`, { json: validatedInput }).json();
298
+ return this.validate(data, alertRuleSchema);
299
+ }
300
+ /**
301
+ * Update an existing alert rule
302
+ */
303
+ async update(projectId, ruleId, input) {
304
+ const validatedInput = this.validate(input, updateAlertRuleSchema);
305
+ const data = await this.http.patch(`api/projects/${projectId}/alert-rules/${ruleId}`, {
306
+ json: validatedInput
307
+ }).json();
308
+ return this.validate(data, alertRuleSchema);
309
+ }
310
+ /**
311
+ * Delete an alert rule
312
+ */
313
+ async delete(projectId, ruleId) {
314
+ await this.http.delete(`api/projects/${projectId}/alert-rules/${ruleId}`);
315
+ }
316
+ /**
317
+ * List alert history for a project
318
+ */
319
+ async listHistory(projectId, options) {
320
+ const searchParams = new URLSearchParams();
321
+ if (options?.limit !== void 0) {
322
+ searchParams.set("limit", options.limit.toString());
323
+ }
324
+ const query = searchParams.toString();
325
+ const url = query ? `api/projects/${projectId}/alert-history?${query}` : `api/projects/${projectId}/alert-history`;
326
+ const data = await this.http.get(url).json();
327
+ return this.validate(data, z.array(alertHistorySchema));
328
+ }
329
+ };
330
+ var userSchema = z.object({
331
+ id: z.number().int().positive(),
332
+ email: z.string().email(),
333
+ is_admin: z.boolean()
334
+ });
335
+ var authResponseSchema = z.object({
336
+ user: userSchema
337
+ });
338
+ z.object({
339
+ user: userSchema,
340
+ cookies: z.array(z.string())
341
+ });
342
+ var loginRequestSchema = z.object({
343
+ email: z.string().email(),
344
+ password: z.string().min(8)
345
+ });
346
+ var registerRequestSchema = z.object({
347
+ email: z.string().email(),
348
+ password: z.string().min(8)
349
+ });
350
+
351
+ // src/resources/auth.ts
352
+ var AuthResource = class extends BaseResource {
353
+ /**
354
+ * Register a new user account
355
+ * Creates a new user and automatically logs them in (sets session cookie)
356
+ * @param credentials - Email and password for the new account
357
+ * @returns LoginResult with user information and session cookies
358
+ */
359
+ async register(credentials) {
360
+ const validatedInput = this.validate(credentials, registerRequestSchema);
361
+ const response = await this.http.post("auth/register", {
362
+ json: validatedInput
363
+ });
364
+ const cookies = response.headers.getSetCookie();
365
+ const data = await response.json();
366
+ const authResponse = this.validate(data, authResponseSchema);
367
+ return {
368
+ user: authResponse.user,
369
+ cookies
370
+ };
371
+ }
372
+ /**
373
+ * Login with email and password
374
+ * Authenticates the user and sets a session cookie
375
+ * @param credentials - Email and password
376
+ * @returns LoginResult with user information and session cookies
377
+ */
378
+ async login(credentials) {
379
+ const validatedInput = this.validate(credentials, loginRequestSchema);
380
+ const response = await this.http.post("auth/login", {
381
+ json: validatedInput
382
+ });
383
+ const cookies = response.headers.getSetCookie();
384
+ const data = await response.json();
385
+ const authResponse = this.validate(data, authResponseSchema);
386
+ return {
387
+ user: authResponse.user,
388
+ cookies
389
+ };
390
+ }
391
+ /**
392
+ * Logout the current user
393
+ * Clears the session cookie
394
+ * @returns Array of Set-Cookie headers (typically clearing cookies)
395
+ */
396
+ async logout() {
397
+ const response = await this.http.post("auth/logout");
398
+ return response.headers.getSetCookie();
399
+ }
400
+ /**
401
+ * Get current authenticated user
402
+ * Requires a valid session cookie
403
+ * @returns User information
404
+ */
405
+ async getCurrentUser() {
406
+ const data = await this.http.get("auth/me").json();
407
+ return this.validate(data, userSchema);
408
+ }
409
+ };
410
+ var eventSchema = z.object({
411
+ id: uuidSchema,
412
+ event_id: uuidSchema,
413
+ issue_id: uuidSchema,
414
+ title: z.string(),
415
+ timestamp: dateTimeSchema,
416
+ level: z.string(),
417
+ platform: z.string(),
418
+ release: z.string(),
419
+ environment: z.string()
420
+ });
421
+ var eventDetailSchema = z.object({
422
+ id: uuidSchema,
423
+ event_id: uuidSchema,
424
+ issue_id: uuidSchema,
425
+ title: z.string(),
426
+ timestamp: dateTimeSchema,
427
+ ingested_at: dateTimeSchema,
428
+ level: z.string(),
429
+ platform: z.string(),
430
+ release: z.string(),
431
+ environment: z.string(),
432
+ server_name: z.string(),
433
+ sdk_name: z.string(),
434
+ sdk_version: z.string(),
435
+ data: z.record(z.string(), z.any())
436
+ // Full Sentry event JSON
437
+ });
438
+ var issueSchema = z.object({
439
+ id: uuidSchema,
440
+ project_id: z.number().int(),
441
+ short_id: z.string(),
442
+ title: z.string(),
443
+ value: z.string(),
444
+ first_seen: dateTimeSchema,
445
+ last_seen: dateTimeSchema,
446
+ event_count: z.number().int(),
447
+ level: z.string().nullable(),
448
+ platform: z.string().nullable(),
449
+ is_resolved: z.boolean(),
450
+ is_muted: z.boolean()
451
+ });
452
+ var updateIssueStateSchema = z.object({
453
+ is_resolved: z.boolean().optional(),
454
+ is_muted: z.boolean().optional()
455
+ });
456
+ var projectSchema = z.object({
457
+ id: z.number().int(),
458
+ name: z.string(),
459
+ slug: z.string(),
460
+ sentry_key: uuidSchema,
461
+ dsn: z.string(),
462
+ stored_event_count: z.number().int(),
463
+ digested_event_count: z.number().int(),
464
+ created_at: dateTimeSchema,
465
+ updated_at: dateTimeSchema
466
+ });
467
+ var createProjectSchema = z.object({
468
+ name: z.string().min(1),
469
+ slug: z.string().optional()
470
+ });
471
+ var updateProjectSchema = z.object({
472
+ name: z.string().min(1).optional()
473
+ });
474
+ var authTokenSchema = z.object({
475
+ id: z.number().int(),
476
+ token_prefix: z.string(),
477
+ description: z.string().nullable(),
478
+ created_at: dateTimeSchema,
479
+ last_used_at: dateTimeSchema.nullable()
480
+ });
481
+ var authTokenCreatedSchema = z.object({
482
+ id: z.number().int(),
483
+ token: z.string(),
484
+ description: z.string().nullable(),
485
+ created_at: dateTimeSchema
486
+ });
487
+ var createAuthTokenSchema = z.object({
488
+ description: z.string().optional()
489
+ });
490
+
491
+ // src/resources/events.ts
492
+ var EventsResource = class extends BaseResource {
493
+ /**
494
+ * List events for an issue with pagination
495
+ */
496
+ async list(projectId, issueId, options) {
497
+ const searchParams = {};
498
+ if (options?.order) {
499
+ searchParams.order = options.order;
500
+ }
501
+ if (options?.cursor) {
502
+ searchParams.cursor = options.cursor;
503
+ }
504
+ const data = await this.http.get(`api/projects/${projectId}/issues/${issueId}/events`, {
505
+ searchParams
506
+ }).json();
507
+ return this.validate(data, paginatedResponseSchema(eventSchema));
508
+ }
509
+ /**
510
+ * Get a single event by ID with full details
511
+ */
512
+ async get(projectId, issueId, eventId) {
513
+ const data = await this.http.get(`api/projects/${projectId}/issues/${issueId}/events/${eventId}`).json();
514
+ return this.validate(data, eventDetailSchema);
515
+ }
516
+ };
517
+
518
+ // src/resources/issues.ts
519
+ var IssuesResource = class extends BaseResource {
520
+ /**
521
+ * List issues for a project with offset-based pagination
522
+ */
523
+ async list(projectId, options) {
524
+ const searchParams = {};
525
+ if (options?.page !== void 0) {
526
+ searchParams.page = options.page.toString();
527
+ }
528
+ if (options?.per_page !== void 0) {
529
+ searchParams.per_page = options.per_page.toString();
530
+ }
531
+ if (options?.sort) {
532
+ searchParams.sort = options.sort;
533
+ }
534
+ if (options?.order) {
535
+ searchParams.order = options.order;
536
+ }
537
+ if (options?.filter) {
538
+ searchParams.filter = options.filter;
539
+ }
540
+ const data = await this.http.get(`api/projects/${projectId}/issues`, { searchParams }).json();
541
+ return this.validate(data, offsetPaginatedResponseSchema(issueSchema));
542
+ }
543
+ /**
544
+ * Get a single issue by ID
545
+ */
546
+ async get(projectId, issueId) {
547
+ const data = await this.http.get(`api/projects/${projectId}/issues/${issueId}`).json();
548
+ return this.validate(data, issueSchema);
549
+ }
550
+ /**
551
+ * Update issue state (resolve, mute, etc.)
552
+ */
553
+ async updateState(projectId, issueId, input) {
554
+ const validatedInput = this.validate(input, updateIssueStateSchema);
555
+ const data = await this.http.patch(`api/projects/${projectId}/issues/${issueId}`, {
556
+ json: validatedInput
557
+ }).json();
558
+ return this.validate(data, issueSchema);
559
+ }
560
+ /**
561
+ * Delete an issue
562
+ */
563
+ async delete(projectId, issueId) {
564
+ await this.http.delete(`api/projects/${projectId}/issues/${issueId}`);
565
+ }
566
+ };
567
+
568
+ // src/resources/projects.ts
569
+ var ProjectsResource = class extends BaseResource {
570
+ /**
571
+ * List projects with pagination
572
+ */
573
+ async list(options) {
574
+ const searchParams = new URLSearchParams();
575
+ if (options?.page !== void 0) {
576
+ searchParams.set("page", options.page.toString());
577
+ }
578
+ if (options?.per_page !== void 0) {
579
+ searchParams.set("per_page", options.per_page.toString());
580
+ }
581
+ if (options?.order) {
582
+ searchParams.set("order", options.order);
583
+ }
584
+ const query = searchParams.toString();
585
+ const url = query ? `api/projects?${query}` : "api/projects";
586
+ const data = await this.http.get(url).json();
587
+ return this.validate(data, offsetPaginatedResponseSchema(projectSchema));
588
+ }
589
+ /**
590
+ * Get a single project by ID
591
+ */
592
+ async get(id) {
593
+ const data = await this.http.get(`api/projects/${id}`).json();
594
+ return this.validate(data, projectSchema);
595
+ }
596
+ /**
597
+ * Create a new project
598
+ */
599
+ async create(input) {
600
+ const validatedInput = this.validate(input, createProjectSchema);
601
+ const data = await this.http.post("api/projects", { json: validatedInput }).json();
602
+ return this.validate(data, projectSchema);
603
+ }
604
+ /**
605
+ * Update an existing project
606
+ */
607
+ async update(id, input) {
608
+ const validatedInput = this.validate(input, updateProjectSchema);
609
+ const data = await this.http.patch(`api/projects/${id}`, { json: validatedInput }).json();
610
+ return this.validate(data, projectSchema);
611
+ }
612
+ /**
613
+ * Delete a project
614
+ */
615
+ async delete(id) {
616
+ await this.http.delete(`api/projects/${id}`);
617
+ }
618
+ };
619
+
620
+ // src/resources/tokens.ts
621
+ var TokensResource = class extends BaseResource {
622
+ /**
623
+ * List all auth tokens (masked)
624
+ */
625
+ async list() {
626
+ const data = await this.http.get("api/tokens").json();
627
+ return this.validate(data, authTokenSchema.array());
628
+ }
629
+ /**
630
+ * Get a single auth token by ID (masked)
631
+ */
632
+ async get(id) {
633
+ const data = await this.http.get(`api/tokens/${id}`).json();
634
+ return this.validate(data, authTokenSchema);
635
+ }
636
+ /**
637
+ * Create a new auth token
638
+ * Note: The full token is only returned once during creation
639
+ */
640
+ async create(input) {
641
+ const validatedInput = this.validate(input, createAuthTokenSchema);
642
+ const data = await this.http.post("api/tokens", { json: validatedInput }).json();
643
+ return this.validate(data, authTokenCreatedSchema);
644
+ }
645
+ /**
646
+ * Delete an auth token
647
+ */
648
+ async delete(id) {
649
+ await this.http.delete(`api/tokens/${id}`);
650
+ }
651
+ };
652
+ function transformHttpError(error) {
653
+ const { response } = error;
654
+ const status = response.status;
655
+ let errorMessage = `HTTP ${status} error`;
656
+ const body = error.data;
657
+ if (body) {
658
+ errorMessage = body.error || body.message || errorMessage;
659
+ }
660
+ switch (status) {
661
+ case 400:
662
+ return new BadRequestError(errorMessage);
663
+ case 401:
664
+ return new AuthenticationError(errorMessage);
665
+ case 403:
666
+ return new AuthorizationError(errorMessage);
667
+ case 404:
668
+ return new NotFoundError(errorMessage);
669
+ case 429: {
670
+ const retryAfter = response.headers.get("Retry-After");
671
+ return new RateLimitError(errorMessage, retryAfter ?? void 0);
672
+ }
673
+ case 500:
674
+ case 502:
675
+ case 503:
676
+ case 504:
677
+ return new ServerError(errorMessage, status);
678
+ default:
679
+ return new RustrakError(errorMessage, { statusCode: status });
680
+ }
681
+ }
682
+ function createKyInstance(config) {
683
+ const headers = {
684
+ "Content-Type": "application/json",
685
+ ...config.headers
686
+ };
687
+ if (config.token) {
688
+ headers.Authorization = `Bearer ${config.token}`;
689
+ }
690
+ return ky.create({
691
+ prefix: config.baseUrl,
692
+ timeout: config.timeout ?? 3e4,
693
+ credentials: "include",
694
+ retry: {
695
+ limit: config.maxRetries ?? 2,
696
+ statusCodes: [408, 500, 502, 503, 504],
697
+ methods: ["get", "post", "put", "patch", "delete"]
698
+ },
699
+ headers,
700
+ hooks: {
701
+ beforeError: [
702
+ ({ error }) => {
703
+ if (error.name === "TimeoutError") {
704
+ throw new NetworkError("Request timed out", error);
705
+ }
706
+ if (isHTTPError(error)) {
707
+ throw transformHttpError(error);
708
+ }
709
+ throw new NetworkError(error.message, error);
710
+ }
711
+ ]
712
+ }
713
+ });
714
+ }
715
+
716
+ // src/client.ts
717
+ var RustrakClient = class {
718
+ http;
719
+ /**
720
+ * Authentication API resource
721
+ */
722
+ auth;
723
+ /**
724
+ * Projects API resource
725
+ */
726
+ projects;
727
+ /**
728
+ * Issues API resource
729
+ */
730
+ issues;
731
+ /**
732
+ * Events API resource
733
+ */
734
+ events;
735
+ /**
736
+ * Auth Tokens API resource
737
+ */
738
+ tokens;
739
+ /**
740
+ * Alert Channels API resource (global notification destinations)
741
+ */
742
+ alertChannels;
743
+ /**
744
+ * Alert Rules API resource (per-project alert configuration)
745
+ */
746
+ alertRules;
747
+ /**
748
+ * Create a new Rustrak API client
749
+ *
750
+ * @param config - Client configuration
751
+ */
752
+ constructor(config) {
753
+ this.http = createKyInstance(config);
754
+ this.auth = new AuthResource(this.http);
755
+ this.projects = new ProjectsResource(this.http);
756
+ this.issues = new IssuesResource(this.http);
757
+ this.events = new EventsResource(this.http);
758
+ this.tokens = new TokensResource(this.http);
759
+ this.alertChannels = new AlertChannelsResource(this.http);
760
+ this.alertRules = new AlertRulesResource(this.http);
761
+ }
762
+ };
763
+
764
+ export { AuthenticationError, AuthorizationError, BadRequestError, NetworkError, NotFoundError, RateLimitError, RustrakClient, RustrakError, ServerError, ValidationError };
765
+ //# sourceMappingURL=index.js.map
766
+ //# sourceMappingURL=index.js.map