@primitivedotdev/sdk 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -210
- package/dist/address-parser-BYn8oW5r.js +111 -0
- package/dist/api/generated/index.js +1 -1
- package/dist/api/generated/sdk.gen.js +17 -0
- package/dist/api/index.d.ts +2 -1877
- package/dist/api/index.js +255 -0
- package/dist/api-COSr-Fqm.js +1311 -0
- package/dist/chunk-pbuEa-1d.js +13 -0
- package/dist/contract/index.d.ts +6 -8
- package/dist/contract/index.js +28 -15
- package/dist/{index-DLmAI4UQ.d.ts → index-CbEivn3S.d.ts} +13 -30
- package/dist/index-DVow4Fjd.d.ts +2140 -0
- package/dist/index.d.ts +12 -3
- package/dist/index.js +10 -3
- package/dist/oclif/api-command.js +89 -1
- package/dist/openapi/index.d.ts +8 -3
- package/dist/openapi/openapi.generated.js +412 -1
- package/dist/openapi/operations.generated.js +255 -0
- package/dist/parser/address-parser.js +129 -0
- package/dist/parser/index.d.ts +4 -19
- package/dist/parser/index.js +7 -122
- package/dist/received-email-D6tKtWwW.js +69 -0
- package/dist/received-email-DNjpq_Wt.d.ts +37 -0
- package/dist/{types-CKFmgitP.d.ts → types-9vXGZjPd.d.ts} +3 -19
- package/dist/types.generated.js +7 -0
- package/dist/types.js +53 -0
- package/dist/webhook/index.d.ts +4 -3
- package/dist/webhook/index.js +3 -3
- package/dist/webhook/received-email.js +82 -0
- package/dist/{webhook-COe5N_Uj.js → webhook-zkN4wUTs.js} +119 -81
- package/oclif.manifest.json +54 -8
- package/package.json +5 -2
- package/dist/chunk-Cl8Af3a2.js +0 -11
|
@@ -0,0 +1,1311 @@
|
|
|
1
|
+
import { t as __exportAll } from "./chunk-pbuEa-1d.js";
|
|
2
|
+
import { r as formatAddress } from "./received-email-D6tKtWwW.js";
|
|
3
|
+
//#region src/api/generated/core/bodySerializer.gen.ts
|
|
4
|
+
const jsonBodySerializer = { bodySerializer: (body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value) };
|
|
5
|
+
//#endregion
|
|
6
|
+
//#region src/api/generated/core/serverSentEvents.gen.ts
|
|
7
|
+
function createSseClient({ onRequest, onSseError, onSseEvent, responseTransformer, responseValidator, sseDefaultRetryDelay, sseMaxRetryAttempts, sseMaxRetryDelay, sseSleepFn, url, ...options }) {
|
|
8
|
+
let lastEventId;
|
|
9
|
+
const sleep = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
10
|
+
const createStream = async function* () {
|
|
11
|
+
let retryDelay = sseDefaultRetryDelay ?? 3e3;
|
|
12
|
+
let attempt = 0;
|
|
13
|
+
const signal = options.signal ?? new AbortController().signal;
|
|
14
|
+
while (true) {
|
|
15
|
+
if (signal.aborted) break;
|
|
16
|
+
attempt++;
|
|
17
|
+
const headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
|
|
18
|
+
if (lastEventId !== void 0) headers.set("Last-Event-ID", lastEventId);
|
|
19
|
+
try {
|
|
20
|
+
const requestInit = {
|
|
21
|
+
redirect: "follow",
|
|
22
|
+
...options,
|
|
23
|
+
body: options.serializedBody,
|
|
24
|
+
headers,
|
|
25
|
+
signal
|
|
26
|
+
};
|
|
27
|
+
let request = new Request(url, requestInit);
|
|
28
|
+
if (onRequest) request = await onRequest(url, requestInit);
|
|
29
|
+
const response = await (options.fetch ?? globalThis.fetch)(request);
|
|
30
|
+
if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`);
|
|
31
|
+
if (!response.body) throw new Error("No body in SSE response");
|
|
32
|
+
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
|
|
33
|
+
let buffer = "";
|
|
34
|
+
const abortHandler = () => {
|
|
35
|
+
try {
|
|
36
|
+
reader.cancel();
|
|
37
|
+
} catch {}
|
|
38
|
+
};
|
|
39
|
+
signal.addEventListener("abort", abortHandler);
|
|
40
|
+
try {
|
|
41
|
+
while (true) {
|
|
42
|
+
const { done, value } = await reader.read();
|
|
43
|
+
if (done) break;
|
|
44
|
+
buffer += value;
|
|
45
|
+
buffer = buffer.replace(/\r\n?/g, "\n");
|
|
46
|
+
const chunks = buffer.split("\n\n");
|
|
47
|
+
buffer = chunks.pop() ?? "";
|
|
48
|
+
for (const chunk of chunks) {
|
|
49
|
+
const lines = chunk.split("\n");
|
|
50
|
+
const dataLines = [];
|
|
51
|
+
let eventName;
|
|
52
|
+
for (const line of lines) if (line.startsWith("data:")) dataLines.push(line.replace(/^data:\s*/, ""));
|
|
53
|
+
else if (line.startsWith("event:")) eventName = line.replace(/^event:\s*/, "");
|
|
54
|
+
else if (line.startsWith("id:")) lastEventId = line.replace(/^id:\s*/, "");
|
|
55
|
+
else if (line.startsWith("retry:")) {
|
|
56
|
+
const parsed = Number.parseInt(line.replace(/^retry:\s*/, ""), 10);
|
|
57
|
+
if (!Number.isNaN(parsed)) retryDelay = parsed;
|
|
58
|
+
}
|
|
59
|
+
let data;
|
|
60
|
+
let parsedJson = false;
|
|
61
|
+
if (dataLines.length) {
|
|
62
|
+
const rawData = dataLines.join("\n");
|
|
63
|
+
try {
|
|
64
|
+
data = JSON.parse(rawData);
|
|
65
|
+
parsedJson = true;
|
|
66
|
+
} catch {
|
|
67
|
+
data = rawData;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (parsedJson) {
|
|
71
|
+
if (responseValidator) await responseValidator(data);
|
|
72
|
+
if (responseTransformer) data = await responseTransformer(data);
|
|
73
|
+
}
|
|
74
|
+
onSseEvent?.({
|
|
75
|
+
data,
|
|
76
|
+
event: eventName,
|
|
77
|
+
id: lastEventId,
|
|
78
|
+
retry: retryDelay
|
|
79
|
+
});
|
|
80
|
+
if (dataLines.length) yield data;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
} finally {
|
|
84
|
+
signal.removeEventListener("abort", abortHandler);
|
|
85
|
+
reader.releaseLock();
|
|
86
|
+
}
|
|
87
|
+
break;
|
|
88
|
+
} catch (error) {
|
|
89
|
+
onSseError?.(error);
|
|
90
|
+
if (sseMaxRetryAttempts !== void 0 && attempt >= sseMaxRetryAttempts) break;
|
|
91
|
+
await sleep(Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 3e4));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
return { stream: createStream() };
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
98
|
+
//#region src/api/generated/core/pathSerializer.gen.ts
|
|
99
|
+
const separatorArrayExplode = (style) => {
|
|
100
|
+
switch (style) {
|
|
101
|
+
case "label": return ".";
|
|
102
|
+
case "matrix": return ";";
|
|
103
|
+
case "simple": return ",";
|
|
104
|
+
default: return "&";
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
const separatorArrayNoExplode = (style) => {
|
|
108
|
+
switch (style) {
|
|
109
|
+
case "form": return ",";
|
|
110
|
+
case "pipeDelimited": return "|";
|
|
111
|
+
case "spaceDelimited": return "%20";
|
|
112
|
+
default: return ",";
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
const separatorObjectExplode = (style) => {
|
|
116
|
+
switch (style) {
|
|
117
|
+
case "label": return ".";
|
|
118
|
+
case "matrix": return ";";
|
|
119
|
+
case "simple": return ",";
|
|
120
|
+
default: return "&";
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
const serializeArrayParam = ({ allowReserved, explode, name, style, value }) => {
|
|
124
|
+
if (!explode) {
|
|
125
|
+
const joinedValues = (allowReserved ? value : value.map((v) => encodeURIComponent(v))).join(separatorArrayNoExplode(style));
|
|
126
|
+
switch (style) {
|
|
127
|
+
case "label": return `.${joinedValues}`;
|
|
128
|
+
case "matrix": return `;${name}=${joinedValues}`;
|
|
129
|
+
case "simple": return joinedValues;
|
|
130
|
+
default: return `${name}=${joinedValues}`;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const separator = separatorArrayExplode(style);
|
|
134
|
+
const joinedValues = value.map((v) => {
|
|
135
|
+
if (style === "label" || style === "simple") return allowReserved ? v : encodeURIComponent(v);
|
|
136
|
+
return serializePrimitiveParam({
|
|
137
|
+
allowReserved,
|
|
138
|
+
name,
|
|
139
|
+
value: v
|
|
140
|
+
});
|
|
141
|
+
}).join(separator);
|
|
142
|
+
return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
|
|
143
|
+
};
|
|
144
|
+
const serializePrimitiveParam = ({ allowReserved, name, value }) => {
|
|
145
|
+
if (value === void 0 || value === null) return "";
|
|
146
|
+
if (typeof value === "object") throw new Error("Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.");
|
|
147
|
+
return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
|
|
148
|
+
};
|
|
149
|
+
const serializeObjectParam = ({ allowReserved, explode, name, style, value, valueOnly }) => {
|
|
150
|
+
if (value instanceof Date) return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
|
|
151
|
+
if (style !== "deepObject" && !explode) {
|
|
152
|
+
let values = [];
|
|
153
|
+
Object.entries(value).forEach(([key, v]) => {
|
|
154
|
+
values = [
|
|
155
|
+
...values,
|
|
156
|
+
key,
|
|
157
|
+
allowReserved ? v : encodeURIComponent(v)
|
|
158
|
+
];
|
|
159
|
+
});
|
|
160
|
+
const joinedValues = values.join(",");
|
|
161
|
+
switch (style) {
|
|
162
|
+
case "form": return `${name}=${joinedValues}`;
|
|
163
|
+
case "label": return `.${joinedValues}`;
|
|
164
|
+
case "matrix": return `;${name}=${joinedValues}`;
|
|
165
|
+
default: return joinedValues;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const separator = separatorObjectExplode(style);
|
|
169
|
+
const joinedValues = Object.entries(value).map(([key, v]) => serializePrimitiveParam({
|
|
170
|
+
allowReserved,
|
|
171
|
+
name: style === "deepObject" ? `${name}[${key}]` : key,
|
|
172
|
+
value: v
|
|
173
|
+
})).join(separator);
|
|
174
|
+
return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
|
|
175
|
+
};
|
|
176
|
+
//#endregion
|
|
177
|
+
//#region src/api/generated/core/utils.gen.ts
|
|
178
|
+
const PATH_PARAM_RE = /\{[^{}]+\}/g;
|
|
179
|
+
const defaultPathSerializer = ({ path, url: _url }) => {
|
|
180
|
+
let url = _url;
|
|
181
|
+
const matches = _url.match(PATH_PARAM_RE);
|
|
182
|
+
if (matches) for (const match of matches) {
|
|
183
|
+
let explode = false;
|
|
184
|
+
let name = match.substring(1, match.length - 1);
|
|
185
|
+
let style = "simple";
|
|
186
|
+
if (name.endsWith("*")) {
|
|
187
|
+
explode = true;
|
|
188
|
+
name = name.substring(0, name.length - 1);
|
|
189
|
+
}
|
|
190
|
+
if (name.startsWith(".")) {
|
|
191
|
+
name = name.substring(1);
|
|
192
|
+
style = "label";
|
|
193
|
+
} else if (name.startsWith(";")) {
|
|
194
|
+
name = name.substring(1);
|
|
195
|
+
style = "matrix";
|
|
196
|
+
}
|
|
197
|
+
const value = path[name];
|
|
198
|
+
if (value === void 0 || value === null) continue;
|
|
199
|
+
if (Array.isArray(value)) {
|
|
200
|
+
url = url.replace(match, serializeArrayParam({
|
|
201
|
+
explode,
|
|
202
|
+
name,
|
|
203
|
+
style,
|
|
204
|
+
value
|
|
205
|
+
}));
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
if (typeof value === "object") {
|
|
209
|
+
url = url.replace(match, serializeObjectParam({
|
|
210
|
+
explode,
|
|
211
|
+
name,
|
|
212
|
+
style,
|
|
213
|
+
value,
|
|
214
|
+
valueOnly: true
|
|
215
|
+
}));
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
if (style === "matrix") {
|
|
219
|
+
url = url.replace(match, `;${serializePrimitiveParam({
|
|
220
|
+
name,
|
|
221
|
+
value
|
|
222
|
+
})}`);
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
const replaceValue = encodeURIComponent(style === "label" ? `.${value}` : value);
|
|
226
|
+
url = url.replace(match, replaceValue);
|
|
227
|
+
}
|
|
228
|
+
return url;
|
|
229
|
+
};
|
|
230
|
+
const getUrl = ({ baseUrl, path, query, querySerializer, url: _url }) => {
|
|
231
|
+
const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
|
|
232
|
+
let url = (baseUrl ?? "") + pathUrl;
|
|
233
|
+
if (path) url = defaultPathSerializer({
|
|
234
|
+
path,
|
|
235
|
+
url
|
|
236
|
+
});
|
|
237
|
+
let search = query ? querySerializer(query) : "";
|
|
238
|
+
if (search.startsWith("?")) search = search.substring(1);
|
|
239
|
+
if (search) url += `?${search}`;
|
|
240
|
+
return url;
|
|
241
|
+
};
|
|
242
|
+
function getValidRequestBody(options) {
|
|
243
|
+
const hasBody = options.body !== void 0;
|
|
244
|
+
if (hasBody && options.bodySerializer) {
|
|
245
|
+
if ("serializedBody" in options) return options.serializedBody !== void 0 && options.serializedBody !== "" ? options.serializedBody : null;
|
|
246
|
+
return options.body !== "" ? options.body : null;
|
|
247
|
+
}
|
|
248
|
+
if (hasBody) return options.body;
|
|
249
|
+
}
|
|
250
|
+
//#endregion
|
|
251
|
+
//#region src/api/generated/core/auth.gen.ts
|
|
252
|
+
const getAuthToken = async (auth, callback) => {
|
|
253
|
+
const token = typeof callback === "function" ? await callback(auth) : callback;
|
|
254
|
+
if (!token) return;
|
|
255
|
+
if (auth.scheme === "bearer") return `Bearer ${token}`;
|
|
256
|
+
if (auth.scheme === "basic") return `Basic ${btoa(token)}`;
|
|
257
|
+
return token;
|
|
258
|
+
};
|
|
259
|
+
//#endregion
|
|
260
|
+
//#region src/api/generated/client/utils.gen.ts
|
|
261
|
+
const createQuerySerializer = ({ parameters = {}, ...args } = {}) => {
|
|
262
|
+
const querySerializer = (queryParams) => {
|
|
263
|
+
const search = [];
|
|
264
|
+
if (queryParams && typeof queryParams === "object") for (const name in queryParams) {
|
|
265
|
+
const value = queryParams[name];
|
|
266
|
+
if (value === void 0 || value === null) continue;
|
|
267
|
+
const options = parameters[name] || args;
|
|
268
|
+
if (Array.isArray(value)) {
|
|
269
|
+
const serializedArray = serializeArrayParam({
|
|
270
|
+
allowReserved: options.allowReserved,
|
|
271
|
+
explode: true,
|
|
272
|
+
name,
|
|
273
|
+
style: "form",
|
|
274
|
+
value,
|
|
275
|
+
...options.array
|
|
276
|
+
});
|
|
277
|
+
if (serializedArray) search.push(serializedArray);
|
|
278
|
+
} else if (typeof value === "object") {
|
|
279
|
+
const serializedObject = serializeObjectParam({
|
|
280
|
+
allowReserved: options.allowReserved,
|
|
281
|
+
explode: true,
|
|
282
|
+
name,
|
|
283
|
+
style: "deepObject",
|
|
284
|
+
value,
|
|
285
|
+
...options.object
|
|
286
|
+
});
|
|
287
|
+
if (serializedObject) search.push(serializedObject);
|
|
288
|
+
} else {
|
|
289
|
+
const serializedPrimitive = serializePrimitiveParam({
|
|
290
|
+
allowReserved: options.allowReserved,
|
|
291
|
+
name,
|
|
292
|
+
value
|
|
293
|
+
});
|
|
294
|
+
if (serializedPrimitive) search.push(serializedPrimitive);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return search.join("&");
|
|
298
|
+
};
|
|
299
|
+
return querySerializer;
|
|
300
|
+
};
|
|
301
|
+
/**
|
|
302
|
+
* Infers parseAs value from provided Content-Type header.
|
|
303
|
+
*/
|
|
304
|
+
const getParseAs = (contentType) => {
|
|
305
|
+
if (!contentType) return "stream";
|
|
306
|
+
const cleanContent = contentType.split(";")[0]?.trim();
|
|
307
|
+
if (!cleanContent) return;
|
|
308
|
+
if (cleanContent.startsWith("application/json") || cleanContent.endsWith("+json")) return "json";
|
|
309
|
+
if (cleanContent === "multipart/form-data") return "formData";
|
|
310
|
+
if ([
|
|
311
|
+
"application/",
|
|
312
|
+
"audio/",
|
|
313
|
+
"image/",
|
|
314
|
+
"video/"
|
|
315
|
+
].some((type) => cleanContent.startsWith(type))) return "blob";
|
|
316
|
+
if (cleanContent.startsWith("text/")) return "text";
|
|
317
|
+
};
|
|
318
|
+
const checkForExistence = (options, name) => {
|
|
319
|
+
if (!name) return false;
|
|
320
|
+
if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) return true;
|
|
321
|
+
return false;
|
|
322
|
+
};
|
|
323
|
+
const setAuthParams = async ({ security, ...options }) => {
|
|
324
|
+
for (const auth of security) {
|
|
325
|
+
if (checkForExistence(options, auth.name)) continue;
|
|
326
|
+
const token = await getAuthToken(auth, options.auth);
|
|
327
|
+
if (!token) continue;
|
|
328
|
+
const name = auth.name ?? "Authorization";
|
|
329
|
+
switch (auth.in) {
|
|
330
|
+
case "query":
|
|
331
|
+
if (!options.query) options.query = {};
|
|
332
|
+
options.query[name] = token;
|
|
333
|
+
break;
|
|
334
|
+
case "cookie":
|
|
335
|
+
options.headers.append("Cookie", `${name}=${token}`);
|
|
336
|
+
break;
|
|
337
|
+
default:
|
|
338
|
+
options.headers.set(name, token);
|
|
339
|
+
break;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
const buildUrl = (options) => getUrl({
|
|
344
|
+
baseUrl: options.baseUrl,
|
|
345
|
+
path: options.path,
|
|
346
|
+
query: options.query,
|
|
347
|
+
querySerializer: typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer(options.querySerializer),
|
|
348
|
+
url: options.url
|
|
349
|
+
});
|
|
350
|
+
const mergeConfigs = (a, b) => {
|
|
351
|
+
const config = {
|
|
352
|
+
...a,
|
|
353
|
+
...b
|
|
354
|
+
};
|
|
355
|
+
if (config.baseUrl?.endsWith("/")) config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
|
|
356
|
+
config.headers = mergeHeaders(a.headers, b.headers);
|
|
357
|
+
return config;
|
|
358
|
+
};
|
|
359
|
+
const headersEntries = (headers) => {
|
|
360
|
+
const entries = [];
|
|
361
|
+
headers.forEach((value, key) => {
|
|
362
|
+
entries.push([key, value]);
|
|
363
|
+
});
|
|
364
|
+
return entries;
|
|
365
|
+
};
|
|
366
|
+
const mergeHeaders = (...headers) => {
|
|
367
|
+
const mergedHeaders = new Headers();
|
|
368
|
+
for (const header of headers) {
|
|
369
|
+
if (!header) continue;
|
|
370
|
+
const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);
|
|
371
|
+
for (const [key, value] of iterator) if (value === null) mergedHeaders.delete(key);
|
|
372
|
+
else if (Array.isArray(value)) for (const v of value) mergedHeaders.append(key, v);
|
|
373
|
+
else if (value !== void 0) mergedHeaders.set(key, typeof value === "object" ? JSON.stringify(value) : value);
|
|
374
|
+
}
|
|
375
|
+
return mergedHeaders;
|
|
376
|
+
};
|
|
377
|
+
var Interceptors = class {
|
|
378
|
+
fns = [];
|
|
379
|
+
clear() {
|
|
380
|
+
this.fns = [];
|
|
381
|
+
}
|
|
382
|
+
eject(id) {
|
|
383
|
+
const index = this.getInterceptorIndex(id);
|
|
384
|
+
if (this.fns[index]) this.fns[index] = null;
|
|
385
|
+
}
|
|
386
|
+
exists(id) {
|
|
387
|
+
const index = this.getInterceptorIndex(id);
|
|
388
|
+
return Boolean(this.fns[index]);
|
|
389
|
+
}
|
|
390
|
+
getInterceptorIndex(id) {
|
|
391
|
+
if (typeof id === "number") return this.fns[id] ? id : -1;
|
|
392
|
+
return this.fns.indexOf(id);
|
|
393
|
+
}
|
|
394
|
+
update(id, fn) {
|
|
395
|
+
const index = this.getInterceptorIndex(id);
|
|
396
|
+
if (this.fns[index]) {
|
|
397
|
+
this.fns[index] = fn;
|
|
398
|
+
return id;
|
|
399
|
+
}
|
|
400
|
+
return false;
|
|
401
|
+
}
|
|
402
|
+
use(fn) {
|
|
403
|
+
this.fns.push(fn);
|
|
404
|
+
return this.fns.length - 1;
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
const createInterceptors = () => ({
|
|
408
|
+
error: new Interceptors(),
|
|
409
|
+
request: new Interceptors(),
|
|
410
|
+
response: new Interceptors()
|
|
411
|
+
});
|
|
412
|
+
const defaultQuerySerializer = createQuerySerializer({
|
|
413
|
+
allowReserved: false,
|
|
414
|
+
array: {
|
|
415
|
+
explode: true,
|
|
416
|
+
style: "form"
|
|
417
|
+
},
|
|
418
|
+
object: {
|
|
419
|
+
explode: true,
|
|
420
|
+
style: "deepObject"
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
const defaultHeaders = { "Content-Type": "application/json" };
|
|
424
|
+
const createConfig = (override = {}) => ({
|
|
425
|
+
...jsonBodySerializer,
|
|
426
|
+
headers: defaultHeaders,
|
|
427
|
+
parseAs: "auto",
|
|
428
|
+
querySerializer: defaultQuerySerializer,
|
|
429
|
+
...override
|
|
430
|
+
});
|
|
431
|
+
//#endregion
|
|
432
|
+
//#region src/api/generated/client/client.gen.ts
|
|
433
|
+
const createClient = (config = {}) => {
|
|
434
|
+
let _config = mergeConfigs(createConfig(), config);
|
|
435
|
+
const getConfig = () => ({ ..._config });
|
|
436
|
+
const setConfig = (config) => {
|
|
437
|
+
_config = mergeConfigs(_config, config);
|
|
438
|
+
return getConfig();
|
|
439
|
+
};
|
|
440
|
+
const interceptors = createInterceptors();
|
|
441
|
+
const beforeRequest = async (options) => {
|
|
442
|
+
const opts = {
|
|
443
|
+
..._config,
|
|
444
|
+
...options,
|
|
445
|
+
fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
|
|
446
|
+
headers: mergeHeaders(_config.headers, options.headers),
|
|
447
|
+
serializedBody: void 0
|
|
448
|
+
};
|
|
449
|
+
if (opts.security) await setAuthParams({
|
|
450
|
+
...opts,
|
|
451
|
+
security: opts.security
|
|
452
|
+
});
|
|
453
|
+
if (opts.requestValidator) await opts.requestValidator(opts);
|
|
454
|
+
if (opts.body !== void 0 && opts.bodySerializer) opts.serializedBody = opts.bodySerializer(opts.body);
|
|
455
|
+
if (opts.body === void 0 || opts.serializedBody === "") opts.headers.delete("Content-Type");
|
|
456
|
+
const resolvedOpts = opts;
|
|
457
|
+
return {
|
|
458
|
+
opts: resolvedOpts,
|
|
459
|
+
url: buildUrl(resolvedOpts)
|
|
460
|
+
};
|
|
461
|
+
};
|
|
462
|
+
const request = async (options) => {
|
|
463
|
+
const { opts, url } = await beforeRequest(options);
|
|
464
|
+
const requestInit = {
|
|
465
|
+
redirect: "follow",
|
|
466
|
+
...opts,
|
|
467
|
+
body: getValidRequestBody(opts)
|
|
468
|
+
};
|
|
469
|
+
let request = new Request(url, requestInit);
|
|
470
|
+
for (const fn of interceptors.request.fns) if (fn) request = await fn(request, opts);
|
|
471
|
+
const _fetch = opts.fetch;
|
|
472
|
+
let response;
|
|
473
|
+
try {
|
|
474
|
+
response = await _fetch(request);
|
|
475
|
+
} catch (error) {
|
|
476
|
+
let finalError = error;
|
|
477
|
+
for (const fn of interceptors.error.fns) if (fn) finalError = await fn(error, void 0, request, opts);
|
|
478
|
+
finalError = finalError || {};
|
|
479
|
+
if (opts.throwOnError) throw finalError;
|
|
480
|
+
return opts.responseStyle === "data" ? void 0 : {
|
|
481
|
+
error: finalError,
|
|
482
|
+
request,
|
|
483
|
+
response: void 0
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
for (const fn of interceptors.response.fns) if (fn) response = await fn(response, request, opts);
|
|
487
|
+
const result = {
|
|
488
|
+
request,
|
|
489
|
+
response
|
|
490
|
+
};
|
|
491
|
+
if (response.ok) {
|
|
492
|
+
const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
|
|
493
|
+
if (response.status === 204 || response.headers.get("Content-Length") === "0") {
|
|
494
|
+
let emptyData;
|
|
495
|
+
switch (parseAs) {
|
|
496
|
+
case "arrayBuffer":
|
|
497
|
+
case "blob":
|
|
498
|
+
case "text":
|
|
499
|
+
emptyData = await response[parseAs]();
|
|
500
|
+
break;
|
|
501
|
+
case "formData":
|
|
502
|
+
emptyData = new FormData();
|
|
503
|
+
break;
|
|
504
|
+
case "stream":
|
|
505
|
+
emptyData = response.body;
|
|
506
|
+
break;
|
|
507
|
+
default:
|
|
508
|
+
emptyData = {};
|
|
509
|
+
break;
|
|
510
|
+
}
|
|
511
|
+
return opts.responseStyle === "data" ? emptyData : {
|
|
512
|
+
data: emptyData,
|
|
513
|
+
...result
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
let data;
|
|
517
|
+
switch (parseAs) {
|
|
518
|
+
case "arrayBuffer":
|
|
519
|
+
case "blob":
|
|
520
|
+
case "formData":
|
|
521
|
+
case "text":
|
|
522
|
+
data = await response[parseAs]();
|
|
523
|
+
break;
|
|
524
|
+
case "json": {
|
|
525
|
+
const text = await response.text();
|
|
526
|
+
data = text ? JSON.parse(text) : {};
|
|
527
|
+
break;
|
|
528
|
+
}
|
|
529
|
+
case "stream": return opts.responseStyle === "data" ? response.body : {
|
|
530
|
+
data: response.body,
|
|
531
|
+
...result
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
if (parseAs === "json") {
|
|
535
|
+
if (opts.responseValidator) await opts.responseValidator(data);
|
|
536
|
+
if (opts.responseTransformer) data = await opts.responseTransformer(data);
|
|
537
|
+
}
|
|
538
|
+
return opts.responseStyle === "data" ? data : {
|
|
539
|
+
data,
|
|
540
|
+
...result
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
const textError = await response.text();
|
|
544
|
+
let jsonError;
|
|
545
|
+
try {
|
|
546
|
+
jsonError = JSON.parse(textError);
|
|
547
|
+
} catch {}
|
|
548
|
+
const error = jsonError ?? textError;
|
|
549
|
+
let finalError = error;
|
|
550
|
+
for (const fn of interceptors.error.fns) if (fn) finalError = await fn(error, response, request, opts);
|
|
551
|
+
finalError = finalError || {};
|
|
552
|
+
if (opts.throwOnError) throw finalError;
|
|
553
|
+
return opts.responseStyle === "data" ? void 0 : {
|
|
554
|
+
error: finalError,
|
|
555
|
+
...result
|
|
556
|
+
};
|
|
557
|
+
};
|
|
558
|
+
const makeMethodFn = (method) => (options) => request({
|
|
559
|
+
...options,
|
|
560
|
+
method
|
|
561
|
+
});
|
|
562
|
+
const makeSseFn = (method) => async (options) => {
|
|
563
|
+
const { opts, url } = await beforeRequest(options);
|
|
564
|
+
return createSseClient({
|
|
565
|
+
...opts,
|
|
566
|
+
body: opts.body,
|
|
567
|
+
headers: opts.headers,
|
|
568
|
+
method,
|
|
569
|
+
onRequest: async (url, init) => {
|
|
570
|
+
let request = new Request(url, init);
|
|
571
|
+
for (const fn of interceptors.request.fns) if (fn) request = await fn(request, opts);
|
|
572
|
+
return request;
|
|
573
|
+
},
|
|
574
|
+
serializedBody: getValidRequestBody(opts),
|
|
575
|
+
url
|
|
576
|
+
});
|
|
577
|
+
};
|
|
578
|
+
const _buildUrl = (options) => buildUrl({
|
|
579
|
+
..._config,
|
|
580
|
+
...options
|
|
581
|
+
});
|
|
582
|
+
return {
|
|
583
|
+
buildUrl: _buildUrl,
|
|
584
|
+
connect: makeMethodFn("CONNECT"),
|
|
585
|
+
delete: makeMethodFn("DELETE"),
|
|
586
|
+
get: makeMethodFn("GET"),
|
|
587
|
+
getConfig,
|
|
588
|
+
head: makeMethodFn("HEAD"),
|
|
589
|
+
interceptors,
|
|
590
|
+
options: makeMethodFn("OPTIONS"),
|
|
591
|
+
patch: makeMethodFn("PATCH"),
|
|
592
|
+
post: makeMethodFn("POST"),
|
|
593
|
+
put: makeMethodFn("PUT"),
|
|
594
|
+
request,
|
|
595
|
+
setConfig,
|
|
596
|
+
sse: {
|
|
597
|
+
connect: makeSseFn("CONNECT"),
|
|
598
|
+
delete: makeSseFn("DELETE"),
|
|
599
|
+
get: makeSseFn("GET"),
|
|
600
|
+
head: makeSseFn("HEAD"),
|
|
601
|
+
options: makeSseFn("OPTIONS"),
|
|
602
|
+
patch: makeSseFn("PATCH"),
|
|
603
|
+
post: makeSseFn("POST"),
|
|
604
|
+
put: makeSseFn("PUT"),
|
|
605
|
+
trace: makeSseFn("TRACE")
|
|
606
|
+
},
|
|
607
|
+
trace: makeMethodFn("TRACE")
|
|
608
|
+
};
|
|
609
|
+
};
|
|
610
|
+
//#endregion
|
|
611
|
+
//#region src/api/generated/client.gen.ts
|
|
612
|
+
const client$1 = createClient(createConfig({ baseUrl: "https://www.primitive.dev/api/v1" }));
|
|
613
|
+
//#endregion
|
|
614
|
+
//#region src/api/generated/sdk.gen.ts
|
|
615
|
+
var sdk_gen_exports = /* @__PURE__ */ __exportAll({
|
|
616
|
+
addDomain: () => addDomain,
|
|
617
|
+
createEndpoint: () => createEndpoint,
|
|
618
|
+
createFilter: () => createFilter,
|
|
619
|
+
deleteDomain: () => deleteDomain,
|
|
620
|
+
deleteEmail: () => deleteEmail,
|
|
621
|
+
deleteEndpoint: () => deleteEndpoint,
|
|
622
|
+
deleteFilter: () => deleteFilter,
|
|
623
|
+
downloadAttachments: () => downloadAttachments,
|
|
624
|
+
downloadRawEmail: () => downloadRawEmail,
|
|
625
|
+
getAccount: () => getAccount,
|
|
626
|
+
getEmail: () => getEmail,
|
|
627
|
+
getStorageStats: () => getStorageStats,
|
|
628
|
+
getWebhookSecret: () => getWebhookSecret,
|
|
629
|
+
listDeliveries: () => listDeliveries,
|
|
630
|
+
listDomains: () => listDomains,
|
|
631
|
+
listEmails: () => listEmails,
|
|
632
|
+
listEndpoints: () => listEndpoints,
|
|
633
|
+
listFilters: () => listFilters,
|
|
634
|
+
replayDelivery: () => replayDelivery,
|
|
635
|
+
replayEmailWebhooks: () => replayEmailWebhooks,
|
|
636
|
+
rotateWebhookSecret: () => rotateWebhookSecret,
|
|
637
|
+
sendEmail: () => sendEmail,
|
|
638
|
+
testEndpoint: () => testEndpoint,
|
|
639
|
+
updateAccount: () => updateAccount,
|
|
640
|
+
updateDomain: () => updateDomain,
|
|
641
|
+
updateEndpoint: () => updateEndpoint,
|
|
642
|
+
updateFilter: () => updateFilter,
|
|
643
|
+
verifyDomain: () => verifyDomain
|
|
644
|
+
});
|
|
645
|
+
/**
|
|
646
|
+
* Get account info
|
|
647
|
+
*/
|
|
648
|
+
const getAccount = (options) => (options?.client ?? client$1).get({
|
|
649
|
+
security: [{
|
|
650
|
+
scheme: "bearer",
|
|
651
|
+
type: "http"
|
|
652
|
+
}],
|
|
653
|
+
url: "/account",
|
|
654
|
+
...options
|
|
655
|
+
});
|
|
656
|
+
/**
|
|
657
|
+
* Update account settings
|
|
658
|
+
*/
|
|
659
|
+
const updateAccount = (options) => (options.client ?? client$1).patch({
|
|
660
|
+
security: [{
|
|
661
|
+
scheme: "bearer",
|
|
662
|
+
type: "http"
|
|
663
|
+
}],
|
|
664
|
+
url: "/account",
|
|
665
|
+
...options,
|
|
666
|
+
headers: {
|
|
667
|
+
"Content-Type": "application/json",
|
|
668
|
+
...options.headers
|
|
669
|
+
}
|
|
670
|
+
});
|
|
671
|
+
/**
|
|
672
|
+
* Get storage usage
|
|
673
|
+
*/
|
|
674
|
+
const getStorageStats = (options) => (options?.client ?? client$1).get({
|
|
675
|
+
security: [{
|
|
676
|
+
scheme: "bearer",
|
|
677
|
+
type: "http"
|
|
678
|
+
}],
|
|
679
|
+
url: "/account/storage",
|
|
680
|
+
...options
|
|
681
|
+
});
|
|
682
|
+
/**
|
|
683
|
+
* Get webhook signing secret
|
|
684
|
+
*
|
|
685
|
+
* Returns the webhook signing secret for your account. If no secret
|
|
686
|
+
* exists yet, one is generated automatically on first access.
|
|
687
|
+
*
|
|
688
|
+
*/
|
|
689
|
+
const getWebhookSecret = (options) => (options?.client ?? client$1).get({
|
|
690
|
+
security: [{
|
|
691
|
+
scheme: "bearer",
|
|
692
|
+
type: "http"
|
|
693
|
+
}],
|
|
694
|
+
url: "/account/webhook-secret",
|
|
695
|
+
...options
|
|
696
|
+
});
|
|
697
|
+
/**
|
|
698
|
+
* Rotate webhook signing secret
|
|
699
|
+
*
|
|
700
|
+
* Generates a new webhook signing secret, replacing the current one.
|
|
701
|
+
* Rate limited to once per 60 minutes.
|
|
702
|
+
*
|
|
703
|
+
*/
|
|
704
|
+
const rotateWebhookSecret = (options) => (options?.client ?? client$1).post({
|
|
705
|
+
security: [{
|
|
706
|
+
scheme: "bearer",
|
|
707
|
+
type: "http"
|
|
708
|
+
}],
|
|
709
|
+
url: "/account/webhook-secret/rotate",
|
|
710
|
+
...options
|
|
711
|
+
});
|
|
712
|
+
/**
|
|
713
|
+
* List all domains
|
|
714
|
+
*
|
|
715
|
+
* Returns all verified and unverified domains for your organization,
|
|
716
|
+
* sorted by creation date (newest first). Each domain includes a
|
|
717
|
+
* `verified` boolean to distinguish between the two states.
|
|
718
|
+
*
|
|
719
|
+
*/
|
|
720
|
+
const listDomains = (options) => (options?.client ?? client$1).get({
|
|
721
|
+
security: [{
|
|
722
|
+
scheme: "bearer",
|
|
723
|
+
type: "http"
|
|
724
|
+
}],
|
|
725
|
+
url: "/domains",
|
|
726
|
+
...options
|
|
727
|
+
});
|
|
728
|
+
/**
|
|
729
|
+
* Claim a new domain
|
|
730
|
+
*
|
|
731
|
+
* Creates an unverified domain claim. You will receive a
|
|
732
|
+
* `verification_token` to add as a DNS TXT record before
|
|
733
|
+
* calling the verify endpoint.
|
|
734
|
+
*
|
|
735
|
+
*/
|
|
736
|
+
const addDomain = (options) => (options.client ?? client$1).post({
|
|
737
|
+
security: [{
|
|
738
|
+
scheme: "bearer",
|
|
739
|
+
type: "http"
|
|
740
|
+
}],
|
|
741
|
+
url: "/domains",
|
|
742
|
+
...options,
|
|
743
|
+
headers: {
|
|
744
|
+
"Content-Type": "application/json",
|
|
745
|
+
...options.headers
|
|
746
|
+
}
|
|
747
|
+
});
|
|
748
|
+
/**
|
|
749
|
+
* Delete a domain
|
|
750
|
+
*
|
|
751
|
+
* Deletes a verified or unverified domain claim.
|
|
752
|
+
*/
|
|
753
|
+
const deleteDomain = (options) => (options.client ?? client$1).delete({
|
|
754
|
+
security: [{
|
|
755
|
+
scheme: "bearer",
|
|
756
|
+
type: "http"
|
|
757
|
+
}],
|
|
758
|
+
url: "/domains/{id}",
|
|
759
|
+
...options
|
|
760
|
+
});
|
|
761
|
+
/**
|
|
762
|
+
* Update domain settings
|
|
763
|
+
*
|
|
764
|
+
* Update a verified domain's settings. Only verified domains can be
|
|
765
|
+
* updated. Per-domain spam thresholds require a Pro plan.
|
|
766
|
+
*
|
|
767
|
+
*/
|
|
768
|
+
const updateDomain = (options) => (options.client ?? client$1).patch({
|
|
769
|
+
security: [{
|
|
770
|
+
scheme: "bearer",
|
|
771
|
+
type: "http"
|
|
772
|
+
}],
|
|
773
|
+
url: "/domains/{id}",
|
|
774
|
+
...options,
|
|
775
|
+
headers: {
|
|
776
|
+
"Content-Type": "application/json",
|
|
777
|
+
...options.headers
|
|
778
|
+
}
|
|
779
|
+
});
|
|
780
|
+
/**
|
|
781
|
+
* Verify domain ownership
|
|
782
|
+
*
|
|
783
|
+
* Checks DNS records (MX and TXT) to verify domain ownership.
|
|
784
|
+
* On success, the domain is promoted from unverified to verified.
|
|
785
|
+
* On failure, returns which checks passed and which failed.
|
|
786
|
+
*
|
|
787
|
+
*/
|
|
788
|
+
const verifyDomain = (options) => (options.client ?? client$1).post({
|
|
789
|
+
security: [{
|
|
790
|
+
scheme: "bearer",
|
|
791
|
+
type: "http"
|
|
792
|
+
}],
|
|
793
|
+
url: "/domains/{id}/verify",
|
|
794
|
+
...options
|
|
795
|
+
});
|
|
796
|
+
/**
|
|
797
|
+
* List emails
|
|
798
|
+
*
|
|
799
|
+
* Returns a paginated list of received emails. Supports filtering by
|
|
800
|
+
* domain, status, date range, and free-text search across subject,
|
|
801
|
+
* sender, and recipient fields.
|
|
802
|
+
*
|
|
803
|
+
*/
|
|
804
|
+
const listEmails = (options) => (options?.client ?? client$1).get({
|
|
805
|
+
security: [{
|
|
806
|
+
scheme: "bearer",
|
|
807
|
+
type: "http"
|
|
808
|
+
}],
|
|
809
|
+
url: "/emails",
|
|
810
|
+
...options
|
|
811
|
+
});
|
|
812
|
+
/**
|
|
813
|
+
* Delete an email
|
|
814
|
+
*/
|
|
815
|
+
const deleteEmail = (options) => (options.client ?? client$1).delete({
|
|
816
|
+
security: [{
|
|
817
|
+
scheme: "bearer",
|
|
818
|
+
type: "http"
|
|
819
|
+
}],
|
|
820
|
+
url: "/emails/{id}",
|
|
821
|
+
...options
|
|
822
|
+
});
|
|
823
|
+
/**
|
|
824
|
+
* Get email details
|
|
825
|
+
*/
|
|
826
|
+
const getEmail = (options) => (options.client ?? client$1).get({
|
|
827
|
+
security: [{
|
|
828
|
+
scheme: "bearer",
|
|
829
|
+
type: "http"
|
|
830
|
+
}],
|
|
831
|
+
url: "/emails/{id}",
|
|
832
|
+
...options
|
|
833
|
+
});
|
|
834
|
+
/**
|
|
835
|
+
* Download raw email
|
|
836
|
+
*
|
|
837
|
+
* Downloads the raw RFC 822 email file (.eml). Authenticates via
|
|
838
|
+
* a signed download token (provided in webhook payloads) or a
|
|
839
|
+
* valid session.
|
|
840
|
+
*
|
|
841
|
+
*/
|
|
842
|
+
const downloadRawEmail = (options) => (options.client ?? client$1).get({
|
|
843
|
+
security: [{
|
|
844
|
+
scheme: "bearer",
|
|
845
|
+
type: "http"
|
|
846
|
+
}, {
|
|
847
|
+
in: "query",
|
|
848
|
+
name: "token",
|
|
849
|
+
type: "apiKey"
|
|
850
|
+
}],
|
|
851
|
+
url: "/emails/{id}/raw",
|
|
852
|
+
...options
|
|
853
|
+
});
|
|
854
|
+
/**
|
|
855
|
+
* Download email attachments
|
|
856
|
+
*
|
|
857
|
+
* Downloads all attachments as a gzip-compressed tar archive.
|
|
858
|
+
* Authenticates via a signed download token (provided in webhook
|
|
859
|
+
* payloads) or a valid session.
|
|
860
|
+
*
|
|
861
|
+
*/
|
|
862
|
+
const downloadAttachments = (options) => (options.client ?? client$1).get({
|
|
863
|
+
security: [{
|
|
864
|
+
scheme: "bearer",
|
|
865
|
+
type: "http"
|
|
866
|
+
}, {
|
|
867
|
+
in: "query",
|
|
868
|
+
name: "token",
|
|
869
|
+
type: "apiKey"
|
|
870
|
+
}],
|
|
871
|
+
url: "/emails/{id}/attachments.tar.gz",
|
|
872
|
+
...options
|
|
873
|
+
});
|
|
874
|
+
/**
|
|
875
|
+
* Replay email webhooks
|
|
876
|
+
*
|
|
877
|
+
* Re-delivers the webhook payload for this email to all active
|
|
878
|
+
* endpoints matching the email's domain. Rate limited per-email
|
|
879
|
+
* (short cooldown between successive replays of the same email)
|
|
880
|
+
* and per-org (burst + sustained windows), sharing an org-wide
|
|
881
|
+
* budget with delivery replays.
|
|
882
|
+
*
|
|
883
|
+
*/
|
|
884
|
+
const replayEmailWebhooks = (options) => (options.client ?? client$1).post({
|
|
885
|
+
security: [{
|
|
886
|
+
scheme: "bearer",
|
|
887
|
+
type: "http"
|
|
888
|
+
}],
|
|
889
|
+
url: "/emails/{id}/replay",
|
|
890
|
+
...options
|
|
891
|
+
});
|
|
892
|
+
/**
|
|
893
|
+
* List webhook endpoints
|
|
894
|
+
*
|
|
895
|
+
* Returns all active (non-deleted) webhook endpoints.
|
|
896
|
+
*/
|
|
897
|
+
const listEndpoints = (options) => (options?.client ?? client$1).get({
|
|
898
|
+
security: [{
|
|
899
|
+
scheme: "bearer",
|
|
900
|
+
type: "http"
|
|
901
|
+
}],
|
|
902
|
+
url: "/endpoints",
|
|
903
|
+
...options
|
|
904
|
+
});
|
|
905
|
+
/**
|
|
906
|
+
* Create a webhook endpoint
|
|
907
|
+
*
|
|
908
|
+
* Creates a new webhook endpoint. If a deactivated endpoint with the
|
|
909
|
+
* same URL and domain exists, it is reactivated instead.
|
|
910
|
+
* Subject to plan limits on the number of active endpoints.
|
|
911
|
+
*
|
|
912
|
+
*/
|
|
913
|
+
const createEndpoint = (options) => (options.client ?? client$1).post({
|
|
914
|
+
security: [{
|
|
915
|
+
scheme: "bearer",
|
|
916
|
+
type: "http"
|
|
917
|
+
}],
|
|
918
|
+
url: "/endpoints",
|
|
919
|
+
...options,
|
|
920
|
+
headers: {
|
|
921
|
+
"Content-Type": "application/json",
|
|
922
|
+
...options.headers
|
|
923
|
+
}
|
|
924
|
+
});
|
|
925
|
+
/**
|
|
926
|
+
* Delete a webhook endpoint
|
|
927
|
+
*
|
|
928
|
+
* Soft-deletes a webhook endpoint. The endpoint will no longer
|
|
929
|
+
* receive webhook deliveries.
|
|
930
|
+
*
|
|
931
|
+
*/
|
|
932
|
+
const deleteEndpoint = (options) => (options.client ?? client$1).delete({
|
|
933
|
+
security: [{
|
|
934
|
+
scheme: "bearer",
|
|
935
|
+
type: "http"
|
|
936
|
+
}],
|
|
937
|
+
url: "/endpoints/{id}",
|
|
938
|
+
...options
|
|
939
|
+
});
|
|
940
|
+
/**
|
|
941
|
+
* Update a webhook endpoint
|
|
942
|
+
*
|
|
943
|
+
* Updates an active webhook endpoint. If the URL is changed, the old
|
|
944
|
+
* endpoint is deactivated and a new one is created (or an existing
|
|
945
|
+
* deactivated endpoint with the new URL is reactivated).
|
|
946
|
+
*
|
|
947
|
+
*/
|
|
948
|
+
const updateEndpoint = (options) => (options.client ?? client$1).patch({
|
|
949
|
+
security: [{
|
|
950
|
+
scheme: "bearer",
|
|
951
|
+
type: "http"
|
|
952
|
+
}],
|
|
953
|
+
url: "/endpoints/{id}",
|
|
954
|
+
...options,
|
|
955
|
+
headers: {
|
|
956
|
+
"Content-Type": "application/json",
|
|
957
|
+
...options.headers
|
|
958
|
+
}
|
|
959
|
+
});
|
|
960
|
+
/**
|
|
961
|
+
* Send a test webhook
|
|
962
|
+
*
|
|
963
|
+
* Sends a sample `email.received` event to the endpoint. The request
|
|
964
|
+
* includes SSRF protection (private IP rejection and DNS pinning).
|
|
965
|
+
* Rate limited to 4 per minute and 30 per hour (non-exempt).
|
|
966
|
+
* Successful deliveries and verified-domain endpoints are exempt
|
|
967
|
+
* from the rate limit.
|
|
968
|
+
*
|
|
969
|
+
*/
|
|
970
|
+
const testEndpoint = (options) => (options.client ?? client$1).post({
|
|
971
|
+
security: [{
|
|
972
|
+
scheme: "bearer",
|
|
973
|
+
type: "http"
|
|
974
|
+
}],
|
|
975
|
+
url: "/endpoints/{id}/test",
|
|
976
|
+
...options
|
|
977
|
+
});
|
|
978
|
+
/**
|
|
979
|
+
* List filter rules
|
|
980
|
+
*
|
|
981
|
+
* Returns all whitelist and blocklist filter rules.
|
|
982
|
+
*/
|
|
983
|
+
const listFilters = (options) => (options?.client ?? client$1).get({
|
|
984
|
+
security: [{
|
|
985
|
+
scheme: "bearer",
|
|
986
|
+
type: "http"
|
|
987
|
+
}],
|
|
988
|
+
url: "/filters",
|
|
989
|
+
...options
|
|
990
|
+
});
|
|
991
|
+
/**
|
|
992
|
+
* Create a filter rule
|
|
993
|
+
*
|
|
994
|
+
* Creates a new whitelist or blocklist filter. Per-domain filters
|
|
995
|
+
* require a Pro plan. Patterns are stored as lowercase.
|
|
996
|
+
*
|
|
997
|
+
*/
|
|
998
|
+
const createFilter = (options) => (options.client ?? client$1).post({
|
|
999
|
+
security: [{
|
|
1000
|
+
scheme: "bearer",
|
|
1001
|
+
type: "http"
|
|
1002
|
+
}],
|
|
1003
|
+
url: "/filters",
|
|
1004
|
+
...options,
|
|
1005
|
+
headers: {
|
|
1006
|
+
"Content-Type": "application/json",
|
|
1007
|
+
...options.headers
|
|
1008
|
+
}
|
|
1009
|
+
});
|
|
1010
|
+
/**
|
|
1011
|
+
* Delete a filter rule
|
|
1012
|
+
*/
|
|
1013
|
+
const deleteFilter = (options) => (options.client ?? client$1).delete({
|
|
1014
|
+
security: [{
|
|
1015
|
+
scheme: "bearer",
|
|
1016
|
+
type: "http"
|
|
1017
|
+
}],
|
|
1018
|
+
url: "/filters/{id}",
|
|
1019
|
+
...options
|
|
1020
|
+
});
|
|
1021
|
+
/**
|
|
1022
|
+
* Update a filter rule
|
|
1023
|
+
*
|
|
1024
|
+
* Toggle a filter's enabled state.
|
|
1025
|
+
*/
|
|
1026
|
+
const updateFilter = (options) => (options.client ?? client$1).patch({
|
|
1027
|
+
security: [{
|
|
1028
|
+
scheme: "bearer",
|
|
1029
|
+
type: "http"
|
|
1030
|
+
}],
|
|
1031
|
+
url: "/filters/{id}",
|
|
1032
|
+
...options,
|
|
1033
|
+
headers: {
|
|
1034
|
+
"Content-Type": "application/json",
|
|
1035
|
+
...options.headers
|
|
1036
|
+
}
|
|
1037
|
+
});
|
|
1038
|
+
/**
|
|
1039
|
+
* List webhook deliveries
|
|
1040
|
+
*
|
|
1041
|
+
* Returns a paginated list of webhook delivery attempts. Each delivery
|
|
1042
|
+
* includes a nested `email` object with sender, recipient, and subject.
|
|
1043
|
+
*
|
|
1044
|
+
*/
|
|
1045
|
+
const listDeliveries = (options) => (options?.client ?? client$1).get({
|
|
1046
|
+
security: [{
|
|
1047
|
+
scheme: "bearer",
|
|
1048
|
+
type: "http"
|
|
1049
|
+
}],
|
|
1050
|
+
url: "/webhooks/deliveries",
|
|
1051
|
+
...options
|
|
1052
|
+
});
|
|
1053
|
+
/**
|
|
1054
|
+
* Replay a webhook delivery
|
|
1055
|
+
*
|
|
1056
|
+
* Re-sends the stored webhook payload from a previous delivery attempt.
|
|
1057
|
+
* If the original endpoint is still active, it is targeted. If the
|
|
1058
|
+
* original endpoint was deleted, the oldest active endpoint is used.
|
|
1059
|
+
* Deactivated endpoints cannot be replayed to. Rate limited per-org,
|
|
1060
|
+
* sharing an org-wide budget with email replays.
|
|
1061
|
+
*
|
|
1062
|
+
*/
|
|
1063
|
+
const replayDelivery = (options) => (options.client ?? client$1).post({
|
|
1064
|
+
security: [{
|
|
1065
|
+
scheme: "bearer",
|
|
1066
|
+
type: "http"
|
|
1067
|
+
}],
|
|
1068
|
+
url: "/webhooks/deliveries/{id}/replay",
|
|
1069
|
+
...options
|
|
1070
|
+
});
|
|
1071
|
+
/**
|
|
1072
|
+
* Send outbound email
|
|
1073
|
+
*
|
|
1074
|
+
* Sends an outbound email through Primitive's outbound relay. By default
|
|
1075
|
+
* the request returns once the relay accepts the message for delivery.
|
|
1076
|
+
* Set `wait: true` to wait for the first downstream SMTP delivery outcome.
|
|
1077
|
+
*
|
|
1078
|
+
*/
|
|
1079
|
+
const sendEmail = (options) => (options.client ?? client$1).post({
|
|
1080
|
+
security: [{
|
|
1081
|
+
scheme: "bearer",
|
|
1082
|
+
type: "http"
|
|
1083
|
+
}],
|
|
1084
|
+
url: "/send-mail",
|
|
1085
|
+
...options,
|
|
1086
|
+
headers: {
|
|
1087
|
+
"Content-Type": "application/json",
|
|
1088
|
+
...options.headers
|
|
1089
|
+
}
|
|
1090
|
+
});
|
|
1091
|
+
//#endregion
|
|
1092
|
+
//#region src/api/index.ts
|
|
1093
|
+
const DEFAULT_BASE_URL = "https://www.primitive.dev/api/v1";
|
|
1094
|
+
const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
1095
|
+
const MAX_THREAD_REFERENCES = 100;
|
|
1096
|
+
const MAX_THREAD_HEADER_BYTES = 8 * 1024;
|
|
1097
|
+
const MAX_FROM_HEADER_LENGTH = 998;
|
|
1098
|
+
const MAX_TO_HEADER_LENGTH = 320;
|
|
1099
|
+
function createDefaultAuth(apiKey) {
|
|
1100
|
+
return (security) => {
|
|
1101
|
+
if (security.type === "http" && security.scheme === "bearer") return apiKey;
|
|
1102
|
+
};
|
|
1103
|
+
}
|
|
1104
|
+
function validateAddressHeader(field, value) {
|
|
1105
|
+
const trimmed = value.trim();
|
|
1106
|
+
const maxLength = field === "from" ? MAX_FROM_HEADER_LENGTH : MAX_TO_HEADER_LENGTH;
|
|
1107
|
+
if (trimmed.length < 3) throw new TypeError(`${field} must be at least 3 characters`);
|
|
1108
|
+
if (trimmed.length > maxLength) throw new TypeError(`${field} must be at most ${maxLength} characters`);
|
|
1109
|
+
}
|
|
1110
|
+
function validateEmailAddress(field, value) {
|
|
1111
|
+
if (!EMAIL_REGEX.test(value) && !/^.+<[^\s@]+@[^\s@]+\.[^\s@]+>$/.test(value)) throw new TypeError(`${field} must be a valid email address`);
|
|
1112
|
+
}
|
|
1113
|
+
function validateThreadHeaderValue(field, value) {
|
|
1114
|
+
if (value.trim().length === 0) throw new TypeError(`${field} must be a non-empty string`);
|
|
1115
|
+
if ([...value].some((char) => {
|
|
1116
|
+
const code = char.charCodeAt(0);
|
|
1117
|
+
return code <= 31 || code === 127;
|
|
1118
|
+
})) throw new TypeError(`${field} must not contain control characters`);
|
|
1119
|
+
if (value.length > 998) throw new TypeError(`${field} must be at most 998 characters`);
|
|
1120
|
+
}
|
|
1121
|
+
function validateSendInput(input) {
|
|
1122
|
+
validateAddressHeader("from", input.from);
|
|
1123
|
+
validateAddressHeader("to", input.to);
|
|
1124
|
+
validateEmailAddress("to", input.to);
|
|
1125
|
+
if (input.subject.trim().length === 0) throw new TypeError("subject must be a non-empty string");
|
|
1126
|
+
if (!input.bodyText && !input.bodyHtml) throw new TypeError("one of bodyText or bodyHtml is required");
|
|
1127
|
+
if (input.thread?.inReplyTo) validateThreadHeaderValue("thread.inReplyTo", input.thread.inReplyTo);
|
|
1128
|
+
if (input.thread?.references) {
|
|
1129
|
+
if (input.thread.references.length > MAX_THREAD_REFERENCES) throw new TypeError(`thread.references must contain at most ${MAX_THREAD_REFERENCES} values`);
|
|
1130
|
+
for (const [index, reference] of input.thread.references.entries()) validateThreadHeaderValue(`thread.references[${index}]`, reference);
|
|
1131
|
+
if (input.thread.references.join(" ").length > MAX_THREAD_HEADER_BYTES) throw new TypeError(`thread.references header must be at most ${MAX_THREAD_HEADER_BYTES} characters`);
|
|
1132
|
+
}
|
|
1133
|
+
if (input.waitTimeoutMs !== void 0) {
|
|
1134
|
+
if (!Number.isInteger(input.waitTimeoutMs)) throw new TypeError("waitTimeoutMs must be an integer");
|
|
1135
|
+
if (input.waitTimeoutMs < 1e3 || input.waitTimeoutMs > 3e4) throw new TypeError("waitTimeoutMs must be between 1000 and 30000");
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
function validateForwardInput(input) {
|
|
1139
|
+
validateEmailAddress("to", input.to);
|
|
1140
|
+
if (input.subject !== void 0 && input.subject.trim().length === 0) throw new TypeError("subject must be a non-empty string");
|
|
1141
|
+
}
|
|
1142
|
+
function parseApiErrorPayload(payload) {
|
|
1143
|
+
const fallback = {
|
|
1144
|
+
message: "Primitive API request failed",
|
|
1145
|
+
code: void 0,
|
|
1146
|
+
gates: void 0,
|
|
1147
|
+
requestId: void 0,
|
|
1148
|
+
details: void 0
|
|
1149
|
+
};
|
|
1150
|
+
if (!payload || typeof payload !== "object") return fallback;
|
|
1151
|
+
if ("error" in payload && payload.error && typeof payload.error === "object") {
|
|
1152
|
+
const err = payload.error;
|
|
1153
|
+
return {
|
|
1154
|
+
message: typeof err.message === "string" ? err.message : fallback.message,
|
|
1155
|
+
code: typeof err.code === "string" ? err.code : void 0,
|
|
1156
|
+
gates: Array.isArray(err.gates) ? err.gates : void 0,
|
|
1157
|
+
requestId: typeof err.request_id === "string" ? err.request_id : void 0,
|
|
1158
|
+
details: err.details && typeof err.details === "object" ? err.details : void 0
|
|
1159
|
+
};
|
|
1160
|
+
}
|
|
1161
|
+
if ("message" in payload && typeof payload.message === "string") return {
|
|
1162
|
+
...fallback,
|
|
1163
|
+
message: payload.message
|
|
1164
|
+
};
|
|
1165
|
+
return fallback;
|
|
1166
|
+
}
|
|
1167
|
+
var PrimitiveApiError = class extends Error {
|
|
1168
|
+
status;
|
|
1169
|
+
code;
|
|
1170
|
+
gates;
|
|
1171
|
+
requestId;
|
|
1172
|
+
retryAfter;
|
|
1173
|
+
details;
|
|
1174
|
+
payload;
|
|
1175
|
+
constructor(message, options) {
|
|
1176
|
+
super(message);
|
|
1177
|
+
this.name = "PrimitiveApiError";
|
|
1178
|
+
this.payload = options.payload;
|
|
1179
|
+
this.status = options.status;
|
|
1180
|
+
this.code = options.code;
|
|
1181
|
+
this.gates = options.gates;
|
|
1182
|
+
this.requestId = options.requestId;
|
|
1183
|
+
this.retryAfter = options.retryAfter;
|
|
1184
|
+
this.details = options.details;
|
|
1185
|
+
}
|
|
1186
|
+
};
|
|
1187
|
+
function parseRetryAfterHeader(response) {
|
|
1188
|
+
if (!response) return void 0;
|
|
1189
|
+
const raw = response.headers.get("retry-after");
|
|
1190
|
+
if (!raw) return void 0;
|
|
1191
|
+
const seconds = Number.parseInt(raw, 10);
|
|
1192
|
+
return Number.isFinite(seconds) ? seconds : void 0;
|
|
1193
|
+
}
|
|
1194
|
+
var PrimitiveApiClient = class {
|
|
1195
|
+
client;
|
|
1196
|
+
constructor(options = {}) {
|
|
1197
|
+
const { apiKey, auth, baseUrl = DEFAULT_BASE_URL, ...config } = options;
|
|
1198
|
+
this.client = createClient(createConfig({
|
|
1199
|
+
...config,
|
|
1200
|
+
auth: auth ?? createDefaultAuth(apiKey),
|
|
1201
|
+
baseUrl
|
|
1202
|
+
}));
|
|
1203
|
+
}
|
|
1204
|
+
getConfig() {
|
|
1205
|
+
return this.client.getConfig();
|
|
1206
|
+
}
|
|
1207
|
+
setConfig(config) {
|
|
1208
|
+
return this.client.setConfig(config);
|
|
1209
|
+
}
|
|
1210
|
+
};
|
|
1211
|
+
var PrimitiveClient = class extends PrimitiveApiClient {
|
|
1212
|
+
async send(input) {
|
|
1213
|
+
validateSendInput(input);
|
|
1214
|
+
const result = await sendEmail({
|
|
1215
|
+
body: {
|
|
1216
|
+
from: input.from,
|
|
1217
|
+
to: input.to,
|
|
1218
|
+
subject: input.subject,
|
|
1219
|
+
...input.bodyText !== void 0 ? { body_text: input.bodyText } : {},
|
|
1220
|
+
...input.bodyHtml !== void 0 ? { body_html: input.bodyHtml } : {},
|
|
1221
|
+
...input.thread?.inReplyTo ? { in_reply_to: input.thread.inReplyTo } : {},
|
|
1222
|
+
...input.thread?.references?.length ? { references: input.thread.references } : {},
|
|
1223
|
+
...input.wait !== void 0 ? { wait: input.wait } : {},
|
|
1224
|
+
...input.waitTimeoutMs !== void 0 ? { wait_timeout_ms: input.waitTimeoutMs } : {}
|
|
1225
|
+
},
|
|
1226
|
+
...input.idempotencyKey ? { headers: { "Idempotency-Key": input.idempotencyKey } } : {},
|
|
1227
|
+
client: this.client,
|
|
1228
|
+
responseStyle: "fields"
|
|
1229
|
+
});
|
|
1230
|
+
const response = result.response;
|
|
1231
|
+
if (result.error) {
|
|
1232
|
+
const parsed = parseApiErrorPayload(result.error);
|
|
1233
|
+
throw new PrimitiveApiError(parsed.message, {
|
|
1234
|
+
payload: result.error,
|
|
1235
|
+
status: response?.status,
|
|
1236
|
+
code: parsed.code,
|
|
1237
|
+
gates: parsed.gates,
|
|
1238
|
+
requestId: parsed.requestId,
|
|
1239
|
+
retryAfter: parseRetryAfterHeader(response),
|
|
1240
|
+
details: parsed.details
|
|
1241
|
+
});
|
|
1242
|
+
}
|
|
1243
|
+
if (!result.data?.data) throw new PrimitiveApiError("Primitive API returned no send result", {
|
|
1244
|
+
payload: result,
|
|
1245
|
+
status: response?.status
|
|
1246
|
+
});
|
|
1247
|
+
return mapSendResult(result.data.data);
|
|
1248
|
+
}
|
|
1249
|
+
async reply(email, input) {
|
|
1250
|
+
const resolved = typeof input === "string" ? { text: input } : input;
|
|
1251
|
+
return this.send({
|
|
1252
|
+
from: resolved.from ?? email.receivedBy,
|
|
1253
|
+
to: email.replyTarget.address,
|
|
1254
|
+
subject: resolved.subject ?? email.replySubject,
|
|
1255
|
+
bodyText: resolved.text,
|
|
1256
|
+
thread: {
|
|
1257
|
+
...email.thread.messageId ? { inReplyTo: email.thread.messageId } : {},
|
|
1258
|
+
references: email.thread.messageId ? [...email.thread.references, email.thread.messageId] : email.thread.references
|
|
1259
|
+
}
|
|
1260
|
+
});
|
|
1261
|
+
}
|
|
1262
|
+
async forward(email, input) {
|
|
1263
|
+
validateForwardInput(input);
|
|
1264
|
+
return this.send({
|
|
1265
|
+
from: input.from ?? email.receivedBy,
|
|
1266
|
+
to: input.to,
|
|
1267
|
+
subject: input.subject ?? email.forwardSubject,
|
|
1268
|
+
bodyText: buildForwardText(email, input.bodyText)
|
|
1269
|
+
});
|
|
1270
|
+
}
|
|
1271
|
+
};
|
|
1272
|
+
function buildForwardText(email, intro) {
|
|
1273
|
+
return [
|
|
1274
|
+
...intro ? [intro.trim(), ""] : [],
|
|
1275
|
+
"---------- Forwarded message ----------",
|
|
1276
|
+
`From: ${formatAddress(email.sender)}`,
|
|
1277
|
+
`To: ${email.raw.email.headers.to}`,
|
|
1278
|
+
`Subject: ${email.subject ?? ""}`,
|
|
1279
|
+
...email.raw.email.headers.date ? [`Date: ${email.raw.email.headers.date}`] : [],
|
|
1280
|
+
...email.thread.messageId ? [`Message-ID: ${email.thread.messageId}`] : [],
|
|
1281
|
+
"",
|
|
1282
|
+
email.text ?? ""
|
|
1283
|
+
].join("\n").trimEnd();
|
|
1284
|
+
}
|
|
1285
|
+
function mapSendResult(result) {
|
|
1286
|
+
return {
|
|
1287
|
+
id: result.id,
|
|
1288
|
+
status: result.status,
|
|
1289
|
+
queueId: result.queue_id,
|
|
1290
|
+
accepted: result.accepted,
|
|
1291
|
+
rejected: result.rejected,
|
|
1292
|
+
clientIdempotencyKey: result.client_idempotency_key,
|
|
1293
|
+
requestId: result.request_id,
|
|
1294
|
+
contentHash: result.content_hash,
|
|
1295
|
+
...result.delivery_status !== void 0 ? { deliveryStatus: result.delivery_status } : {},
|
|
1296
|
+
...result.smtp_response_code !== void 0 ? { smtpResponseCode: result.smtp_response_code } : {},
|
|
1297
|
+
...result.smtp_response_text !== void 0 ? { smtpResponseText: result.smtp_response_text } : {}
|
|
1298
|
+
};
|
|
1299
|
+
}
|
|
1300
|
+
function createPrimitiveApiClient(options = {}) {
|
|
1301
|
+
return new PrimitiveApiClient(options);
|
|
1302
|
+
}
|
|
1303
|
+
function createPrimitiveClient(options = {}) {
|
|
1304
|
+
return new PrimitiveClient(options);
|
|
1305
|
+
}
|
|
1306
|
+
function client(options = {}) {
|
|
1307
|
+
return new PrimitiveClient(options);
|
|
1308
|
+
}
|
|
1309
|
+
const operations = sdk_gen_exports;
|
|
1310
|
+
//#endregion
|
|
1311
|
+
export { sendEmail as A, listDomains as C, replayDelivery as D, listFilters as E, updateFilter as F, verifyDomain as I, updateAccount as M, updateDomain as N, replayEmailWebhooks as O, updateEndpoint as P, listDeliveries as S, listEndpoints as T, downloadRawEmail as _, client as a, getStorageStats as b, operations as c, createFilter as d, deleteDomain as f, downloadAttachments as g, deleteFilter as h, PrimitiveClient as i, testEndpoint as j, rotateWebhookSecret as k, addDomain as l, deleteEndpoint as m, PrimitiveApiClient as n, createPrimitiveApiClient as o, deleteEmail as p, PrimitiveApiError as r, createPrimitiveClient as s, DEFAULT_BASE_URL as t, createEndpoint as u, getAccount as v, listEmails as w, getWebhookSecret as x, getEmail as y };
|