@iteradian-rpc/sdk 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +294 -115
- package/dist/index.d.mts +907 -323
- package/dist/index.d.ts +907 -323
- package/dist/index.js +202 -47
- package/dist/index.mjs +202 -47
- package/package.json +5 -13
package/dist/index.js
CHANGED
|
@@ -48,9 +48,21 @@ var IteradianError = class extends Error {
|
|
|
48
48
|
this.retryAfter = rpc?.retryAfter;
|
|
49
49
|
this.data = rpc?.data;
|
|
50
50
|
}
|
|
51
|
-
/**
|
|
51
|
+
/**
|
|
52
|
+
* True when the request failed because an allowance is used up and retrying
|
|
53
|
+
* will not help until it resets: the subscription quota (-32006), the
|
|
54
|
+
* overage spend cap (-32007) or the API key's daily limit (-32008).
|
|
55
|
+
*/
|
|
52
56
|
get isQuotaExhausted() {
|
|
53
|
-
return this.rpcCode === -32006 || this.rpcCode === -32007;
|
|
57
|
+
return this.rpcCode === -32006 || this.rpcCode === -32007 || this.rpcCode === -32008;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* True when the API key's own daily limit is reached (-32008). `data` then
|
|
61
|
+
* carries `{ dailyLimit, used, cost, resetsAt }`; `resetsAt` is the next
|
|
62
|
+
* 00:00 UTC.
|
|
63
|
+
*/
|
|
64
|
+
get isDailyLimitReached() {
|
|
65
|
+
return this.rpcCode === -32008;
|
|
54
66
|
}
|
|
55
67
|
/** True when the request was throttled and is worth retrying. */
|
|
56
68
|
get isRateLimited() {
|
|
@@ -140,7 +152,11 @@ var HttpClient = class {
|
|
|
140
152
|
if (!response.ok) {
|
|
141
153
|
let errorBody;
|
|
142
154
|
try {
|
|
143
|
-
|
|
155
|
+
const parsed = await response.json();
|
|
156
|
+
if (parsed === null || typeof parsed !== "object") {
|
|
157
|
+
throw new Error("error body is not an object");
|
|
158
|
+
}
|
|
159
|
+
errorBody = parsed;
|
|
144
160
|
} catch {
|
|
145
161
|
errorBody = {
|
|
146
162
|
message: response.statusText || "Unknown error",
|
|
@@ -150,7 +166,7 @@ var HttpClient = class {
|
|
|
150
166
|
const rpc = errorBody?.error;
|
|
151
167
|
const rpcCode = typeof rpc?.code === "number" ? rpc.code : void 0;
|
|
152
168
|
const retryAfter = typeof rpc?.data?.retryAfter === "number" ? rpc.data.retryAfter : void 0;
|
|
153
|
-
const worthRetrying = response.status >= 500 || response.status === 429 && rpcCode !== -32006 && rpcCode !== -32007;
|
|
169
|
+
const worthRetrying = response.status >= 500 || response.status === 429 && rpcCode !== -32006 && rpcCode !== -32007 && rpcCode !== -32008;
|
|
154
170
|
if (this.retry && attempt < this.maxRetries && worthRetrying && isReplayableBody(body) && !controller.signal.aborted) {
|
|
155
171
|
const backoff = Math.min(1e3 * 2 ** (attempt - 1), 1e4);
|
|
156
172
|
const delay = Math.min(
|
|
@@ -160,10 +176,14 @@ var HttpClient = class {
|
|
|
160
176
|
await new Promise((r) => setTimeout(r, delay));
|
|
161
177
|
return this.request(method, path, body, attempt + 1, base, signal);
|
|
162
178
|
}
|
|
179
|
+
const rawMessage = errorBody.message;
|
|
180
|
+
const bodyMessage = Array.isArray(rawMessage) ? rawMessage.map(String).join(", ") : typeof rawMessage === "string" ? rawMessage : "";
|
|
181
|
+
const rpcMessage = typeof rpc?.message === "string" ? rpc.message : "";
|
|
182
|
+
const errorLabel = errorBody.error;
|
|
163
183
|
throw new IteradianError(
|
|
164
|
-
|
|
165
|
-
errorBody.statusCode
|
|
166
|
-
|
|
184
|
+
rpcMessage || bodyMessage || response.statusText || `HTTP ${response.status}`,
|
|
185
|
+
typeof errorBody.statusCode === "number" ? errorBody.statusCode : response.status,
|
|
186
|
+
typeof errorLabel === "string" ? errorLabel : void 0,
|
|
167
187
|
{ code: rpcCode, retryAfter, data: rpc?.data }
|
|
168
188
|
);
|
|
169
189
|
}
|
|
@@ -236,15 +256,40 @@ var AuthResource = class {
|
|
|
236
256
|
constructor(http) {
|
|
237
257
|
this.http = http;
|
|
238
258
|
}
|
|
239
|
-
/**
|
|
259
|
+
/**
|
|
260
|
+
* Register a new user account. Does not sign in: the API answers
|
|
261
|
+
* `{ message, email }` (the same for an address that already has an
|
|
262
|
+
* account) and emails a confirmation link. Call `login()` once the address
|
|
263
|
+
* is confirmed.
|
|
264
|
+
*
|
|
265
|
+
* The server rejects registration (400) unless the user agreed to the
|
|
266
|
+
* Terms of Service, Privacy Policy and DPA, so `data.acceptedTerms` is
|
|
267
|
+
* required and always sent. Pass `acceptedTerms: true` only after the user
|
|
268
|
+
* has ticked the agreement.
|
|
269
|
+
*/
|
|
240
270
|
register(data) {
|
|
241
|
-
return this.http.post("/auth/register",
|
|
271
|
+
return this.http.post("/auth/register", {
|
|
272
|
+
...data,
|
|
273
|
+
acceptedTerms: data?.acceptedTerms === true
|
|
274
|
+
});
|
|
242
275
|
}
|
|
243
|
-
/**
|
|
276
|
+
/**
|
|
277
|
+
* Login with email/password (optionally with a 2FA code or a backup code).
|
|
278
|
+
*
|
|
279
|
+
* When two-factor auth is on and no code was sent, the API answers
|
|
280
|
+
* `{ requires2FA: true }` with no tokens. Check `requires2FA` and call
|
|
281
|
+
* again with `twoFactorCode` or `backupCode`. The stored access token is
|
|
282
|
+
* only replaced when the answer carries one.
|
|
283
|
+
*/
|
|
244
284
|
async login(data) {
|
|
245
|
-
const
|
|
246
|
-
this.
|
|
247
|
-
return
|
|
285
|
+
const result = await this.http.post("/auth/login", data);
|
|
286
|
+
this.storeToken(result);
|
|
287
|
+
return result;
|
|
288
|
+
}
|
|
289
|
+
storeToken(result) {
|
|
290
|
+
if (result && typeof result.accessToken === "string" && result.accessToken) {
|
|
291
|
+
this.http.setAccessToken(result.accessToken);
|
|
292
|
+
}
|
|
248
293
|
}
|
|
249
294
|
/** Logout current session */
|
|
250
295
|
logout() {
|
|
@@ -255,7 +300,7 @@ var AuthResource = class {
|
|
|
255
300
|
const tokens = await this.http.post("/auth/refresh", {
|
|
256
301
|
refreshToken
|
|
257
302
|
});
|
|
258
|
-
this.
|
|
303
|
+
this.storeToken(tokens);
|
|
259
304
|
return tokens;
|
|
260
305
|
}
|
|
261
306
|
/** Verify email with token */
|
|
@@ -280,11 +325,11 @@ var AuthResource = class {
|
|
|
280
325
|
}
|
|
281
326
|
/** Login via magic link token */
|
|
282
327
|
async loginWithMagicLink(token) {
|
|
283
|
-
const
|
|
328
|
+
const result = await this.http.post("/auth/magic-login", {
|
|
284
329
|
token
|
|
285
330
|
});
|
|
286
|
-
this.
|
|
287
|
-
return
|
|
331
|
+
this.storeToken(result);
|
|
332
|
+
return result;
|
|
288
333
|
}
|
|
289
334
|
/** Enable 2FA – returns QR code image and secret */
|
|
290
335
|
enable2FA(password) {
|
|
@@ -313,7 +358,11 @@ var OrganizationsResource = class {
|
|
|
313
358
|
list() {
|
|
314
359
|
return this.http.get("/orgs");
|
|
315
360
|
}
|
|
316
|
-
/**
|
|
361
|
+
/**
|
|
362
|
+
* Create a new organization. `name`, `planId` and `acceptedTerms` are
|
|
363
|
+
* required by the API; pass `acceptedTerms: true` only after the user
|
|
364
|
+
* agreed to the terms.
|
|
365
|
+
*/
|
|
317
366
|
create(data) {
|
|
318
367
|
return this.http.post("/orgs", data);
|
|
319
368
|
}
|
|
@@ -337,10 +386,47 @@ var OrganizationsResource = class {
|
|
|
337
386
|
listMembers(orgId) {
|
|
338
387
|
return this.http.get(`/orgs/${orgId}/members`);
|
|
339
388
|
}
|
|
340
|
-
/**
|
|
389
|
+
/**
|
|
390
|
+
* Invite someone to the organization by email. Creates (or refreshes) a
|
|
391
|
+
* pending invitation — nobody becomes a member until the invitee accepts
|
|
392
|
+
* it while signed in with a verified address.
|
|
393
|
+
*/
|
|
341
394
|
inviteMember(orgId, data) {
|
|
342
395
|
return this.http.post(`/orgs/${orgId}/members`, data);
|
|
343
396
|
}
|
|
397
|
+
/** Open invitations of the organization (owner/admin) */
|
|
398
|
+
listInvites(orgId) {
|
|
399
|
+
return this.http.get(`/orgs/${orgId}/invites`);
|
|
400
|
+
}
|
|
401
|
+
/** Revoke an open invitation (owner/admin) */
|
|
402
|
+
revokeInvite(orgId, inviteId) {
|
|
403
|
+
return this.http.delete(`/orgs/${orgId}/invites/${inviteId}`);
|
|
404
|
+
}
|
|
405
|
+
/** Invitations addressed to the signed-in user */
|
|
406
|
+
listMyInvites() {
|
|
407
|
+
return this.http.get("/invites");
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Accept an invitation addressed to the signed-in user.
|
|
411
|
+
*
|
|
412
|
+
* If the user has not accepted the current terms version yet, the API
|
|
413
|
+
* answers 403 (`TERMS_ACCEPTANCE_REQUIRED`) unless
|
|
414
|
+
* `{ acceptedTerms: true }` is passed — only after the user agreed to the
|
|
415
|
+
* Terms of Service, Privacy Policy and DPA. `acceptedTerms` is sent only
|
|
416
|
+
* when given.
|
|
417
|
+
*/
|
|
418
|
+
acceptInvite(inviteId, options) {
|
|
419
|
+
if (options?.acceptedTerms !== void 0) {
|
|
420
|
+
return this.http.post(`/invites/${inviteId}/accept`, {
|
|
421
|
+
acceptedTerms: options.acceptedTerms === true
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
return this.http.post(`/invites/${inviteId}/accept`);
|
|
425
|
+
}
|
|
426
|
+
/** Decline an invitation addressed to the signed-in user */
|
|
427
|
+
declineInvite(inviteId) {
|
|
428
|
+
return this.http.post(`/invites/${inviteId}/decline`);
|
|
429
|
+
}
|
|
344
430
|
/** Update a member's role */
|
|
345
431
|
updateMemberRole(orgId, memberId, role) {
|
|
346
432
|
return this.http.put(`/orgs/${orgId}/members/${memberId}`, { role });
|
|
@@ -356,6 +442,12 @@ var OrganizationsResource = class {
|
|
|
356
442
|
};
|
|
357
443
|
|
|
358
444
|
// src/resources/api-keys.ts
|
|
445
|
+
function withKeyAlias(k) {
|
|
446
|
+
if (k && typeof k === "object" && typeof k.secret === "string") {
|
|
447
|
+
k.key = k.secret;
|
|
448
|
+
}
|
|
449
|
+
return k;
|
|
450
|
+
}
|
|
359
451
|
var ApiKeysResource = class {
|
|
360
452
|
constructor(http) {
|
|
361
453
|
this.http = http;
|
|
@@ -368,9 +460,16 @@ var ApiKeysResource = class {
|
|
|
368
460
|
get(orgId, keyId) {
|
|
369
461
|
return this.http.get(`/orgs/${orgId}/keys/${keyId}`);
|
|
370
462
|
}
|
|
371
|
-
/**
|
|
372
|
-
|
|
373
|
-
|
|
463
|
+
/**
|
|
464
|
+
* Create a new API key. The full key comes back once, in `secret`
|
|
465
|
+
* (`key` is a deprecated alias with the same value).
|
|
466
|
+
*/
|
|
467
|
+
async create(orgId, data) {
|
|
468
|
+
const created = await this.http.post(
|
|
469
|
+
`/orgs/${orgId}/keys`,
|
|
470
|
+
data
|
|
471
|
+
);
|
|
472
|
+
return withKeyAlias(created);
|
|
374
473
|
}
|
|
375
474
|
/** Update an API key */
|
|
376
475
|
update(orgId, keyId, data) {
|
|
@@ -380,9 +479,15 @@ var ApiKeysResource = class {
|
|
|
380
479
|
revoke(orgId, keyId) {
|
|
381
480
|
return this.http.delete(`/orgs/${orgId}/keys/${keyId}`);
|
|
382
481
|
}
|
|
383
|
-
/**
|
|
384
|
-
|
|
385
|
-
|
|
482
|
+
/**
|
|
483
|
+
* Rotate an API key (revoke old, create new). The new full key is in
|
|
484
|
+
* `secret`; `key` is a deprecated alias.
|
|
485
|
+
*/
|
|
486
|
+
async rotate(orgId, keyId) {
|
|
487
|
+
const rotated = await this.http.post(
|
|
488
|
+
`/orgs/${orgId}/keys/${keyId}/rotate`
|
|
489
|
+
);
|
|
490
|
+
return withKeyAlias(rotated);
|
|
386
491
|
}
|
|
387
492
|
/** Get analytics for an API key */
|
|
388
493
|
getAnalytics(orgId, keyId, timeRange = "7d") {
|
|
@@ -437,12 +542,16 @@ var EndpointsResource = class {
|
|
|
437
542
|
return this.http.post(`/orgs/${orgId}/endpoints/${endpointId}/resume`);
|
|
438
543
|
}
|
|
439
544
|
// ==================== Health & Metrics ====================
|
|
440
|
-
/** Trigger a health check */
|
|
545
|
+
/** Trigger a health check (POST .../health-check) */
|
|
441
546
|
checkHealth(orgId, endpointId) {
|
|
442
547
|
return this.http.post(
|
|
443
548
|
`/orgs/${orgId}/endpoints/${endpointId}/health-check`
|
|
444
549
|
);
|
|
445
550
|
}
|
|
551
|
+
/** Get the current health of an endpoint (GET .../health) */
|
|
552
|
+
getHealth(orgId, endpointId) {
|
|
553
|
+
return this.http.get(`/orgs/${orgId}/endpoints/${endpointId}/health`);
|
|
554
|
+
}
|
|
446
555
|
/** Get endpoint health summary */
|
|
447
556
|
getHealthOverview(orgId) {
|
|
448
557
|
return this.http.get(`/orgs/${orgId}/endpoints/summary`);
|
|
@@ -452,8 +561,9 @@ var EndpointsResource = class {
|
|
|
452
561
|
const params = new URLSearchParams();
|
|
453
562
|
if (from) params.append("from", from);
|
|
454
563
|
if (to) params.append("to", to);
|
|
564
|
+
const qs = params.toString();
|
|
455
565
|
return this.http.get(
|
|
456
|
-
`/orgs/${orgId}/endpoints/${endpointId}/metrics
|
|
566
|
+
`/orgs/${orgId}/endpoints/${endpointId}/metrics${qs ? `?${qs}` : ""}`
|
|
457
567
|
);
|
|
458
568
|
}
|
|
459
569
|
/** Update endpoint priorities */
|
|
@@ -469,9 +579,13 @@ var UsageResource = class {
|
|
|
469
579
|
constructor(http) {
|
|
470
580
|
this.http = http;
|
|
471
581
|
}
|
|
472
|
-
/**
|
|
582
|
+
/**
|
|
583
|
+
* Get usage rows (one per key per day) for a date range. `from` and `to`
|
|
584
|
+
* are ISO dates, e.g. `2026-01-31`.
|
|
585
|
+
*/
|
|
473
586
|
get(orgId, from, to) {
|
|
474
|
-
|
|
587
|
+
const qs = new URLSearchParams({ from, to }).toString();
|
|
588
|
+
return this.http.get(`/orgs/${orgId}/usage?${qs}`);
|
|
475
589
|
}
|
|
476
590
|
/** Get usage summary */
|
|
477
591
|
getSummary(orgId) {
|
|
@@ -480,13 +594,27 @@ var UsageResource = class {
|
|
|
480
594
|
};
|
|
481
595
|
|
|
482
596
|
// src/resources/dashboard.ts
|
|
597
|
+
var TIME_RANGES = {
|
|
598
|
+
"1h": "last_hour",
|
|
599
|
+
"24h": "last_24_hours",
|
|
600
|
+
"7d": "last_7_days",
|
|
601
|
+
"30d": "last_30_days"
|
|
602
|
+
};
|
|
603
|
+
function rangeQuery(timeRange, custom) {
|
|
604
|
+
const qs = new URLSearchParams();
|
|
605
|
+
if (timeRange) qs.set("timeRange", TIME_RANGES[timeRange] ?? timeRange);
|
|
606
|
+
if (custom?.from) qs.set("from", custom.from);
|
|
607
|
+
if (custom?.to) qs.set("to", custom.to);
|
|
608
|
+
const s = qs.toString();
|
|
609
|
+
return s ? `?${s}` : "";
|
|
610
|
+
}
|
|
483
611
|
var DashboardResource = class {
|
|
484
612
|
constructor(http) {
|
|
485
613
|
this.http = http;
|
|
486
614
|
}
|
|
487
615
|
/** Get full dashboard data */
|
|
488
|
-
get(orgId,
|
|
489
|
-
const params =
|
|
616
|
+
get(orgId, timeRange, custom) {
|
|
617
|
+
const params = rangeQuery(timeRange, custom);
|
|
490
618
|
return this.http.get(`/orgs/${orgId}/dashboard${params}`);
|
|
491
619
|
}
|
|
492
620
|
/** Get system health overview */
|
|
@@ -494,23 +622,23 @@ var DashboardResource = class {
|
|
|
494
622
|
return this.http.get(`/orgs/${orgId}/dashboard/health`);
|
|
495
623
|
}
|
|
496
624
|
/** Get quick stats */
|
|
497
|
-
getQuickStats(orgId,
|
|
498
|
-
const params =
|
|
625
|
+
getQuickStats(orgId, timeRange, custom) {
|
|
626
|
+
const params = rangeQuery(timeRange, custom);
|
|
499
627
|
return this.http.get(`/orgs/${orgId}/dashboard/quick-stats${params}`);
|
|
500
628
|
}
|
|
501
629
|
/** Get request rate time series */
|
|
502
|
-
getRequestRate(orgId,
|
|
503
|
-
const params =
|
|
630
|
+
getRequestRate(orgId, timeRange, custom) {
|
|
631
|
+
const params = rangeQuery(timeRange, custom);
|
|
504
632
|
return this.http.get(`/orgs/${orgId}/dashboard/request-rate${params}`);
|
|
505
633
|
}
|
|
506
634
|
/** Get error rate time series */
|
|
507
|
-
getErrorRate(orgId,
|
|
508
|
-
const params =
|
|
635
|
+
getErrorRate(orgId, timeRange, custom) {
|
|
636
|
+
const params = rangeQuery(timeRange, custom);
|
|
509
637
|
return this.http.get(`/orgs/${orgId}/dashboard/error-rate${params}`);
|
|
510
638
|
}
|
|
511
639
|
/** Get latency metrics */
|
|
512
|
-
getLatency(orgId,
|
|
513
|
-
const params =
|
|
640
|
+
getLatency(orgId, timeRange, custom) {
|
|
641
|
+
const params = rangeQuery(timeRange, custom);
|
|
514
642
|
return this.http.get(`/orgs/${orgId}/dashboard/latency${params}`);
|
|
515
643
|
}
|
|
516
644
|
/** Get performance metrics */
|
|
@@ -525,8 +653,17 @@ var AlertsResource = class {
|
|
|
525
653
|
this.http = http;
|
|
526
654
|
}
|
|
527
655
|
// ==================== Alerts ====================
|
|
528
|
-
/**
|
|
529
|
-
|
|
656
|
+
/**
|
|
657
|
+
* List alerts for an organization. The API answers an overview object
|
|
658
|
+
* (`alerts`, counters, rules, channels); this returns just the alerts.
|
|
659
|
+
* Use `overview()` for the rest.
|
|
660
|
+
*/
|
|
661
|
+
async list(orgId) {
|
|
662
|
+
const overview = await this.overview(orgId);
|
|
663
|
+
return Array.isArray(overview?.alerts) ? overview.alerts : [];
|
|
664
|
+
}
|
|
665
|
+
/** The full alerts overview: alerts, counters, rules and channels. */
|
|
666
|
+
overview(orgId) {
|
|
530
667
|
return this.http.get(`/orgs/${orgId}/alerts`);
|
|
531
668
|
}
|
|
532
669
|
/** Acknowledge an alert */
|
|
@@ -602,7 +739,7 @@ var LogsResource = class {
|
|
|
602
739
|
constructor(http) {
|
|
603
740
|
this.http = http;
|
|
604
741
|
}
|
|
605
|
-
/** Query request logs with filters
|
|
742
|
+
/** Query request logs with filters (`limit` / `offset` paginate) */
|
|
606
743
|
query(orgId, params) {
|
|
607
744
|
const searchParams = new URLSearchParams();
|
|
608
745
|
if (params) {
|
|
@@ -638,9 +775,19 @@ var SubscriptionsResource = class {
|
|
|
638
775
|
get(orgId) {
|
|
639
776
|
return this.http.get(`/orgs/${orgId}/subscription`);
|
|
640
777
|
}
|
|
641
|
-
/**
|
|
642
|
-
|
|
643
|
-
|
|
778
|
+
/**
|
|
779
|
+
* Change subscription plan.
|
|
780
|
+
*
|
|
781
|
+
* The server rejects a plan change unless the caller confirms the
|
|
782
|
+
* plan-change billing terms, so `options.acceptedTerms` is required and
|
|
783
|
+
* always sent. Pass `{ acceptedTerms: true }` only after the user has
|
|
784
|
+
* accepted the terms.
|
|
785
|
+
*/
|
|
786
|
+
changePlan(orgId, planId, options) {
|
|
787
|
+
return this.http.put(`/orgs/${orgId}/subscription/plan`, {
|
|
788
|
+
planId,
|
|
789
|
+
acceptedTerms: options?.acceptedTerms === true
|
|
790
|
+
});
|
|
644
791
|
}
|
|
645
792
|
/** Cancel subscription */
|
|
646
793
|
cancel(orgId) {
|
|
@@ -681,8 +828,16 @@ var SupportResource = class {
|
|
|
681
828
|
createTicket(orgId, data) {
|
|
682
829
|
return this.http.post(`/orgs/${orgId}/support/tickets`, data);
|
|
683
830
|
}
|
|
684
|
-
/**
|
|
685
|
-
|
|
831
|
+
/**
|
|
832
|
+
* List support tickets. The API answers `{ tickets, total }`; this
|
|
833
|
+
* returns the tickets. Use `listTicketsWithTotal()` for the total.
|
|
834
|
+
*/
|
|
835
|
+
async listTickets(orgId) {
|
|
836
|
+
const res = await this.listTicketsWithTotal(orgId);
|
|
837
|
+
return Array.isArray(res?.tickets) ? res.tickets : [];
|
|
838
|
+
}
|
|
839
|
+
/** List support tickets with the total count. */
|
|
840
|
+
listTicketsWithTotal(orgId) {
|
|
686
841
|
return this.http.get(`/orgs/${orgId}/support/tickets`);
|
|
687
842
|
}
|
|
688
843
|
/** Get ticket statistics */
|