shipmail 0.4.12 → 0.4.13
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/LICENSE +1 -1
- package/README.md +13 -13
- package/dist/index.cjs +25 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -23
- package/dist/index.d.ts +23 -23
- package/dist/index.js +23 -23
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -53,9 +53,9 @@ pnpm add shipmail
|
|
|
53
53
|
## Quick start
|
|
54
54
|
|
|
55
55
|
```ts
|
|
56
|
-
import {
|
|
56
|
+
import { ShipmailClient } from "shipmail";
|
|
57
57
|
|
|
58
|
-
const shipmail = new
|
|
58
|
+
const shipmail = new ShipmailClient({ apiKey: process.env.SHIPMAIL_API_KEY! });
|
|
59
59
|
|
|
60
60
|
const message = await shipmail.messages.send({
|
|
61
61
|
mailbox_id: "mbx_...",
|
|
@@ -76,13 +76,13 @@ The SDK does not auto-read environment variables. Pass the key explicitly.
|
|
|
76
76
|
You can also pass a key string directly:
|
|
77
77
|
|
|
78
78
|
```ts
|
|
79
|
-
const shipmail = new
|
|
79
|
+
const shipmail = new ShipmailClient("sm_live_...");
|
|
80
80
|
```
|
|
81
81
|
|
|
82
82
|
## Configuration
|
|
83
83
|
|
|
84
84
|
```ts
|
|
85
|
-
const shipmail = new
|
|
85
|
+
const shipmail = new ShipmailClient({
|
|
86
86
|
apiKey: process.env.SHIPMAIL_API_KEY!,
|
|
87
87
|
baseUrl: "https://shipmail.to/api/v1",
|
|
88
88
|
maxRetries: 2,
|
|
@@ -271,7 +271,7 @@ await shipmail.scheduledMessages.cancel(scheduled.id);
|
|
|
271
271
|
Staged IDs expire after 24 hours and are bound to the API key, organization, mailbox, and file
|
|
272
272
|
metadata that created them.
|
|
273
273
|
|
|
274
|
-
For browser-hosted components that must keep the
|
|
274
|
+
For browser-hosted components that must keep the Shipmail API key off the page, prepare a
|
|
275
275
|
five-minute, single-use upload URL:
|
|
276
276
|
|
|
277
277
|
```ts
|
|
@@ -299,7 +299,7 @@ request. The returned upload URL is a secret and cannot be replayed after a succ
|
|
|
299
299
|
Create a test API key (`sm_test_...`) to simulate email without contacting real recipients. Test messages, threads, Assistant automations, webhooks, quota, suppressions, and reputation are isolated from live mode.
|
|
300
300
|
|
|
301
301
|
```ts
|
|
302
|
-
const testClient = new
|
|
302
|
+
const testClient = new ShipmailClient("sm_test_...");
|
|
303
303
|
|
|
304
304
|
await testClient.messages.send({
|
|
305
305
|
mailbox_id: "mbx_...",
|
|
@@ -506,7 +506,7 @@ const child = await shipmail.partner.createOrganization(
|
|
|
506
506
|
{ idempotencyKey: "operator-123" },
|
|
507
507
|
);
|
|
508
508
|
|
|
509
|
-
const delegated = new
|
|
509
|
+
const delegated = new ShipmailClient({
|
|
510
510
|
apiKey: process.env.SHIPMAIL_API_KEY!,
|
|
511
511
|
organizationId: child.organization_id,
|
|
512
512
|
});
|
|
@@ -668,7 +668,7 @@ await shipmail.messages.send(params, { signal: controller.signal });
|
|
|
668
668
|
Inject a custom fetch implementation for proxies, observability, or testing:
|
|
669
669
|
|
|
670
670
|
```ts
|
|
671
|
-
const shipmail = new
|
|
671
|
+
const shipmail = new ShipmailClient({
|
|
672
672
|
apiKey: process.env.SHIPMAIL_API_KEY!,
|
|
673
673
|
fetch: async (url, init) => {
|
|
674
674
|
const start = Date.now();
|
|
@@ -683,11 +683,11 @@ The custom fetch receives the same arguments as the global `fetch` and must retu
|
|
|
683
683
|
|
|
684
684
|
## Errors
|
|
685
685
|
|
|
686
|
-
The SDK throws typed errors that map to HTTP responses. All inherit from `
|
|
686
|
+
The SDK throws typed errors that map to HTTP responses. All inherit from `ShipmailError`:
|
|
687
687
|
|
|
688
688
|
```ts
|
|
689
689
|
import {
|
|
690
|
-
|
|
690
|
+
ShipmailError,
|
|
691
691
|
AuthenticationError,
|
|
692
692
|
AuthorizationError,
|
|
693
693
|
ValidationError,
|
|
@@ -709,7 +709,7 @@ try {
|
|
|
709
709
|
if (err instanceof RateLimitError) {
|
|
710
710
|
err.retryAfter; // seconds
|
|
711
711
|
}
|
|
712
|
-
if (err instanceof
|
|
712
|
+
if (err instanceof ShipmailError) {
|
|
713
713
|
err.status; // HTTP status
|
|
714
714
|
err.type; // error type string
|
|
715
715
|
err.requestId; // include this when contacting support
|
|
@@ -736,7 +736,7 @@ try {
|
|
|
736
736
|
The SDK retries on `5xx`, `429`, and connection errors with exponential backoff and jitter. `Retry-After` is honored when present. Default is 2 retries (3 total attempts).
|
|
737
737
|
|
|
738
738
|
```ts
|
|
739
|
-
new
|
|
739
|
+
new ShipmailClient({ apiKey, maxRetries: 0 }); // disable retries
|
|
740
740
|
```
|
|
741
741
|
|
|
742
742
|
Retries respect any `AbortSignal` you pass via `MethodOptions.signal`.
|
|
@@ -750,7 +750,7 @@ The package ships ESM and CommonJS via `exports`, with `"sideEffects": false` fo
|
|
|
750
750
|
Mock by injecting a custom `fetch` at construction time:
|
|
751
751
|
|
|
752
752
|
```ts
|
|
753
|
-
const shipmail = new
|
|
753
|
+
const shipmail = new ShipmailClient({
|
|
754
754
|
apiKey: "sm_live_test",
|
|
755
755
|
fetch: async () =>
|
|
756
756
|
new Response(JSON.stringify({ id: "msg_123", status: "queued" }), {
|
package/dist/index.cjs
CHANGED
|
@@ -85,29 +85,29 @@ function apiKeyScopesGrant(grantedScopes, requiredScope) {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
// src/errors.ts
|
|
88
|
-
var
|
|
88
|
+
var ShipmailError = class extends Error {
|
|
89
89
|
constructor(message, options) {
|
|
90
90
|
super(message);
|
|
91
|
-
this.name = "
|
|
91
|
+
this.name = "ShipmailError";
|
|
92
92
|
this.status = options?.status;
|
|
93
93
|
this.type = options?.type;
|
|
94
94
|
this.requestId = options?.requestId;
|
|
95
95
|
this.retryable = options?.retryable ?? false;
|
|
96
96
|
}
|
|
97
97
|
};
|
|
98
|
-
var AuthenticationError = class extends
|
|
98
|
+
var AuthenticationError = class extends ShipmailError {
|
|
99
99
|
constructor(message, requestId) {
|
|
100
100
|
super(message, { status: 401, type: "authentication_error", requestId, retryable: false });
|
|
101
101
|
this.name = "AuthenticationError";
|
|
102
102
|
}
|
|
103
103
|
};
|
|
104
|
-
var AuthorizationError = class extends
|
|
104
|
+
var AuthorizationError = class extends ShipmailError {
|
|
105
105
|
constructor(message, requestId) {
|
|
106
106
|
super(message, { status: 403, type: "authorization_error", requestId, retryable: false });
|
|
107
107
|
this.name = "AuthorizationError";
|
|
108
108
|
}
|
|
109
109
|
};
|
|
110
|
-
var ValidationError = class extends
|
|
110
|
+
var ValidationError = class extends ShipmailError {
|
|
111
111
|
constructor(message, options) {
|
|
112
112
|
super(message, {
|
|
113
113
|
status: 422,
|
|
@@ -119,19 +119,19 @@ var ValidationError = class extends ShipMailError {
|
|
|
119
119
|
this.details = options?.details;
|
|
120
120
|
}
|
|
121
121
|
};
|
|
122
|
-
var QuotaExceededError = class extends
|
|
122
|
+
var QuotaExceededError = class extends ShipmailError {
|
|
123
123
|
constructor(message, requestId) {
|
|
124
124
|
super(message, { status: 403, type: "quota_exceeded", requestId, retryable: false });
|
|
125
125
|
this.name = "QuotaExceededError";
|
|
126
126
|
}
|
|
127
127
|
};
|
|
128
|
-
var NotFoundError = class extends
|
|
128
|
+
var NotFoundError = class extends ShipmailError {
|
|
129
129
|
constructor(message, requestId) {
|
|
130
130
|
super(message, { status: 404, type: "not_found", requestId, retryable: false });
|
|
131
131
|
this.name = "NotFoundError";
|
|
132
132
|
}
|
|
133
133
|
};
|
|
134
|
-
var RateLimitError = class extends
|
|
134
|
+
var RateLimitError = class extends ShipmailError {
|
|
135
135
|
constructor(message, options) {
|
|
136
136
|
super(message, {
|
|
137
137
|
status: 429,
|
|
@@ -143,25 +143,25 @@ var RateLimitError = class extends ShipMailError {
|
|
|
143
143
|
this.retryAfter = options?.retryAfter;
|
|
144
144
|
}
|
|
145
145
|
};
|
|
146
|
-
var ConflictError = class extends
|
|
146
|
+
var ConflictError = class extends ShipmailError {
|
|
147
147
|
constructor(message, requestId) {
|
|
148
148
|
super(message, { status: 409, type: "conflict", requestId, retryable: false });
|
|
149
149
|
this.name = "ConflictError";
|
|
150
150
|
}
|
|
151
151
|
};
|
|
152
|
-
var InternalServerError = class extends
|
|
152
|
+
var InternalServerError = class extends ShipmailError {
|
|
153
153
|
constructor(message, requestId) {
|
|
154
154
|
super(message, { status: 500, type: "internal_error", requestId, retryable: true });
|
|
155
155
|
this.name = "InternalServerError";
|
|
156
156
|
}
|
|
157
157
|
};
|
|
158
|
-
var ConnectionError = class extends
|
|
158
|
+
var ConnectionError = class extends ShipmailError {
|
|
159
159
|
constructor(message) {
|
|
160
160
|
super(message, { retryable: true });
|
|
161
161
|
this.name = "ConnectionError";
|
|
162
162
|
}
|
|
163
163
|
};
|
|
164
|
-
var WebhookVerificationError = class extends
|
|
164
|
+
var WebhookVerificationError = class extends ShipmailError {
|
|
165
165
|
constructor(message) {
|
|
166
166
|
super(message, { retryable: false });
|
|
167
167
|
this.name = "WebhookVerificationError";
|
|
@@ -188,7 +188,7 @@ function mapErrorFromResponse(status, body, requestId) {
|
|
|
188
188
|
case "internal_error":
|
|
189
189
|
return new InternalServerError(error.message, rid);
|
|
190
190
|
default:
|
|
191
|
-
return new
|
|
191
|
+
return new ShipmailError(error.message, {
|
|
192
192
|
status,
|
|
193
193
|
type: error.type,
|
|
194
194
|
requestId: rid,
|
|
@@ -1568,7 +1568,7 @@ var Webhooks = class extends ApiResource {
|
|
|
1568
1568
|
};
|
|
1569
1569
|
|
|
1570
1570
|
// src/version.ts
|
|
1571
|
-
var VERSION = "0.4.
|
|
1571
|
+
var VERSION = "0.4.13";
|
|
1572
1572
|
|
|
1573
1573
|
// src/client.ts
|
|
1574
1574
|
var DEFAULT_BASE_URL = "https://shipmail.to/api/v1";
|
|
@@ -1598,9 +1598,9 @@ function rawBodyToBlobPart(rawBody) {
|
|
|
1598
1598
|
new Uint8Array(buffer).set(rawBody);
|
|
1599
1599
|
return buffer;
|
|
1600
1600
|
}
|
|
1601
|
-
var
|
|
1601
|
+
var ShipmailClient = class {
|
|
1602
1602
|
/**
|
|
1603
|
-
* Create a new
|
|
1603
|
+
* Create a new Shipmail client.
|
|
1604
1604
|
* @param config - API key string or full configuration object.
|
|
1605
1605
|
*/
|
|
1606
1606
|
constructor(config) {
|
|
@@ -1674,7 +1674,7 @@ var ShipMailClient = class {
|
|
|
1674
1674
|
}
|
|
1675
1675
|
const targetOrganizationId = methodOpts?.organizationId ?? this.organizationId;
|
|
1676
1676
|
if (targetOrganizationId) {
|
|
1677
|
-
headers["X-
|
|
1677
|
+
headers["X-Shipmail-Organization-Id"] = targetOrganizationId;
|
|
1678
1678
|
}
|
|
1679
1679
|
let body = null;
|
|
1680
1680
|
if (options.rawBody !== void 0) {
|
|
@@ -1708,7 +1708,7 @@ var ShipMailClient = class {
|
|
|
1708
1708
|
if (isApiErrorBody(errorBody)) {
|
|
1709
1709
|
lastError = mapErrorFromResponse(response.status, errorBody);
|
|
1710
1710
|
} else {
|
|
1711
|
-
lastError = new
|
|
1711
|
+
lastError = new ShipmailError(`Request failed with status ${response.status}`, {
|
|
1712
1712
|
status: response.status,
|
|
1713
1713
|
retryable: isRetryableStatus(response.status)
|
|
1714
1714
|
});
|
|
@@ -1717,7 +1717,7 @@ var ShipMailClient = class {
|
|
|
1717
1717
|
throw lastError;
|
|
1718
1718
|
}
|
|
1719
1719
|
}
|
|
1720
|
-
throw lastError ?? new
|
|
1720
|
+
throw lastError ?? new ShipmailError("Request failed after retries");
|
|
1721
1721
|
}
|
|
1722
1722
|
buildUrl(path2, query) {
|
|
1723
1723
|
const url = new URL(`${this.baseUrl}${path2}`);
|
|
@@ -1792,14 +1792,14 @@ async function verifyWebhook(body, headers, secret, options) {
|
|
|
1792
1792
|
const signature = getHeader(headers, "x-shipmail-signature");
|
|
1793
1793
|
const timestampStr = getHeader(headers, "x-shipmail-timestamp");
|
|
1794
1794
|
if (!signature) {
|
|
1795
|
-
throw new WebhookVerificationError("Missing X-
|
|
1795
|
+
throw new WebhookVerificationError("Missing X-Shipmail-Signature header");
|
|
1796
1796
|
}
|
|
1797
1797
|
if (!timestampStr) {
|
|
1798
|
-
throw new WebhookVerificationError("Missing X-
|
|
1798
|
+
throw new WebhookVerificationError("Missing X-Shipmail-Timestamp header");
|
|
1799
1799
|
}
|
|
1800
1800
|
const timestamp = parseInt(timestampStr, 10);
|
|
1801
1801
|
if (isNaN(timestamp)) {
|
|
1802
|
-
throw new WebhookVerificationError("Invalid X-
|
|
1802
|
+
throw new WebhookVerificationError("Invalid X-Shipmail-Timestamp header");
|
|
1803
1803
|
}
|
|
1804
1804
|
const tolerance = options?.toleranceInSeconds ?? DEFAULT_TOLERANCE_SECONDS;
|
|
1805
1805
|
const now = Math.floor(Date.now() / 1e3);
|
|
@@ -1837,15 +1837,15 @@ exports.NotFoundError = NotFoundError;
|
|
|
1837
1837
|
exports.Page = Page;
|
|
1838
1838
|
exports.QuotaExceededError = QuotaExceededError;
|
|
1839
1839
|
exports.RateLimitError = RateLimitError;
|
|
1840
|
-
exports.
|
|
1841
|
-
exports.
|
|
1840
|
+
exports.ShipmailClient = ShipmailClient;
|
|
1841
|
+
exports.ShipmailError = ShipmailError;
|
|
1842
1842
|
exports.ValidationError = ValidationError;
|
|
1843
1843
|
exports.WEBHOOK_DELIVERY_EVENT_TYPES = WEBHOOK_DELIVERY_EVENT_TYPES;
|
|
1844
1844
|
exports.WEBHOOK_DELIVERY_STATUSES = WEBHOOK_DELIVERY_STATUSES;
|
|
1845
1845
|
exports.WEBHOOK_EVENT_TYPES = WEBHOOK_EVENT_TYPES;
|
|
1846
1846
|
exports.WebhookVerificationError = WebhookVerificationError;
|
|
1847
1847
|
exports.apiKeyScopesGrant = apiKeyScopesGrant;
|
|
1848
|
-
exports.default =
|
|
1848
|
+
exports.default = ShipmailClient;
|
|
1849
1849
|
exports.isApiKeyScope = isApiKeyScope;
|
|
1850
1850
|
exports.verifyWebhook = verifyWebhook;
|
|
1851
1851
|
//# sourceMappingURL=index.cjs.map
|