@rustrak/client 0.3.13 → 0.3.15
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 +604 -454
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +198 -131
- package/dist/index.d.ts +198 -131
- package/dist/index.js +604 -454
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -7,7 +7,7 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
|
7
7
|
|
|
8
8
|
var ky__default = /*#__PURE__*/_interopDefault(ky);
|
|
9
9
|
|
|
10
|
-
// src/resources/
|
|
10
|
+
// src/resources/agents.ts
|
|
11
11
|
var paginatedResponseSchema = (itemSchema) => zod.z.object({
|
|
12
12
|
items: zod.z.array(itemSchema),
|
|
13
13
|
next_cursor: zod.z.string().optional(),
|
|
@@ -38,7 +38,29 @@ zod.z.object({
|
|
|
38
38
|
message: zod.z.string().optional()
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
// src/schemas/
|
|
41
|
+
// src/schemas/agent.ts
|
|
42
|
+
var agentTimeseriesPointSchema = zod.z.object({
|
|
43
|
+
bucket: dateTimeSchema,
|
|
44
|
+
value: zod.z.number()
|
|
45
|
+
});
|
|
46
|
+
var agentDurationPointSchema = zod.z.object({
|
|
47
|
+
bucket: dateTimeSchema,
|
|
48
|
+
avg_ms: zod.z.number(),
|
|
49
|
+
p95_ms: zod.z.number()
|
|
50
|
+
});
|
|
51
|
+
var genAiBreakdownRowSchema = zod.z.object({
|
|
52
|
+
label: zod.z.string(),
|
|
53
|
+
value: zod.z.number()
|
|
54
|
+
});
|
|
55
|
+
var agentTraceSummarySchema = zod.z.object({
|
|
56
|
+
trace_id: zod.z.string(),
|
|
57
|
+
/** Every distinct agent that ran in this trace, earliest first. */
|
|
58
|
+
agent_names: zod.z.array(zod.z.string()),
|
|
59
|
+
duration_ms: zod.z.number().nullable(),
|
|
60
|
+
total_tokens: zod.z.number(),
|
|
61
|
+
tool_call_count: zod.z.number().int(),
|
|
62
|
+
started_at: dateTimeSchema
|
|
63
|
+
});
|
|
42
64
|
var providerTypeSchema = zod.z.enum(["webhook", "email", "slack"]);
|
|
43
65
|
var alertTypeSchema = zod.z.enum(["new_issue", "regression", "unmute"]);
|
|
44
66
|
var alertStatusSchema = zod.z.enum([
|
|
@@ -62,443 +84,73 @@ var alertIntegrationSchema = zod.z.object({
|
|
|
62
84
|
});
|
|
63
85
|
var createAlertIntegrationSchema = zod.z.object({
|
|
64
86
|
name: zod.z.string().min(1),
|
|
65
|
-
provider_type: providerTypeSchema,
|
|
66
|
-
credentials: zod.z.record(zod.z.string(), zod.z.unknown()),
|
|
67
|
-
is_enabled: zod.z.boolean().optional()
|
|
68
|
-
});
|
|
69
|
-
var updateAlertIntegrationSchema = zod.z.object({
|
|
70
|
-
name: zod.z.string().min(1).optional(),
|
|
71
|
-
credentials: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
72
|
-
is_enabled: zod.z.boolean().optional()
|
|
73
|
-
});
|
|
74
|
-
var alertRuleChannelInputSchema = zod.z.object({
|
|
75
|
-
integration_id: zod.z.number().int(),
|
|
76
|
-
routing_override: zod.z.record(zod.z.string(), zod.z.unknown()).default({})
|
|
77
|
-
});
|
|
78
|
-
var alertRuleSchema = zod.z.object({
|
|
79
|
-
id: zod.z.number().int(),
|
|
80
|
-
project_id: zod.z.number().int(),
|
|
81
|
-
name: zod.z.string(),
|
|
82
|
-
alert_type: alertTypeSchema,
|
|
83
|
-
is_enabled: zod.z.boolean(),
|
|
84
|
-
conditions: zod.z.record(zod.z.string(), zod.z.unknown()),
|
|
85
|
-
cooldown_minutes: zod.z.number().int(),
|
|
86
|
-
last_triggered_at: dateTimeSchema.nullable(),
|
|
87
|
-
created_at: dateTimeSchema,
|
|
88
|
-
updated_at: dateTimeSchema,
|
|
89
|
-
channels: zod.z.array(alertRuleChannelInputSchema).default([]),
|
|
90
|
-
integration_ids: zod.z.array(zod.z.number().int())
|
|
91
|
-
});
|
|
92
|
-
var createAlertRuleSchema = zod.z.object({
|
|
93
|
-
name: zod.z.string().min(1),
|
|
94
|
-
alert_type: alertTypeSchema,
|
|
95
|
-
channels: zod.z.array(alertRuleChannelInputSchema).default([]),
|
|
96
|
-
is_enabled: zod.z.boolean().optional(),
|
|
97
|
-
conditions: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
98
|
-
cooldown_minutes: zod.z.number().int().min(0).optional()
|
|
99
|
-
});
|
|
100
|
-
var updateAlertRuleSchema = zod.z.object({
|
|
101
|
-
name: zod.z.string().min(1).optional(),
|
|
102
|
-
is_enabled: zod.z.boolean().optional(),
|
|
103
|
-
conditions: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
104
|
-
cooldown_minutes: zod.z.number().int().min(0).optional(),
|
|
105
|
-
channels: zod.z.array(alertRuleChannelInputSchema).optional()
|
|
106
|
-
});
|
|
107
|
-
var alertHistorySchema = zod.z.object({
|
|
108
|
-
id: zod.z.number().int(),
|
|
109
|
-
alert_rule_id: zod.z.number().int().nullable(),
|
|
110
|
-
integration_id: zod.z.number().int().nullable(),
|
|
111
|
-
issue_id: zod.z.string().uuid().nullable(),
|
|
112
|
-
project_id: zod.z.number().int().nullable(),
|
|
113
|
-
alert_type: zod.z.string(),
|
|
114
|
-
channel_type: zod.z.string(),
|
|
115
|
-
channel_name: zod.z.string(),
|
|
116
|
-
status: alertStatusSchema,
|
|
117
|
-
attempt_count: zod.z.number().int(),
|
|
118
|
-
next_retry_at: dateTimeSchema.nullable(),
|
|
119
|
-
error_message: zod.z.string().nullable(),
|
|
120
|
-
http_status_code: zod.z.number().int().nullable(),
|
|
121
|
-
idempotency_key: zod.z.string(),
|
|
122
|
-
created_at: dateTimeSchema,
|
|
123
|
-
sent_at: dateTimeSchema.nullable()
|
|
124
|
-
});
|
|
125
|
-
var testChannelResponseSchema = zod.z.object({
|
|
126
|
-
success: zod.z.boolean(),
|
|
127
|
-
message: zod.z.string()
|
|
128
|
-
});
|
|
129
|
-
var testIntegrationBodySchema = zod.z.object({
|
|
130
|
-
routing_override: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
// src/errors/base.ts
|
|
134
|
-
var RustrakError = class extends Error {
|
|
135
|
-
/**
|
|
136
|
-
* Whether this error is safe to retry
|
|
137
|
-
*/
|
|
138
|
-
retryable;
|
|
139
|
-
/**
|
|
140
|
-
* HTTP status code if applicable
|
|
141
|
-
*/
|
|
142
|
-
statusCode;
|
|
143
|
-
/**
|
|
144
|
-
* Original error cause
|
|
145
|
-
*/
|
|
146
|
-
cause;
|
|
147
|
-
constructor(message, options) {
|
|
148
|
-
super(message);
|
|
149
|
-
this.name = this.constructor.name;
|
|
150
|
-
this.retryable = options?.retryable ?? false;
|
|
151
|
-
this.statusCode = options?.statusCode;
|
|
152
|
-
this.cause = options?.cause;
|
|
153
|
-
if (Error.captureStackTrace) {
|
|
154
|
-
Error.captureStackTrace(this, this.constructor);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
// src/errors/http.ts
|
|
160
|
-
var NetworkError = class extends RustrakError {
|
|
161
|
-
constructor(message, cause) {
|
|
162
|
-
super(message, { retryable: true, cause });
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
var AuthenticationError = class extends RustrakError {
|
|
166
|
-
constructor(message = "Authentication failed") {
|
|
167
|
-
super(message, { retryable: false, statusCode: 401 });
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
var AuthorizationError = class extends RustrakError {
|
|
171
|
-
constructor(message = "Insufficient permissions") {
|
|
172
|
-
super(message, { retryable: false, statusCode: 403 });
|
|
173
|
-
}
|
|
174
|
-
};
|
|
175
|
-
var NotFoundError = class extends RustrakError {
|
|
176
|
-
constructor(resource) {
|
|
177
|
-
super(`Resource not found: ${resource}`, {
|
|
178
|
-
retryable: false,
|
|
179
|
-
statusCode: 404
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
};
|
|
183
|
-
var RateLimitError = class extends RustrakError {
|
|
184
|
-
/**
|
|
185
|
-
* Number of seconds to wait before retrying (from Retry-After header)
|
|
186
|
-
*/
|
|
187
|
-
retryAfter;
|
|
188
|
-
constructor(message = "Rate limit exceeded", retryAfter) {
|
|
189
|
-
super(message, { retryable: true, statusCode: 429 });
|
|
190
|
-
if (retryAfter !== void 0) {
|
|
191
|
-
this.retryAfter = typeof retryAfter === "string" ? parseInt(retryAfter, 10) : retryAfter;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
};
|
|
195
|
-
var ServerError = class extends RustrakError {
|
|
196
|
-
constructor(message, statusCode = 500) {
|
|
197
|
-
super(message, { retryable: true, statusCode });
|
|
198
|
-
}
|
|
199
|
-
};
|
|
200
|
-
var BadRequestError = class extends RustrakError {
|
|
201
|
-
constructor(message) {
|
|
202
|
-
super(message, { retryable: false, statusCode: 400 });
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
// src/errors/validation.ts
|
|
207
|
-
var ValidationError = class extends RustrakError {
|
|
208
|
-
/**
|
|
209
|
-
* Zod validation errors
|
|
210
|
-
*/
|
|
211
|
-
validationErrors;
|
|
212
|
-
constructor(message, validationErrors) {
|
|
213
|
-
super(message, { retryable: false });
|
|
214
|
-
this.validationErrors = validationErrors;
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Get a formatted string of validation errors
|
|
218
|
-
*/
|
|
219
|
-
getValidationDetails() {
|
|
220
|
-
if (!this.validationErrors) {
|
|
221
|
-
return this.message;
|
|
222
|
-
}
|
|
223
|
-
const errors = this.validationErrors.issues.map((err) => `${err.path.map(String).join(".")}: ${err.message}`).join(", ");
|
|
224
|
-
return `${this.message} - ${errors}`;
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
// src/resources/base.ts
|
|
229
|
-
var BaseResource = class {
|
|
230
|
-
http;
|
|
231
|
-
constructor(http) {
|
|
232
|
-
this.http = http;
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Validate API response against Zod schema
|
|
236
|
-
* @throws {ValidationError} if validation fails
|
|
237
|
-
*/
|
|
238
|
-
validate(data, schema) {
|
|
239
|
-
const result = schema.safeParse(data);
|
|
240
|
-
if (!result.success) {
|
|
241
|
-
throw new ValidationError("API response validation failed", result.error);
|
|
242
|
-
}
|
|
243
|
-
return result.data;
|
|
244
|
-
}
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
// src/resources/alert-integrations.ts
|
|
248
|
-
var AlertIntegrationsResource = class extends BaseResource {
|
|
249
|
-
/**
|
|
250
|
-
* List all alert integrations
|
|
251
|
-
*/
|
|
252
|
-
async list() {
|
|
253
|
-
const data = await this.http.get("api/integrations").json();
|
|
254
|
-
return this.validate(data, zod.z.array(alertIntegrationSchema));
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* Get a single alert integration by ID
|
|
258
|
-
*/
|
|
259
|
-
async get(id) {
|
|
260
|
-
const data = await this.http.get(`api/integrations/${id}`).json();
|
|
261
|
-
return this.validate(data, alertIntegrationSchema);
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* Create a new alert integration
|
|
265
|
-
*/
|
|
266
|
-
async create(input) {
|
|
267
|
-
const validatedInput = this.validate(input, createAlertIntegrationSchema);
|
|
268
|
-
const data = await this.http.post("api/integrations", { json: validatedInput }).json();
|
|
269
|
-
return this.validate(data, alertIntegrationSchema);
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* Update an existing alert integration
|
|
273
|
-
*/
|
|
274
|
-
async update(id, input) {
|
|
275
|
-
const validatedInput = this.validate(input, updateAlertIntegrationSchema);
|
|
276
|
-
const data = await this.http.patch(`api/integrations/${id}`, { json: validatedInput }).json();
|
|
277
|
-
return this.validate(data, alertIntegrationSchema);
|
|
278
|
-
}
|
|
279
|
-
/**
|
|
280
|
-
* Delete an alert integration
|
|
281
|
-
*/
|
|
282
|
-
async delete(id) {
|
|
283
|
-
await this.http.delete(`api/integrations/${id}`);
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Send a test notification to verify integration configuration.
|
|
287
|
-
* For Slack bot_token integrations, routingOverride must include `channel`.
|
|
288
|
-
*/
|
|
289
|
-
async test(id, routingOverride) {
|
|
290
|
-
const body = routingOverride !== void 0 ? this.validate(
|
|
291
|
-
{ routing_override: routingOverride },
|
|
292
|
-
testIntegrationBodySchema
|
|
293
|
-
) : void 0;
|
|
294
|
-
const data = await this.http.post(
|
|
295
|
-
`api/integrations/${id}/test`,
|
|
296
|
-
body !== void 0 ? { json: body } : void 0
|
|
297
|
-
).json();
|
|
298
|
-
return this.validate(data, testChannelResponseSchema);
|
|
299
|
-
}
|
|
300
|
-
};
|
|
301
|
-
var AlertRulesResource = class extends BaseResource {
|
|
302
|
-
/**
|
|
303
|
-
* List all alert rules for a project
|
|
304
|
-
*/
|
|
305
|
-
async list(projectId) {
|
|
306
|
-
const data = await this.http.get(`api/projects/${projectId}/alert-rules`).json();
|
|
307
|
-
return this.validate(data, zod.z.array(alertRuleSchema));
|
|
308
|
-
}
|
|
309
|
-
/**
|
|
310
|
-
* Get a single alert rule by ID
|
|
311
|
-
*/
|
|
312
|
-
async get(projectId, ruleId) {
|
|
313
|
-
const data = await this.http.get(`api/projects/${projectId}/alert-rules/${ruleId}`).json();
|
|
314
|
-
return this.validate(data, alertRuleSchema);
|
|
315
|
-
}
|
|
316
|
-
/**
|
|
317
|
-
* Create a new alert rule for a project
|
|
318
|
-
*/
|
|
319
|
-
async create(projectId, input) {
|
|
320
|
-
const validatedInput = this.validate(input, createAlertRuleSchema);
|
|
321
|
-
const data = await this.http.post(`api/projects/${projectId}/alert-rules`, { json: validatedInput }).json();
|
|
322
|
-
return this.validate(data, alertRuleSchema);
|
|
323
|
-
}
|
|
324
|
-
/**
|
|
325
|
-
* Update an existing alert rule
|
|
326
|
-
*/
|
|
327
|
-
async update(projectId, ruleId, input) {
|
|
328
|
-
const validatedInput = this.validate(input, updateAlertRuleSchema);
|
|
329
|
-
const data = await this.http.patch(`api/projects/${projectId}/alert-rules/${ruleId}`, {
|
|
330
|
-
json: validatedInput
|
|
331
|
-
}).json();
|
|
332
|
-
return this.validate(data, alertRuleSchema);
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Delete an alert rule
|
|
336
|
-
*/
|
|
337
|
-
async delete(projectId, ruleId) {
|
|
338
|
-
await this.http.delete(`api/projects/${projectId}/alert-rules/${ruleId}`);
|
|
339
|
-
}
|
|
340
|
-
/**
|
|
341
|
-
* List alert history for a project
|
|
342
|
-
*/
|
|
343
|
-
async listHistory(projectId, options) {
|
|
344
|
-
const searchParams = new URLSearchParams();
|
|
345
|
-
if (options?.limit !== void 0) {
|
|
346
|
-
searchParams.set("limit", options.limit.toString());
|
|
347
|
-
}
|
|
348
|
-
const query = searchParams.toString();
|
|
349
|
-
const url = query ? `api/projects/${projectId}/alert-history?${query}` : `api/projects/${projectId}/alert-history`;
|
|
350
|
-
const data = await this.http.get(url).json();
|
|
351
|
-
return this.validate(data, zod.z.array(alertHistorySchema));
|
|
352
|
-
}
|
|
353
|
-
};
|
|
354
|
-
var globalRoleSchema = zod.z.enum(["admin", "member"]);
|
|
355
|
-
var teamMemberSchema = zod.z.object({
|
|
356
|
-
id: zod.z.number().int(),
|
|
357
|
-
email: zod.z.string().email(),
|
|
358
|
-
role: globalRoleSchema,
|
|
359
|
-
is_active: zod.z.boolean(),
|
|
360
|
-
/** True for the first-registered account, which cannot be demoted or deleted. */
|
|
361
|
-
is_primary: zod.z.boolean().optional(),
|
|
362
|
-
created_at: dateTimeSchema,
|
|
363
|
-
last_login: dateTimeSchema.nullable().optional()
|
|
364
|
-
});
|
|
365
|
-
var updateUserRoleSchema = zod.z.object({
|
|
366
|
-
role: globalRoleSchema
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
// src/schemas/invitation.ts
|
|
370
|
-
var invitationStatusSchema = zod.z.string();
|
|
371
|
-
var invitationSchema = zod.z.object({
|
|
372
|
-
token: zod.z.string(),
|
|
373
|
-
email: zod.z.string().email(),
|
|
374
|
-
role: globalRoleSchema,
|
|
375
|
-
status: invitationStatusSchema,
|
|
376
|
-
expires_at: dateTimeSchema,
|
|
377
|
-
created_at: dateTimeSchema
|
|
378
|
-
});
|
|
379
|
-
var invitationInfoSchema = zod.z.object({
|
|
380
|
-
email: zod.z.string().email(),
|
|
381
|
-
role: globalRoleSchema,
|
|
382
|
-
status: invitationStatusSchema,
|
|
383
|
-
expires_at: dateTimeSchema
|
|
384
|
-
});
|
|
385
|
-
var createInvitationSchema = zod.z.object({
|
|
386
|
-
email: zod.z.string().email(),
|
|
387
|
-
role: globalRoleSchema
|
|
388
|
-
});
|
|
389
|
-
var acceptInvitationSchema = zod.z.object({
|
|
390
|
-
token: zod.z.string().min(1),
|
|
391
|
-
password: zod.z.string().min(1)
|
|
392
|
-
});
|
|
393
|
-
var userSchema = zod.z.object({
|
|
394
|
-
id: zod.z.number().int().positive(),
|
|
395
|
-
email: zod.z.string().email(),
|
|
396
|
-
role: globalRoleSchema,
|
|
397
|
-
is_admin: zod.z.boolean()
|
|
398
|
-
});
|
|
399
|
-
var authResponseSchema = zod.z.object({
|
|
400
|
-
user: userSchema
|
|
401
|
-
});
|
|
402
|
-
zod.z.object({
|
|
403
|
-
user: userSchema,
|
|
404
|
-
cookies: zod.z.array(zod.z.string())
|
|
405
|
-
});
|
|
406
|
-
var loginRequestSchema = zod.z.object({
|
|
407
|
-
email: zod.z.string().email(),
|
|
408
|
-
password: zod.z.string().min(1)
|
|
409
|
-
});
|
|
410
|
-
var registerRequestSchema = zod.z.object({
|
|
411
|
-
email: zod.z.string().email(),
|
|
412
|
-
password: zod.z.string().min(1)
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
// src/resources/auth.ts
|
|
416
|
-
var AuthResource = class extends BaseResource {
|
|
417
|
-
/**
|
|
418
|
-
* Register a new user account
|
|
419
|
-
* Creates a new user and automatically logs them in (sets session cookie)
|
|
420
|
-
* @param credentials - Email and password for the new account
|
|
421
|
-
* @returns LoginResult with user information and session cookies
|
|
422
|
-
*/
|
|
423
|
-
async register(credentials) {
|
|
424
|
-
const validatedInput = this.validate(credentials, registerRequestSchema);
|
|
425
|
-
const response = await this.http.post("auth/register", {
|
|
426
|
-
json: validatedInput
|
|
427
|
-
});
|
|
428
|
-
const cookies = response.headers.getSetCookie();
|
|
429
|
-
const data = await response.json();
|
|
430
|
-
const authResponse = this.validate(data, authResponseSchema);
|
|
431
|
-
return {
|
|
432
|
-
user: authResponse.user,
|
|
433
|
-
cookies
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
/**
|
|
437
|
-
* Login with email and password
|
|
438
|
-
* Authenticates the user and sets a session cookie
|
|
439
|
-
* @param credentials - Email and password
|
|
440
|
-
* @returns LoginResult with user information and session cookies
|
|
441
|
-
*/
|
|
442
|
-
async login(credentials) {
|
|
443
|
-
const validatedInput = this.validate(credentials, loginRequestSchema);
|
|
444
|
-
const response = await this.http.post("auth/login", {
|
|
445
|
-
json: validatedInput
|
|
446
|
-
});
|
|
447
|
-
const cookies = response.headers.getSetCookie();
|
|
448
|
-
const data = await response.json();
|
|
449
|
-
const authResponse = this.validate(data, authResponseSchema);
|
|
450
|
-
return {
|
|
451
|
-
user: authResponse.user,
|
|
452
|
-
cookies
|
|
453
|
-
};
|
|
454
|
-
}
|
|
455
|
-
/**
|
|
456
|
-
* Logout the current user
|
|
457
|
-
* Clears the session cookie
|
|
458
|
-
* @returns Array of Set-Cookie headers (typically clearing cookies)
|
|
459
|
-
*/
|
|
460
|
-
async logout() {
|
|
461
|
-
const response = await this.http.post("auth/logout");
|
|
462
|
-
return response.headers.getSetCookie();
|
|
463
|
-
}
|
|
464
|
-
/**
|
|
465
|
-
* Get current authenticated user
|
|
466
|
-
* Requires a valid session cookie
|
|
467
|
-
* @returns User information
|
|
468
|
-
*/
|
|
469
|
-
async getCurrentUser() {
|
|
470
|
-
const data = await this.http.get("auth/me").json();
|
|
471
|
-
return this.validate(data, userSchema);
|
|
472
|
-
}
|
|
473
|
-
/**
|
|
474
|
-
* Get the details of a pending invitation by its token (public endpoint)
|
|
475
|
-
* Used by the accept-invitation page before the user has an account
|
|
476
|
-
* @param token - Invitation token
|
|
477
|
-
* @returns Invitation info (email, role, status, expiry)
|
|
478
|
-
*/
|
|
479
|
-
async getInvitation(token) {
|
|
480
|
-
const data = await this.http.get(`auth/invitation/${token}`).json();
|
|
481
|
-
return this.validate(data, invitationInfoSchema);
|
|
482
|
-
}
|
|
483
|
-
/**
|
|
484
|
-
* Accept a pending invitation, creating the user account and logging in
|
|
485
|
-
* @param input - Invitation token and the new account's password
|
|
486
|
-
* @returns LoginResult with user information and session cookies
|
|
487
|
-
*/
|
|
488
|
-
async acceptInvitation(input) {
|
|
489
|
-
const validatedInput = this.validate(input, acceptInvitationSchema);
|
|
490
|
-
const response = await this.http.post("auth/accept-invitation", {
|
|
491
|
-
json: validatedInput
|
|
492
|
-
});
|
|
493
|
-
const cookies = response.headers.getSetCookie();
|
|
494
|
-
const data = await response.json();
|
|
495
|
-
const authResponse = this.validate(data, authResponseSchema);
|
|
496
|
-
return {
|
|
497
|
-
user: authResponse.user,
|
|
498
|
-
cookies
|
|
499
|
-
};
|
|
500
|
-
}
|
|
501
|
-
};
|
|
87
|
+
provider_type: providerTypeSchema,
|
|
88
|
+
credentials: zod.z.record(zod.z.string(), zod.z.unknown()),
|
|
89
|
+
is_enabled: zod.z.boolean().optional()
|
|
90
|
+
});
|
|
91
|
+
var updateAlertIntegrationSchema = zod.z.object({
|
|
92
|
+
name: zod.z.string().min(1).optional(),
|
|
93
|
+
credentials: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
94
|
+
is_enabled: zod.z.boolean().optional()
|
|
95
|
+
});
|
|
96
|
+
var alertRuleChannelInputSchema = zod.z.object({
|
|
97
|
+
integration_id: zod.z.number().int(),
|
|
98
|
+
routing_override: zod.z.record(zod.z.string(), zod.z.unknown()).default({})
|
|
99
|
+
});
|
|
100
|
+
var alertRuleSchema = zod.z.object({
|
|
101
|
+
id: zod.z.number().int(),
|
|
102
|
+
project_id: zod.z.number().int(),
|
|
103
|
+
name: zod.z.string(),
|
|
104
|
+
alert_type: alertTypeSchema,
|
|
105
|
+
is_enabled: zod.z.boolean(),
|
|
106
|
+
conditions: zod.z.record(zod.z.string(), zod.z.unknown()),
|
|
107
|
+
cooldown_minutes: zod.z.number().int(),
|
|
108
|
+
last_triggered_at: dateTimeSchema.nullable(),
|
|
109
|
+
created_at: dateTimeSchema,
|
|
110
|
+
updated_at: dateTimeSchema,
|
|
111
|
+
channels: zod.z.array(alertRuleChannelInputSchema).default([]),
|
|
112
|
+
integration_ids: zod.z.array(zod.z.number().int())
|
|
113
|
+
});
|
|
114
|
+
var createAlertRuleSchema = zod.z.object({
|
|
115
|
+
name: zod.z.string().min(1),
|
|
116
|
+
alert_type: alertTypeSchema,
|
|
117
|
+
channels: zod.z.array(alertRuleChannelInputSchema).default([]),
|
|
118
|
+
is_enabled: zod.z.boolean().optional(),
|
|
119
|
+
conditions: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
120
|
+
cooldown_minutes: zod.z.number().int().min(0).optional()
|
|
121
|
+
});
|
|
122
|
+
var updateAlertRuleSchema = zod.z.object({
|
|
123
|
+
name: zod.z.string().min(1).optional(),
|
|
124
|
+
is_enabled: zod.z.boolean().optional(),
|
|
125
|
+
conditions: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
126
|
+
cooldown_minutes: zod.z.number().int().min(0).optional(),
|
|
127
|
+
channels: zod.z.array(alertRuleChannelInputSchema).optional()
|
|
128
|
+
});
|
|
129
|
+
var alertHistorySchema = zod.z.object({
|
|
130
|
+
id: zod.z.number().int(),
|
|
131
|
+
alert_rule_id: zod.z.number().int().nullable(),
|
|
132
|
+
integration_id: zod.z.number().int().nullable(),
|
|
133
|
+
issue_id: zod.z.string().uuid().nullable(),
|
|
134
|
+
project_id: zod.z.number().int().nullable(),
|
|
135
|
+
alert_type: zod.z.string(),
|
|
136
|
+
channel_type: zod.z.string(),
|
|
137
|
+
channel_name: zod.z.string(),
|
|
138
|
+
status: alertStatusSchema,
|
|
139
|
+
attempt_count: zod.z.number().int(),
|
|
140
|
+
next_retry_at: dateTimeSchema.nullable(),
|
|
141
|
+
error_message: zod.z.string().nullable(),
|
|
142
|
+
http_status_code: zod.z.number().int().nullable(),
|
|
143
|
+
idempotency_key: zod.z.string(),
|
|
144
|
+
created_at: dateTimeSchema,
|
|
145
|
+
sent_at: dateTimeSchema.nullable()
|
|
146
|
+
});
|
|
147
|
+
var testChannelResponseSchema = zod.z.object({
|
|
148
|
+
success: zod.z.boolean(),
|
|
149
|
+
message: zod.z.string()
|
|
150
|
+
});
|
|
151
|
+
var testIntegrationBodySchema = zod.z.object({
|
|
152
|
+
routing_override: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
153
|
+
});
|
|
502
154
|
var eventSchema = zod.z.object({
|
|
503
155
|
id: uuidSchema,
|
|
504
156
|
event_id: eventIdSchema,
|
|
@@ -529,6 +181,45 @@ var eventDetailSchema = zod.z.object({
|
|
|
529
181
|
data: zod.z.record(zod.z.string(), zod.z.any())
|
|
530
182
|
// Full Sentry event JSON
|
|
531
183
|
});
|
|
184
|
+
var globalRoleSchema = zod.z.enum(["admin", "member"]);
|
|
185
|
+
var teamMemberSchema = zod.z.object({
|
|
186
|
+
id: zod.z.number().int(),
|
|
187
|
+
email: zod.z.string().email(),
|
|
188
|
+
role: globalRoleSchema,
|
|
189
|
+
is_active: zod.z.boolean(),
|
|
190
|
+
/** True for the first-registered account, which cannot be demoted or deleted. */
|
|
191
|
+
is_primary: zod.z.boolean().optional(),
|
|
192
|
+
created_at: dateTimeSchema,
|
|
193
|
+
last_login: dateTimeSchema.nullable().optional()
|
|
194
|
+
});
|
|
195
|
+
var updateUserRoleSchema = zod.z.object({
|
|
196
|
+
role: globalRoleSchema
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// src/schemas/invitation.ts
|
|
200
|
+
var invitationStatusSchema = zod.z.string();
|
|
201
|
+
var invitationSchema = zod.z.object({
|
|
202
|
+
token: zod.z.string(),
|
|
203
|
+
email: zod.z.string().email(),
|
|
204
|
+
role: globalRoleSchema,
|
|
205
|
+
status: invitationStatusSchema,
|
|
206
|
+
expires_at: dateTimeSchema,
|
|
207
|
+
created_at: dateTimeSchema
|
|
208
|
+
});
|
|
209
|
+
var invitationInfoSchema = zod.z.object({
|
|
210
|
+
email: zod.z.string().email(),
|
|
211
|
+
role: globalRoleSchema,
|
|
212
|
+
status: invitationStatusSchema,
|
|
213
|
+
expires_at: dateTimeSchema
|
|
214
|
+
});
|
|
215
|
+
var createInvitationSchema = zod.z.object({
|
|
216
|
+
email: zod.z.string().email(),
|
|
217
|
+
role: globalRoleSchema
|
|
218
|
+
});
|
|
219
|
+
var acceptInvitationSchema = zod.z.object({
|
|
220
|
+
token: zod.z.string().min(1),
|
|
221
|
+
password: zod.z.string().min(1)
|
|
222
|
+
});
|
|
532
223
|
var issueStatusSchema = zod.z.enum(["unresolved", "resolved", "ignored"]);
|
|
533
224
|
var issuePrioritySchema = zod.z.enum(["low", "medium", "high"]);
|
|
534
225
|
var issueSchema = zod.z.object({
|
|
@@ -649,9 +340,6 @@ var bulkUpdateIssuesSchema = zod.z.object({
|
|
|
649
340
|
var bulkDeleteIssuesSchema = zod.z.object({
|
|
650
341
|
ids: zod.z.array(uuidSchema)
|
|
651
342
|
});
|
|
652
|
-
var createDeploySchema = zod.z.object({
|
|
653
|
-
version: zod.z.string()
|
|
654
|
-
});
|
|
655
343
|
var logSchema = zod.z.object({
|
|
656
344
|
id: uuidSchema,
|
|
657
345
|
trace_id: zod.z.string().nullable(),
|
|
@@ -832,6 +520,8 @@ var transactionDetailSchema = zod.z.object({
|
|
|
832
520
|
});
|
|
833
521
|
var spanSchema = zod.z.object({
|
|
834
522
|
id: uuidSchema,
|
|
523
|
+
/** Parent transaction, if this span was extracted from one. `null` for a standalone span. */
|
|
524
|
+
transaction_id: uuidSchema.nullable(),
|
|
835
525
|
span_id: zod.z.string().nullable(),
|
|
836
526
|
trace_id: zod.z.string().nullable(),
|
|
837
527
|
parent_span_id: zod.z.string().nullable(),
|
|
@@ -843,7 +533,21 @@ var spanSchema = zod.z.object({
|
|
|
843
533
|
duration_ms: zod.z.number().nullable(),
|
|
844
534
|
exclusive_time_ms: zod.z.number().nullable(),
|
|
845
535
|
is_segment: zod.z.boolean(),
|
|
846
|
-
segment_id: zod.z.string().nullable()
|
|
536
|
+
segment_id: zod.z.string().nullable(),
|
|
537
|
+
/** Only ever set for standalone spans — a transaction-embedded span has no parent row to inherit these from. */
|
|
538
|
+
platform: zod.z.string().nullable(),
|
|
539
|
+
release: zod.z.string().nullable(),
|
|
540
|
+
environment: zod.z.string().nullable(),
|
|
541
|
+
/** gen_ai.* denormalized fields — all null unless recognized as an AI span. */
|
|
542
|
+
gen_ai_operation_type: zod.z.string().nullable(),
|
|
543
|
+
gen_ai_agent_name: zod.z.string().nullable(),
|
|
544
|
+
gen_ai_request_model: zod.z.string().nullable(),
|
|
545
|
+
gen_ai_response_model: zod.z.string().nullable(),
|
|
546
|
+
gen_ai_tool_name: zod.z.string().nullable(),
|
|
547
|
+
gen_ai_conversation_id: zod.z.string().nullable(),
|
|
548
|
+
gen_ai_usage_input_tokens: zod.z.number().nullable(),
|
|
549
|
+
gen_ai_usage_output_tokens: zod.z.number().nullable(),
|
|
550
|
+
gen_ai_usage_total_tokens: zod.z.number().nullable()
|
|
847
551
|
});
|
|
848
552
|
var transactionStatsSchema = zod.z.object({
|
|
849
553
|
transaction_name: zod.z.string(),
|
|
@@ -854,6 +558,422 @@ var transactionStatsSchema = zod.z.object({
|
|
|
854
558
|
p99_ms: zod.z.number(),
|
|
855
559
|
failure_rate: zod.z.number()
|
|
856
560
|
});
|
|
561
|
+
var userSchema = zod.z.object({
|
|
562
|
+
id: zod.z.number().int().positive(),
|
|
563
|
+
email: zod.z.string().email(),
|
|
564
|
+
role: globalRoleSchema,
|
|
565
|
+
is_admin: zod.z.boolean()
|
|
566
|
+
});
|
|
567
|
+
var authResponseSchema = zod.z.object({
|
|
568
|
+
user: userSchema
|
|
569
|
+
});
|
|
570
|
+
zod.z.object({
|
|
571
|
+
user: userSchema,
|
|
572
|
+
cookies: zod.z.array(zod.z.string())
|
|
573
|
+
});
|
|
574
|
+
var loginRequestSchema = zod.z.object({
|
|
575
|
+
email: zod.z.string().email(),
|
|
576
|
+
password: zod.z.string().min(1)
|
|
577
|
+
});
|
|
578
|
+
var registerRequestSchema = zod.z.object({
|
|
579
|
+
email: zod.z.string().email(),
|
|
580
|
+
password: zod.z.string().min(1)
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
// src/errors/base.ts
|
|
584
|
+
var RustrakError = class extends Error {
|
|
585
|
+
/**
|
|
586
|
+
* Whether this error is safe to retry
|
|
587
|
+
*/
|
|
588
|
+
retryable;
|
|
589
|
+
/**
|
|
590
|
+
* HTTP status code if applicable
|
|
591
|
+
*/
|
|
592
|
+
statusCode;
|
|
593
|
+
/**
|
|
594
|
+
* Original error cause
|
|
595
|
+
*/
|
|
596
|
+
cause;
|
|
597
|
+
constructor(message, options) {
|
|
598
|
+
super(message);
|
|
599
|
+
this.name = this.constructor.name;
|
|
600
|
+
this.retryable = options?.retryable ?? false;
|
|
601
|
+
this.statusCode = options?.statusCode;
|
|
602
|
+
this.cause = options?.cause;
|
|
603
|
+
if (Error.captureStackTrace) {
|
|
604
|
+
Error.captureStackTrace(this, this.constructor);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
|
|
609
|
+
// src/errors/http.ts
|
|
610
|
+
var NetworkError = class extends RustrakError {
|
|
611
|
+
constructor(message, cause) {
|
|
612
|
+
super(message, { retryable: true, cause });
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
var AuthenticationError = class extends RustrakError {
|
|
616
|
+
constructor(message = "Authentication failed") {
|
|
617
|
+
super(message, { retryable: false, statusCode: 401 });
|
|
618
|
+
}
|
|
619
|
+
};
|
|
620
|
+
var AuthorizationError = class extends RustrakError {
|
|
621
|
+
constructor(message = "Insufficient permissions") {
|
|
622
|
+
super(message, { retryable: false, statusCode: 403 });
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
var NotFoundError = class extends RustrakError {
|
|
626
|
+
constructor(resource) {
|
|
627
|
+
super(`Resource not found: ${resource}`, {
|
|
628
|
+
retryable: false,
|
|
629
|
+
statusCode: 404
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
var RateLimitError = class extends RustrakError {
|
|
634
|
+
/**
|
|
635
|
+
* Number of seconds to wait before retrying (from Retry-After header)
|
|
636
|
+
*/
|
|
637
|
+
retryAfter;
|
|
638
|
+
constructor(message = "Rate limit exceeded", retryAfter) {
|
|
639
|
+
super(message, { retryable: true, statusCode: 429 });
|
|
640
|
+
if (retryAfter !== void 0) {
|
|
641
|
+
this.retryAfter = typeof retryAfter === "string" ? parseInt(retryAfter, 10) : retryAfter;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
};
|
|
645
|
+
var ServerError = class extends RustrakError {
|
|
646
|
+
constructor(message, statusCode = 500) {
|
|
647
|
+
super(message, { retryable: true, statusCode });
|
|
648
|
+
}
|
|
649
|
+
};
|
|
650
|
+
var BadRequestError = class extends RustrakError {
|
|
651
|
+
constructor(message) {
|
|
652
|
+
super(message, { retryable: false, statusCode: 400 });
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
// src/errors/validation.ts
|
|
657
|
+
var ValidationError = class extends RustrakError {
|
|
658
|
+
/**
|
|
659
|
+
* Zod validation errors
|
|
660
|
+
*/
|
|
661
|
+
validationErrors;
|
|
662
|
+
constructor(message, validationErrors) {
|
|
663
|
+
super(message, { retryable: false });
|
|
664
|
+
this.validationErrors = validationErrors;
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* Get a formatted string of validation errors
|
|
668
|
+
*/
|
|
669
|
+
getValidationDetails() {
|
|
670
|
+
if (!this.validationErrors) {
|
|
671
|
+
return this.message;
|
|
672
|
+
}
|
|
673
|
+
const errors = this.validationErrors.issues.map((err) => `${err.path.map(String).join(".")}: ${err.message}`).join(", ");
|
|
674
|
+
return `${this.message} - ${errors}`;
|
|
675
|
+
}
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
// src/resources/base.ts
|
|
679
|
+
var BaseResource = class {
|
|
680
|
+
http;
|
|
681
|
+
constructor(http) {
|
|
682
|
+
this.http = http;
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Validate API response against Zod schema
|
|
686
|
+
* @throws {ValidationError} if validation fails
|
|
687
|
+
*/
|
|
688
|
+
validate(data, schema) {
|
|
689
|
+
const result = schema.safeParse(data);
|
|
690
|
+
if (!result.success) {
|
|
691
|
+
throw new ValidationError("API response validation failed", result.error);
|
|
692
|
+
}
|
|
693
|
+
return result.data;
|
|
694
|
+
}
|
|
695
|
+
};
|
|
696
|
+
|
|
697
|
+
// src/resources/agents.ts
|
|
698
|
+
function timeseriesSearchParams(options) {
|
|
699
|
+
const searchParams = {};
|
|
700
|
+
if (options?.period_hours) {
|
|
701
|
+
searchParams.period_hours = String(options.period_hours);
|
|
702
|
+
}
|
|
703
|
+
if (options?.interval_hours) {
|
|
704
|
+
searchParams.interval_hours = String(options.interval_hours);
|
|
705
|
+
}
|
|
706
|
+
return searchParams;
|
|
707
|
+
}
|
|
708
|
+
function breakdownSearchParams(options) {
|
|
709
|
+
const searchParams = {};
|
|
710
|
+
if (options?.period_hours) {
|
|
711
|
+
searchParams.period_hours = String(options.period_hours);
|
|
712
|
+
}
|
|
713
|
+
if (options?.limit) {
|
|
714
|
+
searchParams.limit = String(options.limit);
|
|
715
|
+
}
|
|
716
|
+
return searchParams;
|
|
717
|
+
}
|
|
718
|
+
var AgentsResource = class extends BaseResource {
|
|
719
|
+
/**
|
|
720
|
+
* Time-bucketed count of agent-run spans (`gen_ai.operation.type:agent`).
|
|
721
|
+
*/
|
|
722
|
+
async getRuns(projectId, options) {
|
|
723
|
+
const data = await this.http.get(`api/projects/${projectId}/agents/runs`, {
|
|
724
|
+
searchParams: timeseriesSearchParams(options)
|
|
725
|
+
}).json();
|
|
726
|
+
return this.validate(data, zod.z.array(agentTimeseriesPointSchema));
|
|
727
|
+
}
|
|
728
|
+
/**
|
|
729
|
+
* Time-bucketed avg/p95 duration for `agent`/`ai_client` spans.
|
|
730
|
+
*/
|
|
731
|
+
async getDuration(projectId, options) {
|
|
732
|
+
const data = await this.http.get(`api/projects/${projectId}/agents/duration`, {
|
|
733
|
+
searchParams: timeseriesSearchParams(options)
|
|
734
|
+
}).json();
|
|
735
|
+
return this.validate(data, zod.z.array(agentDurationPointSchema));
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* Top models by LLM call count (`gen_ai.operation.type:ai_client`).
|
|
739
|
+
*/
|
|
740
|
+
async getModelsByCalls(projectId, options) {
|
|
741
|
+
const data = await this.http.get(`api/projects/${projectId}/agents/models/calls`, {
|
|
742
|
+
searchParams: breakdownSearchParams(options)
|
|
743
|
+
}).json();
|
|
744
|
+
return this.validate(data, zod.z.array(genAiBreakdownRowSchema));
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* Top models by total tokens used (`gen_ai.operation.type:ai_client`).
|
|
748
|
+
*/
|
|
749
|
+
async getModelsByTokens(projectId, options) {
|
|
750
|
+
const data = await this.http.get(`api/projects/${projectId}/agents/models/tokens`, {
|
|
751
|
+
searchParams: breakdownSearchParams(options)
|
|
752
|
+
}).json();
|
|
753
|
+
return this.validate(data, zod.z.array(genAiBreakdownRowSchema));
|
|
754
|
+
}
|
|
755
|
+
/**
|
|
756
|
+
* Top tools by call count (`gen_ai.operation.type:tool`).
|
|
757
|
+
*/
|
|
758
|
+
async getTools(projectId, options) {
|
|
759
|
+
const data = await this.http.get(`api/projects/${projectId}/agents/tools`, {
|
|
760
|
+
searchParams: breakdownSearchParams(options)
|
|
761
|
+
}).json();
|
|
762
|
+
return this.validate(data, zod.z.array(genAiBreakdownRowSchema));
|
|
763
|
+
}
|
|
764
|
+
/**
|
|
765
|
+
* Paginated per-trace_id aggregate (duration, tokens, tool usage) across
|
|
766
|
+
* all AI spans sharing that trace, regardless of origin.
|
|
767
|
+
*/
|
|
768
|
+
async getTraces(projectId, options) {
|
|
769
|
+
const searchParams = {};
|
|
770
|
+
if (options?.page) {
|
|
771
|
+
searchParams.page = String(options.page);
|
|
772
|
+
}
|
|
773
|
+
if (options?.per_page) {
|
|
774
|
+
searchParams.per_page = String(options.per_page);
|
|
775
|
+
}
|
|
776
|
+
const data = await this.http.get(`api/projects/${projectId}/agents/traces`, { searchParams }).json();
|
|
777
|
+
return this.validate(
|
|
778
|
+
data,
|
|
779
|
+
offsetPaginatedResponseSchema(agentTraceSummarySchema)
|
|
780
|
+
);
|
|
781
|
+
}
|
|
782
|
+
};
|
|
783
|
+
var AlertIntegrationsResource = class extends BaseResource {
|
|
784
|
+
/**
|
|
785
|
+
* List all alert integrations
|
|
786
|
+
*/
|
|
787
|
+
async list() {
|
|
788
|
+
const data = await this.http.get("api/integrations").json();
|
|
789
|
+
return this.validate(data, zod.z.array(alertIntegrationSchema));
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* Get a single alert integration by ID
|
|
793
|
+
*/
|
|
794
|
+
async get(id) {
|
|
795
|
+
const data = await this.http.get(`api/integrations/${id}`).json();
|
|
796
|
+
return this.validate(data, alertIntegrationSchema);
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* Create a new alert integration
|
|
800
|
+
*/
|
|
801
|
+
async create(input) {
|
|
802
|
+
const validatedInput = this.validate(input, createAlertIntegrationSchema);
|
|
803
|
+
const data = await this.http.post("api/integrations", { json: validatedInput }).json();
|
|
804
|
+
return this.validate(data, alertIntegrationSchema);
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* Update an existing alert integration
|
|
808
|
+
*/
|
|
809
|
+
async update(id, input) {
|
|
810
|
+
const validatedInput = this.validate(input, updateAlertIntegrationSchema);
|
|
811
|
+
const data = await this.http.patch(`api/integrations/${id}`, { json: validatedInput }).json();
|
|
812
|
+
return this.validate(data, alertIntegrationSchema);
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Delete an alert integration
|
|
816
|
+
*/
|
|
817
|
+
async delete(id) {
|
|
818
|
+
await this.http.delete(`api/integrations/${id}`);
|
|
819
|
+
}
|
|
820
|
+
/**
|
|
821
|
+
* Send a test notification to verify integration configuration.
|
|
822
|
+
* For Slack bot_token integrations, routingOverride must include `channel`.
|
|
823
|
+
*/
|
|
824
|
+
async test(id, routingOverride) {
|
|
825
|
+
const body = routingOverride !== void 0 ? this.validate(
|
|
826
|
+
{ routing_override: routingOverride },
|
|
827
|
+
testIntegrationBodySchema
|
|
828
|
+
) : void 0;
|
|
829
|
+
const data = await this.http.post(
|
|
830
|
+
`api/integrations/${id}/test`,
|
|
831
|
+
body !== void 0 ? { json: body } : void 0
|
|
832
|
+
).json();
|
|
833
|
+
return this.validate(data, testChannelResponseSchema);
|
|
834
|
+
}
|
|
835
|
+
};
|
|
836
|
+
var AlertRulesResource = class extends BaseResource {
|
|
837
|
+
/**
|
|
838
|
+
* List all alert rules for a project
|
|
839
|
+
*/
|
|
840
|
+
async list(projectId) {
|
|
841
|
+
const data = await this.http.get(`api/projects/${projectId}/alert-rules`).json();
|
|
842
|
+
return this.validate(data, zod.z.array(alertRuleSchema));
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
845
|
+
* Get a single alert rule by ID
|
|
846
|
+
*/
|
|
847
|
+
async get(projectId, ruleId) {
|
|
848
|
+
const data = await this.http.get(`api/projects/${projectId}/alert-rules/${ruleId}`).json();
|
|
849
|
+
return this.validate(data, alertRuleSchema);
|
|
850
|
+
}
|
|
851
|
+
/**
|
|
852
|
+
* Create a new alert rule for a project
|
|
853
|
+
*/
|
|
854
|
+
async create(projectId, input) {
|
|
855
|
+
const validatedInput = this.validate(input, createAlertRuleSchema);
|
|
856
|
+
const data = await this.http.post(`api/projects/${projectId}/alert-rules`, { json: validatedInput }).json();
|
|
857
|
+
return this.validate(data, alertRuleSchema);
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* Update an existing alert rule
|
|
861
|
+
*/
|
|
862
|
+
async update(projectId, ruleId, input) {
|
|
863
|
+
const validatedInput = this.validate(input, updateAlertRuleSchema);
|
|
864
|
+
const data = await this.http.patch(`api/projects/${projectId}/alert-rules/${ruleId}`, {
|
|
865
|
+
json: validatedInput
|
|
866
|
+
}).json();
|
|
867
|
+
return this.validate(data, alertRuleSchema);
|
|
868
|
+
}
|
|
869
|
+
/**
|
|
870
|
+
* Delete an alert rule
|
|
871
|
+
*/
|
|
872
|
+
async delete(projectId, ruleId) {
|
|
873
|
+
await this.http.delete(`api/projects/${projectId}/alert-rules/${ruleId}`);
|
|
874
|
+
}
|
|
875
|
+
/**
|
|
876
|
+
* List alert history for a project
|
|
877
|
+
*/
|
|
878
|
+
async listHistory(projectId, options) {
|
|
879
|
+
const searchParams = new URLSearchParams();
|
|
880
|
+
if (options?.limit !== void 0) {
|
|
881
|
+
searchParams.set("limit", options.limit.toString());
|
|
882
|
+
}
|
|
883
|
+
const query = searchParams.toString();
|
|
884
|
+
const url = query ? `api/projects/${projectId}/alert-history?${query}` : `api/projects/${projectId}/alert-history`;
|
|
885
|
+
const data = await this.http.get(url).json();
|
|
886
|
+
return this.validate(data, zod.z.array(alertHistorySchema));
|
|
887
|
+
}
|
|
888
|
+
};
|
|
889
|
+
|
|
890
|
+
// src/resources/auth.ts
|
|
891
|
+
var AuthResource = class extends BaseResource {
|
|
892
|
+
/**
|
|
893
|
+
* Register a new user account
|
|
894
|
+
* Creates a new user and automatically logs them in (sets session cookie)
|
|
895
|
+
* @param credentials - Email and password for the new account
|
|
896
|
+
* @returns LoginResult with user information and session cookies
|
|
897
|
+
*/
|
|
898
|
+
async register(credentials) {
|
|
899
|
+
const validatedInput = this.validate(credentials, registerRequestSchema);
|
|
900
|
+
const response = await this.http.post("auth/register", {
|
|
901
|
+
json: validatedInput
|
|
902
|
+
});
|
|
903
|
+
const cookies = response.headers.getSetCookie();
|
|
904
|
+
const data = await response.json();
|
|
905
|
+
const authResponse = this.validate(data, authResponseSchema);
|
|
906
|
+
return {
|
|
907
|
+
user: authResponse.user,
|
|
908
|
+
cookies
|
|
909
|
+
};
|
|
910
|
+
}
|
|
911
|
+
/**
|
|
912
|
+
* Login with email and password
|
|
913
|
+
* Authenticates the user and sets a session cookie
|
|
914
|
+
* @param credentials - Email and password
|
|
915
|
+
* @returns LoginResult with user information and session cookies
|
|
916
|
+
*/
|
|
917
|
+
async login(credentials) {
|
|
918
|
+
const validatedInput = this.validate(credentials, loginRequestSchema);
|
|
919
|
+
const response = await this.http.post("auth/login", {
|
|
920
|
+
json: validatedInput
|
|
921
|
+
});
|
|
922
|
+
const cookies = response.headers.getSetCookie();
|
|
923
|
+
const data = await response.json();
|
|
924
|
+
const authResponse = this.validate(data, authResponseSchema);
|
|
925
|
+
return {
|
|
926
|
+
user: authResponse.user,
|
|
927
|
+
cookies
|
|
928
|
+
};
|
|
929
|
+
}
|
|
930
|
+
/**
|
|
931
|
+
* Logout the current user
|
|
932
|
+
* Clears the session cookie
|
|
933
|
+
* @returns Array of Set-Cookie headers (typically clearing cookies)
|
|
934
|
+
*/
|
|
935
|
+
async logout() {
|
|
936
|
+
const response = await this.http.post("auth/logout");
|
|
937
|
+
return response.headers.getSetCookie();
|
|
938
|
+
}
|
|
939
|
+
/**
|
|
940
|
+
* Get current authenticated user
|
|
941
|
+
* Requires a valid session cookie
|
|
942
|
+
* @returns User information
|
|
943
|
+
*/
|
|
944
|
+
async getCurrentUser() {
|
|
945
|
+
const data = await this.http.get("auth/me").json();
|
|
946
|
+
return this.validate(data, userSchema);
|
|
947
|
+
}
|
|
948
|
+
/**
|
|
949
|
+
* Get the details of a pending invitation by its token (public endpoint)
|
|
950
|
+
* Used by the accept-invitation page before the user has an account
|
|
951
|
+
* @param token - Invitation token
|
|
952
|
+
* @returns Invitation info (email, role, status, expiry)
|
|
953
|
+
*/
|
|
954
|
+
async getInvitation(token) {
|
|
955
|
+
const data = await this.http.get(`auth/invitation/${token}`).json();
|
|
956
|
+
return this.validate(data, invitationInfoSchema);
|
|
957
|
+
}
|
|
958
|
+
/**
|
|
959
|
+
* Accept a pending invitation, creating the user account and logging in
|
|
960
|
+
* @param input - Invitation token and the new account's password
|
|
961
|
+
* @returns LoginResult with user information and session cookies
|
|
962
|
+
*/
|
|
963
|
+
async acceptInvitation(input) {
|
|
964
|
+
const validatedInput = this.validate(input, acceptInvitationSchema);
|
|
965
|
+
const response = await this.http.post("auth/accept-invitation", {
|
|
966
|
+
json: validatedInput
|
|
967
|
+
});
|
|
968
|
+
const cookies = response.headers.getSetCookie();
|
|
969
|
+
const data = await response.json();
|
|
970
|
+
const authResponse = this.validate(data, authResponseSchema);
|
|
971
|
+
return {
|
|
972
|
+
user: authResponse.user,
|
|
973
|
+
cookies
|
|
974
|
+
};
|
|
975
|
+
}
|
|
976
|
+
};
|
|
857
977
|
|
|
858
978
|
// src/resources/events.ts
|
|
859
979
|
var EventsResource = class extends BaseResource {
|
|
@@ -1085,17 +1205,6 @@ var IssuesResource = class extends BaseResource {
|
|
|
1085
1205
|
}).json();
|
|
1086
1206
|
return this.validate(data, userReportSchema);
|
|
1087
1207
|
}
|
|
1088
|
-
/**
|
|
1089
|
-
* Record a deploy of a release, finalizing resolve-in-next-release issues.
|
|
1090
|
-
*/
|
|
1091
|
-
async createDeploy(projectId, input) {
|
|
1092
|
-
const validatedInput = this.validate(input, createDeploySchema);
|
|
1093
|
-
const data = await this.http.post(`api/projects/${projectId}/deploys`, { json: validatedInput }).json();
|
|
1094
|
-
return this.validate(
|
|
1095
|
-
data,
|
|
1096
|
-
zod.z.object({ version: zod.z.string(), finalized: zod.z.number().int() })
|
|
1097
|
-
);
|
|
1098
|
-
}
|
|
1099
1208
|
};
|
|
1100
1209
|
|
|
1101
1210
|
// src/resources/logs.ts
|
|
@@ -1330,6 +1439,37 @@ var SourceMapsResource = class extends BaseResource {
|
|
|
1330
1439
|
return this.validate(data, listSourceMapsResponseSchema);
|
|
1331
1440
|
}
|
|
1332
1441
|
};
|
|
1442
|
+
|
|
1443
|
+
// src/resources/spans.ts
|
|
1444
|
+
var SpansResource = class extends BaseResource {
|
|
1445
|
+
/**
|
|
1446
|
+
* List spans for a project with offset-based pagination (newest first),
|
|
1447
|
+
* optionally filtered by op/status/trace_id/operation_type.
|
|
1448
|
+
*/
|
|
1449
|
+
async list(projectId, options) {
|
|
1450
|
+
const searchParams = {};
|
|
1451
|
+
if (options?.page) {
|
|
1452
|
+
searchParams.page = String(options.page);
|
|
1453
|
+
}
|
|
1454
|
+
if (options?.per_page) {
|
|
1455
|
+
searchParams.per_page = String(options.per_page);
|
|
1456
|
+
}
|
|
1457
|
+
if (options?.op) {
|
|
1458
|
+
searchParams.op = options.op;
|
|
1459
|
+
}
|
|
1460
|
+
if (options?.status) {
|
|
1461
|
+
searchParams.status = options.status;
|
|
1462
|
+
}
|
|
1463
|
+
if (options?.trace_id) {
|
|
1464
|
+
searchParams.trace_id = options.trace_id;
|
|
1465
|
+
}
|
|
1466
|
+
if (options?.operation_type) {
|
|
1467
|
+
searchParams.operation_type = options.operation_type;
|
|
1468
|
+
}
|
|
1469
|
+
const data = await this.http.get(`api/projects/${projectId}/spans`, { searchParams }).json();
|
|
1470
|
+
return this.validate(data, offsetPaginatedResponseSchema(spanSchema));
|
|
1471
|
+
}
|
|
1472
|
+
};
|
|
1333
1473
|
var StorageResource = class extends BaseResource {
|
|
1334
1474
|
/**
|
|
1335
1475
|
* Get the instance-wide storage summary: row counts per data category, the
|
|
@@ -1658,6 +1798,14 @@ var RustrakClient = class {
|
|
|
1658
1798
|
* Logs API resource (standalone logs)
|
|
1659
1799
|
*/
|
|
1660
1800
|
logs;
|
|
1801
|
+
/**
|
|
1802
|
+
* Spans API resource (standalone + transaction-embedded spans, shared table)
|
|
1803
|
+
*/
|
|
1804
|
+
spans;
|
|
1805
|
+
/**
|
|
1806
|
+
* AI Agent Monitoring dashboard API resource
|
|
1807
|
+
*/
|
|
1808
|
+
agents;
|
|
1661
1809
|
/**
|
|
1662
1810
|
* Storage API resource (usage + retention cleanup, admin only)
|
|
1663
1811
|
*/
|
|
@@ -1688,6 +1836,8 @@ var RustrakClient = class {
|
|
|
1688
1836
|
this.releases = new ReleasesResource(this.http);
|
|
1689
1837
|
this.transactions = new TransactionsResource(this.http);
|
|
1690
1838
|
this.logs = new LogsResource(this.http);
|
|
1839
|
+
this.spans = new SpansResource(this.http);
|
|
1840
|
+
this.agents = new AgentsResource(this.http);
|
|
1691
1841
|
this.storage = new StorageResource(this.http);
|
|
1692
1842
|
this.health = new HealthResource(this.http);
|
|
1693
1843
|
}
|