@messagebird/sdk 0.3.0 → 0.4.1
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.d.mts +3904 -0
- package/dist/index.mjs +3030 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +6 -4
- package/dist/index.d.ts +0 -3054
- package/dist/index.js +0 -2211
- package/dist/index.js.map +0 -1
package/dist/index.js
DELETED
|
@@ -1,2211 +0,0 @@
|
|
|
1
|
-
import { Webhook } from 'standardwebhooks';
|
|
2
|
-
|
|
3
|
-
// src/generated/core/bodySerializer.gen.ts
|
|
4
|
-
var jsonBodySerializer = {
|
|
5
|
-
bodySerializer: (body) => JSON.stringify(
|
|
6
|
-
body,
|
|
7
|
-
(_key, value) => typeof value === "bigint" ? value.toString() : value
|
|
8
|
-
)
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
// src/generated/core/serverSentEvents.gen.ts
|
|
12
|
-
function createSseClient({
|
|
13
|
-
onRequest,
|
|
14
|
-
onSseError,
|
|
15
|
-
onSseEvent,
|
|
16
|
-
responseTransformer,
|
|
17
|
-
responseValidator,
|
|
18
|
-
sseDefaultRetryDelay,
|
|
19
|
-
sseMaxRetryAttempts,
|
|
20
|
-
sseMaxRetryDelay,
|
|
21
|
-
sseSleepFn,
|
|
22
|
-
url,
|
|
23
|
-
...options
|
|
24
|
-
}) {
|
|
25
|
-
let lastEventId;
|
|
26
|
-
const sleep2 = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
27
|
-
const createStream = async function* () {
|
|
28
|
-
let retryDelay2 = sseDefaultRetryDelay ?? 3e3;
|
|
29
|
-
let attempt = 0;
|
|
30
|
-
const signal = options.signal ?? new AbortController().signal;
|
|
31
|
-
while (true) {
|
|
32
|
-
if (signal.aborted) break;
|
|
33
|
-
attempt++;
|
|
34
|
-
const headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
|
|
35
|
-
if (lastEventId !== void 0) {
|
|
36
|
-
headers.set("Last-Event-ID", lastEventId);
|
|
37
|
-
}
|
|
38
|
-
try {
|
|
39
|
-
const requestInit = {
|
|
40
|
-
redirect: "follow",
|
|
41
|
-
...options,
|
|
42
|
-
body: options.serializedBody,
|
|
43
|
-
headers,
|
|
44
|
-
signal
|
|
45
|
-
};
|
|
46
|
-
let request = new Request(url, requestInit);
|
|
47
|
-
if (onRequest) {
|
|
48
|
-
request = await onRequest(url, requestInit);
|
|
49
|
-
}
|
|
50
|
-
const _fetch = options.fetch ?? globalThis.fetch;
|
|
51
|
-
const response = await _fetch(request);
|
|
52
|
-
if (!response.ok)
|
|
53
|
-
throw new Error(
|
|
54
|
-
`SSE failed: ${response.status} ${response.statusText}`
|
|
55
|
-
);
|
|
56
|
-
if (!response.body) throw new Error("No body in SSE response");
|
|
57
|
-
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
|
|
58
|
-
let buffer = "";
|
|
59
|
-
const abortHandler = () => {
|
|
60
|
-
try {
|
|
61
|
-
reader.cancel();
|
|
62
|
-
} catch {
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
signal.addEventListener("abort", abortHandler);
|
|
66
|
-
try {
|
|
67
|
-
while (true) {
|
|
68
|
-
const { done, value } = await reader.read();
|
|
69
|
-
if (done) break;
|
|
70
|
-
buffer += value;
|
|
71
|
-
buffer = buffer.replace(/\r\n?/g, "\n");
|
|
72
|
-
const chunks = buffer.split("\n\n");
|
|
73
|
-
buffer = chunks.pop() ?? "";
|
|
74
|
-
for (const chunk of chunks) {
|
|
75
|
-
const lines = chunk.split("\n");
|
|
76
|
-
const dataLines = [];
|
|
77
|
-
let eventName;
|
|
78
|
-
for (const line of lines) {
|
|
79
|
-
if (line.startsWith("data:")) {
|
|
80
|
-
dataLines.push(line.replace(/^data:\s*/, ""));
|
|
81
|
-
} else if (line.startsWith("event:")) {
|
|
82
|
-
eventName = line.replace(/^event:\s*/, "");
|
|
83
|
-
} else if (line.startsWith("id:")) {
|
|
84
|
-
lastEventId = line.replace(/^id:\s*/, "");
|
|
85
|
-
} else if (line.startsWith("retry:")) {
|
|
86
|
-
const parsed = Number.parseInt(
|
|
87
|
-
line.replace(/^retry:\s*/, ""),
|
|
88
|
-
10
|
|
89
|
-
);
|
|
90
|
-
if (!Number.isNaN(parsed)) {
|
|
91
|
-
retryDelay2 = parsed;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
let data;
|
|
96
|
-
let parsedJson = false;
|
|
97
|
-
if (dataLines.length) {
|
|
98
|
-
const rawData = dataLines.join("\n");
|
|
99
|
-
try {
|
|
100
|
-
data = JSON.parse(rawData);
|
|
101
|
-
parsedJson = true;
|
|
102
|
-
} catch {
|
|
103
|
-
data = rawData;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
if (parsedJson) {
|
|
107
|
-
if (responseValidator) {
|
|
108
|
-
await responseValidator(data);
|
|
109
|
-
}
|
|
110
|
-
if (responseTransformer) {
|
|
111
|
-
data = await responseTransformer(data);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
onSseEvent?.({
|
|
115
|
-
data,
|
|
116
|
-
event: eventName,
|
|
117
|
-
id: lastEventId,
|
|
118
|
-
retry: retryDelay2
|
|
119
|
-
});
|
|
120
|
-
if (dataLines.length) {
|
|
121
|
-
yield data;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
} finally {
|
|
126
|
-
signal.removeEventListener("abort", abortHandler);
|
|
127
|
-
reader.releaseLock();
|
|
128
|
-
}
|
|
129
|
-
break;
|
|
130
|
-
} catch (error) {
|
|
131
|
-
onSseError?.(error);
|
|
132
|
-
if (sseMaxRetryAttempts !== void 0 && attempt >= sseMaxRetryAttempts) {
|
|
133
|
-
break;
|
|
134
|
-
}
|
|
135
|
-
const backoff = Math.min(
|
|
136
|
-
retryDelay2 * 2 ** (attempt - 1),
|
|
137
|
-
sseMaxRetryDelay ?? 3e4
|
|
138
|
-
);
|
|
139
|
-
await sleep2(backoff);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
const stream = createStream();
|
|
144
|
-
return { stream };
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// src/generated/core/pathSerializer.gen.ts
|
|
148
|
-
var separatorArrayExplode = (style) => {
|
|
149
|
-
switch (style) {
|
|
150
|
-
case "label":
|
|
151
|
-
return ".";
|
|
152
|
-
case "matrix":
|
|
153
|
-
return ";";
|
|
154
|
-
case "simple":
|
|
155
|
-
return ",";
|
|
156
|
-
default:
|
|
157
|
-
return "&";
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
var separatorArrayNoExplode = (style) => {
|
|
161
|
-
switch (style) {
|
|
162
|
-
case "form":
|
|
163
|
-
return ",";
|
|
164
|
-
case "pipeDelimited":
|
|
165
|
-
return "|";
|
|
166
|
-
case "spaceDelimited":
|
|
167
|
-
return "%20";
|
|
168
|
-
default:
|
|
169
|
-
return ",";
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
var separatorObjectExplode = (style) => {
|
|
173
|
-
switch (style) {
|
|
174
|
-
case "label":
|
|
175
|
-
return ".";
|
|
176
|
-
case "matrix":
|
|
177
|
-
return ";";
|
|
178
|
-
case "simple":
|
|
179
|
-
return ",";
|
|
180
|
-
default:
|
|
181
|
-
return "&";
|
|
182
|
-
}
|
|
183
|
-
};
|
|
184
|
-
var serializeArrayParam = ({
|
|
185
|
-
allowReserved,
|
|
186
|
-
explode,
|
|
187
|
-
name,
|
|
188
|
-
style,
|
|
189
|
-
value
|
|
190
|
-
}) => {
|
|
191
|
-
if (!explode) {
|
|
192
|
-
const joinedValues2 = (allowReserved ? value : value.map((v) => encodeURIComponent(v))).join(separatorArrayNoExplode(style));
|
|
193
|
-
switch (style) {
|
|
194
|
-
case "label":
|
|
195
|
-
return `.${joinedValues2}`;
|
|
196
|
-
case "matrix":
|
|
197
|
-
return `;${name}=${joinedValues2}`;
|
|
198
|
-
case "simple":
|
|
199
|
-
return joinedValues2;
|
|
200
|
-
default:
|
|
201
|
-
return `${name}=${joinedValues2}`;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
const separator = separatorArrayExplode(style);
|
|
205
|
-
const joinedValues = value.map((v) => {
|
|
206
|
-
if (style === "label" || style === "simple") {
|
|
207
|
-
return allowReserved ? v : encodeURIComponent(v);
|
|
208
|
-
}
|
|
209
|
-
return serializePrimitiveParam({
|
|
210
|
-
allowReserved,
|
|
211
|
-
name,
|
|
212
|
-
value: v
|
|
213
|
-
});
|
|
214
|
-
}).join(separator);
|
|
215
|
-
return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
|
|
216
|
-
};
|
|
217
|
-
var serializePrimitiveParam = ({
|
|
218
|
-
allowReserved,
|
|
219
|
-
name,
|
|
220
|
-
value
|
|
221
|
-
}) => {
|
|
222
|
-
if (value === void 0 || value === null) {
|
|
223
|
-
return "";
|
|
224
|
-
}
|
|
225
|
-
if (typeof value === "object") {
|
|
226
|
-
throw new Error(
|
|
227
|
-
"Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these."
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
|
|
231
|
-
};
|
|
232
|
-
var serializeObjectParam = ({
|
|
233
|
-
allowReserved,
|
|
234
|
-
explode,
|
|
235
|
-
name,
|
|
236
|
-
style,
|
|
237
|
-
value,
|
|
238
|
-
valueOnly
|
|
239
|
-
}) => {
|
|
240
|
-
if (value instanceof Date) {
|
|
241
|
-
return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
|
|
242
|
-
}
|
|
243
|
-
if (style !== "deepObject" && !explode) {
|
|
244
|
-
let values = [];
|
|
245
|
-
Object.entries(value).forEach(([key, v]) => {
|
|
246
|
-
values = [
|
|
247
|
-
...values,
|
|
248
|
-
key,
|
|
249
|
-
allowReserved ? v : encodeURIComponent(v)
|
|
250
|
-
];
|
|
251
|
-
});
|
|
252
|
-
const joinedValues2 = values.join(",");
|
|
253
|
-
switch (style) {
|
|
254
|
-
case "form":
|
|
255
|
-
return `${name}=${joinedValues2}`;
|
|
256
|
-
case "label":
|
|
257
|
-
return `.${joinedValues2}`;
|
|
258
|
-
case "matrix":
|
|
259
|
-
return `;${name}=${joinedValues2}`;
|
|
260
|
-
default:
|
|
261
|
-
return joinedValues2;
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
const separator = separatorObjectExplode(style);
|
|
265
|
-
const joinedValues = Object.entries(value).map(
|
|
266
|
-
([key, v]) => serializePrimitiveParam({
|
|
267
|
-
allowReserved,
|
|
268
|
-
name: style === "deepObject" ? `${name}[${key}]` : key,
|
|
269
|
-
value: v
|
|
270
|
-
})
|
|
271
|
-
).join(separator);
|
|
272
|
-
return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
// src/generated/core/utils.gen.ts
|
|
276
|
-
var PATH_PARAM_RE = /\{[^{}]+\}/g;
|
|
277
|
-
var defaultPathSerializer = ({ path, url: _url }) => {
|
|
278
|
-
let url = _url;
|
|
279
|
-
const matches = _url.match(PATH_PARAM_RE);
|
|
280
|
-
if (matches) {
|
|
281
|
-
for (const match of matches) {
|
|
282
|
-
let explode = false;
|
|
283
|
-
let name = match.substring(1, match.length - 1);
|
|
284
|
-
let style = "simple";
|
|
285
|
-
if (name.endsWith("*")) {
|
|
286
|
-
explode = true;
|
|
287
|
-
name = name.substring(0, name.length - 1);
|
|
288
|
-
}
|
|
289
|
-
if (name.startsWith(".")) {
|
|
290
|
-
name = name.substring(1);
|
|
291
|
-
style = "label";
|
|
292
|
-
} else if (name.startsWith(";")) {
|
|
293
|
-
name = name.substring(1);
|
|
294
|
-
style = "matrix";
|
|
295
|
-
}
|
|
296
|
-
const value = path[name];
|
|
297
|
-
if (value === void 0 || value === null) {
|
|
298
|
-
continue;
|
|
299
|
-
}
|
|
300
|
-
if (Array.isArray(value)) {
|
|
301
|
-
url = url.replace(
|
|
302
|
-
match,
|
|
303
|
-
serializeArrayParam({ explode, name, style, value })
|
|
304
|
-
);
|
|
305
|
-
continue;
|
|
306
|
-
}
|
|
307
|
-
if (typeof value === "object") {
|
|
308
|
-
url = url.replace(
|
|
309
|
-
match,
|
|
310
|
-
serializeObjectParam({
|
|
311
|
-
explode,
|
|
312
|
-
name,
|
|
313
|
-
style,
|
|
314
|
-
value,
|
|
315
|
-
valueOnly: true
|
|
316
|
-
})
|
|
317
|
-
);
|
|
318
|
-
continue;
|
|
319
|
-
}
|
|
320
|
-
if (style === "matrix") {
|
|
321
|
-
url = url.replace(
|
|
322
|
-
match,
|
|
323
|
-
`;${serializePrimitiveParam({
|
|
324
|
-
name,
|
|
325
|
-
value
|
|
326
|
-
})}`
|
|
327
|
-
);
|
|
328
|
-
continue;
|
|
329
|
-
}
|
|
330
|
-
const replaceValue = encodeURIComponent(
|
|
331
|
-
style === "label" ? `.${value}` : value
|
|
332
|
-
);
|
|
333
|
-
url = url.replace(match, replaceValue);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
return url;
|
|
337
|
-
};
|
|
338
|
-
var getUrl = ({
|
|
339
|
-
baseUrl,
|
|
340
|
-
path,
|
|
341
|
-
query,
|
|
342
|
-
querySerializer,
|
|
343
|
-
url: _url
|
|
344
|
-
}) => {
|
|
345
|
-
const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
|
|
346
|
-
let url = (baseUrl ?? "") + pathUrl;
|
|
347
|
-
if (path) {
|
|
348
|
-
url = defaultPathSerializer({ path, url });
|
|
349
|
-
}
|
|
350
|
-
let search = query ? querySerializer(query) : "";
|
|
351
|
-
if (search.startsWith("?")) {
|
|
352
|
-
search = search.substring(1);
|
|
353
|
-
}
|
|
354
|
-
if (search) {
|
|
355
|
-
url += `?${search}`;
|
|
356
|
-
}
|
|
357
|
-
return url;
|
|
358
|
-
};
|
|
359
|
-
function getValidRequestBody(options) {
|
|
360
|
-
const hasBody = options.body !== void 0;
|
|
361
|
-
const isSerializedBody = hasBody && options.bodySerializer;
|
|
362
|
-
if (isSerializedBody) {
|
|
363
|
-
if ("serializedBody" in options) {
|
|
364
|
-
const hasSerializedBody = options.serializedBody !== void 0 && options.serializedBody !== "";
|
|
365
|
-
return hasSerializedBody ? options.serializedBody : null;
|
|
366
|
-
}
|
|
367
|
-
return options.body !== "" ? options.body : null;
|
|
368
|
-
}
|
|
369
|
-
if (hasBody) {
|
|
370
|
-
return options.body;
|
|
371
|
-
}
|
|
372
|
-
return void 0;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
// src/generated/core/auth.gen.ts
|
|
376
|
-
var getAuthToken = async (auth, callback) => {
|
|
377
|
-
const token = typeof callback === "function" ? await callback(auth) : callback;
|
|
378
|
-
if (!token) {
|
|
379
|
-
return;
|
|
380
|
-
}
|
|
381
|
-
if (auth.scheme === "bearer") {
|
|
382
|
-
return `Bearer ${token}`;
|
|
383
|
-
}
|
|
384
|
-
if (auth.scheme === "basic") {
|
|
385
|
-
return `Basic ${btoa(token)}`;
|
|
386
|
-
}
|
|
387
|
-
return token;
|
|
388
|
-
};
|
|
389
|
-
|
|
390
|
-
// src/generated/client/utils.gen.ts
|
|
391
|
-
var createQuerySerializer = ({
|
|
392
|
-
parameters = {},
|
|
393
|
-
...args
|
|
394
|
-
} = {}) => {
|
|
395
|
-
const querySerializer = (queryParams) => {
|
|
396
|
-
const search = [];
|
|
397
|
-
if (queryParams && typeof queryParams === "object") {
|
|
398
|
-
for (const name in queryParams) {
|
|
399
|
-
const value = queryParams[name];
|
|
400
|
-
if (value === void 0 || value === null) {
|
|
401
|
-
continue;
|
|
402
|
-
}
|
|
403
|
-
const options = parameters[name] || args;
|
|
404
|
-
if (Array.isArray(value)) {
|
|
405
|
-
const serializedArray = serializeArrayParam({
|
|
406
|
-
allowReserved: options.allowReserved,
|
|
407
|
-
explode: true,
|
|
408
|
-
name,
|
|
409
|
-
style: "form",
|
|
410
|
-
value,
|
|
411
|
-
...options.array
|
|
412
|
-
});
|
|
413
|
-
if (serializedArray) search.push(serializedArray);
|
|
414
|
-
} else if (typeof value === "object") {
|
|
415
|
-
const serializedObject = serializeObjectParam({
|
|
416
|
-
allowReserved: options.allowReserved,
|
|
417
|
-
explode: true,
|
|
418
|
-
name,
|
|
419
|
-
style: "deepObject",
|
|
420
|
-
value,
|
|
421
|
-
...options.object
|
|
422
|
-
});
|
|
423
|
-
if (serializedObject) search.push(serializedObject);
|
|
424
|
-
} else {
|
|
425
|
-
const serializedPrimitive = serializePrimitiveParam({
|
|
426
|
-
allowReserved: options.allowReserved,
|
|
427
|
-
name,
|
|
428
|
-
value
|
|
429
|
-
});
|
|
430
|
-
if (serializedPrimitive) search.push(serializedPrimitive);
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
return search.join("&");
|
|
435
|
-
};
|
|
436
|
-
return querySerializer;
|
|
437
|
-
};
|
|
438
|
-
var getParseAs = (contentType) => {
|
|
439
|
-
if (!contentType) {
|
|
440
|
-
return "stream";
|
|
441
|
-
}
|
|
442
|
-
const cleanContent = contentType.split(";")[0]?.trim();
|
|
443
|
-
if (!cleanContent) {
|
|
444
|
-
return;
|
|
445
|
-
}
|
|
446
|
-
if (cleanContent.startsWith("application/json") || cleanContent.endsWith("+json")) {
|
|
447
|
-
return "json";
|
|
448
|
-
}
|
|
449
|
-
if (cleanContent === "multipart/form-data") {
|
|
450
|
-
return "formData";
|
|
451
|
-
}
|
|
452
|
-
if (["application/", "audio/", "image/", "video/"].some(
|
|
453
|
-
(type) => cleanContent.startsWith(type)
|
|
454
|
-
)) {
|
|
455
|
-
return "blob";
|
|
456
|
-
}
|
|
457
|
-
if (cleanContent.startsWith("text/")) {
|
|
458
|
-
return "text";
|
|
459
|
-
}
|
|
460
|
-
return;
|
|
461
|
-
};
|
|
462
|
-
var checkForExistence = (options, name) => {
|
|
463
|
-
if (!name) {
|
|
464
|
-
return false;
|
|
465
|
-
}
|
|
466
|
-
if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) {
|
|
467
|
-
return true;
|
|
468
|
-
}
|
|
469
|
-
return false;
|
|
470
|
-
};
|
|
471
|
-
async function setAuthParams(options) {
|
|
472
|
-
for (const auth of options.security ?? []) {
|
|
473
|
-
if (checkForExistence(options, auth.name)) {
|
|
474
|
-
continue;
|
|
475
|
-
}
|
|
476
|
-
const token = await getAuthToken(auth, options.auth);
|
|
477
|
-
if (!token) {
|
|
478
|
-
continue;
|
|
479
|
-
}
|
|
480
|
-
const name = auth.name ?? "Authorization";
|
|
481
|
-
switch (auth.in) {
|
|
482
|
-
case "query":
|
|
483
|
-
if (!options.query) {
|
|
484
|
-
options.query = {};
|
|
485
|
-
}
|
|
486
|
-
options.query[name] = token;
|
|
487
|
-
break;
|
|
488
|
-
case "cookie":
|
|
489
|
-
options.headers.append("Cookie", `${name}=${token}`);
|
|
490
|
-
break;
|
|
491
|
-
case "header":
|
|
492
|
-
default:
|
|
493
|
-
options.headers.set(name, token);
|
|
494
|
-
break;
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
var buildUrl = (options) => getUrl({
|
|
499
|
-
baseUrl: options.baseUrl,
|
|
500
|
-
path: options.path,
|
|
501
|
-
query: options.query,
|
|
502
|
-
querySerializer: typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer(options.querySerializer),
|
|
503
|
-
url: options.url
|
|
504
|
-
});
|
|
505
|
-
var mergeConfigs = (a, b) => {
|
|
506
|
-
const config = { ...a, ...b };
|
|
507
|
-
if (config.baseUrl?.endsWith("/")) {
|
|
508
|
-
config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
|
|
509
|
-
}
|
|
510
|
-
config.headers = mergeHeaders(a.headers, b.headers);
|
|
511
|
-
return config;
|
|
512
|
-
};
|
|
513
|
-
var headersEntries = (headers) => {
|
|
514
|
-
const entries = [];
|
|
515
|
-
headers.forEach((value, key) => {
|
|
516
|
-
entries.push([key, value]);
|
|
517
|
-
});
|
|
518
|
-
return entries;
|
|
519
|
-
};
|
|
520
|
-
var mergeHeaders = (...headers) => {
|
|
521
|
-
const mergedHeaders = new Headers();
|
|
522
|
-
for (const header of headers) {
|
|
523
|
-
if (!header) {
|
|
524
|
-
continue;
|
|
525
|
-
}
|
|
526
|
-
const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);
|
|
527
|
-
for (const [key, value] of iterator) {
|
|
528
|
-
if (value === null) {
|
|
529
|
-
mergedHeaders.delete(key);
|
|
530
|
-
} else if (Array.isArray(value)) {
|
|
531
|
-
for (const v of value) {
|
|
532
|
-
mergedHeaders.append(key, v);
|
|
533
|
-
}
|
|
534
|
-
} else if (value !== void 0) {
|
|
535
|
-
mergedHeaders.set(
|
|
536
|
-
key,
|
|
537
|
-
typeof value === "object" ? JSON.stringify(value) : value
|
|
538
|
-
);
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
return mergedHeaders;
|
|
543
|
-
};
|
|
544
|
-
var Interceptors = class {
|
|
545
|
-
fns = [];
|
|
546
|
-
clear() {
|
|
547
|
-
this.fns = [];
|
|
548
|
-
}
|
|
549
|
-
eject(id) {
|
|
550
|
-
const index = this.getInterceptorIndex(id);
|
|
551
|
-
if (this.fns[index]) {
|
|
552
|
-
this.fns[index] = null;
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
exists(id) {
|
|
556
|
-
const index = this.getInterceptorIndex(id);
|
|
557
|
-
return Boolean(this.fns[index]);
|
|
558
|
-
}
|
|
559
|
-
getInterceptorIndex(id) {
|
|
560
|
-
if (typeof id === "number") {
|
|
561
|
-
return this.fns[id] ? id : -1;
|
|
562
|
-
}
|
|
563
|
-
return this.fns.indexOf(id);
|
|
564
|
-
}
|
|
565
|
-
update(id, fn) {
|
|
566
|
-
const index = this.getInterceptorIndex(id);
|
|
567
|
-
if (this.fns[index]) {
|
|
568
|
-
this.fns[index] = fn;
|
|
569
|
-
return id;
|
|
570
|
-
}
|
|
571
|
-
return false;
|
|
572
|
-
}
|
|
573
|
-
use(fn) {
|
|
574
|
-
this.fns.push(fn);
|
|
575
|
-
return this.fns.length - 1;
|
|
576
|
-
}
|
|
577
|
-
};
|
|
578
|
-
var createInterceptors = () => ({
|
|
579
|
-
error: new Interceptors(),
|
|
580
|
-
request: new Interceptors(),
|
|
581
|
-
response: new Interceptors()
|
|
582
|
-
});
|
|
583
|
-
var defaultQuerySerializer = createQuerySerializer({
|
|
584
|
-
allowReserved: false,
|
|
585
|
-
array: {
|
|
586
|
-
explode: true,
|
|
587
|
-
style: "form"
|
|
588
|
-
},
|
|
589
|
-
object: {
|
|
590
|
-
explode: true,
|
|
591
|
-
style: "deepObject"
|
|
592
|
-
}
|
|
593
|
-
});
|
|
594
|
-
var defaultHeaders = {
|
|
595
|
-
"Content-Type": "application/json"
|
|
596
|
-
};
|
|
597
|
-
var createConfig = (override = {}) => ({
|
|
598
|
-
...jsonBodySerializer,
|
|
599
|
-
headers: defaultHeaders,
|
|
600
|
-
parseAs: "auto",
|
|
601
|
-
querySerializer: defaultQuerySerializer,
|
|
602
|
-
...override
|
|
603
|
-
});
|
|
604
|
-
|
|
605
|
-
// src/generated/client/client.gen.ts
|
|
606
|
-
var createClient = (config = {}) => {
|
|
607
|
-
let _config = mergeConfigs(createConfig(), config);
|
|
608
|
-
const getConfig = () => ({ ..._config });
|
|
609
|
-
const setConfig = (config2) => {
|
|
610
|
-
_config = mergeConfigs(_config, config2);
|
|
611
|
-
return getConfig();
|
|
612
|
-
};
|
|
613
|
-
const interceptors = createInterceptors();
|
|
614
|
-
const beforeRequest = async (options) => {
|
|
615
|
-
const opts = {
|
|
616
|
-
..._config,
|
|
617
|
-
...options,
|
|
618
|
-
fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
|
|
619
|
-
headers: mergeHeaders(_config.headers, options.headers),
|
|
620
|
-
serializedBody: void 0
|
|
621
|
-
};
|
|
622
|
-
if (opts.security) {
|
|
623
|
-
await setAuthParams(opts);
|
|
624
|
-
}
|
|
625
|
-
if (opts.requestValidator) {
|
|
626
|
-
await opts.requestValidator(opts);
|
|
627
|
-
}
|
|
628
|
-
if (opts.body !== void 0 && opts.bodySerializer) {
|
|
629
|
-
opts.serializedBody = opts.bodySerializer(opts.body);
|
|
630
|
-
}
|
|
631
|
-
if (opts.body === void 0 || opts.serializedBody === "") {
|
|
632
|
-
opts.headers.delete("Content-Type");
|
|
633
|
-
}
|
|
634
|
-
const resolvedOpts = opts;
|
|
635
|
-
const url = buildUrl(resolvedOpts);
|
|
636
|
-
return { opts: resolvedOpts, url };
|
|
637
|
-
};
|
|
638
|
-
const request = async (options) => {
|
|
639
|
-
const throwOnError = options.throwOnError ?? _config.throwOnError;
|
|
640
|
-
const responseStyle = options.responseStyle ?? _config.responseStyle;
|
|
641
|
-
let request2;
|
|
642
|
-
let response;
|
|
643
|
-
try {
|
|
644
|
-
const { opts, url } = await beforeRequest(options);
|
|
645
|
-
const requestInit = {
|
|
646
|
-
redirect: "follow",
|
|
647
|
-
...opts,
|
|
648
|
-
body: getValidRequestBody(opts)
|
|
649
|
-
};
|
|
650
|
-
request2 = new Request(url, requestInit);
|
|
651
|
-
for (const fn of interceptors.request.fns) {
|
|
652
|
-
if (fn) {
|
|
653
|
-
request2 = await fn(request2, opts);
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
const _fetch = opts.fetch;
|
|
657
|
-
response = await _fetch(request2);
|
|
658
|
-
for (const fn of interceptors.response.fns) {
|
|
659
|
-
if (fn) {
|
|
660
|
-
response = await fn(response, request2, opts);
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
const result = {
|
|
664
|
-
request: request2,
|
|
665
|
-
response
|
|
666
|
-
};
|
|
667
|
-
if (response.ok) {
|
|
668
|
-
const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
|
|
669
|
-
if (response.status === 204 || response.headers.get("Content-Length") === "0") {
|
|
670
|
-
let emptyData;
|
|
671
|
-
switch (parseAs) {
|
|
672
|
-
case "arrayBuffer":
|
|
673
|
-
case "blob":
|
|
674
|
-
case "text":
|
|
675
|
-
emptyData = await response[parseAs]();
|
|
676
|
-
break;
|
|
677
|
-
case "formData":
|
|
678
|
-
emptyData = new FormData();
|
|
679
|
-
break;
|
|
680
|
-
case "stream":
|
|
681
|
-
emptyData = response.body;
|
|
682
|
-
break;
|
|
683
|
-
case "json":
|
|
684
|
-
default:
|
|
685
|
-
emptyData = {};
|
|
686
|
-
break;
|
|
687
|
-
}
|
|
688
|
-
return opts.responseStyle === "data" ? emptyData : {
|
|
689
|
-
data: emptyData,
|
|
690
|
-
...result
|
|
691
|
-
};
|
|
692
|
-
}
|
|
693
|
-
let data;
|
|
694
|
-
switch (parseAs) {
|
|
695
|
-
case "arrayBuffer":
|
|
696
|
-
case "blob":
|
|
697
|
-
case "formData":
|
|
698
|
-
case "text":
|
|
699
|
-
data = await response[parseAs]();
|
|
700
|
-
break;
|
|
701
|
-
case "json": {
|
|
702
|
-
const text = await response.text();
|
|
703
|
-
data = text ? JSON.parse(text) : {};
|
|
704
|
-
break;
|
|
705
|
-
}
|
|
706
|
-
case "stream":
|
|
707
|
-
return opts.responseStyle === "data" ? response.body : {
|
|
708
|
-
data: response.body,
|
|
709
|
-
...result
|
|
710
|
-
};
|
|
711
|
-
}
|
|
712
|
-
if (parseAs === "json") {
|
|
713
|
-
if (opts.responseValidator) {
|
|
714
|
-
await opts.responseValidator(data);
|
|
715
|
-
}
|
|
716
|
-
if (opts.responseTransformer) {
|
|
717
|
-
data = await opts.responseTransformer(data);
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
return opts.responseStyle === "data" ? data : {
|
|
721
|
-
data,
|
|
722
|
-
...result
|
|
723
|
-
};
|
|
724
|
-
}
|
|
725
|
-
const textError = await response.text();
|
|
726
|
-
let jsonError;
|
|
727
|
-
try {
|
|
728
|
-
jsonError = JSON.parse(textError);
|
|
729
|
-
} catch {
|
|
730
|
-
}
|
|
731
|
-
throw jsonError ?? textError;
|
|
732
|
-
} catch (error) {
|
|
733
|
-
let finalError = error;
|
|
734
|
-
for (const fn of interceptors.error.fns) {
|
|
735
|
-
if (fn) {
|
|
736
|
-
finalError = await fn(
|
|
737
|
-
finalError,
|
|
738
|
-
response,
|
|
739
|
-
request2,
|
|
740
|
-
options
|
|
741
|
-
);
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
finalError = finalError || {};
|
|
745
|
-
if (throwOnError) {
|
|
746
|
-
throw finalError;
|
|
747
|
-
}
|
|
748
|
-
return responseStyle === "data" ? void 0 : {
|
|
749
|
-
error: finalError,
|
|
750
|
-
request: request2,
|
|
751
|
-
response
|
|
752
|
-
};
|
|
753
|
-
}
|
|
754
|
-
};
|
|
755
|
-
const makeMethodFn = (method) => (options) => request({ ...options, method });
|
|
756
|
-
const makeSseFn = (method) => async (options) => {
|
|
757
|
-
const { opts, url } = await beforeRequest(options);
|
|
758
|
-
return createSseClient({
|
|
759
|
-
...opts,
|
|
760
|
-
body: opts.body,
|
|
761
|
-
method,
|
|
762
|
-
onRequest: async (url2, init) => {
|
|
763
|
-
let request2 = new Request(url2, init);
|
|
764
|
-
for (const fn of interceptors.request.fns) {
|
|
765
|
-
if (fn) {
|
|
766
|
-
request2 = await fn(request2, opts);
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
return request2;
|
|
770
|
-
},
|
|
771
|
-
serializedBody: getValidRequestBody(opts),
|
|
772
|
-
url
|
|
773
|
-
});
|
|
774
|
-
};
|
|
775
|
-
const _buildUrl = (options) => buildUrl({ ..._config, ...options });
|
|
776
|
-
return {
|
|
777
|
-
buildUrl: _buildUrl,
|
|
778
|
-
connect: makeMethodFn("CONNECT"),
|
|
779
|
-
delete: makeMethodFn("DELETE"),
|
|
780
|
-
get: makeMethodFn("GET"),
|
|
781
|
-
getConfig,
|
|
782
|
-
head: makeMethodFn("HEAD"),
|
|
783
|
-
interceptors,
|
|
784
|
-
options: makeMethodFn("OPTIONS"),
|
|
785
|
-
patch: makeMethodFn("PATCH"),
|
|
786
|
-
post: makeMethodFn("POST"),
|
|
787
|
-
put: makeMethodFn("PUT"),
|
|
788
|
-
request,
|
|
789
|
-
setConfig,
|
|
790
|
-
sse: {
|
|
791
|
-
connect: makeSseFn("CONNECT"),
|
|
792
|
-
delete: makeSseFn("DELETE"),
|
|
793
|
-
get: makeSseFn("GET"),
|
|
794
|
-
head: makeSseFn("HEAD"),
|
|
795
|
-
options: makeSseFn("OPTIONS"),
|
|
796
|
-
patch: makeSseFn("PATCH"),
|
|
797
|
-
post: makeSseFn("POST"),
|
|
798
|
-
put: makeSseFn("PUT"),
|
|
799
|
-
trace: makeSseFn("TRACE")
|
|
800
|
-
},
|
|
801
|
-
trace: makeMethodFn("TRACE")
|
|
802
|
-
};
|
|
803
|
-
};
|
|
804
|
-
|
|
805
|
-
// src/region.ts
|
|
806
|
-
var REGION_PATTERN = /^[a-z]{2}[0-9]+$/;
|
|
807
|
-
function regionFromApiKey(apiKey) {
|
|
808
|
-
const [prefix, region, token] = apiKey.split("_");
|
|
809
|
-
if (prefix !== "bk" || !region || !token) return void 0;
|
|
810
|
-
return REGION_PATTERN.test(region) ? region : void 0;
|
|
811
|
-
}
|
|
812
|
-
function baseUrlForRegion(region) {
|
|
813
|
-
return `https://${region}.platform.bird.com`;
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
// src/errors.ts
|
|
817
|
-
var BirdError = class extends Error {
|
|
818
|
-
constructor(message) {
|
|
819
|
-
super(message);
|
|
820
|
-
this.name = "BirdError";
|
|
821
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
822
|
-
}
|
|
823
|
-
};
|
|
824
|
-
var BirdConnectionError = class extends BirdError {
|
|
825
|
-
constructor(message) {
|
|
826
|
-
super(message);
|
|
827
|
-
this.name = "BirdConnectionError";
|
|
828
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
829
|
-
}
|
|
830
|
-
};
|
|
831
|
-
var BirdTimeoutError = class extends BirdError {
|
|
832
|
-
timeoutMs;
|
|
833
|
-
constructor(message, timeoutMs) {
|
|
834
|
-
super(message);
|
|
835
|
-
this.name = "BirdTimeoutError";
|
|
836
|
-
this.timeoutMs = timeoutMs;
|
|
837
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
838
|
-
}
|
|
839
|
-
};
|
|
840
|
-
var BirdWebhookVerificationError = class extends BirdError {
|
|
841
|
-
constructor(message) {
|
|
842
|
-
super(message);
|
|
843
|
-
this.name = "BirdWebhookVerificationError";
|
|
844
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
845
|
-
}
|
|
846
|
-
};
|
|
847
|
-
var BirdAPIError = class extends BirdError {
|
|
848
|
-
statusCode;
|
|
849
|
-
code;
|
|
850
|
-
type;
|
|
851
|
-
errorName;
|
|
852
|
-
docUrl;
|
|
853
|
-
requestId;
|
|
854
|
-
param;
|
|
855
|
-
vendorCode;
|
|
856
|
-
remediation;
|
|
857
|
-
next;
|
|
858
|
-
constructor(fields) {
|
|
859
|
-
super(fields.message);
|
|
860
|
-
this.name = "BirdAPIError";
|
|
861
|
-
this.statusCode = fields.statusCode;
|
|
862
|
-
this.code = fields.code;
|
|
863
|
-
this.type = fields.type;
|
|
864
|
-
this.errorName = fields.errorName;
|
|
865
|
-
this.docUrl = fields.docUrl;
|
|
866
|
-
this.requestId = fields.requestId;
|
|
867
|
-
this.param = fields.param;
|
|
868
|
-
this.vendorCode = fields.vendorCode;
|
|
869
|
-
this.remediation = fields.remediation;
|
|
870
|
-
this.next = fields.next;
|
|
871
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
872
|
-
}
|
|
873
|
-
};
|
|
874
|
-
var BirdAuthError = class extends BirdAPIError {
|
|
875
|
-
constructor(fields) {
|
|
876
|
-
super(fields);
|
|
877
|
-
this.name = "BirdAuthError";
|
|
878
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
879
|
-
}
|
|
880
|
-
};
|
|
881
|
-
var BirdPermissionError = class extends BirdAPIError {
|
|
882
|
-
constructor(fields) {
|
|
883
|
-
super(fields);
|
|
884
|
-
this.name = "BirdPermissionError";
|
|
885
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
886
|
-
}
|
|
887
|
-
};
|
|
888
|
-
var BirdNotFoundError = class extends BirdAPIError {
|
|
889
|
-
constructor(fields) {
|
|
890
|
-
super(fields);
|
|
891
|
-
this.name = "BirdNotFoundError";
|
|
892
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
893
|
-
}
|
|
894
|
-
};
|
|
895
|
-
var BirdConflictError = class extends BirdAPIError {
|
|
896
|
-
constructor(fields) {
|
|
897
|
-
super(fields);
|
|
898
|
-
this.name = "BirdConflictError";
|
|
899
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
900
|
-
}
|
|
901
|
-
};
|
|
902
|
-
var BirdBadRequestError = class extends BirdAPIError {
|
|
903
|
-
constructor(fields) {
|
|
904
|
-
super(fields);
|
|
905
|
-
this.name = "BirdBadRequestError";
|
|
906
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
907
|
-
}
|
|
908
|
-
};
|
|
909
|
-
var BirdBillingError = class extends BirdAPIError {
|
|
910
|
-
constructor(fields) {
|
|
911
|
-
super(fields);
|
|
912
|
-
this.name = "BirdBillingError";
|
|
913
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
914
|
-
}
|
|
915
|
-
};
|
|
916
|
-
var BirdPreconditionError = class extends BirdAPIError {
|
|
917
|
-
constructor(fields) {
|
|
918
|
-
super(fields);
|
|
919
|
-
this.name = "BirdPreconditionError";
|
|
920
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
921
|
-
}
|
|
922
|
-
};
|
|
923
|
-
var BirdPayloadTooLargeError = class extends BirdAPIError {
|
|
924
|
-
constructor(fields) {
|
|
925
|
-
super(fields);
|
|
926
|
-
this.name = "BirdPayloadTooLargeError";
|
|
927
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
928
|
-
}
|
|
929
|
-
};
|
|
930
|
-
var BirdInternalError = class extends BirdAPIError {
|
|
931
|
-
constructor(fields) {
|
|
932
|
-
super(fields);
|
|
933
|
-
this.name = "BirdInternalError";
|
|
934
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
935
|
-
}
|
|
936
|
-
};
|
|
937
|
-
var BirdNotImplementedError = class extends BirdAPIError {
|
|
938
|
-
constructor(fields) {
|
|
939
|
-
super(fields);
|
|
940
|
-
this.name = "BirdNotImplementedError";
|
|
941
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
942
|
-
}
|
|
943
|
-
};
|
|
944
|
-
var BirdMisdirectedError = class extends BirdAPIError {
|
|
945
|
-
constructor(fields) {
|
|
946
|
-
super(fields);
|
|
947
|
-
this.name = "BirdMisdirectedError";
|
|
948
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
949
|
-
}
|
|
950
|
-
};
|
|
951
|
-
var BirdServiceUnavailableError = class extends BirdAPIError {
|
|
952
|
-
constructor(fields) {
|
|
953
|
-
super(fields);
|
|
954
|
-
this.name = "BirdServiceUnavailableError";
|
|
955
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
956
|
-
}
|
|
957
|
-
};
|
|
958
|
-
var BirdValidationError = class extends BirdAPIError {
|
|
959
|
-
details;
|
|
960
|
-
constructor(fields) {
|
|
961
|
-
super(fields);
|
|
962
|
-
this.name = "BirdValidationError";
|
|
963
|
-
this.details = fields.details;
|
|
964
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
965
|
-
}
|
|
966
|
-
};
|
|
967
|
-
var BirdRateLimitError = class extends BirdAPIError {
|
|
968
|
-
retryAfter;
|
|
969
|
-
constructor(fields) {
|
|
970
|
-
super(fields);
|
|
971
|
-
this.name = "BirdRateLimitError";
|
|
972
|
-
this.retryAfter = fields.retryAfter;
|
|
973
|
-
Object.setPrototypeOf(this, new.target.prototype);
|
|
974
|
-
}
|
|
975
|
-
};
|
|
976
|
-
function parseRetryAfter(headers) {
|
|
977
|
-
const header = headers?.get("Retry-After");
|
|
978
|
-
if (!header) return void 0;
|
|
979
|
-
const seconds = Number(header);
|
|
980
|
-
const value = Number.isFinite(seconds) ? seconds : (Date.parse(header) - Date.now()) / 1e3;
|
|
981
|
-
return Number.isFinite(value) && value >= 0 ? Math.round(value) : void 0;
|
|
982
|
-
}
|
|
983
|
-
function inferType(status) {
|
|
984
|
-
switch (status) {
|
|
985
|
-
case 400:
|
|
986
|
-
return "bad_request_error";
|
|
987
|
-
case 401:
|
|
988
|
-
return "auth_error";
|
|
989
|
-
case 402:
|
|
990
|
-
return "billing_error";
|
|
991
|
-
case 403:
|
|
992
|
-
return "permission_error";
|
|
993
|
-
case 404:
|
|
994
|
-
return "not_found_error";
|
|
995
|
-
case 409:
|
|
996
|
-
return "conflict_error";
|
|
997
|
-
case 412:
|
|
998
|
-
case 428:
|
|
999
|
-
return "precondition_error";
|
|
1000
|
-
case 413:
|
|
1001
|
-
return "payload_too_large_error";
|
|
1002
|
-
case 421:
|
|
1003
|
-
return "misdirected_error";
|
|
1004
|
-
case 422:
|
|
1005
|
-
return "validation_error";
|
|
1006
|
-
case 429:
|
|
1007
|
-
return "rate_limit_error";
|
|
1008
|
-
case 501:
|
|
1009
|
-
return "not_implemented_error";
|
|
1010
|
-
case 503:
|
|
1011
|
-
return "service_unavailable_error";
|
|
1012
|
-
default:
|
|
1013
|
-
return status >= 500 ? "internal_error" : "bad_request_error";
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
function mapResponseToError(status, body, headers) {
|
|
1017
|
-
const raw = body ?? {};
|
|
1018
|
-
const b = raw.error ?? raw ?? {};
|
|
1019
|
-
const fields = {
|
|
1020
|
-
statusCode: status,
|
|
1021
|
-
code: b.code ?? "unknown",
|
|
1022
|
-
type: b.type ?? inferType(status),
|
|
1023
|
-
errorName: b.name ?? "",
|
|
1024
|
-
message: b.message ?? `Request failed with status ${status}`,
|
|
1025
|
-
docUrl: b.doc_url ?? "",
|
|
1026
|
-
requestId: b.request_id ?? headers?.get("X-Request-Id") ?? "",
|
|
1027
|
-
param: b.param,
|
|
1028
|
-
vendorCode: b.vendor_code,
|
|
1029
|
-
remediation: b.remediation,
|
|
1030
|
-
next: b.next ?? []
|
|
1031
|
-
// normalize a null/absent wire `next` to [] so callers can always iterate
|
|
1032
|
-
};
|
|
1033
|
-
switch (fields.type) {
|
|
1034
|
-
case "auth_error":
|
|
1035
|
-
return new BirdAuthError(fields);
|
|
1036
|
-
case "permission_error":
|
|
1037
|
-
return new BirdPermissionError(fields);
|
|
1038
|
-
case "not_found_error":
|
|
1039
|
-
return new BirdNotFoundError(fields);
|
|
1040
|
-
case "conflict_error":
|
|
1041
|
-
return new BirdConflictError(fields);
|
|
1042
|
-
case "bad_request_error":
|
|
1043
|
-
return new BirdBadRequestError(fields);
|
|
1044
|
-
case "billing_error":
|
|
1045
|
-
return new BirdBillingError(fields);
|
|
1046
|
-
case "precondition_error":
|
|
1047
|
-
return new BirdPreconditionError(fields);
|
|
1048
|
-
case "payload_too_large_error":
|
|
1049
|
-
return new BirdPayloadTooLargeError(fields);
|
|
1050
|
-
case "internal_error":
|
|
1051
|
-
return new BirdInternalError(fields);
|
|
1052
|
-
case "not_implemented_error":
|
|
1053
|
-
return new BirdNotImplementedError(fields);
|
|
1054
|
-
case "misdirected_error":
|
|
1055
|
-
return new BirdMisdirectedError(fields);
|
|
1056
|
-
case "service_unavailable_error":
|
|
1057
|
-
return new BirdServiceUnavailableError(fields);
|
|
1058
|
-
case "rate_limit_error":
|
|
1059
|
-
return new BirdRateLimitError({
|
|
1060
|
-
...fields,
|
|
1061
|
-
retryAfter: parseRetryAfter(headers)
|
|
1062
|
-
});
|
|
1063
|
-
case "validation_error":
|
|
1064
|
-
return new BirdValidationError({ ...fields, details: b.details ?? [] });
|
|
1065
|
-
default:
|
|
1066
|
-
return new BirdAPIError(fields);
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1069
|
-
|
|
1070
|
-
// src/core/http.ts
|
|
1071
|
-
var BACKOFF_BASE_MS = 500;
|
|
1072
|
-
var BACKOFF_CAP_MS = 8e3;
|
|
1073
|
-
var RETRY_AFTER_CAP_MS = 6e4;
|
|
1074
|
-
var BirdHTTPClient = class {
|
|
1075
|
-
constructor(defaults) {
|
|
1076
|
-
this.defaults = defaults;
|
|
1077
|
-
}
|
|
1078
|
-
defaults;
|
|
1079
|
-
/**
|
|
1080
|
-
* Run a generated hey-api SDK call through the request lifecycle.
|
|
1081
|
-
*
|
|
1082
|
-
* @param call Invokes the SDK function; receives the per-attempt signal and
|
|
1083
|
-
* the idempotency key to set as a header.
|
|
1084
|
-
* @returns the parsed body plus transport metadata.
|
|
1085
|
-
* @throws a `BirdError` subclass on terminal failure; the native
|
|
1086
|
-
* `AbortError` if the caller's signal aborts.
|
|
1087
|
-
*/
|
|
1088
|
-
async request(call, options) {
|
|
1089
|
-
const maxRetries = options.maxRetries ?? this.defaults.maxRetries;
|
|
1090
|
-
const timeout = options.timeout ?? this.defaults.timeout;
|
|
1091
|
-
const idempotencyKey = options.idempotencyKey ?? (isMutation(options.method) ? crypto.randomUUID() : void 0);
|
|
1092
|
-
for (let attempt = 0; ; attempt++) {
|
|
1093
|
-
throwIfAborted(options.signal);
|
|
1094
|
-
const retryOrThrow = async (terminal) => {
|
|
1095
|
-
if (attempt >= maxRetries) throw terminal();
|
|
1096
|
-
await sleep(backoffDelay(attempt), options.signal);
|
|
1097
|
-
};
|
|
1098
|
-
const timeoutSignal = AbortSignal.timeout(timeout);
|
|
1099
|
-
const signal = options.signal ? AbortSignal.any([options.signal, timeoutSignal]) : timeoutSignal;
|
|
1100
|
-
let outcome;
|
|
1101
|
-
try {
|
|
1102
|
-
outcome = await call({ signal, idempotencyKey });
|
|
1103
|
-
} catch (err) {
|
|
1104
|
-
throwIfAborted(options.signal);
|
|
1105
|
-
await retryOrThrow(
|
|
1106
|
-
() => timeoutSignal.aborted ? new BirdTimeoutError(`Request timed out after ${timeout}ms`, timeout) : new BirdConnectionError(errorMessage(err))
|
|
1107
|
-
);
|
|
1108
|
-
continue;
|
|
1109
|
-
}
|
|
1110
|
-
const res = outcome.response;
|
|
1111
|
-
if (!res) {
|
|
1112
|
-
await retryOrThrow(() => new BirdConnectionError("No response received from the server"));
|
|
1113
|
-
continue;
|
|
1114
|
-
}
|
|
1115
|
-
if (res.ok) {
|
|
1116
|
-
return { data: outcome.data, response: toBirdResponse(res) };
|
|
1117
|
-
}
|
|
1118
|
-
if (!isRetryableStatus(res.status) || attempt >= maxRetries) {
|
|
1119
|
-
throw mapResponseToError(res.status, outcome.error, res.headers);
|
|
1120
|
-
}
|
|
1121
|
-
await sleep(retryDelay(attempt, res.headers), options.signal);
|
|
1122
|
-
}
|
|
1123
|
-
}
|
|
1124
|
-
};
|
|
1125
|
-
function isMutation(method) {
|
|
1126
|
-
return ["POST", "PATCH", "DELETE"].includes(method.toUpperCase());
|
|
1127
|
-
}
|
|
1128
|
-
function isRetryableStatus(status) {
|
|
1129
|
-
return [408, 429, 500, 502, 503, 504].includes(status);
|
|
1130
|
-
}
|
|
1131
|
-
function backoffDelay(attempt) {
|
|
1132
|
-
const ceiling = Math.min(BACKOFF_CAP_MS, BACKOFF_BASE_MS * 2 ** attempt);
|
|
1133
|
-
return Math.random() * ceiling;
|
|
1134
|
-
}
|
|
1135
|
-
function retryDelay(attempt, headers) {
|
|
1136
|
-
const seconds = parseRetryAfter(headers);
|
|
1137
|
-
return seconds === void 0 ? backoffDelay(attempt) : Math.min(seconds * 1e3, RETRY_AFTER_CAP_MS);
|
|
1138
|
-
}
|
|
1139
|
-
function toBirdResponse(res) {
|
|
1140
|
-
return {
|
|
1141
|
-
status: res.status,
|
|
1142
|
-
headers: res.headers,
|
|
1143
|
-
requestId: res.headers.get("X-Request-Id") ?? ""
|
|
1144
|
-
};
|
|
1145
|
-
}
|
|
1146
|
-
function abortReason(signal) {
|
|
1147
|
-
return signal?.reason ?? new DOMException("Aborted", "AbortError");
|
|
1148
|
-
}
|
|
1149
|
-
function throwIfAborted(signal) {
|
|
1150
|
-
if (signal?.aborted) throw abortReason(signal);
|
|
1151
|
-
}
|
|
1152
|
-
function sleep(ms, signal) {
|
|
1153
|
-
return new Promise((resolve, reject) => {
|
|
1154
|
-
if (signal?.aborted) {
|
|
1155
|
-
reject(abortReason(signal));
|
|
1156
|
-
return;
|
|
1157
|
-
}
|
|
1158
|
-
const timer = setTimeout(() => {
|
|
1159
|
-
signal?.removeEventListener("abort", onAbort);
|
|
1160
|
-
resolve();
|
|
1161
|
-
}, ms);
|
|
1162
|
-
const onAbort = () => {
|
|
1163
|
-
clearTimeout(timer);
|
|
1164
|
-
reject(abortReason(signal));
|
|
1165
|
-
};
|
|
1166
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
1167
|
-
});
|
|
1168
|
-
}
|
|
1169
|
-
function errorMessage(err) {
|
|
1170
|
-
if (err instanceof Error) return err.message;
|
|
1171
|
-
return String(err);
|
|
1172
|
-
}
|
|
1173
|
-
|
|
1174
|
-
// src/core/result.ts
|
|
1175
|
-
function basePromise(inner) {
|
|
1176
|
-
const promise = inner.then((r) => r.data);
|
|
1177
|
-
void promise.catch(() => {
|
|
1178
|
-
});
|
|
1179
|
-
promise.withResponse = () => inner;
|
|
1180
|
-
promise.safe = () => toSafe(inner);
|
|
1181
|
-
return promise;
|
|
1182
|
-
}
|
|
1183
|
-
function apiPromise(inner) {
|
|
1184
|
-
return basePromise(inner);
|
|
1185
|
-
}
|
|
1186
|
-
function paginate(fetchPage) {
|
|
1187
|
-
const first = fetchPage();
|
|
1188
|
-
const promise = basePromise(first);
|
|
1189
|
-
promise[Symbol.asyncIterator] = async function* () {
|
|
1190
|
-
let result = await first;
|
|
1191
|
-
for (; ; ) {
|
|
1192
|
-
for (const item of result.data.data) yield item;
|
|
1193
|
-
if (result.data.next_cursor == null) return;
|
|
1194
|
-
result = await fetchPage(result.data.next_cursor);
|
|
1195
|
-
}
|
|
1196
|
-
};
|
|
1197
|
-
return promise;
|
|
1198
|
-
}
|
|
1199
|
-
function toSafe(inner) {
|
|
1200
|
-
return inner.then(
|
|
1201
|
-
({ data, response }) => ({ data, error: null, response }),
|
|
1202
|
-
(error) => {
|
|
1203
|
-
if (error instanceof BirdError) return { data: null, error, response: null };
|
|
1204
|
-
throw error;
|
|
1205
|
-
}
|
|
1206
|
-
);
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
// src/generated/client.gen.ts
|
|
1210
|
-
var client = createClient(createConfig());
|
|
1211
|
-
|
|
1212
|
-
// src/generated/sdk.gen.ts
|
|
1213
|
-
var listEmailMessages = (options) => (options?.client ?? client).get({
|
|
1214
|
-
security: [
|
|
1215
|
-
{ scheme: "bearer", type: "http" },
|
|
1216
|
-
{
|
|
1217
|
-
in: "cookie",
|
|
1218
|
-
name: "bird_session",
|
|
1219
|
-
type: "apiKey"
|
|
1220
|
-
}
|
|
1221
|
-
],
|
|
1222
|
-
url: "/v1/email/messages",
|
|
1223
|
-
...options
|
|
1224
|
-
});
|
|
1225
|
-
var createEmailMessage = (options) => (options.client ?? client).post({
|
|
1226
|
-
security: [
|
|
1227
|
-
{ scheme: "bearer", type: "http" },
|
|
1228
|
-
{
|
|
1229
|
-
in: "cookie",
|
|
1230
|
-
name: "bird_session",
|
|
1231
|
-
type: "apiKey"
|
|
1232
|
-
}
|
|
1233
|
-
],
|
|
1234
|
-
url: "/v1/email/messages",
|
|
1235
|
-
...options,
|
|
1236
|
-
headers: {
|
|
1237
|
-
"Content-Type": "application/json",
|
|
1238
|
-
...options.headers
|
|
1239
|
-
}
|
|
1240
|
-
});
|
|
1241
|
-
var createEmailMessageBatch = (options) => (options.client ?? client).post({
|
|
1242
|
-
security: [
|
|
1243
|
-
{ scheme: "bearer", type: "http" },
|
|
1244
|
-
{
|
|
1245
|
-
in: "cookie",
|
|
1246
|
-
name: "bird_session",
|
|
1247
|
-
type: "apiKey"
|
|
1248
|
-
}
|
|
1249
|
-
],
|
|
1250
|
-
url: "/v1/email/batches",
|
|
1251
|
-
...options,
|
|
1252
|
-
headers: {
|
|
1253
|
-
"Content-Type": "application/json",
|
|
1254
|
-
...options.headers
|
|
1255
|
-
}
|
|
1256
|
-
});
|
|
1257
|
-
var getEmailMessage = (options) => (options.client ?? client).get({
|
|
1258
|
-
security: [
|
|
1259
|
-
{ scheme: "bearer", type: "http" },
|
|
1260
|
-
{
|
|
1261
|
-
in: "cookie",
|
|
1262
|
-
name: "bird_session",
|
|
1263
|
-
type: "apiKey"
|
|
1264
|
-
}
|
|
1265
|
-
],
|
|
1266
|
-
url: "/v1/email/messages/{message_id}",
|
|
1267
|
-
...options
|
|
1268
|
-
});
|
|
1269
|
-
var listSmsMessages = (options) => (options?.client ?? client).get({
|
|
1270
|
-
security: [
|
|
1271
|
-
{ scheme: "bearer", type: "http" },
|
|
1272
|
-
{
|
|
1273
|
-
in: "cookie",
|
|
1274
|
-
name: "bird_session",
|
|
1275
|
-
type: "apiKey"
|
|
1276
|
-
}
|
|
1277
|
-
],
|
|
1278
|
-
url: "/v1/sms/messages",
|
|
1279
|
-
...options
|
|
1280
|
-
});
|
|
1281
|
-
var createSmsMessage = (options) => (options.client ?? client).post({
|
|
1282
|
-
security: [
|
|
1283
|
-
{ scheme: "bearer", type: "http" },
|
|
1284
|
-
{
|
|
1285
|
-
in: "cookie",
|
|
1286
|
-
name: "bird_session",
|
|
1287
|
-
type: "apiKey"
|
|
1288
|
-
}
|
|
1289
|
-
],
|
|
1290
|
-
url: "/v1/sms/messages",
|
|
1291
|
-
...options,
|
|
1292
|
-
headers: {
|
|
1293
|
-
"Content-Type": "application/json",
|
|
1294
|
-
...options.headers
|
|
1295
|
-
}
|
|
1296
|
-
});
|
|
1297
|
-
var createSmsMessageBatch = (options) => (options.client ?? client).post({
|
|
1298
|
-
security: [
|
|
1299
|
-
{ scheme: "bearer", type: "http" },
|
|
1300
|
-
{
|
|
1301
|
-
in: "cookie",
|
|
1302
|
-
name: "bird_session",
|
|
1303
|
-
type: "apiKey"
|
|
1304
|
-
}
|
|
1305
|
-
],
|
|
1306
|
-
url: "/v1/sms/batches",
|
|
1307
|
-
...options,
|
|
1308
|
-
headers: {
|
|
1309
|
-
"Content-Type": "application/json",
|
|
1310
|
-
...options.headers
|
|
1311
|
-
}
|
|
1312
|
-
});
|
|
1313
|
-
var getSmsMessage = (options) => (options.client ?? client).get({
|
|
1314
|
-
security: [
|
|
1315
|
-
{ scheme: "bearer", type: "http" },
|
|
1316
|
-
{
|
|
1317
|
-
in: "cookie",
|
|
1318
|
-
name: "bird_session",
|
|
1319
|
-
type: "apiKey"
|
|
1320
|
-
}
|
|
1321
|
-
],
|
|
1322
|
-
url: "/v1/sms/messages/{message_id}",
|
|
1323
|
-
...options
|
|
1324
|
-
});
|
|
1325
|
-
var listSmsTemplates = (options) => (options?.client ?? client).get({
|
|
1326
|
-
security: [
|
|
1327
|
-
{ scheme: "bearer", type: "http" },
|
|
1328
|
-
{
|
|
1329
|
-
in: "cookie",
|
|
1330
|
-
name: "bird_session",
|
|
1331
|
-
type: "apiKey"
|
|
1332
|
-
}
|
|
1333
|
-
],
|
|
1334
|
-
url: "/v1/sms/templates",
|
|
1335
|
-
...options
|
|
1336
|
-
});
|
|
1337
|
-
var getSmsTemplate = (options) => (options.client ?? client).get({
|
|
1338
|
-
security: [
|
|
1339
|
-
{ scheme: "bearer", type: "http" },
|
|
1340
|
-
{
|
|
1341
|
-
in: "cookie",
|
|
1342
|
-
name: "bird_session",
|
|
1343
|
-
type: "apiKey"
|
|
1344
|
-
}
|
|
1345
|
-
],
|
|
1346
|
-
url: "/v1/sms/templates/{template_ref}",
|
|
1347
|
-
...options
|
|
1348
|
-
});
|
|
1349
|
-
var listEmailTemplates = (options) => (options?.client ?? client).get({
|
|
1350
|
-
security: [
|
|
1351
|
-
{ scheme: "bearer", type: "http" },
|
|
1352
|
-
{
|
|
1353
|
-
in: "cookie",
|
|
1354
|
-
name: "bird_session",
|
|
1355
|
-
type: "apiKey"
|
|
1356
|
-
}
|
|
1357
|
-
],
|
|
1358
|
-
url: "/v1/email/templates",
|
|
1359
|
-
...options
|
|
1360
|
-
});
|
|
1361
|
-
var createEmailTemplate = (options) => (options.client ?? client).post({
|
|
1362
|
-
security: [
|
|
1363
|
-
{ scheme: "bearer", type: "http" },
|
|
1364
|
-
{
|
|
1365
|
-
in: "cookie",
|
|
1366
|
-
name: "bird_session",
|
|
1367
|
-
type: "apiKey"
|
|
1368
|
-
}
|
|
1369
|
-
],
|
|
1370
|
-
url: "/v1/email/templates",
|
|
1371
|
-
...options,
|
|
1372
|
-
headers: {
|
|
1373
|
-
"Content-Type": "application/json",
|
|
1374
|
-
...options.headers
|
|
1375
|
-
}
|
|
1376
|
-
});
|
|
1377
|
-
var deleteEmailTemplate = (options) => (options.client ?? client).delete({
|
|
1378
|
-
security: [
|
|
1379
|
-
{ scheme: "bearer", type: "http" },
|
|
1380
|
-
{
|
|
1381
|
-
in: "cookie",
|
|
1382
|
-
name: "bird_session",
|
|
1383
|
-
type: "apiKey"
|
|
1384
|
-
}
|
|
1385
|
-
],
|
|
1386
|
-
url: "/v1/email/templates/{template_id}",
|
|
1387
|
-
...options
|
|
1388
|
-
});
|
|
1389
|
-
var getEmailTemplate = (options) => (options.client ?? client).get({
|
|
1390
|
-
security: [
|
|
1391
|
-
{ scheme: "bearer", type: "http" },
|
|
1392
|
-
{
|
|
1393
|
-
in: "cookie",
|
|
1394
|
-
name: "bird_session",
|
|
1395
|
-
type: "apiKey"
|
|
1396
|
-
}
|
|
1397
|
-
],
|
|
1398
|
-
url: "/v1/email/templates/{template_id}",
|
|
1399
|
-
...options
|
|
1400
|
-
});
|
|
1401
|
-
var updateEmailTemplate = (options) => (options.client ?? client).patch({
|
|
1402
|
-
security: [
|
|
1403
|
-
{ scheme: "bearer", type: "http" },
|
|
1404
|
-
{
|
|
1405
|
-
in: "cookie",
|
|
1406
|
-
name: "bird_session",
|
|
1407
|
-
type: "apiKey"
|
|
1408
|
-
}
|
|
1409
|
-
],
|
|
1410
|
-
url: "/v1/email/templates/{template_id}",
|
|
1411
|
-
...options,
|
|
1412
|
-
headers: {
|
|
1413
|
-
"Content-Type": "application/json",
|
|
1414
|
-
...options.headers
|
|
1415
|
-
}
|
|
1416
|
-
});
|
|
1417
|
-
var listEmailTemplateVersions = (options) => (options.client ?? client).get({
|
|
1418
|
-
security: [
|
|
1419
|
-
{ scheme: "bearer", type: "http" },
|
|
1420
|
-
{
|
|
1421
|
-
in: "cookie",
|
|
1422
|
-
name: "bird_session",
|
|
1423
|
-
type: "apiKey"
|
|
1424
|
-
}
|
|
1425
|
-
],
|
|
1426
|
-
url: "/v1/email/templates/{template_id}/versions",
|
|
1427
|
-
...options
|
|
1428
|
-
});
|
|
1429
|
-
var getEmailTemplateVersion = (options) => (options.client ?? client).get({
|
|
1430
|
-
security: [
|
|
1431
|
-
{ scheme: "bearer", type: "http" },
|
|
1432
|
-
{
|
|
1433
|
-
in: "cookie",
|
|
1434
|
-
name: "bird_session",
|
|
1435
|
-
type: "apiKey"
|
|
1436
|
-
}
|
|
1437
|
-
],
|
|
1438
|
-
url: "/v1/email/templates/{template_id}/versions/{version_id}",
|
|
1439
|
-
...options
|
|
1440
|
-
});
|
|
1441
|
-
var publishEmailTemplate = (options) => (options.client ?? client).post({
|
|
1442
|
-
security: [
|
|
1443
|
-
{ scheme: "bearer", type: "http" },
|
|
1444
|
-
{
|
|
1445
|
-
in: "cookie",
|
|
1446
|
-
name: "bird_session",
|
|
1447
|
-
type: "apiKey"
|
|
1448
|
-
}
|
|
1449
|
-
],
|
|
1450
|
-
url: "/v1/email/templates/{template_id}/publish",
|
|
1451
|
-
...options
|
|
1452
|
-
});
|
|
1453
|
-
|
|
1454
|
-
// src/resources/base.ts
|
|
1455
|
-
var Resource = class {
|
|
1456
|
-
constructor(core, client2) {
|
|
1457
|
-
this.core = core;
|
|
1458
|
-
this.client = client2;
|
|
1459
|
-
}
|
|
1460
|
-
core;
|
|
1461
|
-
client;
|
|
1462
|
-
/** Run a single typed call through the lifecycle. */
|
|
1463
|
-
call(method, options, invoke) {
|
|
1464
|
-
return apiPromise(
|
|
1465
|
-
this.core.request((ctx) => invoke(callContext(ctx, options)), lifecycle(method, options))
|
|
1466
|
-
);
|
|
1467
|
-
}
|
|
1468
|
-
/** Run a cursor-paginated list through the lifecycle (each page retried independently). */
|
|
1469
|
-
paginated(method, options, invoke) {
|
|
1470
|
-
return paginate(
|
|
1471
|
-
(cursor) => this.core.request(
|
|
1472
|
-
(ctx) => invoke(callContext(ctx, options), cursor),
|
|
1473
|
-
lifecycle(method, options)
|
|
1474
|
-
)
|
|
1475
|
-
);
|
|
1476
|
-
}
|
|
1477
|
-
};
|
|
1478
|
-
function callContext(ctx, options) {
|
|
1479
|
-
return { signal: ctx.signal, headers: mergeHeaders2(ctx.idempotencyKey, options?.headers) };
|
|
1480
|
-
}
|
|
1481
|
-
function lifecycle(method, options) {
|
|
1482
|
-
return {
|
|
1483
|
-
method,
|
|
1484
|
-
idempotencyKey: options?.idempotencyKey,
|
|
1485
|
-
signal: options?.signal,
|
|
1486
|
-
timeout: options?.timeout,
|
|
1487
|
-
maxRetries: options?.maxRetries
|
|
1488
|
-
};
|
|
1489
|
-
}
|
|
1490
|
-
function mergeHeaders2(idempotencyKey, extra) {
|
|
1491
|
-
return {
|
|
1492
|
-
...extra,
|
|
1493
|
-
...idempotencyKey ? { "Idempotency-Key": idempotencyKey } : {}
|
|
1494
|
-
};
|
|
1495
|
-
}
|
|
1496
|
-
|
|
1497
|
-
// src/resources/email.ts
|
|
1498
|
-
var EmailResource = class extends Resource {
|
|
1499
|
-
#defaults;
|
|
1500
|
-
constructor(core, client2, defaults) {
|
|
1501
|
-
super(core, client2);
|
|
1502
|
-
this.#defaults = defaults;
|
|
1503
|
-
}
|
|
1504
|
-
/**
|
|
1505
|
-
* Send an email message. Resolves once the message is accepted for delivery
|
|
1506
|
-
* (the API's 202). Throws on failure — a 422 (unverified sender, all
|
|
1507
|
-
* recipients suppressed, validation) is a `BirdValidationError`. Fields set as
|
|
1508
|
-
* channel defaults may be omitted (per-send value wins).
|
|
1509
|
-
*
|
|
1510
|
-
* @example Send a message
|
|
1511
|
-
* const msg = await bird.email.send({
|
|
1512
|
-
* from: { email: "onboarding@messagebird.dev", name: "Bird" },
|
|
1513
|
-
* to: ["delivered@messagebird.dev"],
|
|
1514
|
-
* subject: "Hello from Bird",
|
|
1515
|
-
* html: "<p>My first Bird email.</p>",
|
|
1516
|
-
* });
|
|
1517
|
-
* console.log(msg.id, msg.status); // "em_…", "accepted"
|
|
1518
|
-
*
|
|
1519
|
-
* @example A richer send — cc/bcc, reply-to, tags, metadata, click-tracking off, and an idempotency key (safe to retry; the server dedupes)
|
|
1520
|
-
* await bird.email.send(
|
|
1521
|
-
* {
|
|
1522
|
-
* from: "hello@acme.com",
|
|
1523
|
-
* to: ["a@example.com", "b@example.com"],
|
|
1524
|
-
* cc: ["manager@example.com"],
|
|
1525
|
-
* reply_to: ["support@acme.com"],
|
|
1526
|
-
* subject: "Your March invoice",
|
|
1527
|
-
* html: "<p>Attached.</p>",
|
|
1528
|
-
* tags: [{ name: "category", value: "billing" }],
|
|
1529
|
-
* metadata: { invoice_id: "inv_123" },
|
|
1530
|
-
* track_clicks: false,
|
|
1531
|
-
* },
|
|
1532
|
-
* { idempotencyKey: "invoice-march/cust_1" },
|
|
1533
|
-
* );
|
|
1534
|
-
*
|
|
1535
|
-
* @example Branch on the typed error hierarchy
|
|
1536
|
-
* import { BirdRateLimitError, BirdValidationError, BirdAPIError } from "@messagebird/sdk";
|
|
1537
|
-
*
|
|
1538
|
-
* try {
|
|
1539
|
-
* await bird.email.send({
|
|
1540
|
-
* from: { email: "onboarding@messagebird.dev", name: "Bird" },
|
|
1541
|
-
* to: ["delivered@messagebird.dev"],
|
|
1542
|
-
* subject: "Hello from Bird",
|
|
1543
|
-
* html: "<p>My first Bird email.</p>",
|
|
1544
|
-
* });
|
|
1545
|
-
* } catch (err) {
|
|
1546
|
-
* if (err instanceof BirdRateLimitError) console.log(`rate limited — retry in ${err.retryAfter}s`);
|
|
1547
|
-
* else if (err instanceof BirdValidationError) console.error(err.details);
|
|
1548
|
-
* else if (err instanceof BirdAPIError) console.error(err.code, err.requestId);
|
|
1549
|
-
* else throw err;
|
|
1550
|
-
* }
|
|
1551
|
-
*
|
|
1552
|
-
* @example Errors as values with `.safe()`
|
|
1553
|
-
* const { data, error } = await bird.email
|
|
1554
|
-
* .send({
|
|
1555
|
-
* from: { email: "onboarding@messagebird.dev", name: "Bird" },
|
|
1556
|
-
* to: ["delivered@messagebird.dev"],
|
|
1557
|
-
* subject: "Hello from Bird",
|
|
1558
|
-
* html: "<p>My first Bird email.</p>",
|
|
1559
|
-
* })
|
|
1560
|
-
* .safe();
|
|
1561
|
-
* if (error) console.error(error.message);
|
|
1562
|
-
* else console.log(data.id);
|
|
1563
|
-
*/
|
|
1564
|
-
send(params, options) {
|
|
1565
|
-
const body = { ...this.#defaults, ...params };
|
|
1566
|
-
return this.call(
|
|
1567
|
-
"POST",
|
|
1568
|
-
options,
|
|
1569
|
-
({ signal, headers }) => createEmailMessage({ client: this.client, body, headers, signal })
|
|
1570
|
-
);
|
|
1571
|
-
}
|
|
1572
|
-
/**
|
|
1573
|
-
* Send a batch of up to 100 independent email messages in one request. The
|
|
1574
|
-
* batch is validated as a unit — if any item fails validation (unverified
|
|
1575
|
-
* sender, all recipients suppressed, field-level errors) the whole batch is
|
|
1576
|
-
* rejected with a `BirdValidationError` and nothing is queued. Resolves with
|
|
1577
|
-
* one accepted item per submitted message, in submission order, once the batch
|
|
1578
|
-
* is accepted (the API's 202). Channel defaults are applied per item.
|
|
1579
|
-
*
|
|
1580
|
-
* @example Send a batch of messages
|
|
1581
|
-
* const batch = await bird.email.sendBatch([
|
|
1582
|
-
* {
|
|
1583
|
-
* from: { email: "onboarding@messagebird.dev", name: "Bird" },
|
|
1584
|
-
* to: ["alice@example.com"],
|
|
1585
|
-
* subject: "Your receipt",
|
|
1586
|
-
* html: "<p>Thanks, Alice.</p>",
|
|
1587
|
-
* },
|
|
1588
|
-
* {
|
|
1589
|
-
* from: { email: "onboarding@messagebird.dev", name: "Bird" },
|
|
1590
|
-
* to: ["bob@example.com"],
|
|
1591
|
-
* subject: "Your receipt",
|
|
1592
|
-
* html: "<p>Thanks, Bob.</p>",
|
|
1593
|
-
* },
|
|
1594
|
-
* ]);
|
|
1595
|
-
* for (const item of batch.data) console.log(item.id, item.status);
|
|
1596
|
-
*/
|
|
1597
|
-
sendBatch(params, options) {
|
|
1598
|
-
const body = params.map((item) => ({
|
|
1599
|
-
...this.#defaults,
|
|
1600
|
-
...item
|
|
1601
|
-
}));
|
|
1602
|
-
return this.call(
|
|
1603
|
-
"POST",
|
|
1604
|
-
options,
|
|
1605
|
-
({ signal, headers }) => createEmailMessageBatch({ client: this.client, body, headers, signal })
|
|
1606
|
-
);
|
|
1607
|
-
}
|
|
1608
|
-
/**
|
|
1609
|
-
* Fetch a message with aggregate delivery status.
|
|
1610
|
-
*
|
|
1611
|
-
* @example
|
|
1612
|
-
* const msg = await bird.email.get("em_abc123");
|
|
1613
|
-
* msg.status; // "accepted" | "processed" | "delivered" | "bounced" | …
|
|
1614
|
-
* msg.delivered_count;
|
|
1615
|
-
* msg.bounced_count;
|
|
1616
|
-
*/
|
|
1617
|
-
get(messageId, options) {
|
|
1618
|
-
return this.call(
|
|
1619
|
-
"GET",
|
|
1620
|
-
options,
|
|
1621
|
-
({ signal, headers }) => getEmailMessage({
|
|
1622
|
-
client: this.client,
|
|
1623
|
-
path: { message_id: messageId },
|
|
1624
|
-
headers,
|
|
1625
|
-
signal
|
|
1626
|
-
})
|
|
1627
|
-
);
|
|
1628
|
-
}
|
|
1629
|
-
/**
|
|
1630
|
-
* List messages, newest first. `await` resolves the first page; `for await`
|
|
1631
|
-
* walks every message across all pages.
|
|
1632
|
-
*
|
|
1633
|
-
* @example Iterate every message, or take one page
|
|
1634
|
-
* for await (const message of bird.email.list({ status: "bounced" })) {
|
|
1635
|
-
* console.log(message.id);
|
|
1636
|
-
* }
|
|
1637
|
-
* const page = await bird.email.list({ limit: 50 }); // page.data, page.next_cursor
|
|
1638
|
-
*/
|
|
1639
|
-
list(query, options) {
|
|
1640
|
-
return this.paginated(
|
|
1641
|
-
"GET",
|
|
1642
|
-
options,
|
|
1643
|
-
({ signal, headers }, cursor) => listEmailMessages({
|
|
1644
|
-
client: this.client,
|
|
1645
|
-
query: { ...query, starting_after: cursor ?? query?.starting_after },
|
|
1646
|
-
headers,
|
|
1647
|
-
signal
|
|
1648
|
-
})
|
|
1649
|
-
);
|
|
1650
|
-
}
|
|
1651
|
-
};
|
|
1652
|
-
|
|
1653
|
-
// src/resources/emailTemplates.ts
|
|
1654
|
-
var EmailTemplatesResource = class extends Resource {
|
|
1655
|
-
/**
|
|
1656
|
-
* Create a template and its initial editable draft. Pick the authoring format
|
|
1657
|
-
* with `source` (`liquid`, `handlebars`, or `html`); the name must be unique
|
|
1658
|
-
* in the workspace or the call throws a `BirdConflictError`.
|
|
1659
|
-
*
|
|
1660
|
-
* @example Create a template
|
|
1661
|
-
* const tpl = await bird.emailTemplates.create({
|
|
1662
|
-
* name: "Welcome",
|
|
1663
|
-
* category: "transactional",
|
|
1664
|
-
* source: "handlebars",
|
|
1665
|
-
* subject: "Welcome, {{ first_name }}!",
|
|
1666
|
-
* html: "<h1>Hi {{ first_name }}</h1>",
|
|
1667
|
-
* });
|
|
1668
|
-
* console.log(tpl.id, tpl.revision); // "emt_…", 0
|
|
1669
|
-
*/
|
|
1670
|
-
create(params, options) {
|
|
1671
|
-
return this.call(
|
|
1672
|
-
"POST",
|
|
1673
|
-
options,
|
|
1674
|
-
({ signal, headers }) => createEmailTemplate({
|
|
1675
|
-
client: this.client,
|
|
1676
|
-
body: params,
|
|
1677
|
-
headers,
|
|
1678
|
-
signal
|
|
1679
|
-
})
|
|
1680
|
-
);
|
|
1681
|
-
}
|
|
1682
|
-
/**
|
|
1683
|
-
* List the workspace's templates, newest first. `await` resolves the first
|
|
1684
|
-
* page; `for await` walks every template across all pages. Filter by
|
|
1685
|
-
* `category`, `source`, or a case-insensitive `name` prefix.
|
|
1686
|
-
*
|
|
1687
|
-
* @example Iterate every template, or take one page
|
|
1688
|
-
* for await (const tpl of bird.emailTemplates.list({ category: "transactional" })) {
|
|
1689
|
-
* console.log(tpl.id, tpl.name);
|
|
1690
|
-
* }
|
|
1691
|
-
* const page = await bird.emailTemplates.list({ limit: 50 }); // page.data, page.next_cursor
|
|
1692
|
-
*/
|
|
1693
|
-
list(query, options) {
|
|
1694
|
-
return this.paginated(
|
|
1695
|
-
"GET",
|
|
1696
|
-
options,
|
|
1697
|
-
({ signal, headers }, cursor) => listEmailTemplates({
|
|
1698
|
-
client: this.client,
|
|
1699
|
-
query: { ...query, starting_after: cursor ?? query?.starting_after },
|
|
1700
|
-
headers,
|
|
1701
|
-
signal
|
|
1702
|
-
})
|
|
1703
|
-
);
|
|
1704
|
-
}
|
|
1705
|
-
/**
|
|
1706
|
-
* Fetch a template with its current draft content (subject, HTML, text), the
|
|
1707
|
-
* draft `revision`, and its draft/published version ids.
|
|
1708
|
-
*
|
|
1709
|
-
* @example
|
|
1710
|
-
* const tpl = await bird.emailTemplates.get("emt_abc123");
|
|
1711
|
-
* tpl.subject;
|
|
1712
|
-
* tpl.published_version_id; // null until first publish
|
|
1713
|
-
*/
|
|
1714
|
-
get(templateId, options) {
|
|
1715
|
-
return this.call(
|
|
1716
|
-
"GET",
|
|
1717
|
-
options,
|
|
1718
|
-
({ signal, headers }) => getEmailTemplate({
|
|
1719
|
-
client: this.client,
|
|
1720
|
-
path: { template_id: templateId },
|
|
1721
|
-
headers,
|
|
1722
|
-
signal
|
|
1723
|
-
})
|
|
1724
|
-
);
|
|
1725
|
-
}
|
|
1726
|
-
/**
|
|
1727
|
-
* Update a template's metadata and draft content. Only the fields you send
|
|
1728
|
-
* change. Pass the draft `revision` you last read; if another edit landed
|
|
1729
|
-
* first the call throws a `BirdConflictError` — reload and retry.
|
|
1730
|
-
*
|
|
1731
|
-
* @example Edit the draft, guarded by the revision you read
|
|
1732
|
-
* const tpl = await bird.emailTemplates.get("emt_abc123");
|
|
1733
|
-
* const updated = await bird.emailTemplates.update("emt_abc123", {
|
|
1734
|
-
* revision: tpl.revision,
|
|
1735
|
-
* subject: "Welcome aboard, {{ first_name }}!",
|
|
1736
|
-
* });
|
|
1737
|
-
*/
|
|
1738
|
-
update(templateId, params, options) {
|
|
1739
|
-
return this.call(
|
|
1740
|
-
"PATCH",
|
|
1741
|
-
options,
|
|
1742
|
-
({ signal, headers }) => updateEmailTemplate({
|
|
1743
|
-
client: this.client,
|
|
1744
|
-
path: { template_id: templateId },
|
|
1745
|
-
body: params,
|
|
1746
|
-
headers,
|
|
1747
|
-
signal
|
|
1748
|
-
})
|
|
1749
|
-
);
|
|
1750
|
-
}
|
|
1751
|
-
/**
|
|
1752
|
-
* Delete a template and all its versions. The name becomes available for
|
|
1753
|
-
* reuse in the workspace.
|
|
1754
|
-
*
|
|
1755
|
-
* @example
|
|
1756
|
-
* await bird.emailTemplates.delete("emt_abc123");
|
|
1757
|
-
*/
|
|
1758
|
-
delete(templateId, options) {
|
|
1759
|
-
return this.call(
|
|
1760
|
-
"DELETE",
|
|
1761
|
-
options,
|
|
1762
|
-
({ signal, headers }) => deleteEmailTemplate({
|
|
1763
|
-
client: this.client,
|
|
1764
|
-
path: { template_id: templateId },
|
|
1765
|
-
headers,
|
|
1766
|
-
signal
|
|
1767
|
-
})
|
|
1768
|
-
);
|
|
1769
|
-
}
|
|
1770
|
-
/**
|
|
1771
|
-
* Publish the current draft as a new immutable, numbered version and make it
|
|
1772
|
-
* the live version used by sends. The draft stays editable. The draft must
|
|
1773
|
-
* have a subject and a body, or the call throws.
|
|
1774
|
-
*
|
|
1775
|
-
* @example Publish, then send by template
|
|
1776
|
-
* const version = await bird.emailTemplates.publish("emt_abc123");
|
|
1777
|
-
* console.log(version.version_number); // 1, 2, 3…
|
|
1778
|
-
* await bird.email.send({
|
|
1779
|
-
* from: "hello@acme.com",
|
|
1780
|
-
* to: ["alice@example.com"],
|
|
1781
|
-
* template: { id: "emt_abc123", parameters: { first_name: "Alice" } },
|
|
1782
|
-
* });
|
|
1783
|
-
*/
|
|
1784
|
-
publish(templateId, options) {
|
|
1785
|
-
return this.call(
|
|
1786
|
-
"POST",
|
|
1787
|
-
options,
|
|
1788
|
-
({ signal, headers }) => publishEmailTemplate({
|
|
1789
|
-
client: this.client,
|
|
1790
|
-
path: { template_id: templateId },
|
|
1791
|
-
headers,
|
|
1792
|
-
signal
|
|
1793
|
-
})
|
|
1794
|
-
);
|
|
1795
|
-
}
|
|
1796
|
-
/**
|
|
1797
|
-
* List every version of a template — the current draft plus all published
|
|
1798
|
-
* versions — newest first. Returns the full set in one response (`.data`);
|
|
1799
|
-
* this list is not paginated.
|
|
1800
|
-
*
|
|
1801
|
-
* @example
|
|
1802
|
-
* const { data } = await bird.emailTemplates.listVersions("emt_abc123");
|
|
1803
|
-
* for (const v of data) console.log(v.version_number, v.status);
|
|
1804
|
-
*/
|
|
1805
|
-
listVersions(templateId, options) {
|
|
1806
|
-
return this.call(
|
|
1807
|
-
"GET",
|
|
1808
|
-
options,
|
|
1809
|
-
({ signal, headers }) => listEmailTemplateVersions({
|
|
1810
|
-
client: this.client,
|
|
1811
|
-
path: { template_id: templateId },
|
|
1812
|
-
headers,
|
|
1813
|
-
signal
|
|
1814
|
-
})
|
|
1815
|
-
);
|
|
1816
|
-
}
|
|
1817
|
-
/**
|
|
1818
|
-
* Fetch a single version of a template.
|
|
1819
|
-
*
|
|
1820
|
-
* @example
|
|
1821
|
-
* const version = await bird.emailTemplates.getVersion("emt_abc123", "emv_def456");
|
|
1822
|
-
* version.status; // "draft" | "published"
|
|
1823
|
-
*/
|
|
1824
|
-
getVersion(templateId, versionId, options) {
|
|
1825
|
-
return this.call(
|
|
1826
|
-
"GET",
|
|
1827
|
-
options,
|
|
1828
|
-
({ signal, headers }) => getEmailTemplateVersion({
|
|
1829
|
-
client: this.client,
|
|
1830
|
-
path: { template_id: templateId, version_id: versionId },
|
|
1831
|
-
headers,
|
|
1832
|
-
signal
|
|
1833
|
-
})
|
|
1834
|
-
);
|
|
1835
|
-
}
|
|
1836
|
-
};
|
|
1837
|
-
|
|
1838
|
-
// src/resources/sms.ts
|
|
1839
|
-
var SmsResource = class extends Resource {
|
|
1840
|
-
/**
|
|
1841
|
-
* Send one SMS to a single recipient. Supply either `text` (with a `category`)
|
|
1842
|
-
* or a stored `template` (by `id` or `alias`, with its `parameters`). The
|
|
1843
|
-
* result is `accepted`, not yet delivered — read it back with `get` to confirm.
|
|
1844
|
-
*
|
|
1845
|
-
* @example Send free text
|
|
1846
|
-
* const msg = await bird.sms.send({
|
|
1847
|
-
* to: "+15551234567",
|
|
1848
|
-
* text: "Your verification code is 123456.",
|
|
1849
|
-
* category: "authentication",
|
|
1850
|
-
* });
|
|
1851
|
-
* console.log(msg.id, msg.status);
|
|
1852
|
-
*
|
|
1853
|
-
* @example Send by template
|
|
1854
|
-
* await bird.sms.send({
|
|
1855
|
-
* to: "+15551234567",
|
|
1856
|
-
* template: { alias: "bird_otp_verification", parameters: { code: "123456" } },
|
|
1857
|
-
* });
|
|
1858
|
-
*/
|
|
1859
|
-
send(params, options) {
|
|
1860
|
-
return this.call(
|
|
1861
|
-
"POST",
|
|
1862
|
-
options,
|
|
1863
|
-
({ signal, headers }) => createSmsMessage({ client: this.client, body: params, headers, signal })
|
|
1864
|
-
);
|
|
1865
|
-
}
|
|
1866
|
-
/**
|
|
1867
|
-
* Send up to 100 independent SMS messages in one call. Each item is a full send
|
|
1868
|
-
* (free text or template); all items are validated before any are queued.
|
|
1869
|
-
*
|
|
1870
|
-
* @example
|
|
1871
|
-
* const result = await bird.sms.sendBatch([
|
|
1872
|
-
* { to: "+15551111111", text: "Hi Alice!", category: "marketing" },
|
|
1873
|
-
* { to: "+15552222222", text: "Hi Bob!", category: "marketing" },
|
|
1874
|
-
* ]);
|
|
1875
|
-
*/
|
|
1876
|
-
sendBatch(params, options) {
|
|
1877
|
-
return this.call(
|
|
1878
|
-
"POST",
|
|
1879
|
-
options,
|
|
1880
|
-
({ signal, headers }) => createSmsMessageBatch({
|
|
1881
|
-
client: this.client,
|
|
1882
|
-
body: params,
|
|
1883
|
-
headers,
|
|
1884
|
-
signal
|
|
1885
|
-
})
|
|
1886
|
-
);
|
|
1887
|
-
}
|
|
1888
|
-
/**
|
|
1889
|
-
* Fetch a single SMS message: its current delivery status, segment breakdown,
|
|
1890
|
-
* cost, and failure detail if it failed.
|
|
1891
|
-
*
|
|
1892
|
-
* @example
|
|
1893
|
-
* const msg = await bird.sms.get("sms_abc123");
|
|
1894
|
-
* msg.status; // "accepted" | "delivered" | …
|
|
1895
|
-
*/
|
|
1896
|
-
get(messageId, options) {
|
|
1897
|
-
return this.call(
|
|
1898
|
-
"GET",
|
|
1899
|
-
options,
|
|
1900
|
-
({ signal, headers }) => getSmsMessage({
|
|
1901
|
-
client: this.client,
|
|
1902
|
-
path: { message_id: messageId },
|
|
1903
|
-
headers,
|
|
1904
|
-
signal
|
|
1905
|
-
})
|
|
1906
|
-
);
|
|
1907
|
-
}
|
|
1908
|
-
/**
|
|
1909
|
-
* List SMS messages, newest first. `await` resolves the first page; `for await`
|
|
1910
|
-
* walks every message across all pages. Filter by direction, status, category,
|
|
1911
|
-
* recipient, sender, or tag.
|
|
1912
|
-
*
|
|
1913
|
-
* @example
|
|
1914
|
-
* for await (const msg of bird.sms.list({ direction: "outbound" })) {
|
|
1915
|
-
* console.log(msg.id, msg.status);
|
|
1916
|
-
* }
|
|
1917
|
-
*/
|
|
1918
|
-
list(query, options) {
|
|
1919
|
-
return this.paginated(
|
|
1920
|
-
"GET",
|
|
1921
|
-
options,
|
|
1922
|
-
({ signal, headers }, cursor) => listSmsMessages({
|
|
1923
|
-
client: this.client,
|
|
1924
|
-
query: { ...query, starting_after: cursor ?? query?.starting_after },
|
|
1925
|
-
headers,
|
|
1926
|
-
signal
|
|
1927
|
-
})
|
|
1928
|
-
);
|
|
1929
|
-
}
|
|
1930
|
-
};
|
|
1931
|
-
|
|
1932
|
-
// src/resources/smsTemplates.ts
|
|
1933
|
-
var SmsTemplatesResource = class extends Resource {
|
|
1934
|
-
/**
|
|
1935
|
-
* List the SMS templates available to the workspace — Bird's built-in
|
|
1936
|
-
* templates plus any the workspace authored. The catalogue is small and
|
|
1937
|
-
* returned in full (`.data`); this list is not paginated. Filter by `scope`,
|
|
1938
|
-
* `category`, or `locale` (a BCP-47 language tag).
|
|
1939
|
-
*
|
|
1940
|
-
* @example List the built-in templates
|
|
1941
|
-
* const { data } = await bird.smsTemplates.list({ scope: "system" });
|
|
1942
|
-
* for (const tpl of data) console.log(tpl.id, tpl.name);
|
|
1943
|
-
*/
|
|
1944
|
-
list(query, options) {
|
|
1945
|
-
return this.call(
|
|
1946
|
-
"GET",
|
|
1947
|
-
options,
|
|
1948
|
-
({ signal, headers }) => listSmsTemplates({
|
|
1949
|
-
client: this.client,
|
|
1950
|
-
query,
|
|
1951
|
-
headers,
|
|
1952
|
-
signal
|
|
1953
|
-
})
|
|
1954
|
-
);
|
|
1955
|
-
}
|
|
1956
|
-
/**
|
|
1957
|
-
* Fetch a single SMS template by its alias or id, including its body and the
|
|
1958
|
-
* variables it expects.
|
|
1959
|
-
*
|
|
1960
|
-
* @example
|
|
1961
|
-
* const tpl = await bird.smsTemplates.get("bird_otp_verification");
|
|
1962
|
-
* console.log(tpl.body, tpl.variables);
|
|
1963
|
-
*/
|
|
1964
|
-
get(templateRef, options) {
|
|
1965
|
-
return this.call(
|
|
1966
|
-
"GET",
|
|
1967
|
-
options,
|
|
1968
|
-
({ signal, headers }) => getSmsTemplate({
|
|
1969
|
-
client: this.client,
|
|
1970
|
-
path: { template_ref: templateRef },
|
|
1971
|
-
headers,
|
|
1972
|
-
signal
|
|
1973
|
-
})
|
|
1974
|
-
);
|
|
1975
|
-
}
|
|
1976
|
-
};
|
|
1977
|
-
var WebhooksResource = class {
|
|
1978
|
-
#secret;
|
|
1979
|
-
constructor(config) {
|
|
1980
|
-
this.#secret = config?.secret;
|
|
1981
|
-
}
|
|
1982
|
-
/**
|
|
1983
|
-
* Verify a webhook delivery and return the typed event.
|
|
1984
|
-
*
|
|
1985
|
-
* **Pass the raw request body**, exactly as received — do NOT parse it first.
|
|
1986
|
-
* The Standard Webhooks signature is computed over the raw bytes, so parsing
|
|
1987
|
-
* and re-serializing before verifying is the classic webhook bug.
|
|
1988
|
-
*
|
|
1989
|
-
* The secret comes from `webhooks.secret` on the client; pass `{ secret }` to
|
|
1990
|
-
* override per call. Throws {@link BirdWebhookVerificationError} on a bad
|
|
1991
|
-
* signature, a stale timestamp, or missing/malformed headers. Unknown event
|
|
1992
|
-
* types are returned as-is (handle them in a `default` case) so a newer server
|
|
1993
|
-
* event can't break an older SDK.
|
|
1994
|
-
*
|
|
1995
|
-
* @example One call verifies the signature and returns the typed event
|
|
1996
|
-
* // Pass the RAW request body; set the secret via new BirdClient({ webhooks: { secret } }).
|
|
1997
|
-
* const event = bird.webhooks.unwrap(rawBody, headers);
|
|
1998
|
-
* console.log(event.type); // discriminated union — narrow on event.type
|
|
1999
|
-
*
|
|
2000
|
-
* @example Verify and dispatch — pass the raw request body, never the parsed JSON
|
|
2001
|
-
* // new BirdClient({ apiKey, webhooks: { secret } })
|
|
2002
|
-
* try {
|
|
2003
|
-
* const event = bird.webhooks.unwrap(rawBody, req.headers);
|
|
2004
|
-
* switch (event.type) {
|
|
2005
|
-
* case "email.delivered":
|
|
2006
|
-
* markDelivered(event.email_id, event.recipient); // narrowed; fields are flat
|
|
2007
|
-
* break;
|
|
2008
|
-
* case "email.bounced":
|
|
2009
|
-
* case "email.complained":
|
|
2010
|
-
* suppress(event.recipient);
|
|
2011
|
-
* break;
|
|
2012
|
-
* default: // unknown future event types — an older SDK won't break on a new one
|
|
2013
|
-
* }
|
|
2014
|
-
* } catch (err) {
|
|
2015
|
-
* if (err instanceof BirdWebhookVerificationError) {
|
|
2016
|
-
* // reject with 400 — bad signature, stale timestamp, or missing/malformed headers
|
|
2017
|
-
* } else throw err;
|
|
2018
|
-
* }
|
|
2019
|
-
*/
|
|
2020
|
-
unwrap(payload, headers, options) {
|
|
2021
|
-
const secret = options?.secret ?? this.#secret;
|
|
2022
|
-
if (!secret) {
|
|
2023
|
-
throw new Error(
|
|
2024
|
-
"No webhook secret. Set `webhooks: { secret }` on the client, or pass `{ secret }` to unwrap."
|
|
2025
|
-
);
|
|
2026
|
-
}
|
|
2027
|
-
const wh = new Webhook(secret);
|
|
2028
|
-
let verified;
|
|
2029
|
-
try {
|
|
2030
|
-
verified = wh.verify(payload, toHeaderRecord(headers));
|
|
2031
|
-
} catch (err) {
|
|
2032
|
-
throw new BirdWebhookVerificationError(
|
|
2033
|
-
err instanceof Error ? err.message : "Webhook signature verification failed"
|
|
2034
|
-
);
|
|
2035
|
-
}
|
|
2036
|
-
return verified;
|
|
2037
|
-
}
|
|
2038
|
-
};
|
|
2039
|
-
function toHeaderRecord(headers) {
|
|
2040
|
-
return headers instanceof Headers ? Object.fromEntries(headers) : headers;
|
|
2041
|
-
}
|
|
2042
|
-
|
|
2043
|
-
// src/client.ts
|
|
2044
|
-
var DEFAULT_TIMEOUT_MS = 6e4;
|
|
2045
|
-
var DEFAULT_MAX_RETRIES = 2;
|
|
2046
|
-
function resolveBaseUrl(options) {
|
|
2047
|
-
if (options.baseUrl) return options.baseUrl;
|
|
2048
|
-
const region = options.region ?? regionFromApiKey(options.apiKey);
|
|
2049
|
-
if (!region) {
|
|
2050
|
-
throw new Error(
|
|
2051
|
-
"Unable to determine region: API key is not in the expected bk_{region}_{token} format. Pass an explicit `region` or `baseUrl`."
|
|
2052
|
-
);
|
|
2053
|
-
}
|
|
2054
|
-
return baseUrlForRegion(region);
|
|
2055
|
-
}
|
|
2056
|
-
function resolveRawRequestUrl(baseUrl, path) {
|
|
2057
|
-
if (!path.startsWith("/") || path.startsWith("//")) {
|
|
2058
|
-
throw new TypeError(
|
|
2059
|
-
"bird.request path must be an absolute path starting with a single `/`"
|
|
2060
|
-
);
|
|
2061
|
-
}
|
|
2062
|
-
const base = new URL(baseUrl);
|
|
2063
|
-
const url = new URL(baseUrl + path);
|
|
2064
|
-
if (url.origin !== base.origin) {
|
|
2065
|
-
throw new TypeError(
|
|
2066
|
-
"bird.request path must stay on the configured Bird API origin"
|
|
2067
|
-
);
|
|
2068
|
-
}
|
|
2069
|
-
return url;
|
|
2070
|
-
}
|
|
2071
|
-
var BirdClient = class {
|
|
2072
|
-
core;
|
|
2073
|
-
// The generated hey-api client, configured with this instance's base URL,
|
|
2074
|
-
// auth, and fetch. Resources call the generated SDK functions through it.
|
|
2075
|
-
#client;
|
|
2076
|
-
#baseUrl;
|
|
2077
|
-
#fetch;
|
|
2078
|
-
#headers;
|
|
2079
|
-
/** The email channel — `bird.email.send(...)`, `.get(...)`, `.list(...)`. */
|
|
2080
|
-
email;
|
|
2081
|
-
/** Email templates — `bird.emailTemplates.create(...)`, `.list(...)`, `.publish(...)`, … */
|
|
2082
|
-
emailTemplates;
|
|
2083
|
-
/** The SMS channel — `bird.sms.send(...)`, `.get(...)`, `.list(...)`. */
|
|
2084
|
-
sms;
|
|
2085
|
-
/** SMS templates — `bird.smsTemplates.list(...)`, `.get(...)`. */
|
|
2086
|
-
smsTemplates;
|
|
2087
|
-
/** Webhooks — `bird.webhooks.unwrap(payload, headers)` verifies an inbound delivery. */
|
|
2088
|
-
webhooks;
|
|
2089
|
-
constructor(options) {
|
|
2090
|
-
const opts = options;
|
|
2091
|
-
this.#baseUrl = resolveBaseUrl(opts);
|
|
2092
|
-
this.#fetch = opts.fetch ?? fetch;
|
|
2093
|
-
this.#headers = {
|
|
2094
|
-
...opts.defaultHeaders,
|
|
2095
|
-
Authorization: `Bearer ${opts.apiKey}`,
|
|
2096
|
-
"User-Agent": `bird-sdk-js/${"0.3.0"}`,
|
|
2097
|
-
// Bird-* client-identity headers (ADR-0074): the API attributes the SDK
|
|
2098
|
-
// surface from these, not the User-Agent. Edge-safe, so no os/arch/runtime
|
|
2099
|
-
// (those need Node globals this SDK must not touch); surface + version only.
|
|
2100
|
-
"Bird-Surface": "sdk-js",
|
|
2101
|
-
"Bird-Version": "0.3.0"
|
|
2102
|
-
};
|
|
2103
|
-
this.#client = createClient(
|
|
2104
|
-
createConfig({
|
|
2105
|
-
baseUrl: this.#baseUrl,
|
|
2106
|
-
fetch: this.#fetch,
|
|
2107
|
-
headers: this.#headers
|
|
2108
|
-
})
|
|
2109
|
-
);
|
|
2110
|
-
this.core = new BirdHTTPClient({
|
|
2111
|
-
timeout: opts.timeout ?? DEFAULT_TIMEOUT_MS,
|
|
2112
|
-
maxRetries: opts.maxRetries ?? DEFAULT_MAX_RETRIES
|
|
2113
|
-
});
|
|
2114
|
-
this.email = new EmailResource(
|
|
2115
|
-
this.core,
|
|
2116
|
-
this.#client,
|
|
2117
|
-
opts.email
|
|
2118
|
-
);
|
|
2119
|
-
this.emailTemplates = new EmailTemplatesResource(this.core, this.#client);
|
|
2120
|
-
this.sms = new SmsResource(this.core, this.#client);
|
|
2121
|
-
this.smsTemplates = new SmsTemplatesResource(this.core, this.#client);
|
|
2122
|
-
this.webhooks = new WebhooksResource(opts.webhooks);
|
|
2123
|
-
}
|
|
2124
|
-
/**
|
|
2125
|
-
* Escape hatch for endpoints the typed resources don't cover. Runs the full
|
|
2126
|
-
* lifecycle (auth, retries, idempotency, error mapping); you supply the
|
|
2127
|
-
* response type. Prefer a typed resource method where one exists.
|
|
2128
|
-
*
|
|
2129
|
-
* @throws {TypeError} if `req.path` does not start with exactly one `/` or
|
|
2130
|
-
* resolves to a different origin than the configured Bird API base URL.
|
|
2131
|
-
*
|
|
2132
|
-
* @example Reach an endpoint outside the curated surface — you supply the response type
|
|
2133
|
-
* type Suppressions = { data: Array<{ recipient: string }> };
|
|
2134
|
-
* const suppressions = await bird.request<Suppressions>({ method: "GET", path: "/v1/email/suppressions" });
|
|
2135
|
-
* console.log(suppressions.data.length);
|
|
2136
|
-
*/
|
|
2137
|
-
request(req, options) {
|
|
2138
|
-
const url = resolveRawRequestUrl(this.#baseUrl, req.path);
|
|
2139
|
-
return apiPromise(
|
|
2140
|
-
this.core.request(
|
|
2141
|
-
(ctx) => this.#raw(url, req, ctx, options?.headers),
|
|
2142
|
-
{
|
|
2143
|
-
method: req.method,
|
|
2144
|
-
idempotencyKey: options?.idempotencyKey,
|
|
2145
|
-
signal: options?.signal,
|
|
2146
|
-
timeout: options?.timeout,
|
|
2147
|
-
maxRetries: options?.maxRetries
|
|
2148
|
-
}
|
|
2149
|
-
)
|
|
2150
|
-
);
|
|
2151
|
-
}
|
|
2152
|
-
async #raw(url, req, ctx, extraHeaders) {
|
|
2153
|
-
url = new URL(url);
|
|
2154
|
-
if (req.query) {
|
|
2155
|
-
for (const [key, value] of Object.entries(req.query)) {
|
|
2156
|
-
if (value !== void 0) url.searchParams.set(key, String(value));
|
|
2157
|
-
}
|
|
2158
|
-
}
|
|
2159
|
-
const headers = {
|
|
2160
|
-
...extraHeaders,
|
|
2161
|
-
...this.#headers
|
|
2162
|
-
};
|
|
2163
|
-
if (ctx.idempotencyKey) headers["Idempotency-Key"] = ctx.idempotencyKey;
|
|
2164
|
-
if (req.body !== void 0) headers["Content-Type"] = "application/json";
|
|
2165
|
-
const response = await this.#fetch(url, {
|
|
2166
|
-
method: req.method,
|
|
2167
|
-
headers,
|
|
2168
|
-
body: req.body !== void 0 ? JSON.stringify(req.body) : void 0,
|
|
2169
|
-
signal: ctx.signal
|
|
2170
|
-
});
|
|
2171
|
-
if (response.ok) {
|
|
2172
|
-
const data = response.status === 204 ? void 0 : await response.json().catch(() => void 0);
|
|
2173
|
-
return { data, response };
|
|
2174
|
-
}
|
|
2175
|
-
const error = await response.clone().json().catch(() => void 0);
|
|
2176
|
-
return { error, response };
|
|
2177
|
-
}
|
|
2178
|
-
};
|
|
2179
|
-
|
|
2180
|
-
// src/event-types.gen.ts
|
|
2181
|
-
var WebhookEventType = {
|
|
2182
|
-
DomainFailed: "domain.failed",
|
|
2183
|
-
DomainVerified: "domain.verified",
|
|
2184
|
-
EmailAccepted: "email.accepted",
|
|
2185
|
-
EmailBounced: "email.bounced",
|
|
2186
|
-
EmailCanceled: "email.canceled",
|
|
2187
|
-
EmailClicked: "email.clicked",
|
|
2188
|
-
EmailComplained: "email.complained",
|
|
2189
|
-
EmailDeferred: "email.deferred",
|
|
2190
|
-
EmailDelivered: "email.delivered",
|
|
2191
|
-
EmailListUnsubscribed: "email.list_unsubscribed",
|
|
2192
|
-
EmailOpened: "email.opened",
|
|
2193
|
-
EmailOutOfBandBounce: "email.out_of_band_bounce",
|
|
2194
|
-
EmailProcessed: "email.processed",
|
|
2195
|
-
EmailReceived: "email.received",
|
|
2196
|
-
EmailRejected: "email.rejected",
|
|
2197
|
-
EmailScheduled: "email.scheduled",
|
|
2198
|
-
EmailSuppressionCreated: "email_suppression.created",
|
|
2199
|
-
EmailUnsubscribed: "email.unsubscribed",
|
|
2200
|
-
SmsAccepted: "sms.accepted",
|
|
2201
|
-
SmsDelivered: "sms.delivered",
|
|
2202
|
-
SmsExpired: "sms.expired",
|
|
2203
|
-
SmsFailed: "sms.failed",
|
|
2204
|
-
SmsRejected: "sms.rejected",
|
|
2205
|
-
SmsSent: "sms.sent",
|
|
2206
|
-
SmsUndelivered: "sms.undelivered"
|
|
2207
|
-
};
|
|
2208
|
-
|
|
2209
|
-
export { BirdAPIError, BirdAuthError, BirdBadRequestError, BirdBillingError, BirdClient, BirdConflictError, BirdConnectionError, BirdError, BirdInternalError, BirdMisdirectedError, BirdNotFoundError, BirdNotImplementedError, BirdPayloadTooLargeError, BirdPermissionError, BirdPreconditionError, BirdRateLimitError, BirdServiceUnavailableError, BirdTimeoutError, BirdValidationError, BirdWebhookVerificationError, WebhookEventType, baseUrlForRegion, regionFromApiKey };
|
|
2210
|
-
//# sourceMappingURL=index.js.map
|
|
2211
|
-
//# sourceMappingURL=index.js.map
|