@primitivedotdev/sdk 0.8.0 → 0.10.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.
@@ -1,12 +1,10 @@
1
- import { __export } from "./chunk-Cl8Af3a2.js";
2
- import { formatAddress } from "./received-email-Q6Cha3wc.js";
3
-
1
+ import { t as __exportAll } from "./chunk-pbuEa-1d.js";
2
+ import { r as formatAddress } from "./received-email-D6tKtWwW.js";
4
3
  //#region src/api/generated/core/bodySerializer.gen.ts
5
4
  const jsonBodySerializer = { bodySerializer: (body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value) };
6
-
7
5
  //#endregion
8
6
  //#region src/api/generated/core/serverSentEvents.gen.ts
9
- function createSseClient({ onRequest, onSseError, onSseEvent, responseTransformer, responseValidator, sseDefaultRetryDelay, sseMaxRetryAttempts, sseMaxRetryDelay, sseSleepFn, url,...options }) {
7
+ function createSseClient({ onRequest, onSseError, onSseEvent, responseTransformer, responseValidator, sseDefaultRetryDelay, sseMaxRetryAttempts, sseMaxRetryDelay, sseSleepFn, url, ...options }) {
10
8
  let lastEventId;
11
9
  const sleep = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
12
10
  const createStream = async function* () {
@@ -28,8 +26,7 @@ function createSseClient({ onRequest, onSseError, onSseEvent, responseTransforme
28
26
  };
29
27
  let request = new Request(url, requestInit);
30
28
  if (onRequest) request = await onRequest(url, requestInit);
31
- const _fetch = options.fetch ?? globalThis.fetch;
32
- const response = await _fetch(request);
29
+ const response = await (options.fetch ?? globalThis.fetch)(request);
33
30
  if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`);
34
31
  if (!response.body) throw new Error("No body in SSE response");
35
32
  const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
@@ -91,15 +88,12 @@ function createSseClient({ onRequest, onSseError, onSseEvent, responseTransforme
91
88
  } catch (error) {
92
89
  onSseError?.(error);
93
90
  if (sseMaxRetryAttempts !== void 0 && attempt >= sseMaxRetryAttempts) break;
94
- const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 3e4);
95
- await sleep(backoff);
91
+ await sleep(Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 3e4));
96
92
  }
97
93
  }
98
94
  };
99
- const stream = createStream();
100
- return { stream };
95
+ return { stream: createStream() };
101
96
  }
102
-
103
97
  //#endregion
104
98
  //#region src/api/generated/core/pathSerializer.gen.ts
105
99
  const separatorArrayExplode = (style) => {
@@ -128,12 +122,12 @@ const separatorObjectExplode = (style) => {
128
122
  };
129
123
  const serializeArrayParam = ({ allowReserved, explode, name, style, value }) => {
130
124
  if (!explode) {
131
- const joinedValues$1 = (allowReserved ? value : value.map((v) => encodeURIComponent(v))).join(separatorArrayNoExplode(style));
125
+ const joinedValues = (allowReserved ? value : value.map((v) => encodeURIComponent(v))).join(separatorArrayNoExplode(style));
132
126
  switch (style) {
133
- case "label": return `.${joinedValues$1}`;
134
- case "matrix": return `;${name}=${joinedValues$1}`;
135
- case "simple": return joinedValues$1;
136
- default: return `${name}=${joinedValues$1}`;
127
+ case "label": return `.${joinedValues}`;
128
+ case "matrix": return `;${name}=${joinedValues}`;
129
+ case "simple": return joinedValues;
130
+ default: return `${name}=${joinedValues}`;
137
131
  }
138
132
  }
139
133
  const separator = separatorArrayExplode(style);
@@ -163,12 +157,12 @@ const serializeObjectParam = ({ allowReserved, explode, name, style, value, valu
163
157
  allowReserved ? v : encodeURIComponent(v)
164
158
  ];
165
159
  });
166
- const joinedValues$1 = values.join(",");
160
+ const joinedValues = values.join(",");
167
161
  switch (style) {
168
- case "form": return `${name}=${joinedValues$1}`;
169
- case "label": return `.${joinedValues$1}`;
170
- case "matrix": return `;${name}=${joinedValues$1}`;
171
- default: return joinedValues$1;
162
+ case "form": return `${name}=${joinedValues}`;
163
+ case "label": return `.${joinedValues}`;
164
+ case "matrix": return `;${name}=${joinedValues}`;
165
+ default: return joinedValues;
172
166
  }
173
167
  }
174
168
  const separator = separatorObjectExplode(style);
@@ -179,7 +173,6 @@ const serializeObjectParam = ({ allowReserved, explode, name, style, value, valu
179
173
  })).join(separator);
180
174
  return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
181
175
  };
182
-
183
176
  //#endregion
184
177
  //#region src/api/generated/core/utils.gen.ts
185
178
  const PATH_PARAM_RE = /\{[^{}]+\}/g;
@@ -248,18 +241,12 @@ const getUrl = ({ baseUrl, path, query, querySerializer, url: _url }) => {
248
241
  };
249
242
  function getValidRequestBody(options) {
250
243
  const hasBody = options.body !== void 0;
251
- const isSerializedBody = hasBody && options.bodySerializer;
252
- if (isSerializedBody) {
253
- if ("serializedBody" in options) {
254
- const hasSerializedBody = options.serializedBody !== void 0 && options.serializedBody !== "";
255
- return hasSerializedBody ? options.serializedBody : null;
256
- }
244
+ if (hasBody && options.bodySerializer) {
245
+ if ("serializedBody" in options) return options.serializedBody !== void 0 && options.serializedBody !== "" ? options.serializedBody : null;
257
246
  return options.body !== "" ? options.body : null;
258
247
  }
259
248
  if (hasBody) return options.body;
260
- return void 0;
261
249
  }
262
-
263
250
  //#endregion
264
251
  //#region src/api/generated/core/auth.gen.ts
265
252
  const getAuthToken = async (auth, callback) => {
@@ -269,10 +256,9 @@ const getAuthToken = async (auth, callback) => {
269
256
  if (auth.scheme === "basic") return `Basic ${btoa(token)}`;
270
257
  return token;
271
258
  };
272
-
273
259
  //#endregion
274
260
  //#region src/api/generated/client/utils.gen.ts
275
- const createQuerySerializer = ({ parameters = {},...args } = {}) => {
261
+ const createQuerySerializer = ({ parameters = {}, ...args } = {}) => {
276
262
  const querySerializer = (queryParams) => {
277
263
  const search = [];
278
264
  if (queryParams && typeof queryParams === "object") for (const name in queryParams) {
@@ -328,14 +314,13 @@ const getParseAs = (contentType) => {
328
314
  "video/"
329
315
  ].some((type) => cleanContent.startsWith(type))) return "blob";
330
316
  if (cleanContent.startsWith("text/")) return "text";
331
- return;
332
317
  };
333
318
  const checkForExistence = (options, name) => {
334
319
  if (!name) return false;
335
320
  if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) return true;
336
321
  return false;
337
322
  };
338
- const setAuthParams = async ({ security,...options }) => {
323
+ const setAuthParams = async ({ security, ...options }) => {
339
324
  for (const auth of security) {
340
325
  if (checkForExistence(options, auth.name)) continue;
341
326
  const token = await getAuthToken(auth, options.auth);
@@ -349,7 +334,6 @@ const setAuthParams = async ({ security,...options }) => {
349
334
  case "cookie":
350
335
  options.headers.append("Cookie", `${name}=${token}`);
351
336
  break;
352
- case "header":
353
337
  default:
354
338
  options.headers.set(name, token);
355
339
  break;
@@ -444,14 +428,13 @@ const createConfig = (override = {}) => ({
444
428
  querySerializer: defaultQuerySerializer,
445
429
  ...override
446
430
  });
447
-
448
431
  //#endregion
449
432
  //#region src/api/generated/client/client.gen.ts
450
433
  const createClient = (config = {}) => {
451
434
  let _config = mergeConfigs(createConfig(), config);
452
435
  const getConfig = () => ({ ..._config });
453
- const setConfig = (config$1) => {
454
- _config = mergeConfigs(_config, config$1);
436
+ const setConfig = (config) => {
437
+ _config = mergeConfigs(_config, config);
455
438
  return getConfig();
456
439
  };
457
440
  const interceptors = createInterceptors();
@@ -471,10 +454,9 @@ const createClient = (config = {}) => {
471
454
  if (opts.body !== void 0 && opts.bodySerializer) opts.serializedBody = opts.bodySerializer(opts.body);
472
455
  if (opts.body === void 0 || opts.serializedBody === "") opts.headers.delete("Content-Type");
473
456
  const resolvedOpts = opts;
474
- const url = buildUrl(resolvedOpts);
475
457
  return {
476
458
  opts: resolvedOpts,
477
- url
459
+ url: buildUrl(resolvedOpts)
478
460
  };
479
461
  };
480
462
  const request = async (options) => {
@@ -484,26 +466,26 @@ const createClient = (config = {}) => {
484
466
  ...opts,
485
467
  body: getValidRequestBody(opts)
486
468
  };
487
- let request$1 = new Request(url, requestInit);
488
- for (const fn of interceptors.request.fns) if (fn) request$1 = await fn(request$1, opts);
469
+ let request = new Request(url, requestInit);
470
+ for (const fn of interceptors.request.fns) if (fn) request = await fn(request, opts);
489
471
  const _fetch = opts.fetch;
490
472
  let response;
491
473
  try {
492
- response = await _fetch(request$1);
493
- } catch (error$1) {
494
- let finalError$1 = error$1;
495
- for (const fn of interceptors.error.fns) if (fn) finalError$1 = await fn(error$1, void 0, request$1, opts);
496
- finalError$1 = finalError$1 || {};
497
- if (opts.throwOnError) throw finalError$1;
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;
498
480
  return opts.responseStyle === "data" ? void 0 : {
499
- error: finalError$1,
500
- request: request$1,
481
+ error: finalError,
482
+ request,
501
483
  response: void 0
502
484
  };
503
485
  }
504
- for (const fn of interceptors.response.fns) if (fn) response = await fn(response, request$1, opts);
486
+ for (const fn of interceptors.response.fns) if (fn) response = await fn(response, request, opts);
505
487
  const result = {
506
- request: request$1,
488
+ request,
507
489
  response
508
490
  };
509
491
  if (response.ok) {
@@ -522,7 +504,6 @@ const createClient = (config = {}) => {
522
504
  case "stream":
523
505
  emptyData = response.body;
524
506
  break;
525
- case "json":
526
507
  default:
527
508
  emptyData = {};
528
509
  break;
@@ -566,7 +547,7 @@ const createClient = (config = {}) => {
566
547
  } catch {}
567
548
  const error = jsonError ?? textError;
568
549
  let finalError = error;
569
- for (const fn of interceptors.error.fns) if (fn) finalError = await fn(error, response, request$1, opts);
550
+ for (const fn of interceptors.error.fns) if (fn) finalError = await fn(error, response, request, opts);
570
551
  finalError = finalError || {};
571
552
  if (opts.throwOnError) throw finalError;
572
553
  return opts.responseStyle === "data" ? void 0 : {
@@ -585,10 +566,10 @@ const createClient = (config = {}) => {
585
566
  body: opts.body,
586
567
  headers: opts.headers,
587
568
  method,
588
- onRequest: async (url$1, init) => {
589
- let request$1 = new Request(url$1, init);
590
- for (const fn of interceptors.request.fns) if (fn) request$1 = await fn(request$1, opts);
591
- return request$1;
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;
592
573
  },
593
574
  serializedBody: getValidRequestBody(opts),
594
575
  url
@@ -626,15 +607,12 @@ const createClient = (config = {}) => {
626
607
  trace: makeMethodFn("TRACE")
627
608
  };
628
609
  };
629
-
630
610
  //#endregion
631
611
  //#region src/api/generated/client.gen.ts
632
612
  const client$1 = createClient(createConfig({ baseUrl: "https://www.primitive.dev/api/v1" }));
633
-
634
613
  //#endregion
635
614
  //#region src/api/generated/sdk.gen.ts
636
- var sdk_gen_exports = {};
637
- __export(sdk_gen_exports, {
615
+ var sdk_gen_exports = /* @__PURE__ */ __exportAll({
638
616
  addDomain: () => addDomain,
639
617
  createEndpoint: () => createEndpoint,
640
618
  createFilter: () => createFilter,
@@ -655,6 +633,7 @@ __export(sdk_gen_exports, {
655
633
  listFilters: () => listFilters,
656
634
  replayDelivery: () => replayDelivery,
657
635
  replayEmailWebhooks: () => replayEmailWebhooks,
636
+ replyToEmail: () => replyToEmail,
658
637
  rotateWebhookSecret: () => rotateWebhookSecret,
659
638
  sendEmail: () => sendEmail,
660
639
  testEndpoint: () => testEndpoint,
@@ -894,6 +873,35 @@ const downloadAttachments = (options) => (options.client ?? client$1).get({
894
873
  ...options
895
874
  });
896
875
  /**
876
+ * Reply to an inbound email
877
+ *
878
+ * Sends an outbound reply to the inbound email identified by `id`.
879
+ * Threading headers (`In-Reply-To`, `References`), recipient
880
+ * derivation (Reply-To, then From, then bare sender), and the
881
+ * `Re:` subject prefix are all derived server-side from the
882
+ * stored inbound row. The request body carries only the message
883
+ * body and optional `wait` flag; passing any header or recipient
884
+ * override is rejected by the schema (`additionalProperties:
885
+ * false`).
886
+ *
887
+ * Forwards through the same gates as `/send-mail`: the response
888
+ * status, error envelope, and `idempotent_replay` flag mirror
889
+ * the send-mail contract verbatim.
890
+ *
891
+ */
892
+ const replyToEmail = (options) => (options.client ?? client$1).post({
893
+ security: [{
894
+ scheme: "bearer",
895
+ type: "http"
896
+ }],
897
+ url: "/emails/{id}/reply",
898
+ ...options,
899
+ headers: {
900
+ "Content-Type": "application/json",
901
+ ...options.headers
902
+ }
903
+ });
904
+ /**
897
905
  * Replay email webhooks
898
906
  *
899
907
  * Re-delivers the webhook payload for this email to all active
@@ -1110,7 +1118,6 @@ const sendEmail = (options) => (options.client ?? client$1).post({
1110
1118
  ...options.headers
1111
1119
  }
1112
1120
  });
1113
-
1114
1121
  //#endregion
1115
1122
  //#region src/api/index.ts
1116
1123
  const DEFAULT_BASE_URL = "https://www.primitive.dev/api/v1";
@@ -1122,7 +1129,6 @@ const MAX_TO_HEADER_LENGTH = 320;
1122
1129
  function createDefaultAuth(apiKey) {
1123
1130
  return (security) => {
1124
1131
  if (security.type === "http" && security.scheme === "bearer") return apiKey;
1125
- return void 0;
1126
1132
  };
1127
1133
  }
1128
1134
  function validateAddressHeader(field, value) {
@@ -1218,7 +1224,7 @@ function parseRetryAfterHeader(response) {
1218
1224
  var PrimitiveApiClient = class {
1219
1225
  client;
1220
1226
  constructor(options = {}) {
1221
- const { apiKey, auth, baseUrl = DEFAULT_BASE_URL,...config } = options;
1227
+ const { apiKey, auth, baseUrl = DEFAULT_BASE_URL, ...config } = options;
1222
1228
  this.client = createClient(createConfig({
1223
1229
  ...config,
1224
1230
  auth: auth ?? createDefaultAuth(apiKey),
@@ -1235,54 +1241,52 @@ var PrimitiveApiClient = class {
1235
1241
  var PrimitiveClient = class extends PrimitiveApiClient {
1236
1242
  async send(input) {
1237
1243
  validateSendInput(input);
1238
- const body = {
1239
- from: input.from,
1240
- to: input.to,
1241
- subject: input.subject,
1242
- ...input.bodyText !== void 0 ? { body_text: input.bodyText } : {},
1243
- ...input.bodyHtml !== void 0 ? { body_html: input.bodyHtml } : {},
1244
- ...input.thread?.inReplyTo ? { in_reply_to: input.thread.inReplyTo } : {},
1245
- ...input.thread?.references?.length ? { references: input.thread.references } : {},
1246
- ...input.wait !== void 0 ? { wait: input.wait } : {},
1247
- ...input.waitTimeoutMs !== void 0 ? { wait_timeout_ms: input.waitTimeoutMs } : {}
1248
- };
1249
- const result = await sendEmail({
1250
- body,
1244
+ return unwrapSendResult(await sendEmail({
1245
+ body: {
1246
+ from: input.from,
1247
+ to: input.to,
1248
+ subject: input.subject,
1249
+ ...input.bodyText !== void 0 ? { body_text: input.bodyText } : {},
1250
+ ...input.bodyHtml !== void 0 ? { body_html: input.bodyHtml } : {},
1251
+ ...input.thread?.inReplyTo ? { in_reply_to: input.thread.inReplyTo } : {},
1252
+ ...input.thread?.references?.length ? { references: input.thread.references } : {},
1253
+ ...input.wait !== void 0 ? { wait: input.wait } : {},
1254
+ ...input.waitTimeoutMs !== void 0 ? { wait_timeout_ms: input.waitTimeoutMs } : {}
1255
+ },
1251
1256
  ...input.idempotencyKey ? { headers: { "Idempotency-Key": input.idempotencyKey } } : {},
1252
1257
  client: this.client,
1253
1258
  responseStyle: "fields"
1254
- });
1255
- const response = result.response;
1256
- if (result.error) {
1257
- const parsed = parseApiErrorPayload(result.error);
1258
- throw new PrimitiveApiError(parsed.message, {
1259
- payload: result.error,
1260
- status: response?.status,
1261
- code: parsed.code,
1262
- gates: parsed.gates,
1263
- requestId: parsed.requestId,
1264
- retryAfter: parseRetryAfterHeader(response),
1265
- details: parsed.details
1266
- });
1267
- }
1268
- if (!result.data?.data) throw new PrimitiveApiError("Primitive API returned no send result", {
1269
- payload: result,
1270
- status: response?.status
1271
- });
1272
- return mapSendResult(result.data.data);
1259
+ }));
1273
1260
  }
1261
+ /**
1262
+ * Reply to an inbound email.
1263
+ *
1264
+ * Calls `POST /emails/{id}/reply`. The server derives recipients
1265
+ * (Reply-To, then From, then sender), subject (`Re: <parent>` with
1266
+ * idempotent prefix), and threading headers (`In-Reply-To`,
1267
+ * `References`) from the stored inbound row. The customer controls
1268
+ * only the body, an optional `from` override, and the `wait` flag.
1269
+ *
1270
+ * Subject overrides are intentionally not supported: Gmail's
1271
+ * Conversation View needs both a References match and a normalized-
1272
+ * subject match to thread, so a custom subject silently breaks the
1273
+ * thread for half the recipient population.
1274
+ */
1274
1275
  async reply(email, input) {
1275
1276
  const resolved = typeof input === "string" ? { text: input } : input;
1276
- return this.send({
1277
- from: resolved.from ?? email.receivedBy,
1278
- to: email.replyTarget.address,
1279
- subject: resolved.subject ?? email.replySubject,
1280
- bodyText: resolved.text,
1281
- thread: {
1282
- ...email.thread.messageId ? { inReplyTo: email.thread.messageId } : {},
1283
- references: email.thread.messageId ? [...email.thread.references, email.thread.messageId] : email.thread.references
1284
- }
1285
- });
1277
+ if ("subject" in resolved) throw new TypeError("reply does not support a subject override; the server prepends 'Re:' to the parent's subject for thread continuity");
1278
+ if (!resolved.text && !resolved.html) throw new TypeError("reply requires text or html");
1279
+ return unwrapSendResult(await replyToEmail({
1280
+ body: {
1281
+ ...resolved.text !== void 0 ? { body_text: resolved.text } : {},
1282
+ ...resolved.html !== void 0 ? { body_html: resolved.html } : {},
1283
+ ...resolved.from !== void 0 ? { from: resolved.from } : {},
1284
+ ...resolved.wait !== void 0 ? { wait: resolved.wait } : {}
1285
+ },
1286
+ path: { id: email.id },
1287
+ client: this.client,
1288
+ responseStyle: "fields"
1289
+ }));
1286
1290
  }
1287
1291
  async forward(email, input) {
1288
1292
  validateForwardInput(input);
@@ -1295,7 +1299,7 @@ var PrimitiveClient = class extends PrimitiveApiClient {
1295
1299
  }
1296
1300
  };
1297
1301
  function buildForwardText(email, intro) {
1298
- const lines = [
1302
+ return [
1299
1303
  ...intro ? [intro.trim(), ""] : [],
1300
1304
  "---------- Forwarded message ----------",
1301
1305
  `From: ${formatAddress(email.sender)}`,
@@ -1305,8 +1309,33 @@ function buildForwardText(email, intro) {
1305
1309
  ...email.thread.messageId ? [`Message-ID: ${email.thread.messageId}`] : [],
1306
1310
  "",
1307
1311
  email.text ?? ""
1308
- ];
1309
- return lines.join("\n").trimEnd();
1312
+ ].join("\n").trimEnd();
1313
+ }
1314
+ /**
1315
+ * Shared response handler for `send`, `reply`, and any future
1316
+ * operation that returns a SendMailResult envelope. Unifies the
1317
+ * error-mapping path so the network call sites only have to invoke
1318
+ * the generated operation.
1319
+ */
1320
+ function unwrapSendResult(result) {
1321
+ const response = result.response;
1322
+ if (result.error) {
1323
+ const parsed = parseApiErrorPayload(result.error);
1324
+ throw new PrimitiveApiError(parsed.message, {
1325
+ payload: result.error,
1326
+ status: response?.status,
1327
+ code: parsed.code,
1328
+ gates: parsed.gates,
1329
+ requestId: parsed.requestId,
1330
+ retryAfter: parseRetryAfterHeader(response),
1331
+ details: parsed.details
1332
+ });
1333
+ }
1334
+ if (!result.data?.data) throw new PrimitiveApiError("Primitive API returned no send result", {
1335
+ payload: result,
1336
+ status: response?.status
1337
+ });
1338
+ return mapSendResult(result.data.data);
1310
1339
  }
1311
1340
  function mapSendResult(result) {
1312
1341
  return {
@@ -1318,6 +1347,7 @@ function mapSendResult(result) {
1318
1347
  clientIdempotencyKey: result.client_idempotency_key,
1319
1348
  requestId: result.request_id,
1320
1349
  contentHash: result.content_hash,
1350
+ idempotentReplay: result.idempotent_replay ?? false,
1321
1351
  ...result.delivery_status !== void 0 ? { deliveryStatus: result.delivery_status } : {},
1322
1352
  ...result.smtp_response_code !== void 0 ? { smtpResponseCode: result.smtp_response_code } : {},
1323
1353
  ...result.smtp_response_text !== void 0 ? { smtpResponseText: result.smtp_response_text } : {}
@@ -1333,6 +1363,5 @@ function client(options = {}) {
1333
1363
  return new PrimitiveClient(options);
1334
1364
  }
1335
1365
  const operations = sdk_gen_exports;
1336
-
1337
1366
  //#endregion
1338
- export { DEFAULT_BASE_URL, PrimitiveApiClient, PrimitiveApiError, PrimitiveClient, addDomain, client, createEndpoint, createFilter, createPrimitiveApiClient, createPrimitiveClient, deleteDomain, deleteEmail, deleteEndpoint, deleteFilter, downloadAttachments, downloadRawEmail, getAccount, getEmail, getStorageStats, getWebhookSecret, listDeliveries, listDomains, listEmails, listEndpoints, listFilters, operations, replayDelivery, replayEmailWebhooks, rotateWebhookSecret, sendEmail, testEndpoint, updateAccount, updateDomain, updateEndpoint, updateFilter, verifyDomain };
1367
+ export { rotateWebhookSecret as A, listDomains as C, replayDelivery as D, listFilters as E, updateEndpoint as F, updateFilter as I, verifyDomain as L, testEndpoint as M, updateAccount as N, replayEmailWebhooks as O, updateDomain 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, sendEmail as j, replyToEmail 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 };
@@ -0,0 +1,13 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __exportAll = (all, no_symbols) => {
4
+ let target = {};
5
+ for (var name in all) __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true
8
+ });
9
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
10
+ return target;
11
+ };
12
+ //#endregion
13
+ export { __exportAll as t };
@@ -1,10 +1,7 @@
1
- import { EmailAddress, EmailAnalysis, EmailAuth, EmailReceivedEvent, ParsedDataComplete, ParsedDataFailed, ParsedError, RawContentDownloadOnly, RawContentInline, WebhookAttachment } from "../types-CIOzt1FY.js";
2
- import "../received-email-C67Z7Dha.js";
3
- import { SignResult, StandardWebhooksSignResult, WEBHOOK_VERSION$1 as WEBHOOK_VERSION, signStandardWebhooksPayload$1 as signStandardWebhooksPayload, signWebhookPayload$1 as signWebhookPayload } from "../index-CuuP1JkG.js";
1
+ import { C as ParsedDataFailed, D as RawContentDownloadOnly, M as WebhookAttachment, O as RawContentInline, S as ParsedDataComplete, c as EmailAnalysis, l as EmailAuth, s as EmailAddress, u as EmailReceivedEvent, w as ParsedError } from "../types-9vXGZjPd.js";
2
+ import { C as signStandardWebhooksPayload, h as WEBHOOK_VERSION, j as signWebhookPayload, k as SignResult, x as StandardWebhooksSignResult } from "../index-CbEivn3S.js";
4
3
 
5
4
  //#region src/contract/contract.d.ts
6
- /** Maximum raw email size for inline inclusion (256 KB). */
7
-
8
5
  /** Maximum raw email size for inline inclusion (256 KB). */
9
6
  declare const RAW_EMAIL_INLINE_THRESHOLD = 262144;
10
7
  /** Parsed content input when parsing succeeded. */
@@ -143,8 +140,7 @@ declare function generateEventId(endpoint_id: string, email_id: string): string;
143
140
  * ```
144
141
  */
145
142
  declare function buildEmailReceivedEvent(input: EmailReceivedEventInput, options?: {
146
- /** Override the attempted-at timestamp, typically for tests. */
147
- attempted_at?: string;
143
+ /** Override the attempted-at timestamp, typically for tests. */attempted_at?: string;
148
144
  }): EmailReceivedEvent;
149
145
  /**
150
146
  * Input for building an `EmailReceivedEvent` directly from parser output.
@@ -222,5 +218,6 @@ interface BuildEventFromParsedDataOptions {
222
218
  * @throws Error if `smtpRcptTo` is empty.
223
219
  * @throws WebhookValidationError if the assembled event fails schema validation.
224
220
  */
225
- declare function buildEventFromParsedData(params: BuildEventFromParsedDataOptions): EmailReceivedEvent; //#endregion
226
- export { BuildEventFromParsedDataOptions, EmailAddress, EmailAnalysis, EmailAuth, EmailReceivedEvent, EmailReceivedEventInput, ParsedDataComplete, ParsedDataFailed, ParsedError, ParsedInput, ParsedInputComplete, ParsedInputFailed, RAW_EMAIL_INLINE_THRESHOLD, RawContentDownloadOnly, RawContentInline, SignResult, StandardWebhooksSignResult, WEBHOOK_VERSION, WebhookAttachment, buildEmailReceivedEvent, buildEventFromParsedData, generateEventId, signStandardWebhooksPayload, signWebhookPayload };
221
+ declare function buildEventFromParsedData(params: BuildEventFromParsedDataOptions): EmailReceivedEvent;
222
+ //#endregion
223
+ export { BuildEventFromParsedDataOptions, type EmailAddress, type EmailAnalysis, type EmailAuth, type EmailReceivedEvent, EmailReceivedEventInput, type ParsedDataComplete, type ParsedDataFailed, type ParsedError, ParsedInput, ParsedInputComplete, ParsedInputFailed, RAW_EMAIL_INLINE_THRESHOLD, type RawContentDownloadOnly, type RawContentInline, type SignResult, type StandardWebhooksSignResult, WEBHOOK_VERSION, type WebhookAttachment, buildEmailReceivedEvent, buildEventFromParsedData, generateEventId, signStandardWebhooksPayload, signWebhookPayload };
@@ -1,9 +1,25 @@
1
- import "../address-parser-CfPHs3mE.js";
2
- import "../received-email-Q6Cha3wc.js";
3
- import { WEBHOOK_VERSION, signStandardWebhooksPayload, signWebhookPayload, validateEmailReceivedEvent } from "../webhook-2TALcBQz.js";
1
+ import { E as signStandardWebhooksPayload, L as validateEmailReceivedEvent, M as signWebhookPayload, d as WEBHOOK_VERSION } from "../webhook-zkN4wUTs.js";
4
2
  import { createHash } from "node:crypto";
5
-
6
3
  //#region src/contract/contract.ts
4
+ /**
5
+ * Primitive Contract
6
+ *
7
+ * This module exposes the exact functions used by Primitive servers to construct
8
+ * webhook payloads. It serves two purposes:
9
+ *
10
+ * 1. **Build-time type safety**: Primitive producer code can import these types
11
+ * and functions so schema changes surface as TypeScript errors instead of
12
+ * runtime contract drift.
13
+ *
14
+ * 2. **Debugging transparency**: If you receive a malformed payload, you can
15
+ * compare it against these exact types and builder functions to identify
16
+ * which side broke the contract.
17
+ *
18
+ * This package is also useful for building test fixtures that match real
19
+ * payloads exactly.
20
+ *
21
+ * @module @primitivedotdev/sdk/contract
22
+ */
7
23
  /** Maximum raw email size for inline inclusion (256 KB). */
8
24
  const RAW_EMAIL_INLINE_THRESHOLD = 262144;
9
25
  /**
@@ -42,8 +58,7 @@ function validateTimestamp(timestamp, fieldName) {
42
58
  */
43
59
  function generateEventId(endpoint_id, email_id) {
44
60
  const hashInput = `email.received:${WEBHOOK_VERSION}:${endpoint_id}:${email_id}`;
45
- const hash = createHash("sha256").update(hashInput).digest("hex");
46
- return `evt_${hash}`;
61
+ return `evt_${createHash("sha256").update(hashInput).digest("hex")}`;
47
62
  }
48
63
  /**
49
64
  * Build an `EmailReceivedEvent` from producer-side input.
@@ -94,13 +109,12 @@ function generateEventId(endpoint_id, email_id) {
94
109
  */
95
110
  function buildEmailReceivedEvent(input, options) {
96
111
  const event_id = generateEventId(input.endpoint_id, input.email_id);
97
- const attempted_at = options?.attempted_at ? validateTimestamp(options.attempted_at, "attempted_at") : new Date().toISOString();
112
+ const attempted_at = options?.attempted_at ? validateTimestamp(options.attempted_at, "attempted_at") : (/* @__PURE__ */ new Date()).toISOString();
98
113
  const raw_size_bytes = input.raw_bytes.length;
99
114
  if (input.raw_size_bytes !== raw_size_bytes) throw new Error(`[@primitivedotdev/sdk/contract] Invalid raw_size_bytes: ${input.raw_size_bytes}. Expected ${raw_size_bytes} based on raw_bytes length`);
100
115
  const raw_sha256 = createHash("sha256").update(input.raw_bytes).digest("hex");
101
116
  if (input.raw_sha256 !== raw_sha256) throw new Error(`[@primitivedotdev/sdk/contract] Invalid raw_sha256: "${input.raw_sha256}". Expected ${raw_sha256} based on raw_bytes`);
102
- const shouldInline = raw_size_bytes <= RAW_EMAIL_INLINE_THRESHOLD;
103
- const rawContent = shouldInline ? {
117
+ const rawContent = raw_size_bytes <= 262144 ? {
104
118
  included: true,
105
119
  encoding: "base64",
106
120
  max_inline_bytes: RAW_EMAIL_INLINE_THRESHOLD,
@@ -158,7 +172,7 @@ function buildEmailReceivedEvent(input, options) {
158
172
  attachments: [],
159
173
  attachments_download_url: null
160
174
  };
161
- const event = {
175
+ return validateEmailReceivedEvent({
162
176
  id: event_id,
163
177
  event: "email.received",
164
178
  version: WEBHOOK_VERSION,
@@ -193,8 +207,7 @@ function buildEmailReceivedEvent(input, options) {
193
207
  analysis: input.analysis,
194
208
  auth: input.auth
195
209
  }
196
- };
197
- return validateEmailReceivedEvent(event);
210
+ });
198
211
  }
199
212
  /**
200
213
  * Build an `EmailReceivedEvent` from parsed email data plus delivery metadata.
@@ -241,7 +254,7 @@ function buildEventFromParsedData(params) {
241
254
  references: parsed.references,
242
255
  attachments: parsed.attachments
243
256
  };
244
- const input = {
257
+ return buildEmailReceivedEvent({
245
258
  email_id: params.emailId,
246
259
  endpoint_id: params.endpointId,
247
260
  message_id: params.messageId,
@@ -263,9 +276,7 @@ function buildEventFromParsedData(params) {
263
276
  parsed: parsedInput,
264
277
  auth: params.auth,
265
278
  analysis: params.analysis
266
- };
267
- return buildEmailReceivedEvent(input, params.buildOptions);
279
+ }, params.buildOptions);
268
280
  }
269
-
270
281
  //#endregion
271
- export { RAW_EMAIL_INLINE_THRESHOLD, WEBHOOK_VERSION, buildEmailReceivedEvent, buildEventFromParsedData, generateEventId, signStandardWebhooksPayload, signWebhookPayload };
282
+ export { RAW_EMAIL_INLINE_THRESHOLD, WEBHOOK_VERSION, buildEmailReceivedEvent, buildEventFromParsedData, generateEventId, signStandardWebhooksPayload, signWebhookPayload };