@atribu/node 0.1.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/CHANGELOG.md +27 -0
- package/LICENSE +21 -0
- package/README.md +423 -0
- package/dist/admin/index.cjs +326 -0
- package/dist/admin/index.cjs.map +1 -0
- package/dist/admin/index.d.cts +46 -0
- package/dist/admin/index.d.ts +46 -0
- package/dist/admin/index.js +323 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/api.d-BXINTQo6.d.cts +3547 -0
- package/dist/api.d-BXINTQo6.d.ts +3547 -0
- package/dist/errors-D3ApBz8J.d.cts +86 -0
- package/dist/errors-D3ApBz8J.d.ts +86 -0
- package/dist/index.cjs +549 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +198 -0
- package/dist/index.d.ts +198 -0
- package/dist/index.js +536 -0
- package/dist/index.js.map +1 -0
- package/dist/next/index.cjs +153 -0
- package/dist/next/index.cjs.map +1 -0
- package/dist/next/index.d.cts +43 -0
- package/dist/next/index.d.ts +43 -0
- package/dist/next/index.js +151 -0
- package/dist/next/index.js.map +1 -0
- package/dist/oauth/index.cjs +299 -0
- package/dist/oauth/index.cjs.map +1 -0
- package/dist/oauth/index.d.cts +117 -0
- package/dist/oauth/index.d.ts +117 -0
- package/dist/oauth/index.js +291 -0
- package/dist/oauth/index.js.map +1 -0
- package/dist/test/index.cjs +443 -0
- package/dist/test/index.cjs.map +1 -0
- package/dist/test/index.d.cts +321 -0
- package/dist/test/index.d.ts +321 -0
- package/dist/test/index.js +437 -0
- package/dist/test/index.js.map +1 -0
- package/dist/types-Dc6tIN_V.d.cts +101 -0
- package/dist/types-Dc6tIN_V.d.ts +101 -0
- package/dist/webhooks/index.cjs +97 -0
- package/dist/webhooks/index.cjs.map +1 -0
- package/dist/webhooks/index.d.cts +35 -0
- package/dist/webhooks/index.d.ts +35 -0
- package/dist/webhooks/index.js +94 -0
- package/dist/webhooks/index.js.map +1 -0
- package/package.json +101 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { H as HttpClientLike, p as paths, R as RequestOptions } from './api.d-BXINTQo6.cjs';
|
|
2
|
+
import { A as AtribuError } from './errors-D3ApBz8J.cjs';
|
|
3
|
+
export { a as ApiErrorBody, b as ApiErrorCode, c as AtribuApiError, d as AtribuConfigError, e as AtribuOauthError, f as AtribuTransportError, g as AtribuWebhookError, O as OauthErrorCode, R as RetryHint, W as WebhookErrorCode } from './errors-D3ApBz8J.cjs';
|
|
4
|
+
|
|
5
|
+
interface AtribuClientConfig {
|
|
6
|
+
apiKey: string;
|
|
7
|
+
baseUrl?: string;
|
|
8
|
+
fetch?: typeof fetch;
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
userAgent?: string;
|
|
11
|
+
defaultIdempotencyKeyGenerator?: () => string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type SendBody = NonNullable<paths["/api/v1/messages"]["post"]["requestBody"]>["content"]["application/json"];
|
|
15
|
+
type SendResponse = paths["/api/v1/messages"]["post"]["responses"][200]["content"]["application/json"];
|
|
16
|
+
type MessageSendInput = SendBody;
|
|
17
|
+
type MessageContent = SendBody["content"];
|
|
18
|
+
type MessageSendResponse = SendResponse["data"];
|
|
19
|
+
interface SendOptions {
|
|
20
|
+
idempotencyKey?: string;
|
|
21
|
+
signal?: AbortSignal;
|
|
22
|
+
}
|
|
23
|
+
declare class MessagesResource {
|
|
24
|
+
private readonly http;
|
|
25
|
+
constructor(http: HttpClientLike);
|
|
26
|
+
send(input: MessageSendInput, opts?: SendOptions): Promise<MessageSendResponse>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type ReplyBody = NonNullable<paths["/api/v1/comments/{comment_id}/reply"]["post"]["requestBody"]>["content"]["application/json"];
|
|
30
|
+
type PrivateReplyBody = NonNullable<paths["/api/v1/comments/{comment_id}/private-reply"]["post"]["requestBody"]>["content"]["application/json"];
|
|
31
|
+
type ReplyResponse = paths["/api/v1/comments/{comment_id}/reply"]["post"]["responses"][200]["content"]["application/json"];
|
|
32
|
+
type CommentReplyInput = ReplyBody & {
|
|
33
|
+
comment_id: string;
|
|
34
|
+
};
|
|
35
|
+
type CommentPrivateReplyInput = PrivateReplyBody & {
|
|
36
|
+
comment_id: string;
|
|
37
|
+
};
|
|
38
|
+
type CommentReplyResponse = ReplyResponse["data"];
|
|
39
|
+
interface CommentReplyOptions {
|
|
40
|
+
idempotencyKey?: string;
|
|
41
|
+
signal?: AbortSignal;
|
|
42
|
+
}
|
|
43
|
+
declare class CommentsResource {
|
|
44
|
+
private readonly http;
|
|
45
|
+
constructor(http: HttpClientLike);
|
|
46
|
+
reply(input: CommentReplyInput, opts?: CommentReplyOptions): Promise<CommentReplyResponse>;
|
|
47
|
+
privateReply(input: CommentPrivateReplyInput, opts?: CommentReplyOptions): Promise<CommentReplyResponse>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
type ListResponse = paths["/api/v1/webhooks/subscriptions"]["get"]["responses"][200]["content"]["application/json"];
|
|
51
|
+
type CreateBody = NonNullable<paths["/api/v1/webhooks/subscriptions"]["post"]["requestBody"]>["content"]["application/json"];
|
|
52
|
+
type CreateResponse = paths["/api/v1/webhooks/subscriptions"]["post"]["responses"][201]["content"]["application/json"];
|
|
53
|
+
type UpdateBody = NonNullable<paths["/api/v1/webhooks/subscriptions/{id}"]["patch"]["requestBody"]>["content"]["application/json"];
|
|
54
|
+
type RotateBody = NonNullable<NonNullable<paths["/api/v1/webhooks/subscriptions/{id}/rotate-secret"]["post"]["requestBody"]>["content"]["application/json"]>;
|
|
55
|
+
type RotateResponse = paths["/api/v1/webhooks/subscriptions/{id}/rotate-secret"]["post"]["responses"][200]["content"]["application/json"];
|
|
56
|
+
type TestResponse = paths["/api/v1/webhooks/test/{id}"]["post"]["responses"][200]["content"]["application/json"];
|
|
57
|
+
type WebhookSubscription = ListResponse["data"][number];
|
|
58
|
+
type WebhookSubscriptionWithSecret = CreateResponse["data"];
|
|
59
|
+
type WebhookSubscriptionCreateInput = CreateBody;
|
|
60
|
+
type WebhookSubscriptionUpdateInput = UpdateBody;
|
|
61
|
+
type WebhookSubscriptionRotateOptions = RotateBody;
|
|
62
|
+
type WebhookSubscriptionRotateResult = RotateResponse["data"];
|
|
63
|
+
type WebhookSubscriptionTestResult = TestResponse["data"];
|
|
64
|
+
interface MutationOptions {
|
|
65
|
+
idempotencyKey?: string;
|
|
66
|
+
signal?: AbortSignal;
|
|
67
|
+
}
|
|
68
|
+
declare class WebhookSubscriptionsResource {
|
|
69
|
+
private readonly http;
|
|
70
|
+
constructor(http: HttpClientLike);
|
|
71
|
+
list(opts?: {
|
|
72
|
+
signal?: AbortSignal;
|
|
73
|
+
}): Promise<WebhookSubscription[]>;
|
|
74
|
+
create(input: WebhookSubscriptionCreateInput, opts?: MutationOptions): Promise<WebhookSubscriptionWithSecret>;
|
|
75
|
+
update(id: string, input: WebhookSubscriptionUpdateInput, opts?: MutationOptions): Promise<WebhookSubscription>;
|
|
76
|
+
delete(id: string, opts?: MutationOptions): Promise<void>;
|
|
77
|
+
rotateSecret(id: string, options?: WebhookSubscriptionRotateOptions, opts?: MutationOptions): Promise<WebhookSubscriptionRotateResult>;
|
|
78
|
+
test(id: string, opts?: MutationOptions): Promise<WebhookSubscriptionTestResult>;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
type ReplayResponse = paths["/api/v1/webhooks/deliveries/{id}/replay"]["post"]["responses"][200]["content"]["application/json"];
|
|
82
|
+
type WebhookDeliveryReplayResult = ReplayResponse["data"];
|
|
83
|
+
interface ReplayOptions {
|
|
84
|
+
idempotencyKey?: string;
|
|
85
|
+
signal?: AbortSignal;
|
|
86
|
+
}
|
|
87
|
+
declare class WebhookDeliveriesResource {
|
|
88
|
+
private readonly http;
|
|
89
|
+
constructor(http: HttpClientLike);
|
|
90
|
+
replay(id: string, opts?: ReplayOptions): Promise<WebhookDeliveryReplayResult>;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Opt-in retry layer.
|
|
95
|
+
*
|
|
96
|
+
* Why opt-in: hiding retries inside the SDK by default obscures backpressure
|
|
97
|
+
* signals and amplifies load on a failing server. Consumers that want them
|
|
98
|
+
* call `.withRetry({...})`; others write their own retry logic against the
|
|
99
|
+
* typed `retry` hint on AtribuApiError.
|
|
100
|
+
*
|
|
101
|
+
* What gets retried:
|
|
102
|
+
* - `AtribuApiError` with `retry.action === "retry"` (5xx, 408)
|
|
103
|
+
* - `AtribuApiError` with `retry.action === "retry_after"` (429, 503 w/
|
|
104
|
+
* Retry-After) — honors retryAfterMs
|
|
105
|
+
* - `AtribuTransportError` (network glitches, ECONNRESET, timeouts)
|
|
106
|
+
*
|
|
107
|
+
* What does NOT retry:
|
|
108
|
+
* - `AtribuApiError` with `retry.action === "do_not_retry"` (403)
|
|
109
|
+
* - `AtribuApiError` with `retry.action === "fix_and_retry"` (422 etc — the
|
|
110
|
+
* caller's input is wrong; retrying with the same body won't help)
|
|
111
|
+
* - `AtribuApiError` with `retry.action === "refresh_token"` (401 — needs
|
|
112
|
+
* credential refresh, not a retry)
|
|
113
|
+
* - `AtribuConfigError`, `AtribuWebhookError`, anything else
|
|
114
|
+
*/
|
|
115
|
+
|
|
116
|
+
type BackoffStrategy = "exponential" | "fixed" | "none";
|
|
117
|
+
interface RetryOptions {
|
|
118
|
+
/**
|
|
119
|
+
* Max attempts including the initial call. `maxAttempts: 3` = initial + 2
|
|
120
|
+
* retries. Must be ≥ 1. Default 3.
|
|
121
|
+
*/
|
|
122
|
+
maxAttempts?: number;
|
|
123
|
+
/**
|
|
124
|
+
* Backoff strategy between retries. "exponential" = `baseDelayMs * 2^n`
|
|
125
|
+
* (capped by `maxDelayMs`). "fixed" = `baseDelayMs`. "none" = no delay.
|
|
126
|
+
* Default "exponential".
|
|
127
|
+
*/
|
|
128
|
+
backoff?: BackoffStrategy;
|
|
129
|
+
/** Base delay between retries in ms. Default 500. */
|
|
130
|
+
baseDelayMs?: number;
|
|
131
|
+
/** Cap on the delay between retries. Default 30000 (30s). */
|
|
132
|
+
maxDelayMs?: number;
|
|
133
|
+
/**
|
|
134
|
+
* Jitter factor 0..1. Multiplies the computed delay by `1 + random*jitter`
|
|
135
|
+
* (jitter=0 means deterministic). Default 0.3.
|
|
136
|
+
*/
|
|
137
|
+
jitter?: number;
|
|
138
|
+
/** Inject for tests. Default `(ms) => new Promise(r => setTimeout(r, ms))`. */
|
|
139
|
+
sleep?: (ms: number) => Promise<void>;
|
|
140
|
+
/** Inject for jitter tests. Default Math.random. */
|
|
141
|
+
random?: () => number;
|
|
142
|
+
}
|
|
143
|
+
declare class RetryingHttpClient implements HttpClientLike {
|
|
144
|
+
private readonly base;
|
|
145
|
+
private readonly r;
|
|
146
|
+
constructor(base: HttpClientLike, options: RetryOptions);
|
|
147
|
+
request<T>(opts: RequestOptions): Promise<T>;
|
|
148
|
+
/**
|
|
149
|
+
* Returns the delay in ms before the next attempt, or null if the error
|
|
150
|
+
* is non-retryable (caller should throw immediately).
|
|
151
|
+
*/
|
|
152
|
+
private computeDelay;
|
|
153
|
+
private backoffDelay;
|
|
154
|
+
private applyJitter;
|
|
155
|
+
}
|
|
156
|
+
declare function isRetryableError(err: unknown): err is AtribuError;
|
|
157
|
+
|
|
158
|
+
interface ResourceBundle {
|
|
159
|
+
messages: MessagesResource;
|
|
160
|
+
comments: CommentsResource;
|
|
161
|
+
webhooks: {
|
|
162
|
+
subscriptions: WebhookSubscriptionsResource;
|
|
163
|
+
deliveries: WebhookDeliveriesResource;
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
declare class AtribuClient {
|
|
167
|
+
readonly messages: MessagesResource;
|
|
168
|
+
readonly comments: CommentsResource;
|
|
169
|
+
readonly webhooks: ResourceBundle["webhooks"];
|
|
170
|
+
/** @internal — exposed for `withRetry` chaining; do not depend on this. */
|
|
171
|
+
protected readonly _http: HttpClientLike;
|
|
172
|
+
constructor(config: AtribuClientConfig);
|
|
173
|
+
/**
|
|
174
|
+
* Returns a new AtribuClient that retries on transient errors. The
|
|
175
|
+
* original client is not mutated. The wrapper respects the typed
|
|
176
|
+
* `retry` hint on AtribuApiError — `do_not_retry`, `fix_and_retry`,
|
|
177
|
+
* and `refresh_token` are NOT retried (those need caller action, not
|
|
178
|
+
* a repeat call).
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* const client = new AtribuClient({...}).withRetry({
|
|
182
|
+
* maxAttempts: 3,
|
|
183
|
+
* backoff: "exponential",
|
|
184
|
+
* baseDelayMs: 500,
|
|
185
|
+
* });
|
|
186
|
+
* await client.messages.send({...});
|
|
187
|
+
*/
|
|
188
|
+
withRetry(options: RetryOptions): AtribuClient;
|
|
189
|
+
private static _fromHttp;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
declare const SDK_VERSION = "0.1.0";
|
|
193
|
+
|
|
194
|
+
type Runtime = "node" | "bun" | "deno" | "edge" | "browser" | "unknown";
|
|
195
|
+
declare function detectRuntime(): Runtime;
|
|
196
|
+
declare function runtimeTag(): string;
|
|
197
|
+
|
|
198
|
+
export { AtribuClient, type AtribuClientConfig, AtribuError, type BackoffStrategy, type CommentPrivateReplyInput, type CommentReplyInput, type CommentReplyOptions, type CommentReplyResponse, type MessageContent, type MessageSendInput, type MessageSendResponse, type MutationOptions, type ReplayOptions, type RetryOptions, RetryingHttpClient, type Runtime, SDK_VERSION, type SendOptions, type WebhookDeliveryReplayResult, type WebhookSubscription, type WebhookSubscriptionCreateInput, type WebhookSubscriptionRotateOptions, type WebhookSubscriptionRotateResult, type WebhookSubscriptionTestResult, type WebhookSubscriptionUpdateInput, type WebhookSubscriptionWithSecret, detectRuntime, isRetryableError, runtimeTag };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { H as HttpClientLike, p as paths, R as RequestOptions } from './api.d-BXINTQo6.js';
|
|
2
|
+
import { A as AtribuError } from './errors-D3ApBz8J.js';
|
|
3
|
+
export { a as ApiErrorBody, b as ApiErrorCode, c as AtribuApiError, d as AtribuConfigError, e as AtribuOauthError, f as AtribuTransportError, g as AtribuWebhookError, O as OauthErrorCode, R as RetryHint, W as WebhookErrorCode } from './errors-D3ApBz8J.js';
|
|
4
|
+
|
|
5
|
+
interface AtribuClientConfig {
|
|
6
|
+
apiKey: string;
|
|
7
|
+
baseUrl?: string;
|
|
8
|
+
fetch?: typeof fetch;
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
userAgent?: string;
|
|
11
|
+
defaultIdempotencyKeyGenerator?: () => string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type SendBody = NonNullable<paths["/api/v1/messages"]["post"]["requestBody"]>["content"]["application/json"];
|
|
15
|
+
type SendResponse = paths["/api/v1/messages"]["post"]["responses"][200]["content"]["application/json"];
|
|
16
|
+
type MessageSendInput = SendBody;
|
|
17
|
+
type MessageContent = SendBody["content"];
|
|
18
|
+
type MessageSendResponse = SendResponse["data"];
|
|
19
|
+
interface SendOptions {
|
|
20
|
+
idempotencyKey?: string;
|
|
21
|
+
signal?: AbortSignal;
|
|
22
|
+
}
|
|
23
|
+
declare class MessagesResource {
|
|
24
|
+
private readonly http;
|
|
25
|
+
constructor(http: HttpClientLike);
|
|
26
|
+
send(input: MessageSendInput, opts?: SendOptions): Promise<MessageSendResponse>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type ReplyBody = NonNullable<paths["/api/v1/comments/{comment_id}/reply"]["post"]["requestBody"]>["content"]["application/json"];
|
|
30
|
+
type PrivateReplyBody = NonNullable<paths["/api/v1/comments/{comment_id}/private-reply"]["post"]["requestBody"]>["content"]["application/json"];
|
|
31
|
+
type ReplyResponse = paths["/api/v1/comments/{comment_id}/reply"]["post"]["responses"][200]["content"]["application/json"];
|
|
32
|
+
type CommentReplyInput = ReplyBody & {
|
|
33
|
+
comment_id: string;
|
|
34
|
+
};
|
|
35
|
+
type CommentPrivateReplyInput = PrivateReplyBody & {
|
|
36
|
+
comment_id: string;
|
|
37
|
+
};
|
|
38
|
+
type CommentReplyResponse = ReplyResponse["data"];
|
|
39
|
+
interface CommentReplyOptions {
|
|
40
|
+
idempotencyKey?: string;
|
|
41
|
+
signal?: AbortSignal;
|
|
42
|
+
}
|
|
43
|
+
declare class CommentsResource {
|
|
44
|
+
private readonly http;
|
|
45
|
+
constructor(http: HttpClientLike);
|
|
46
|
+
reply(input: CommentReplyInput, opts?: CommentReplyOptions): Promise<CommentReplyResponse>;
|
|
47
|
+
privateReply(input: CommentPrivateReplyInput, opts?: CommentReplyOptions): Promise<CommentReplyResponse>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
type ListResponse = paths["/api/v1/webhooks/subscriptions"]["get"]["responses"][200]["content"]["application/json"];
|
|
51
|
+
type CreateBody = NonNullable<paths["/api/v1/webhooks/subscriptions"]["post"]["requestBody"]>["content"]["application/json"];
|
|
52
|
+
type CreateResponse = paths["/api/v1/webhooks/subscriptions"]["post"]["responses"][201]["content"]["application/json"];
|
|
53
|
+
type UpdateBody = NonNullable<paths["/api/v1/webhooks/subscriptions/{id}"]["patch"]["requestBody"]>["content"]["application/json"];
|
|
54
|
+
type RotateBody = NonNullable<NonNullable<paths["/api/v1/webhooks/subscriptions/{id}/rotate-secret"]["post"]["requestBody"]>["content"]["application/json"]>;
|
|
55
|
+
type RotateResponse = paths["/api/v1/webhooks/subscriptions/{id}/rotate-secret"]["post"]["responses"][200]["content"]["application/json"];
|
|
56
|
+
type TestResponse = paths["/api/v1/webhooks/test/{id}"]["post"]["responses"][200]["content"]["application/json"];
|
|
57
|
+
type WebhookSubscription = ListResponse["data"][number];
|
|
58
|
+
type WebhookSubscriptionWithSecret = CreateResponse["data"];
|
|
59
|
+
type WebhookSubscriptionCreateInput = CreateBody;
|
|
60
|
+
type WebhookSubscriptionUpdateInput = UpdateBody;
|
|
61
|
+
type WebhookSubscriptionRotateOptions = RotateBody;
|
|
62
|
+
type WebhookSubscriptionRotateResult = RotateResponse["data"];
|
|
63
|
+
type WebhookSubscriptionTestResult = TestResponse["data"];
|
|
64
|
+
interface MutationOptions {
|
|
65
|
+
idempotencyKey?: string;
|
|
66
|
+
signal?: AbortSignal;
|
|
67
|
+
}
|
|
68
|
+
declare class WebhookSubscriptionsResource {
|
|
69
|
+
private readonly http;
|
|
70
|
+
constructor(http: HttpClientLike);
|
|
71
|
+
list(opts?: {
|
|
72
|
+
signal?: AbortSignal;
|
|
73
|
+
}): Promise<WebhookSubscription[]>;
|
|
74
|
+
create(input: WebhookSubscriptionCreateInput, opts?: MutationOptions): Promise<WebhookSubscriptionWithSecret>;
|
|
75
|
+
update(id: string, input: WebhookSubscriptionUpdateInput, opts?: MutationOptions): Promise<WebhookSubscription>;
|
|
76
|
+
delete(id: string, opts?: MutationOptions): Promise<void>;
|
|
77
|
+
rotateSecret(id: string, options?: WebhookSubscriptionRotateOptions, opts?: MutationOptions): Promise<WebhookSubscriptionRotateResult>;
|
|
78
|
+
test(id: string, opts?: MutationOptions): Promise<WebhookSubscriptionTestResult>;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
type ReplayResponse = paths["/api/v1/webhooks/deliveries/{id}/replay"]["post"]["responses"][200]["content"]["application/json"];
|
|
82
|
+
type WebhookDeliveryReplayResult = ReplayResponse["data"];
|
|
83
|
+
interface ReplayOptions {
|
|
84
|
+
idempotencyKey?: string;
|
|
85
|
+
signal?: AbortSignal;
|
|
86
|
+
}
|
|
87
|
+
declare class WebhookDeliveriesResource {
|
|
88
|
+
private readonly http;
|
|
89
|
+
constructor(http: HttpClientLike);
|
|
90
|
+
replay(id: string, opts?: ReplayOptions): Promise<WebhookDeliveryReplayResult>;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Opt-in retry layer.
|
|
95
|
+
*
|
|
96
|
+
* Why opt-in: hiding retries inside the SDK by default obscures backpressure
|
|
97
|
+
* signals and amplifies load on a failing server. Consumers that want them
|
|
98
|
+
* call `.withRetry({...})`; others write their own retry logic against the
|
|
99
|
+
* typed `retry` hint on AtribuApiError.
|
|
100
|
+
*
|
|
101
|
+
* What gets retried:
|
|
102
|
+
* - `AtribuApiError` with `retry.action === "retry"` (5xx, 408)
|
|
103
|
+
* - `AtribuApiError` with `retry.action === "retry_after"` (429, 503 w/
|
|
104
|
+
* Retry-After) — honors retryAfterMs
|
|
105
|
+
* - `AtribuTransportError` (network glitches, ECONNRESET, timeouts)
|
|
106
|
+
*
|
|
107
|
+
* What does NOT retry:
|
|
108
|
+
* - `AtribuApiError` with `retry.action === "do_not_retry"` (403)
|
|
109
|
+
* - `AtribuApiError` with `retry.action === "fix_and_retry"` (422 etc — the
|
|
110
|
+
* caller's input is wrong; retrying with the same body won't help)
|
|
111
|
+
* - `AtribuApiError` with `retry.action === "refresh_token"` (401 — needs
|
|
112
|
+
* credential refresh, not a retry)
|
|
113
|
+
* - `AtribuConfigError`, `AtribuWebhookError`, anything else
|
|
114
|
+
*/
|
|
115
|
+
|
|
116
|
+
type BackoffStrategy = "exponential" | "fixed" | "none";
|
|
117
|
+
interface RetryOptions {
|
|
118
|
+
/**
|
|
119
|
+
* Max attempts including the initial call. `maxAttempts: 3` = initial + 2
|
|
120
|
+
* retries. Must be ≥ 1. Default 3.
|
|
121
|
+
*/
|
|
122
|
+
maxAttempts?: number;
|
|
123
|
+
/**
|
|
124
|
+
* Backoff strategy between retries. "exponential" = `baseDelayMs * 2^n`
|
|
125
|
+
* (capped by `maxDelayMs`). "fixed" = `baseDelayMs`. "none" = no delay.
|
|
126
|
+
* Default "exponential".
|
|
127
|
+
*/
|
|
128
|
+
backoff?: BackoffStrategy;
|
|
129
|
+
/** Base delay between retries in ms. Default 500. */
|
|
130
|
+
baseDelayMs?: number;
|
|
131
|
+
/** Cap on the delay between retries. Default 30000 (30s). */
|
|
132
|
+
maxDelayMs?: number;
|
|
133
|
+
/**
|
|
134
|
+
* Jitter factor 0..1. Multiplies the computed delay by `1 + random*jitter`
|
|
135
|
+
* (jitter=0 means deterministic). Default 0.3.
|
|
136
|
+
*/
|
|
137
|
+
jitter?: number;
|
|
138
|
+
/** Inject for tests. Default `(ms) => new Promise(r => setTimeout(r, ms))`. */
|
|
139
|
+
sleep?: (ms: number) => Promise<void>;
|
|
140
|
+
/** Inject for jitter tests. Default Math.random. */
|
|
141
|
+
random?: () => number;
|
|
142
|
+
}
|
|
143
|
+
declare class RetryingHttpClient implements HttpClientLike {
|
|
144
|
+
private readonly base;
|
|
145
|
+
private readonly r;
|
|
146
|
+
constructor(base: HttpClientLike, options: RetryOptions);
|
|
147
|
+
request<T>(opts: RequestOptions): Promise<T>;
|
|
148
|
+
/**
|
|
149
|
+
* Returns the delay in ms before the next attempt, or null if the error
|
|
150
|
+
* is non-retryable (caller should throw immediately).
|
|
151
|
+
*/
|
|
152
|
+
private computeDelay;
|
|
153
|
+
private backoffDelay;
|
|
154
|
+
private applyJitter;
|
|
155
|
+
}
|
|
156
|
+
declare function isRetryableError(err: unknown): err is AtribuError;
|
|
157
|
+
|
|
158
|
+
interface ResourceBundle {
|
|
159
|
+
messages: MessagesResource;
|
|
160
|
+
comments: CommentsResource;
|
|
161
|
+
webhooks: {
|
|
162
|
+
subscriptions: WebhookSubscriptionsResource;
|
|
163
|
+
deliveries: WebhookDeliveriesResource;
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
declare class AtribuClient {
|
|
167
|
+
readonly messages: MessagesResource;
|
|
168
|
+
readonly comments: CommentsResource;
|
|
169
|
+
readonly webhooks: ResourceBundle["webhooks"];
|
|
170
|
+
/** @internal — exposed for `withRetry` chaining; do not depend on this. */
|
|
171
|
+
protected readonly _http: HttpClientLike;
|
|
172
|
+
constructor(config: AtribuClientConfig);
|
|
173
|
+
/**
|
|
174
|
+
* Returns a new AtribuClient that retries on transient errors. The
|
|
175
|
+
* original client is not mutated. The wrapper respects the typed
|
|
176
|
+
* `retry` hint on AtribuApiError — `do_not_retry`, `fix_and_retry`,
|
|
177
|
+
* and `refresh_token` are NOT retried (those need caller action, not
|
|
178
|
+
* a repeat call).
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* const client = new AtribuClient({...}).withRetry({
|
|
182
|
+
* maxAttempts: 3,
|
|
183
|
+
* backoff: "exponential",
|
|
184
|
+
* baseDelayMs: 500,
|
|
185
|
+
* });
|
|
186
|
+
* await client.messages.send({...});
|
|
187
|
+
*/
|
|
188
|
+
withRetry(options: RetryOptions): AtribuClient;
|
|
189
|
+
private static _fromHttp;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
declare const SDK_VERSION = "0.1.0";
|
|
193
|
+
|
|
194
|
+
type Runtime = "node" | "bun" | "deno" | "edge" | "browser" | "unknown";
|
|
195
|
+
declare function detectRuntime(): Runtime;
|
|
196
|
+
declare function runtimeTag(): string;
|
|
197
|
+
|
|
198
|
+
export { AtribuClient, type AtribuClientConfig, AtribuError, type BackoffStrategy, type CommentPrivateReplyInput, type CommentReplyInput, type CommentReplyOptions, type CommentReplyResponse, type MessageContent, type MessageSendInput, type MessageSendResponse, type MutationOptions, type ReplayOptions, type RetryOptions, RetryingHttpClient, type Runtime, SDK_VERSION, type SendOptions, type WebhookDeliveryReplayResult, type WebhookSubscription, type WebhookSubscriptionCreateInput, type WebhookSubscriptionRotateOptions, type WebhookSubscriptionRotateResult, type WebhookSubscriptionTestResult, type WebhookSubscriptionUpdateInput, type WebhookSubscriptionWithSecret, detectRuntime, isRetryableError, runtimeTag };
|