@stackshift-cloud/sdk 0.1.1 → 0.1.2

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/client.js CHANGED
@@ -1,11 +1,17 @@
1
1
  import { AssetsClient } from './assets.js';
2
+ import { MailClient } from './mail.js';
2
3
  import { ProjectsClient } from './projects.js';
3
4
  const defaultBaseUrl = 'https://api.stackshift.cloud/api/v1';
5
+ const defaultMailBaseUrl = 'https://api.stackshift.cloud/v1';
6
+ const defaultCdnBaseUrl = 'https://cdn.stackshift.cloud';
4
7
  export class StackShift {
5
8
  apiKey;
6
9
  baseUrl;
10
+ mailBaseUrl;
11
+ cdnBaseUrl;
7
12
  projects;
8
13
  assets;
14
+ mail;
9
15
  fetcher;
10
16
  constructor(options = {}) {
11
17
  const apiKey = options.apiKey ?? env('STACKSHIFT_API_KEY');
@@ -14,13 +20,22 @@ export class StackShift {
14
20
  }
15
21
  this.apiKey = apiKey;
16
22
  this.baseUrl = (options.baseUrl ?? defaultBaseUrl).replace(/\/$/, '');
23
+ this.mailBaseUrl = (options.mailBaseUrl ?? defaultMailBaseUrl).replace(/\/$/, '');
24
+ this.cdnBaseUrl = (options.cdnBaseUrl ?? defaultCdnBaseUrl).replace(/\/$/, '');
17
25
  this.fetcher = options.fetch ?? fetch;
18
26
  this.projects = new ProjectsClient(this);
19
27
  this.assets = new AssetsClient(this);
28
+ this.mail = new MailClient(this);
20
29
  }
21
30
  async request(path, init = {}) {
31
+ return this.requestFrom(this.baseUrl, path, init);
32
+ }
33
+ async mailRequest(path, init = {}) {
34
+ return this.requestFrom(this.mailBaseUrl, path, init);
35
+ }
36
+ async requestFrom(baseUrl, path, init) {
22
37
  const isFormData = typeof FormData !== 'undefined' && init.body instanceof FormData;
23
- const response = await this.fetcher(`${this.baseUrl}${path}`, {
38
+ const response = await this.fetcher(`${baseUrl}${path}`, {
24
39
  method: init.method ?? 'GET',
25
40
  headers: stripUndefined({
26
41
  Authorization: `Bearer ${this.apiKey}`,
@@ -32,7 +47,8 @@ export class StackShift {
32
47
  const raw = await response.text();
33
48
  const parsed = raw ? JSON.parse(raw) : null;
34
49
  if (!response.ok) {
35
- throw new Error(parsed?.message ?? parsed?.error ?? `StackShift API request failed with ${response.status}`);
50
+ const apiError = parsed?.error && typeof parsed.error === 'object' ? parsed.error : undefined;
51
+ throw new StackShiftAPIError(apiError?.message ?? parsed?.message ?? parsed?.error ?? `StackShift API request failed with ${response.status}`, response.status, apiError?.code, apiError?.details);
36
52
  }
37
53
  if (parsed && typeof parsed === 'object' && 'success' in parsed && 'data' in parsed) {
38
54
  return parsed.data;
@@ -40,6 +56,18 @@ export class StackShift {
40
56
  return parsed;
41
57
  }
42
58
  }
59
+ export class StackShiftAPIError extends Error {
60
+ status;
61
+ code;
62
+ details;
63
+ constructor(message, status, code, details) {
64
+ super(message);
65
+ this.status = status;
66
+ this.code = code;
67
+ this.details = details;
68
+ this.name = 'StackShiftAPIError';
69
+ }
70
+ }
43
71
  function env(key) {
44
72
  const maybeProcess = globalThis.process;
45
73
  return maybeProcess?.env?.[key];
package/dist/index.d.ts CHANGED
@@ -1,4 +1,11 @@
1
- export { StackShift } from './client.js';
2
- export { AssetsClient } from './assets.js';
1
+ export { StackShift, StackShiftAPIError } from './client.js';
2
+ export { AssetsClient, assetTransformOptions, assetTransformPresets, assetTransformSpec, getAssetTransformPreset } from './assets.js';
3
+ export { MailBouncesClient, MailClient, MailDomainsClient, MailEventsClient, MailLimitsClient, MailMessagesClient, MailScheduledClient, MailBatchClient, MailInboundClient, MailAnalyticsClient, MailOtpChallengesClient, MailOtpClient, MailReputationClient, MailReputationEventsClient, MailSuppressionsClient, MailTemplatesClient, MailWebhooksClient, } from './mail.js';
3
4
  export { ProjectsClient } from './projects.js';
4
- export type { Asset, AssetListOptions, AssetListResult, AssetSignedUploadUrl, AssetSignedUploadUrlOptions, AssetSignedUrl, AssetSignedUrlOptions, AssetUploadOptions, AssetVisibility, JsonValue, Project, ProjectListOptions, StackShiftOptions, } from './types.js';
5
+ export type { Asset, AssetAIAnnotation, AssetAIInfo, AssetCollection, AssetListOptions, AssetListResult, AssetModerationResult, AssetSavedSearch, AssetSignedUploadUrl, AssetSignedUploadUrlOptions, AssetSignedUrl, AssetSignedUrlOptions, AssetTranscript, AssetTransformOptions, AssetTransformPreset, AssetTransformPresetCategory, AssetUploadOptions, AssetVisibility, AssetVersion, JsonValue, MailAddress, MailAddressInput, MailDnsRecord, MailDomain, MailDomainListResult, MailDomainStatus, MailIdempotencyStatus, MailLog, MailMessage, MailMessageListOptions, MailMessageListResult, MailMessageSummary, MailRecordStatus, MailSendAttempt, MailSendInput, MailSendResponse, MailStatus, Project, ProjectListOptions, StackShiftOptions, } from './types.js';
6
+ export type { MailBounce, MailBounceListOptions, MailBounceListResult, MailBounceType, MailSuppression, MailSuppressionCreateInput, MailSuppressionListOptions, MailSuppressionListResult, MailSuppressionReason, MailSuppressionSource, } from './mail-phase4-types.js';
7
+ export type { MailOtpChallenge, MailOtpChallengeListOptions, MailOtpChallengeListResult, MailOtpSendInput, MailOtpSendResponse, MailOtpStatus, MailOtpVerifyInput, MailOtpVerifyResponse, } from './mail-otp-types.js';
8
+ export type { MailSendTemplateInput, MailSendTemplateResponse, MailTemplate, MailTemplateCreateInput, MailTemplateDetail, MailTemplateListOptions, MailTemplateListResult, MailTemplatePreview, MailTemplatePreviewInput, MailTemplateStatus, MailTemplateTestSendInput, MailTemplateTestSendResponse, MailTemplateUpdateInput, MailTemplateVersion, } from './mail-template-types.js';
9
+ export type { MailEvent, MailEventListOptions, MailEventListResult, MailEventType, MailTimelineItem, MailWebhook, MailWebhookCreateInput, MailWebhookCreateResponse, MailWebhookDelivery, MailWebhookDeliveryAttempt, MailWebhookDeliveryDetail, MailWebhookDeliveryListOptions, MailWebhookListOptions, MailWebhookListResult, MailWebhookUpdateInput, } from './mail-webhook-types.js';
10
+ export type { MailDomainReputation, MailLimits, MailManualReviewStatus, MailReputation, MailReputationEvent, MailReputationEventListOptions, MailReputationEventListResult, MailReputationEventSeverity, MailReputationStatus, MailReputationTier, MailReputationWorkspace, } from './mail-reputation-types.js';
11
+ export type { MailAnalytics, MailAnalyticsInput, MailAttachmentInput, MailBatch, MailBatchSendInput, MailBatchTemplateInput, MailInboundDomain, MailInboundMessage, MailScheduledCreateInput, MailScheduledMessage, } from './mail-advanced-types.js';
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
- export { StackShift } from './client.js';
2
- export { AssetsClient } from './assets.js';
1
+ export { StackShift, StackShiftAPIError } from './client.js';
2
+ export { AssetsClient, assetTransformOptions, assetTransformPresets, assetTransformSpec, getAssetTransformPreset } from './assets.js';
3
+ export { MailBouncesClient, MailClient, MailDomainsClient, MailEventsClient, MailLimitsClient, MailMessagesClient, MailScheduledClient, MailBatchClient, MailInboundClient, MailAnalyticsClient, MailOtpChallengesClient, MailOtpClient, MailReputationClient, MailReputationEventsClient, MailSuppressionsClient, MailTemplatesClient, MailWebhooksClient, } from './mail.js';
3
4
  export { ProjectsClient } from './projects.js';
@@ -0,0 +1,83 @@
1
+ import type { JsonValue, MailAddress, MailAddressInput, MailSendInput, MailSendResponse } from './types.js';
2
+ import type { MailSendTemplateInput } from './mail-template-types.js';
3
+ export interface MailAttachmentInput {
4
+ assetId?: string;
5
+ uploadId?: string;
6
+ filename: string;
7
+ contentType?: string;
8
+ }
9
+ export interface MailScheduledCreateInput {
10
+ sendAt: string;
11
+ message?: MailSendInput;
12
+ template?: string;
13
+ versionId?: string;
14
+ to?: MailAddressInput;
15
+ from?: string | MailAddress;
16
+ data?: Record<string, JsonValue>;
17
+ idempotencyKey?: string;
18
+ attachments?: MailAttachmentInput[];
19
+ }
20
+ export interface MailScheduledMessage {
21
+ id: string;
22
+ status: 'scheduled' | 'queued' | 'sent' | 'canceled' | 'failed';
23
+ sendAt: string;
24
+ messageId?: string | null;
25
+ createdAt?: string;
26
+ canceledAt?: string | null;
27
+ sentAt?: string | null;
28
+ }
29
+ export interface MailBatchSendInput {
30
+ from: string | MailAddress;
31
+ messages: MailSendInput[];
32
+ }
33
+ export interface MailBatchTemplateInput {
34
+ template: string;
35
+ versionId?: string;
36
+ from: string | MailAddress;
37
+ recipients: Array<{
38
+ to: MailAddressInput;
39
+ data?: Record<string, JsonValue>;
40
+ idempotencyKey?: string;
41
+ }>;
42
+ }
43
+ export interface MailBatch {
44
+ id: string;
45
+ status: 'queued' | 'processing' | 'completed' | 'failed';
46
+ messageCount: number;
47
+ }
48
+ export interface MailInboundDomain {
49
+ id: string;
50
+ domain: string;
51
+ status: 'pending' | 'verified' | 'disabled';
52
+ records?: Array<{
53
+ type: string;
54
+ name: string;
55
+ value: string;
56
+ required: boolean;
57
+ }>;
58
+ }
59
+ export interface MailInboundMessage {
60
+ id: string;
61
+ fromEmail: string;
62
+ toEmails: string[];
63
+ ccEmails?: string[] | null;
64
+ subject?: string | null;
65
+ text?: string | null;
66
+ html?: string | null;
67
+ rawRef?: string | null;
68
+ receivedAt: string;
69
+ }
70
+ export interface MailAnalyticsInput {
71
+ range?: '24h' | '7d' | '30d' | '90d' | string;
72
+ from?: string;
73
+ to?: string;
74
+ interval?: 'hour' | 'day';
75
+ domain?: string;
76
+ template?: string;
77
+ event?: string;
78
+ }
79
+ export interface MailAnalytics {
80
+ summary: Record<string, number>;
81
+ series: Array<Record<string, number | string>>;
82
+ }
83
+ export type { MailSendResponse, MailSendTemplateInput };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,45 @@
1
+ import type { StackShift } from './client.js';
2
+ import type { MailAnalytics, MailAnalyticsInput, MailBatch, MailBatchSendInput, MailBatchTemplateInput, MailInboundDomain, MailInboundMessage, MailScheduledCreateInput, MailScheduledMessage } from './mail-advanced-types.js';
3
+ export declare class MailScheduledClient {
4
+ private readonly client;
5
+ constructor(client: StackShift);
6
+ create(input: MailScheduledCreateInput): Promise<MailScheduledMessage>;
7
+ list(): Promise<{
8
+ data: MailScheduledMessage[];
9
+ }>;
10
+ get(id: string): Promise<MailScheduledMessage>;
11
+ cancel(id: string): Promise<MailScheduledMessage>;
12
+ }
13
+ export declare class MailBatchClient {
14
+ private readonly client;
15
+ constructor(client: StackShift);
16
+ send(input: MailBatchSendInput): Promise<MailBatch>;
17
+ sendTemplate(input: MailBatchTemplateInput): Promise<MailBatch>;
18
+ }
19
+ export declare class MailInboundClient {
20
+ readonly domains: MailInboundDomainsClient;
21
+ readonly messages: MailInboundMessagesClient;
22
+ constructor(client: StackShift);
23
+ }
24
+ export declare class MailInboundDomainsClient {
25
+ private readonly client;
26
+ constructor(client: StackShift);
27
+ create(domain: string): Promise<MailInboundDomain>;
28
+ list(): Promise<{
29
+ data: MailInboundDomain[];
30
+ }>;
31
+ verify(id: string): Promise<MailInboundDomain>;
32
+ }
33
+ export declare class MailInboundMessagesClient {
34
+ private readonly client;
35
+ constructor(client: StackShift);
36
+ list(): Promise<{
37
+ data: MailInboundMessage[];
38
+ }>;
39
+ get(id: string): Promise<MailInboundMessage>;
40
+ }
41
+ export declare class MailAnalyticsClient {
42
+ private readonly client;
43
+ constructor(client: StackShift);
44
+ get(input?: MailAnalyticsInput): Promise<MailAnalytics>;
45
+ }
@@ -0,0 +1,88 @@
1
+ export class MailScheduledClient {
2
+ client;
3
+ constructor(client) {
4
+ this.client = client;
5
+ }
6
+ create(input) {
7
+ return this.client.mailRequest('/mail/scheduled', { method: 'POST', body: input });
8
+ }
9
+ list() {
10
+ return this.client.mailRequest('/mail/scheduled');
11
+ }
12
+ get(id) {
13
+ return this.client.mailRequest(`/mail/scheduled/${encodeURIComponent(id)}`);
14
+ }
15
+ cancel(id) {
16
+ return this.client.mailRequest(`/mail/scheduled/${encodeURIComponent(id)}/cancel`, { method: 'POST' });
17
+ }
18
+ }
19
+ export class MailBatchClient {
20
+ client;
21
+ constructor(client) {
22
+ this.client = client;
23
+ }
24
+ send(input) {
25
+ return this.client.mailRequest('/mail/batch', { method: 'POST', body: input });
26
+ }
27
+ sendTemplate(input) {
28
+ return this.client.mailRequest('/mail/batch-template', { method: 'POST', body: input });
29
+ }
30
+ }
31
+ export class MailInboundClient {
32
+ domains;
33
+ messages;
34
+ constructor(client) {
35
+ this.domains = new MailInboundDomainsClient(client);
36
+ this.messages = new MailInboundMessagesClient(client);
37
+ }
38
+ }
39
+ export class MailInboundDomainsClient {
40
+ client;
41
+ constructor(client) {
42
+ this.client = client;
43
+ }
44
+ create(domain) {
45
+ return this.client.mailRequest('/mail/inbound/domains', { method: 'POST', body: { domain } });
46
+ }
47
+ list() {
48
+ return this.client.mailRequest('/mail/inbound/domains');
49
+ }
50
+ verify(id) {
51
+ return this.client.mailRequest(`/mail/inbound/domains/${encodeURIComponent(id)}/verify`, { method: 'POST' });
52
+ }
53
+ }
54
+ export class MailInboundMessagesClient {
55
+ client;
56
+ constructor(client) {
57
+ this.client = client;
58
+ }
59
+ list() {
60
+ return this.client.mailRequest('/mail/inbound/messages');
61
+ }
62
+ get(id) {
63
+ return this.client.mailRequest(`/mail/inbound/messages/${encodeURIComponent(id)}`);
64
+ }
65
+ }
66
+ export class MailAnalyticsClient {
67
+ client;
68
+ constructor(client) {
69
+ this.client = client;
70
+ }
71
+ get(input = {}) {
72
+ const query = new URLSearchParams();
73
+ append(query, 'range', input.range);
74
+ append(query, 'from', input.from);
75
+ append(query, 'to', input.to);
76
+ append(query, 'interval', input.interval);
77
+ append(query, 'domain', input.domain);
78
+ append(query, 'template', input.template);
79
+ append(query, 'event', input.event);
80
+ const suffix = query.toString();
81
+ return this.client.mailRequest(`/mail/analytics${suffix ? `?${suffix}` : ''}`);
82
+ }
83
+ }
84
+ function append(target, key, value) {
85
+ if (value !== undefined && value !== null && value !== '') {
86
+ target.append(key, String(value));
87
+ }
88
+ }
@@ -0,0 +1,43 @@
1
+ import type { StackShift } from './client.js';
2
+ import type { MailEvent, MailEventListOptions, MailEventListResult, MailTimelineItem, MailWebhook, MailWebhookCreateInput, MailWebhookCreateResponse, MailWebhookDelivery, MailWebhookDeliveryDetail, MailWebhookDeliveryListOptions, MailWebhookListOptions, MailWebhookListResult, MailWebhookUpdateInput } from './mail-webhook-types.js';
3
+ export declare class MailEventsClient {
4
+ private readonly client;
5
+ constructor(client: StackShift);
6
+ list(options?: MailEventListOptions): Promise<MailEventListResult>;
7
+ get(eventId: string): Promise<MailEvent>;
8
+ }
9
+ export declare class MailWebhooksClient {
10
+ private readonly client;
11
+ constructor(client: StackShift);
12
+ create(input: MailWebhookCreateInput): Promise<MailWebhookCreateResponse>;
13
+ list(options?: MailWebhookListOptions): Promise<MailWebhookListResult>;
14
+ get(webhookId: string): Promise<MailWebhook>;
15
+ update(webhookId: string, input: MailWebhookUpdateInput): Promise<MailWebhook>;
16
+ rotateSecret(webhookId: string): Promise<{
17
+ secret: string;
18
+ }>;
19
+ delete(webhookId: string): Promise<void>;
20
+ deliveries(webhookId: string, options?: MailWebhookDeliveryListOptions): Promise<{
21
+ data: MailWebhookDelivery[];
22
+ nextCursor?: string | null;
23
+ }>;
24
+ getDelivery(deliveryId: string): Promise<MailWebhookDeliveryDetail>;
25
+ retryDelivery(deliveryId: string): Promise<MailWebhookDelivery>;
26
+ verifySignature(input: {
27
+ rawBody: string | Uint8Array;
28
+ signatureHeader?: string | null;
29
+ timestampHeader?: string | null;
30
+ secret: string;
31
+ toleranceSeconds?: number;
32
+ }): boolean;
33
+ }
34
+ export declare function verifyWebhookSignature(input: {
35
+ rawBody: string | Uint8Array;
36
+ signatureHeader?: string | null;
37
+ timestampHeader?: string | null;
38
+ secret: string;
39
+ toleranceSeconds?: number;
40
+ }): boolean;
41
+ export declare function timeline(client: StackShift, messageId: string): Promise<{
42
+ data: MailTimelineItem[];
43
+ }>;
@@ -0,0 +1,194 @@
1
+ export class MailEventsClient {
2
+ client;
3
+ constructor(client) {
4
+ this.client = client;
5
+ }
6
+ list(options = {}) {
7
+ const query = queryString(options);
8
+ return this.client.mailRequest(`/mail/events${query}`);
9
+ }
10
+ get(eventId) {
11
+ return this.client.mailRequest(`/mail/events/${encodeURIComponent(eventId)}`);
12
+ }
13
+ }
14
+ export class MailWebhooksClient {
15
+ client;
16
+ constructor(client) {
17
+ this.client = client;
18
+ }
19
+ create(input) {
20
+ return this.client.mailRequest('/mail/webhooks', {
21
+ method: 'POST',
22
+ body: input,
23
+ });
24
+ }
25
+ list(options = {}) {
26
+ return this.client.mailRequest(`/mail/webhooks${queryString(options)}`);
27
+ }
28
+ get(webhookId) {
29
+ return this.client.mailRequest(`/mail/webhooks/${encodeURIComponent(webhookId)}`);
30
+ }
31
+ update(webhookId, input) {
32
+ return this.client.mailRequest(`/mail/webhooks/${encodeURIComponent(webhookId)}`, {
33
+ method: 'PATCH',
34
+ body: input,
35
+ });
36
+ }
37
+ rotateSecret(webhookId) {
38
+ return this.client.mailRequest(`/mail/webhooks/${encodeURIComponent(webhookId)}/rotate-secret`, {
39
+ method: 'POST',
40
+ });
41
+ }
42
+ delete(webhookId) {
43
+ return this.client.mailRequest(`/mail/webhooks/${encodeURIComponent(webhookId)}`, {
44
+ method: 'DELETE',
45
+ });
46
+ }
47
+ deliveries(webhookId, options = {}) {
48
+ return this.client.mailRequest(`/mail/webhooks/${encodeURIComponent(webhookId)}/deliveries${queryString(options)}`);
49
+ }
50
+ getDelivery(deliveryId) {
51
+ return this.client.mailRequest(`/mail/webhook-deliveries/${encodeURIComponent(deliveryId)}`);
52
+ }
53
+ retryDelivery(deliveryId) {
54
+ return this.client.mailRequest(`/mail/webhook-deliveries/${encodeURIComponent(deliveryId)}/retry`, {
55
+ method: 'POST',
56
+ });
57
+ }
58
+ verifySignature(input) {
59
+ return verifyWebhookSignature(input);
60
+ }
61
+ }
62
+ export function verifyWebhookSignature(input) {
63
+ const timestamp = Number(input.timestampHeader);
64
+ if (!Number.isFinite(timestamp))
65
+ return false;
66
+ const tolerance = input.toleranceSeconds ?? 300;
67
+ if (tolerance > 0 && Math.abs(Date.now() / 1000 - timestamp) > tolerance)
68
+ return false;
69
+ const expected = hex(hmacSha256(utf8(`${timestamp}.`), bytes(input.rawBody), utf8(input.secret)));
70
+ const actual = signatureValue(input.signatureHeader ?? '');
71
+ if (!actual || actual.length !== expected.length)
72
+ return false;
73
+ return constantTimeEqual(actual, expected);
74
+ }
75
+ export function timeline(client, messageId) {
76
+ return client.mailRequest(`/mail/messages/${encodeURIComponent(messageId)}/timeline`);
77
+ }
78
+ function queryString(options) {
79
+ const query = new URLSearchParams();
80
+ for (const [key, value] of Object.entries(options)) {
81
+ if (value !== undefined && value !== null && value !== '') {
82
+ query.append(key, String(value));
83
+ }
84
+ }
85
+ const suffix = query.toString();
86
+ return suffix ? `?${suffix}` : '';
87
+ }
88
+ function signatureValue(header) {
89
+ return header.split(',').map((part) => part.trim()).find((part) => part.startsWith('v1='))?.slice(3) ?? '';
90
+ }
91
+ function hmacSha256(prefix, body, key) {
92
+ let normalized = key;
93
+ if (normalized.length > 64)
94
+ normalized = sha256(normalized);
95
+ const inner = new Uint8Array(64);
96
+ const outer = new Uint8Array(64);
97
+ inner.fill(0x36);
98
+ outer.fill(0x5c);
99
+ for (let i = 0; i < normalized.length; i += 1) {
100
+ inner[i] ^= normalized[i];
101
+ outer[i] ^= normalized[i];
102
+ }
103
+ return sha256(concat(outer, sha256(concat(inner, prefix, body))));
104
+ }
105
+ function sha256(message) {
106
+ const k = [
107
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
108
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
109
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
110
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
111
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
112
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
113
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
114
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
115
+ ];
116
+ let h0 = 0x6a09e667, h1 = 0xbb67ae85, h2 = 0x3c6ef372, h3 = 0xa54ff53a;
117
+ let h4 = 0x510e527f, h5 = 0x9b05688c, h6 = 0x1f83d9ab, h7 = 0x5be0cd19;
118
+ const padded = pad(message);
119
+ const w = new Uint32Array(64);
120
+ for (let offset = 0; offset < padded.length; offset += 64) {
121
+ for (let i = 0; i < 16; i += 1)
122
+ w[i] = read32(padded, offset + i * 4);
123
+ for (let i = 16; i < 64; i += 1)
124
+ w[i] = (sigma1(w[i - 2]) + w[i - 7] + sigma0(w[i - 15]) + w[i - 16]) >>> 0;
125
+ let a = h0, b = h1, c = h2, d = h3, e = h4, f = h5, g = h6, h = h7;
126
+ for (let i = 0; i < 64; i += 1) {
127
+ const t1 = (h + capsigma1(e) + ch(e, f, g) + k[i] + w[i]) >>> 0;
128
+ const t2 = (capsigma0(a) + maj(a, b, c)) >>> 0;
129
+ h = g;
130
+ g = f;
131
+ f = e;
132
+ e = (d + t1) >>> 0;
133
+ d = c;
134
+ c = b;
135
+ b = a;
136
+ a = (t1 + t2) >>> 0;
137
+ }
138
+ h0 = (h0 + a) >>> 0;
139
+ h1 = (h1 + b) >>> 0;
140
+ h2 = (h2 + c) >>> 0;
141
+ h3 = (h3 + d) >>> 0;
142
+ h4 = (h4 + e) >>> 0;
143
+ h5 = (h5 + f) >>> 0;
144
+ h6 = (h6 + g) >>> 0;
145
+ h7 = (h7 + h) >>> 0;
146
+ }
147
+ const out = new Uint8Array(32);
148
+ [h0, h1, h2, h3, h4, h5, h6, h7].forEach((value, i) => write32(out, i * 4, value));
149
+ return out;
150
+ }
151
+ const rotr = (x, n) => (x >>> n) | (x << (32 - n));
152
+ const ch = (x, y, z) => (x & y) ^ (~x & z);
153
+ const maj = (x, y, z) => (x & y) ^ (x & z) ^ (y & z);
154
+ const capsigma0 = (x) => rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22);
155
+ const capsigma1 = (x) => rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25);
156
+ const sigma0 = (x) => rotr(x, 7) ^ rotr(x, 18) ^ (x >>> 3);
157
+ const sigma1 = (x) => rotr(x, 17) ^ rotr(x, 19) ^ (x >>> 10);
158
+ const utf8 = (value) => new TextEncoder().encode(value);
159
+ const bytes = (value) => (typeof value === 'string' ? utf8(value) : value);
160
+ const concat = (...arrays) => {
161
+ const out = new Uint8Array(arrays.reduce((sum, item) => sum + item.length, 0));
162
+ let offset = 0;
163
+ for (const item of arrays) {
164
+ out.set(item, offset);
165
+ offset += item.length;
166
+ }
167
+ return out;
168
+ };
169
+ function pad(message) {
170
+ const length = (((message.length + 9 + 63) >> 6) << 6);
171
+ const out = new Uint8Array(length);
172
+ out.set(message);
173
+ out[message.length] = 0x80;
174
+ const bitLength = message.length * 8;
175
+ write32(out, length - 4, bitLength >>> 0);
176
+ write32(out, length - 8, Math.floor(bitLength / 0x100000000));
177
+ return out;
178
+ }
179
+ const read32 = (data, offset) => ((data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3]) >>> 0;
180
+ function write32(data, offset, value) {
181
+ data[offset] = value >>> 24;
182
+ data[offset + 1] = value >>> 16;
183
+ data[offset + 2] = value >>> 8;
184
+ data[offset + 3] = value;
185
+ }
186
+ function hex(data) {
187
+ return Array.from(data, (byte) => byte.toString(16).padStart(2, '0')).join('');
188
+ }
189
+ function constantTimeEqual(a, b) {
190
+ let diff = 0;
191
+ for (let i = 0; i < a.length; i += 1)
192
+ diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
193
+ return diff === 0;
194
+ }
@@ -0,0 +1,63 @@
1
+ import type { JsonValue } from './types.js';
2
+ export type MailOtpStatus = 'pending' | 'verified' | 'expired' | 'failed' | 'canceled';
3
+ export interface MailOtpSendInput {
4
+ to: string;
5
+ purpose: string;
6
+ from?: string;
7
+ expiresIn?: string;
8
+ codeLength?: number;
9
+ metadata?: Record<string, JsonValue>;
10
+ idempotencyKey?: string;
11
+ subject?: string;
12
+ brandName?: string;
13
+ }
14
+ export interface MailOtpVerifyInput {
15
+ to?: string;
16
+ purpose?: string;
17
+ challengeId?: string;
18
+ code: string;
19
+ }
20
+ export interface MailOtpChallengeListOptions {
21
+ to?: string;
22
+ purpose?: string;
23
+ status?: MailOtpStatus;
24
+ limit?: number;
25
+ cursor?: string;
26
+ }
27
+ export interface MailOtpChallenge {
28
+ id: string;
29
+ to: string;
30
+ purpose: string;
31
+ status: MailOtpStatus;
32
+ attempts: number;
33
+ maxAttempts: number;
34
+ attemptsRemaining?: number;
35
+ expiresAt: string;
36
+ resendAvailableAt?: string;
37
+ messageId?: string | null;
38
+ metadata?: Record<string, JsonValue> | null;
39
+ createdAt: string;
40
+ verifiedAt?: string | null;
41
+ failedAt?: string | null;
42
+ canceledAt?: string | null;
43
+ }
44
+ export interface MailOtpChallengeListResult {
45
+ data: MailOtpChallenge[];
46
+ nextCursor?: string | null;
47
+ }
48
+ export interface MailOtpSendResponse {
49
+ id: string;
50
+ to: string;
51
+ purpose: string;
52
+ status: MailOtpStatus;
53
+ expiresAt: string;
54
+ attemptsRemaining: number;
55
+ resendAvailableAt: string;
56
+ messageId?: string | null;
57
+ idempotencyStatus?: 'created' | 'reused';
58
+ }
59
+ export interface MailOtpVerifyResponse {
60
+ verified: boolean;
61
+ challengeId: string;
62
+ status: MailOtpStatus;
63
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,49 @@
1
+ import type { JsonValue } from './types.js';
2
+ export type MailBounceType = 'hard' | 'soft' | 'unknown';
3
+ export type MailSuppressionReason = 'hard_bounce' | 'complaint' | 'manual' | 'repeated_soft_bounce' | 'blocked' | 'unsubscribe';
4
+ export type MailSuppressionSource = 'bounce_processor' | 'user' | 'system' | 'future_complaint_processor';
5
+ export interface MailSuppression {
6
+ id: string;
7
+ email: string;
8
+ reason: MailSuppressionReason;
9
+ source: MailSuppressionSource;
10
+ messageId?: string | null;
11
+ createdAt: string;
12
+ expiresAt?: string | null;
13
+ }
14
+ export interface MailSuppressionListOptions {
15
+ email?: string;
16
+ reason?: MailSuppressionReason;
17
+ limit?: number;
18
+ cursor?: string;
19
+ }
20
+ export interface MailSuppressionCreateInput {
21
+ email: string;
22
+ reason?: 'manual' | 'blocked';
23
+ metadata?: JsonValue;
24
+ }
25
+ export interface MailSuppressionListResult {
26
+ data: MailSuppression[];
27
+ nextCursor?: string | null;
28
+ }
29
+ export interface MailBounce {
30
+ id: string;
31
+ messageId?: string | null;
32
+ recipientEmail: string;
33
+ bounceType: MailBounceType;
34
+ reason: string;
35
+ smtpStatusCode?: string | null;
36
+ diagnosticCode?: string | null;
37
+ receivedAt: string;
38
+ }
39
+ export interface MailBounceListOptions {
40
+ email?: string;
41
+ type?: MailBounceType;
42
+ messageId?: string;
43
+ limit?: number;
44
+ cursor?: string;
45
+ }
46
+ export interface MailBounceListResult {
47
+ data: MailBounce[];
48
+ nextCursor?: string | null;
49
+ }
@@ -0,0 +1 @@
1
+ export {};