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