millionsend 0.0.1 → 0.1.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 +153 -4
- package/dist/error.d.ts +24 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +16 -0
- package/dist/error.js.map +1 -0
- package/dist/http.d.ts +34 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +75 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -0
- package/dist/query.d.ts +4 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +7 -0
- package/dist/query.js.map +1 -0
- package/dist/resources/audiences.d.ts +17 -0
- package/dist/resources/audiences.d.ts.map +1 -0
- package/dist/resources/audiences.js +25 -0
- package/dist/resources/audiences.js.map +1 -0
- package/dist/resources/broadcasts.d.ts +16 -0
- package/dist/resources/broadcasts.d.ts.map +1 -0
- package/dist/resources/broadcasts.js +54 -0
- package/dist/resources/broadcasts.js.map +1 -0
- package/dist/resources/contacts.d.ts +22 -0
- package/dist/resources/contacts.d.ts.map +1 -0
- package/dist/resources/contacts.js +73 -0
- package/dist/resources/contacts.js.map +1 -0
- package/dist/resources/emails.d.ts +28 -0
- package/dist/resources/emails.d.ts.map +1 -0
- package/dist/resources/emails.js +64 -0
- package/dist/resources/emails.js.map +1 -0
- package/dist/resources/segments.d.ts +17 -0
- package/dist/resources/segments.d.ts.map +1 -0
- package/dist/resources/segments.js +35 -0
- package/dist/resources/segments.js.map +1 -0
- package/dist/resources/topics.d.ts +16 -0
- package/dist/resources/topics.d.ts.map +1 -0
- package/dist/resources/topics.js +29 -0
- package/dist/resources/topics.js.map +1 -0
- package/dist/types.d.ts +254 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/package.json +34 -9
- package/index.d.ts +0 -4
- package/index.js +0 -14
package/README.md
CHANGED
|
@@ -1,7 +1,156 @@
|
|
|
1
1
|
# millionsend
|
|
2
2
|
|
|
3
|
-
Official Node.js SDK for [MillionSend](https://github.com/MillionSend) —
|
|
4
|
-
self-hostable email platform (bring your own AWS SES, or use the hosted cloud).
|
|
3
|
+
Official Node.js / TypeScript SDK for [MillionSend](https://github.com/MillionSend/millionsend) — a self-hostable, Resend-compatible email API on AWS SES.
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
The API is wire-compatible with Resend, and this SDK deliberately mirrors the
|
|
6
|
+
shape of `resend`, so migrating is mostly a find-and-replace: swap the import,
|
|
7
|
+
the class name, and point `baseUrl` at your instance.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install millionsend
|
|
13
|
+
# or: pnpm add millionsend / yarn add millionsend / bun add millionsend
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Requires Node.js 18+ (uses the global `fetch`).
|
|
17
|
+
|
|
18
|
+
## Quickstart
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import { MillionSend } from "millionsend";
|
|
22
|
+
|
|
23
|
+
const ms = new MillionSend("ms_123", { baseUrl: "https://mail.acme.dev" });
|
|
24
|
+
|
|
25
|
+
const { data, error } = await ms.emails.send({
|
|
26
|
+
from: "Acme <onboarding@acme.dev>",
|
|
27
|
+
to: "delivered@resend.dev",
|
|
28
|
+
subject: "Hello from MillionSend",
|
|
29
|
+
html: "<strong>It works!</strong>",
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
if (error) {
|
|
33
|
+
console.error(error.name, error.message);
|
|
34
|
+
} else {
|
|
35
|
+
console.log("sent", data.id);
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Configuration
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
new MillionSend(apiKey?, {
|
|
43
|
+
baseUrl?, // your instance URL; defaults to MILLIONSEND_BASE_URL, then http://localhost:3001
|
|
44
|
+
fetch?, // custom fetch implementation (proxies, tests, custom agents)
|
|
45
|
+
userAgent?, // extra User-Agent suffix
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
- `apiKey` falls back to `process.env.MILLIONSEND_API_KEY`. Missing key → throws at construction.
|
|
50
|
+
- `baseUrl` falls back to `process.env.MILLIONSEND_BASE_URL`. MillionSend is self-hosted, so **set this to your deployment in production.**
|
|
51
|
+
|
|
52
|
+
## Errors
|
|
53
|
+
|
|
54
|
+
No method throws for an API error — every call resolves to `{ data, error }`.
|
|
55
|
+
`error` is `null` on success; otherwise `{ name, message, statusCode }` where
|
|
56
|
+
`name` is a stable snake_case code you can switch on (`validation_error`,
|
|
57
|
+
`not_found`, `restricted_api_key`, `sending_paused`, …). Client-side and
|
|
58
|
+
transport failures carry `statusCode: null`.
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
const { data, error } = await ms.emails.get(id);
|
|
62
|
+
if (error?.name === "not_found") { /* … */ }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Resources
|
|
66
|
+
|
|
67
|
+
### Emails
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
await ms.emails.send(payload, { idempotencyKey }); // POST /emails
|
|
71
|
+
await ms.emails.get(id); // GET /emails/:id
|
|
72
|
+
await ms.emails.cancel(id); // POST /emails/:id/cancel (scheduled only)
|
|
73
|
+
await ms.batch.send([payloadA, payloadB], { idempotencyKey }); // up to 100
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Send options are camelCase and mapped to the wire: `replyTo` → `reply_to`,
|
|
77
|
+
`scheduledAt` → `scheduled_at`. `to`/`cc`/`bcc`/`replyTo` accept a string or an array.
|
|
78
|
+
|
|
79
|
+
### Audiences & contacts
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
const { data: audience } = await ms.audiences.create({ name: "Registered users" });
|
|
83
|
+
await ms.audiences.list({ limit: 20, after });
|
|
84
|
+
await ms.audiences.get(id);
|
|
85
|
+
await ms.audiences.remove(id);
|
|
86
|
+
|
|
87
|
+
await ms.contacts.create({ audienceId, email: "ada@acme.dev", firstName: "Ada",
|
|
88
|
+
properties: { plan: "pro" } });
|
|
89
|
+
await ms.contacts.get({ audienceId, email }); // by id or email (email wins)
|
|
90
|
+
await ms.contacts.get(contactId); // bare string works too
|
|
91
|
+
await ms.contacts.update({ id, unsubscribed: true, firstName: null }); // null clears
|
|
92
|
+
await ms.contacts.remove({ email });
|
|
93
|
+
await ms.contacts.list({ audienceId, limit: 50 });
|
|
94
|
+
|
|
95
|
+
// Topic subscriptions (granular unsubscribe)
|
|
96
|
+
await ms.contacts.topics.update({ email, topics: [{ id: topicId, subscription: "opt_out" }] });
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Topics
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
await ms.topics.create({ name: "Product updates", defaultSubscription: "opt_in" });
|
|
103
|
+
await ms.topics.get(id);
|
|
104
|
+
await ms.topics.list(); // bare { data } — topics are unpaginated
|
|
105
|
+
await ms.topics.remove(id);
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Broadcasts
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
const { data } = await ms.broadcasts.create({
|
|
112
|
+
audienceId, from: "Acme <news@acme.dev>", subject: "Launch",
|
|
113
|
+
html: "<p>Hi {{{FIRST_NAME|there}}}</p>",
|
|
114
|
+
});
|
|
115
|
+
await ms.broadcasts.list();
|
|
116
|
+
await ms.broadcasts.get(id);
|
|
117
|
+
await ms.broadcasts.update(id, { subject: "Launch 🚀" }); // draft only
|
|
118
|
+
await ms.broadcasts.send(id, { scheduledAt: "2026-09-01T09:00:00Z" }); // omit to send now
|
|
119
|
+
await ms.broadcasts.cancel(id); // scheduled only
|
|
120
|
+
await ms.broadcasts.remove(id); // draft only
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Segments (MillionSend extension)
|
|
124
|
+
|
|
125
|
+
Dynamic segments are a saved filter over an audience's contacts — a MillionSend
|
|
126
|
+
superset with no Resend equivalent.
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
await ms.segments.create({
|
|
130
|
+
name: "Pro plan",
|
|
131
|
+
audienceId,
|
|
132
|
+
filter: { match: "all", conditions: [{ field: "property:plan", op: "equals", value: "pro" }] },
|
|
133
|
+
});
|
|
134
|
+
await ms.segments.get(id); // includes a live contact_count
|
|
135
|
+
await ms.segments.list();
|
|
136
|
+
await ms.segments.update(id, { name: "Pro tier" });
|
|
137
|
+
await ms.segments.remove(id);
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Migrating from Resend
|
|
141
|
+
|
|
142
|
+
```diff
|
|
143
|
+
- import { Resend } from "resend";
|
|
144
|
+
- const resend = new Resend("re_123");
|
|
145
|
+
+ import { MillionSend } from "millionsend";
|
|
146
|
+
+ const ms = new MillionSend("ms_123", { baseUrl: "https://mail.acme.dev" });
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Method names and payloads match. Notes:
|
|
150
|
+
|
|
151
|
+
- **Domains and API keys** are managed in the MillionSend dashboard, not via the API, so there are no `.domains`/`.apiKeys` resources here.
|
|
152
|
+
- Resend's `.segments` is an alias of audiences; MillionSend's `.segments` is the distinct dynamic-filter feature. Use `.audiences` for a straight port.
|
|
153
|
+
|
|
154
|
+
## License
|
|
155
|
+
|
|
156
|
+
MIT
|
package/dist/error.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The error shape the MillionSend API returns on every non-2xx response, plus
|
|
3
|
+
* the two client-side conditions (a bad request never sent, a transport
|
|
4
|
+
* failure) which carry `statusCode: null`. Mirrors Resend's `ErrorResponse`, so
|
|
5
|
+
* code that switches on `error.name` ports across unchanged.
|
|
6
|
+
*/
|
|
7
|
+
export interface ErrorResponse {
|
|
8
|
+
/** Stable snake_case code — the discriminant, e.g. "validation_error", "not_found". */
|
|
9
|
+
name: string;
|
|
10
|
+
message: string;
|
|
11
|
+
/** HTTP status; null when the request never reached the API. */
|
|
12
|
+
statusCode: number | null;
|
|
13
|
+
}
|
|
14
|
+
/** Every method resolves to this — it never throws for an API error. */
|
|
15
|
+
export type Result<T> = {
|
|
16
|
+
data: T;
|
|
17
|
+
error: null;
|
|
18
|
+
} | {
|
|
19
|
+
data: null;
|
|
20
|
+
error: ErrorResponse;
|
|
21
|
+
};
|
|
22
|
+
/** Coerce an arbitrary parsed error body into the canonical shape. */
|
|
23
|
+
export declare function toErrorResponse(body: unknown, status: number): ErrorResponse;
|
|
24
|
+
//# sourceMappingURL=error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,uFAAuF;IACvF,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,wEAAwE;AACxE,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI;IAAE,IAAI,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,aAAa,CAAA;CAAE,CAAC;AAExF,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CAa5E"}
|
package/dist/error.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Coerce an arbitrary parsed error body into the canonical shape. */
|
|
2
|
+
export function toErrorResponse(body, status) {
|
|
3
|
+
if (body && typeof body === "object") {
|
|
4
|
+
const b = body;
|
|
5
|
+
const name = typeof b.name === "string" ? b.name : "application_error";
|
|
6
|
+
const message = typeof b.message === "string" ? b.message : `Request failed with status ${status}`;
|
|
7
|
+
const statusCode = typeof b.statusCode === "number" ? b.statusCode : status;
|
|
8
|
+
return { name, message, statusCode };
|
|
9
|
+
}
|
|
10
|
+
return {
|
|
11
|
+
name: "application_error",
|
|
12
|
+
message: `Request failed with status ${status}`,
|
|
13
|
+
statusCode: status,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAiBA,sEAAsE;AACtE,MAAM,UAAU,eAAe,CAAC,IAAa,EAAE,MAAc;IAC3D,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAA+B,CAAC;QAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC;QACvE,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,8BAA8B,MAAM,EAAE,CAAC;QACnG,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC;QAC5E,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IACvC,CAAC;IACD,OAAO;QACL,IAAI,EAAE,mBAAmB;QACzB,OAAO,EAAE,8BAA8B,MAAM,EAAE;QAC/C,UAAU,EAAE,MAAM;KACnB,CAAC;AACJ,CAAC"}
|
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type Result } from "./error.js";
|
|
2
|
+
export interface MillionSendOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Your MillionSend instance URL (no trailing slash needed). Falls back to
|
|
5
|
+
* `MILLIONSEND_BASE_URL`, then `http://localhost:3001`. Self-hosted, so there
|
|
6
|
+
* is no cloud default — set this to your deployment in production.
|
|
7
|
+
*/
|
|
8
|
+
baseUrl?: string;
|
|
9
|
+
/** Inject a fetch implementation (tests, proxies, custom agents). */
|
|
10
|
+
fetch?: typeof fetch;
|
|
11
|
+
/** Extra User-Agent suffix appended after the SDK's own token. */
|
|
12
|
+
userAgent?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface RequestOptions {
|
|
15
|
+
/** POST-only idempotency key (emails.send, batch.send). */
|
|
16
|
+
idempotencyKey?: string;
|
|
17
|
+
}
|
|
18
|
+
interface DoRequest {
|
|
19
|
+
method: "GET" | "POST" | "PATCH" | "DELETE";
|
|
20
|
+
path: string;
|
|
21
|
+
body?: unknown;
|
|
22
|
+
query?: Record<string, string | number | undefined> | undefined;
|
|
23
|
+
idempotencyKey?: string | undefined;
|
|
24
|
+
}
|
|
25
|
+
export declare class HttpClient {
|
|
26
|
+
private readonly apiKey;
|
|
27
|
+
private readonly baseUrl;
|
|
28
|
+
private readonly fetchImpl;
|
|
29
|
+
private readonly userAgent;
|
|
30
|
+
constructor(apiKey: string, options?: MillionSendOptions);
|
|
31
|
+
request<T>({ method, path, body, query, idempotencyKey }: DoRequest): Promise<Result<T>>;
|
|
32
|
+
}
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,MAAM,EAAmB,MAAM,YAAY,CAAC;AAK9E,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,2DAA2D;IAC3D,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,SAAS;IACjB,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;IAChE,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AAYD,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB;IAkBtD,OAAO,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;CA0C/F"}
|
package/dist/http.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { toErrorResponse } from "./error.js";
|
|
2
|
+
const DEFAULT_BASE_URL = "http://localhost:3001";
|
|
3
|
+
const SDK_VERSION = "0.1.0";
|
|
4
|
+
function queryString(query) {
|
|
5
|
+
if (!query)
|
|
6
|
+
return "";
|
|
7
|
+
const params = new URLSearchParams();
|
|
8
|
+
for (const [key, value] of Object.entries(query)) {
|
|
9
|
+
if (value !== undefined)
|
|
10
|
+
params.set(key, String(value));
|
|
11
|
+
}
|
|
12
|
+
const s = params.toString();
|
|
13
|
+
return s ? `?${s}` : "";
|
|
14
|
+
}
|
|
15
|
+
export class HttpClient {
|
|
16
|
+
apiKey;
|
|
17
|
+
baseUrl;
|
|
18
|
+
fetchImpl;
|
|
19
|
+
userAgent;
|
|
20
|
+
constructor(apiKey, options = {}) {
|
|
21
|
+
this.apiKey = apiKey;
|
|
22
|
+
this.baseUrl = (options.baseUrl ?? process.env.MILLIONSEND_BASE_URL ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
23
|
+
// Bind so a passed-in fetch keeps its own `this`; default to the global.
|
|
24
|
+
const chosen = options.fetch ?? globalThis.fetch;
|
|
25
|
+
if (!chosen) {
|
|
26
|
+
throw new Error("No fetch implementation found. Use Node 18+ or pass `fetch` in the client options.");
|
|
27
|
+
}
|
|
28
|
+
this.fetchImpl = chosen;
|
|
29
|
+
const base = `millionsend-node/${SDK_VERSION}`;
|
|
30
|
+
this.userAgent = options.userAgent ? `${base} ${options.userAgent}` : base;
|
|
31
|
+
}
|
|
32
|
+
async request({ method, path, body, query, idempotencyKey }) {
|
|
33
|
+
const url = `${this.baseUrl}${path}${queryString(query)}`;
|
|
34
|
+
const headers = {
|
|
35
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
36
|
+
Accept: "application/json",
|
|
37
|
+
"User-Agent": this.userAgent,
|
|
38
|
+
};
|
|
39
|
+
const init = { method, headers };
|
|
40
|
+
if (body !== undefined && method !== "GET" && method !== "DELETE") {
|
|
41
|
+
headers["Content-Type"] = "application/json";
|
|
42
|
+
init.body = JSON.stringify(body);
|
|
43
|
+
}
|
|
44
|
+
// Idempotency is POST-only on the wire; sending it elsewhere is a no-op.
|
|
45
|
+
if (idempotencyKey && method === "POST")
|
|
46
|
+
headers["Idempotency-Key"] = idempotencyKey;
|
|
47
|
+
let response;
|
|
48
|
+
try {
|
|
49
|
+
response = await this.fetchImpl(url, init);
|
|
50
|
+
}
|
|
51
|
+
catch (cause) {
|
|
52
|
+
const error = {
|
|
53
|
+
name: "application_error",
|
|
54
|
+
message: cause instanceof Error ? cause.message : String(cause),
|
|
55
|
+
statusCode: null,
|
|
56
|
+
};
|
|
57
|
+
return { data: null, error };
|
|
58
|
+
}
|
|
59
|
+
const text = await response.text();
|
|
60
|
+
let parsed = null;
|
|
61
|
+
if (text) {
|
|
62
|
+
try {
|
|
63
|
+
parsed = JSON.parse(text);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
parsed = text;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (!response.ok) {
|
|
70
|
+
return { data: null, error: toErrorResponse(parsed, response.status) };
|
|
71
|
+
}
|
|
72
|
+
return { data: parsed, error: null };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=http.js.map
|
package/dist/http.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type MillionSendOptions } from "./http.js";
|
|
2
|
+
import { Audiences } from "./resources/audiences.js";
|
|
3
|
+
import { Broadcasts } from "./resources/broadcasts.js";
|
|
4
|
+
import { Contacts } from "./resources/contacts.js";
|
|
5
|
+
import { Batch, Emails } from "./resources/emails.js";
|
|
6
|
+
import { Segments } from "./resources/segments.js";
|
|
7
|
+
import { Topics } from "./resources/topics.js";
|
|
8
|
+
/**
|
|
9
|
+
* The MillionSend client. Construct once and reuse.
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { MillionSend } from "millionsend";
|
|
13
|
+
* const ms = new MillionSend("ms_...", { baseUrl: "https://mail.acme.dev" });
|
|
14
|
+
* const { data, error } = await ms.emails.send({
|
|
15
|
+
* from: "Acme <onboarding@acme.dev>",
|
|
16
|
+
* to: "delivered@resend.dev",
|
|
17
|
+
* subject: "Hello",
|
|
18
|
+
* html: "<strong>it works</strong>",
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* No method throws for an API error — each resolves to `{ data, error }`, with
|
|
23
|
+
* `error` being an {@link ErrorResponse} discriminated by `error.name`. The only
|
|
24
|
+
* throw is a missing API key at construction.
|
|
25
|
+
*/
|
|
26
|
+
export declare class MillionSend {
|
|
27
|
+
readonly emails: Emails;
|
|
28
|
+
readonly batch: Batch;
|
|
29
|
+
readonly audiences: Audiences;
|
|
30
|
+
readonly contacts: Contacts;
|
|
31
|
+
readonly broadcasts: Broadcasts;
|
|
32
|
+
readonly topics: Topics;
|
|
33
|
+
readonly segments: Segments;
|
|
34
|
+
constructor(apiKey?: string, options?: MillionSendOptions);
|
|
35
|
+
}
|
|
36
|
+
export default MillionSend;
|
|
37
|
+
export type { ErrorResponse, Result } from "./error.js";
|
|
38
|
+
export type { MillionSendOptions, RequestOptions } from "./http.js";
|
|
39
|
+
export type * from "./types.js";
|
|
40
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE/C;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,WAAW;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;gBAEhB,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB;CAgB1D;AAED,eAAe,WAAW,CAAC;AAE3B,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACpE,mBAAmB,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { HttpClient } from "./http.js";
|
|
2
|
+
import { Audiences } from "./resources/audiences.js";
|
|
3
|
+
import { Broadcasts } from "./resources/broadcasts.js";
|
|
4
|
+
import { Contacts } from "./resources/contacts.js";
|
|
5
|
+
import { Batch, Emails } from "./resources/emails.js";
|
|
6
|
+
import { Segments } from "./resources/segments.js";
|
|
7
|
+
import { Topics } from "./resources/topics.js";
|
|
8
|
+
/**
|
|
9
|
+
* The MillionSend client. Construct once and reuse.
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { MillionSend } from "millionsend";
|
|
13
|
+
* const ms = new MillionSend("ms_...", { baseUrl: "https://mail.acme.dev" });
|
|
14
|
+
* const { data, error } = await ms.emails.send({
|
|
15
|
+
* from: "Acme <onboarding@acme.dev>",
|
|
16
|
+
* to: "delivered@resend.dev",
|
|
17
|
+
* subject: "Hello",
|
|
18
|
+
* html: "<strong>it works</strong>",
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* No method throws for an API error — each resolves to `{ data, error }`, with
|
|
23
|
+
* `error` being an {@link ErrorResponse} discriminated by `error.name`. The only
|
|
24
|
+
* throw is a missing API key at construction.
|
|
25
|
+
*/
|
|
26
|
+
export class MillionSend {
|
|
27
|
+
emails;
|
|
28
|
+
batch;
|
|
29
|
+
audiences;
|
|
30
|
+
contacts;
|
|
31
|
+
broadcasts;
|
|
32
|
+
topics;
|
|
33
|
+
segments;
|
|
34
|
+
constructor(apiKey, options) {
|
|
35
|
+
const key = apiKey ?? process.env.MILLIONSEND_API_KEY;
|
|
36
|
+
if (!key) {
|
|
37
|
+
throw new Error("Missing API key. Pass it to new MillionSend(apiKey) or set MILLIONSEND_API_KEY.");
|
|
38
|
+
}
|
|
39
|
+
const http = new HttpClient(key, options);
|
|
40
|
+
this.emails = new Emails(http);
|
|
41
|
+
this.batch = new Batch(http);
|
|
42
|
+
this.audiences = new Audiences(http);
|
|
43
|
+
this.contacts = new Contacts(http);
|
|
44
|
+
this.broadcasts = new Broadcasts(http);
|
|
45
|
+
this.topics = new Topics(http);
|
|
46
|
+
this.segments = new Segments(http);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export default MillionSend;
|
|
50
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA2B,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE/C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAO,WAAW;IACb,MAAM,CAAS;IACf,KAAK,CAAQ;IACb,SAAS,CAAY;IACrB,QAAQ,CAAW;IACnB,UAAU,CAAa;IACvB,MAAM,CAAS;IACf,QAAQ,CAAW;IAE5B,YAAY,MAAe,EAAE,OAA4B;QACvD,MAAM,GAAG,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;QACtD,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CACb,iFAAiF,CAClF,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,SAAS,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,QAAQ,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,UAAU,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,QAAQ,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;CACF;AAED,eAAe,WAAW,CAAC"}
|
package/dist/query.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ListOptions } from "./types.js";
|
|
2
|
+
/** Flatten keyset list options into the query map (undefined values are dropped). */
|
|
3
|
+
export declare function listQuery(options?: ListOptions): Record<string, string | number | undefined> | undefined;
|
|
4
|
+
//# sourceMappingURL=query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,qFAAqF;AACrF,wBAAgB,SAAS,CACvB,OAAO,CAAC,EAAE,WAAW,GACpB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAGzD"}
|
package/dist/query.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Flatten keyset list options into the query map (undefined values are dropped). */
|
|
2
|
+
export function listQuery(options) {
|
|
3
|
+
if (!options)
|
|
4
|
+
return undefined;
|
|
5
|
+
return { limit: options.limit, after: options.after, before: options.before };
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAEA,qFAAqF;AACrF,MAAM,UAAU,SAAS,CACvB,OAAqB;IAErB,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;AAChF,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Result } from "../error.js";
|
|
2
|
+
import type { HttpClient } from "../http.js";
|
|
3
|
+
import type { Audience, AudienceListItem, CreateAudienceOptions, List, ListOptions, RemoveAudienceResponse } from "../types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Audiences — named contact lists. Resend-compatible: a migrating app's
|
|
6
|
+
* `audiences.*` calls map straight over. (MillionSend's dynamic-filter
|
|
7
|
+
* `segments` are a separate, richer resource — see `client.segments`.)
|
|
8
|
+
*/
|
|
9
|
+
export declare class Audiences {
|
|
10
|
+
private readonly http;
|
|
11
|
+
constructor(http: HttpClient);
|
|
12
|
+
create(payload: CreateAudienceOptions): Promise<Result<Audience>>;
|
|
13
|
+
get(id: string): Promise<Result<Audience>>;
|
|
14
|
+
list(options?: ListOptions): Promise<Result<List<AudienceListItem>>>;
|
|
15
|
+
remove(id: string): Promise<Result<RemoveAudienceResponse>>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=audiences.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audiences.d.ts","sourceRoot":"","sources":["../../src/resources/audiences.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,KAAK,EACV,QAAQ,EACR,gBAAgB,EAChB,qBAAqB,EACrB,IAAI,EACJ,WAAW,EACX,sBAAsB,EACvB,MAAM,aAAa,CAAC;AAErB;;;;GAIG;AACH,qBAAa,SAAS;IACR,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C,MAAM,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAIjE,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAI1C,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAIpE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;CAG5D"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { listQuery } from "../query.js";
|
|
2
|
+
/**
|
|
3
|
+
* Audiences — named contact lists. Resend-compatible: a migrating app's
|
|
4
|
+
* `audiences.*` calls map straight over. (MillionSend's dynamic-filter
|
|
5
|
+
* `segments` are a separate, richer resource — see `client.segments`.)
|
|
6
|
+
*/
|
|
7
|
+
export class Audiences {
|
|
8
|
+
http;
|
|
9
|
+
constructor(http) {
|
|
10
|
+
this.http = http;
|
|
11
|
+
}
|
|
12
|
+
create(payload) {
|
|
13
|
+
return this.http.request({ method: "POST", path: "/audiences", body: { name: payload.name } });
|
|
14
|
+
}
|
|
15
|
+
get(id) {
|
|
16
|
+
return this.http.request({ method: "GET", path: `/audiences/${encodeURIComponent(id)}` });
|
|
17
|
+
}
|
|
18
|
+
list(options) {
|
|
19
|
+
return this.http.request({ method: "GET", path: "/audiences", query: listQuery(options) });
|
|
20
|
+
}
|
|
21
|
+
remove(id) {
|
|
22
|
+
return this.http.request({ method: "DELETE", path: `/audiences/${encodeURIComponent(id)}` });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=audiences.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audiences.js","sourceRoot":"","sources":["../../src/resources/audiences.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAUxC;;;;GAIG;AACH,MAAM,OAAO,SAAS;IACS;IAA7B,YAA6B,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;IAAG,CAAC;IAEjD,MAAM,CAAC,OAA8B;QACnC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACjG,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5F,CAAC;IAED,IAAI,CAAC,OAAqB;QACxB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7F,CAAC;IAED,MAAM,CAAC,EAAU;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/F,CAAC;CACF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Result } from "../error.js";
|
|
2
|
+
import type { HttpClient } from "../http.js";
|
|
3
|
+
import type { Broadcast, BroadcastId, BroadcastListItem, CancelBroadcastResponse, CreateBroadcastOptions, List, ListOptions, RemoveBroadcastResponse, SendBroadcastOptions, UpdateBroadcastOptions } from "../types.js";
|
|
4
|
+
export declare class Broadcasts {
|
|
5
|
+
private readonly http;
|
|
6
|
+
constructor(http: HttpClient);
|
|
7
|
+
create(payload: CreateBroadcastOptions): Promise<Result<BroadcastId>>;
|
|
8
|
+
get(id: string): Promise<Result<Broadcast>>;
|
|
9
|
+
list(options?: ListOptions): Promise<Result<List<BroadcastListItem>>>;
|
|
10
|
+
update(id: string, payload: UpdateBroadcastOptions): Promise<Result<BroadcastId>>;
|
|
11
|
+
remove(id: string): Promise<Result<RemoveBroadcastResponse>>;
|
|
12
|
+
/** POST /broadcasts/:id/send — omit scheduledAt to send now. */
|
|
13
|
+
send(id: string, options?: SendBroadcastOptions): Promise<Result<BroadcastId>>;
|
|
14
|
+
cancel(id: string): Promise<Result<CancelBroadcastResponse>>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=broadcasts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broadcasts.d.ts","sourceRoot":"","sources":["../../src/resources/broadcasts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,KAAK,EACV,SAAS,EACT,WAAW,EACX,iBAAiB,EACjB,uBAAuB,EACvB,sBAAsB,EACtB,IAAI,EACJ,WAAW,EACX,uBAAuB,EACvB,oBAAoB,EACpB,sBAAsB,EACvB,MAAM,aAAa,CAAC;AAgBrB,qBAAa,UAAU;IACT,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C,MAAM,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAIrE,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAI3C,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAIrE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAQjF,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC;IAI5D,gEAAgE;IAChE,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAQlF,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC;CAM7D"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { listQuery } from "../query.js";
|
|
2
|
+
function toWire(o) {
|
|
3
|
+
return {
|
|
4
|
+
name: o.name,
|
|
5
|
+
audience_id: o.audienceId,
|
|
6
|
+
segment_id: o.segmentId,
|
|
7
|
+
from: o.from,
|
|
8
|
+
subject: o.subject,
|
|
9
|
+
html: o.html,
|
|
10
|
+
text: o.text,
|
|
11
|
+
reply_to: o.replyTo,
|
|
12
|
+
topic_id: o.topicId,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export class Broadcasts {
|
|
16
|
+
http;
|
|
17
|
+
constructor(http) {
|
|
18
|
+
this.http = http;
|
|
19
|
+
}
|
|
20
|
+
create(payload) {
|
|
21
|
+
return this.http.request({ method: "POST", path: "/broadcasts", body: toWire(payload) });
|
|
22
|
+
}
|
|
23
|
+
get(id) {
|
|
24
|
+
return this.http.request({ method: "GET", path: `/broadcasts/${encodeURIComponent(id)}` });
|
|
25
|
+
}
|
|
26
|
+
list(options) {
|
|
27
|
+
return this.http.request({ method: "GET", path: "/broadcasts", query: listQuery(options) });
|
|
28
|
+
}
|
|
29
|
+
update(id, payload) {
|
|
30
|
+
return this.http.request({
|
|
31
|
+
method: "PATCH",
|
|
32
|
+
path: `/broadcasts/${encodeURIComponent(id)}`,
|
|
33
|
+
body: toWire(payload),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
remove(id) {
|
|
37
|
+
return this.http.request({ method: "DELETE", path: `/broadcasts/${encodeURIComponent(id)}` });
|
|
38
|
+
}
|
|
39
|
+
/** POST /broadcasts/:id/send — omit scheduledAt to send now. */
|
|
40
|
+
send(id, options = {}) {
|
|
41
|
+
return this.http.request({
|
|
42
|
+
method: "POST",
|
|
43
|
+
path: `/broadcasts/${encodeURIComponent(id)}/send`,
|
|
44
|
+
body: { scheduled_at: options.scheduledAt },
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
cancel(id) {
|
|
48
|
+
return this.http.request({
|
|
49
|
+
method: "POST",
|
|
50
|
+
path: `/broadcasts/${encodeURIComponent(id)}/cancel`,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=broadcasts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broadcasts.js","sourceRoot":"","sources":["../../src/resources/broadcasts.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAcxC,SAAS,MAAM,CAAC,CAAkD;IAChE,OAAO;QACL,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,WAAW,EAAE,CAAC,CAAC,UAAU;QACzB,UAAU,EAAE,CAAC,CAAC,SAAS;QACvB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,QAAQ,EAAE,CAAC,CAAC,OAAO;QACnB,QAAQ,EAAE,CAAC,CAAC,OAAO;KACpB,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,UAAU;IACQ;IAA7B,YAA6B,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;IAAG,CAAC;IAEjD,MAAM,CAAC,OAA+B;QACpC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC3F,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAC7F,CAAC;IAED,IAAI,CAAC,OAAqB;QACxB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9F,CAAC;IAED,MAAM,CAAC,EAAU,EAAE,OAA+B;QAChD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;YACvB,MAAM,EAAE,OAAO;YACf,IAAI,EAAE,eAAe,kBAAkB,CAAC,EAAE,CAAC,EAAE;YAC7C,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC;SACtB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,EAAU;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,eAAe,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAChG,CAAC;IAED,gEAAgE;IAChE,IAAI,CAAC,EAAU,EAAE,UAAgC,EAAE;QACjD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;YACvB,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,eAAe,kBAAkB,CAAC,EAAE,CAAC,OAAO;YAClD,IAAI,EAAE,EAAE,YAAY,EAAE,OAAO,CAAC,WAAW,EAAE;SAC5C,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,EAAU;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;YACvB,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,eAAe,kBAAkB,CAAC,EAAE,CAAC,SAAS;SACrD,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Result } from "../error.js";
|
|
2
|
+
import type { HttpClient } from "../http.js";
|
|
3
|
+
import type { Contact, ContactAddress, ContactId, ContactListItem, CreateContactOptions, List, ListOptions, RemoveContactResponse, UpdateContactOptions, UpdateContactTopicsOptions, UpdateContactTopicsResponse } from "../types.js";
|
|
4
|
+
/** Per-contact topic subscriptions (opt in/out of a topic). */
|
|
5
|
+
export declare class ContactTopics {
|
|
6
|
+
private readonly http;
|
|
7
|
+
constructor(http: HttpClient);
|
|
8
|
+
update(options: UpdateContactTopicsOptions): Promise<Result<UpdateContactTopicsResponse>>;
|
|
9
|
+
}
|
|
10
|
+
export declare class Contacts {
|
|
11
|
+
private readonly http;
|
|
12
|
+
readonly topics: ContactTopics;
|
|
13
|
+
constructor(http: HttpClient);
|
|
14
|
+
create(payload: CreateContactOptions): Promise<Result<ContactId>>;
|
|
15
|
+
get(address: string | ContactAddress): Promise<Result<Contact>>;
|
|
16
|
+
update(options: UpdateContactOptions): Promise<Result<ContactId>>;
|
|
17
|
+
remove(address: string | ContactAddress): Promise<Result<RemoveContactResponse>>;
|
|
18
|
+
list(options?: ListOptions & {
|
|
19
|
+
audienceId?: string;
|
|
20
|
+
}): Promise<Result<List<ContactListItem>>>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=contacts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contacts.d.ts","sourceRoot":"","sources":["../../src/resources/contacts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EACd,SAAS,EACT,eAAe,EACf,oBAAoB,EACpB,IAAI,EACJ,WAAW,EACX,qBAAqB,EACrB,oBAAoB,EACpB,0BAA0B,EAC1B,2BAA2B,EAC5B,MAAM,aAAa,CAAC;AAiCrB,+DAA+D;AAC/D,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C,MAAM,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC;CAQ1F;AAED,qBAAa,QAAQ;IAGP,OAAO,CAAC,QAAQ,CAAC,IAAI;IAFjC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;gBAEF,IAAI,EAAE,UAAU;IAI7C,MAAM,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAOjE,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAI/D,MAAM,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAIjE,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;IAIhF,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;CAM9F"}
|