millionsend 0.0.1 → 0.2.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.
Files changed (44) hide show
  1. package/README.md +151 -4
  2. package/dist/error.d.ts +24 -0
  3. package/dist/error.d.ts.map +1 -0
  4. package/dist/error.js +16 -0
  5. package/dist/error.js.map +1 -0
  6. package/dist/http.d.ts +34 -0
  7. package/dist/http.d.ts.map +1 -0
  8. package/dist/http.js +75 -0
  9. package/dist/http.js.map +1 -0
  10. package/dist/index.d.ts +38 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +47 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/query.d.ts +4 -0
  15. package/dist/query.d.ts.map +1 -0
  16. package/dist/query.js +7 -0
  17. package/dist/query.js.map +1 -0
  18. package/dist/resources/broadcasts.d.ts +16 -0
  19. package/dist/resources/broadcasts.d.ts.map +1 -0
  20. package/dist/resources/broadcasts.js +53 -0
  21. package/dist/resources/broadcasts.js.map +1 -0
  22. package/dist/resources/contacts.d.ts +20 -0
  23. package/dist/resources/contacts.d.ts.map +1 -0
  24. package/dist/resources/contacts.js +64 -0
  25. package/dist/resources/contacts.js.map +1 -0
  26. package/dist/resources/emails.d.ts +28 -0
  27. package/dist/resources/emails.d.ts.map +1 -0
  28. package/dist/resources/emails.js +64 -0
  29. package/dist/resources/emails.js.map +1 -0
  30. package/dist/resources/segments.d.ts +17 -0
  31. package/dist/resources/segments.d.ts.map +1 -0
  32. package/dist/resources/segments.js +35 -0
  33. package/dist/resources/segments.js.map +1 -0
  34. package/dist/resources/topics.d.ts +16 -0
  35. package/dist/resources/topics.d.ts.map +1 -0
  36. package/dist/resources/topics.js +29 -0
  37. package/dist/resources/topics.js.map +1 -0
  38. package/dist/types.d.ts +224 -0
  39. package/dist/types.d.ts.map +1 -0
  40. package/dist/types.js +7 -0
  41. package/dist/types.js.map +1 -0
  42. package/package.json +34 -9
  43. package/index.d.ts +0 -4
  44. package/index.js +0 -14
package/README.md CHANGED
@@ -1,7 +1,154 @@
1
1
  # millionsend
2
2
 
3
- Official Node.js SDK for [MillionSend](https://github.com/MillionSend) — the open-source,
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
- **Status: under active development.** This release reserves the package name; the first working
7
- SDK will land here. Watch the [MillionSend GitHub org](https://github.com/MillionSend) for progress.
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
+ ### Contacts
80
+
81
+ Contacts are team-global — one list per team, no audiences.
82
+
83
+ ```ts
84
+ await ms.contacts.create({ email: "ada@acme.dev", firstName: "Ada",
85
+ properties: { plan: "pro" } });
86
+ await ms.contacts.get({ email }); // by id or email (email wins)
87
+ await ms.contacts.get(contactId); // bare string works too
88
+ await ms.contacts.update({ id, unsubscribed: true, firstName: null }); // null clears
89
+ await ms.contacts.remove({ email });
90
+ await ms.contacts.list({ limit: 50 });
91
+
92
+ // Topic subscriptions (granular unsubscribe)
93
+ await ms.contacts.topics.update({ email, topics: [{ id: topicId, subscription: "opt_out" }] });
94
+ ```
95
+
96
+ ### Topics
97
+
98
+ ```ts
99
+ await ms.topics.create({ name: "Product updates", defaultSubscription: "opt_in" });
100
+ await ms.topics.get(id);
101
+ await ms.topics.list(); // bare { data } — topics are unpaginated
102
+ await ms.topics.remove(id);
103
+ ```
104
+
105
+ ### Broadcasts
106
+
107
+ Target a `segmentId` and/or `topicId`; omit both to send to all contacts.
108
+
109
+ ```ts
110
+ const { data } = await ms.broadcasts.create({
111
+ segmentId, from: "Acme <news@acme.dev>", subject: "Launch",
112
+ html: "<p>Hi {{{FIRST_NAME|there}}}</p>",
113
+ });
114
+ await ms.broadcasts.list();
115
+ await ms.broadcasts.get(id);
116
+ await ms.broadcasts.update(id, { subject: "Launch 🚀" }); // draft only
117
+ await ms.broadcasts.send(id, { scheduledAt: "2026-09-01T09:00:00Z" }); // omit to send now
118
+ await ms.broadcasts.cancel(id); // scheduled only
119
+ await ms.broadcasts.remove(id); // draft only
120
+ ```
121
+
122
+ ### Segments (MillionSend extension)
123
+
124
+ Dynamic segments are a saved filter over the team's contacts — a MillionSend
125
+ superset with no Resend equivalent.
126
+
127
+ ```ts
128
+ await ms.segments.create({
129
+ name: "Pro plan",
130
+ filter: { match: "all", conditions: [{ field: "property:plan", op: "equals", value: "pro" }] },
131
+ });
132
+ await ms.segments.get(id); // includes a live contact_count
133
+ await ms.segments.list();
134
+ await ms.segments.update(id, { name: "Pro tier" });
135
+ await ms.segments.remove(id);
136
+ ```
137
+
138
+ ## Migrating from Resend
139
+
140
+ ```diff
141
+ - import { Resend } from "resend";
142
+ - const resend = new Resend("re_123");
143
+ + import { MillionSend } from "millionsend";
144
+ + const ms = new MillionSend("ms_123", { baseUrl: "https://mail.acme.dev" });
145
+ ```
146
+
147
+ Method names and payloads match. Notes:
148
+
149
+ - **Domains and API keys** are managed in the MillionSend dashboard, not via the API, so there are no `.domains`/`.apiKeys` resources here.
150
+ - **No audiences.** Contacts are team-global, so `.audiences` calls have no equivalent — drop them and call `.contacts` directly. For subsets of contacts, use `.segments` (dynamic filters) or topics.
151
+
152
+ ## License
153
+
154
+ MIT
@@ -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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { type MillionSendOptions } from "./http.js";
2
+ import { Broadcasts } from "./resources/broadcasts.js";
3
+ import { Contacts } from "./resources/contacts.js";
4
+ import { Batch, Emails } from "./resources/emails.js";
5
+ import { Segments } from "./resources/segments.js";
6
+ import { Topics } from "./resources/topics.js";
7
+ /**
8
+ * The MillionSend client. Construct once and reuse.
9
+ *
10
+ * ```ts
11
+ * import { MillionSend } from "millionsend";
12
+ * const ms = new MillionSend("ms_...", { baseUrl: "https://mail.acme.dev" });
13
+ * const { data, error } = await ms.emails.send({
14
+ * from: "Acme <onboarding@acme.dev>",
15
+ * to: "delivered@resend.dev",
16
+ * subject: "Hello",
17
+ * html: "<strong>it works</strong>",
18
+ * });
19
+ * ```
20
+ *
21
+ * No method throws for an API error — each resolves to `{ data, error }`, with
22
+ * `error` being an {@link ErrorResponse} discriminated by `error.name`. The only
23
+ * throw is a missing API key at construction.
24
+ */
25
+ export declare class MillionSend {
26
+ readonly emails: Emails;
27
+ readonly batch: Batch;
28
+ readonly contacts: Contacts;
29
+ readonly broadcasts: Broadcasts;
30
+ readonly topics: Topics;
31
+ readonly segments: Segments;
32
+ constructor(apiKey?: string, options?: MillionSendOptions);
33
+ }
34
+ export default MillionSend;
35
+ export type { ErrorResponse, Result } from "./error.js";
36
+ export type { MillionSendOptions, RequestOptions } from "./http.js";
37
+ export type * from "./types.js";
38
+ //# 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,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,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;CAe1D;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,47 @@
1
+ import { HttpClient } from "./http.js";
2
+ import { Broadcasts } from "./resources/broadcasts.js";
3
+ import { Contacts } from "./resources/contacts.js";
4
+ import { Batch, Emails } from "./resources/emails.js";
5
+ import { Segments } from "./resources/segments.js";
6
+ import { Topics } from "./resources/topics.js";
7
+ /**
8
+ * The MillionSend client. Construct once and reuse.
9
+ *
10
+ * ```ts
11
+ * import { MillionSend } from "millionsend";
12
+ * const ms = new MillionSend("ms_...", { baseUrl: "https://mail.acme.dev" });
13
+ * const { data, error } = await ms.emails.send({
14
+ * from: "Acme <onboarding@acme.dev>",
15
+ * to: "delivered@resend.dev",
16
+ * subject: "Hello",
17
+ * html: "<strong>it works</strong>",
18
+ * });
19
+ * ```
20
+ *
21
+ * No method throws for an API error — each resolves to `{ data, error }`, with
22
+ * `error` being an {@link ErrorResponse} discriminated by `error.name`. The only
23
+ * throw is a missing API key at construction.
24
+ */
25
+ export class MillionSend {
26
+ emails;
27
+ batch;
28
+ contacts;
29
+ broadcasts;
30
+ topics;
31
+ segments;
32
+ constructor(apiKey, options) {
33
+ const key = apiKey ?? process.env.MILLIONSEND_API_KEY;
34
+ if (!key) {
35
+ throw new Error("Missing API key. Pass it to new MillionSend(apiKey) or set MILLIONSEND_API_KEY.");
36
+ }
37
+ const http = new HttpClient(key, options);
38
+ this.emails = new Emails(http);
39
+ this.batch = new Batch(http);
40
+ this.contacts = new Contacts(http);
41
+ this.broadcasts = new Broadcasts(http);
42
+ this.topics = new Topics(http);
43
+ this.segments = new Segments(http);
44
+ }
45
+ }
46
+ export default MillionSend;
47
+ //# 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,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,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,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"}
@@ -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,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;AAerB,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,53 @@
1
+ import { listQuery } from "../query.js";
2
+ function toWire(o) {
3
+ return {
4
+ name: o.name,
5
+ segment_id: o.segmentId,
6
+ from: o.from,
7
+ subject: o.subject,
8
+ html: o.html,
9
+ text: o.text,
10
+ reply_to: o.replyTo,
11
+ topic_id: o.topicId,
12
+ };
13
+ }
14
+ export class Broadcasts {
15
+ http;
16
+ constructor(http) {
17
+ this.http = http;
18
+ }
19
+ create(payload) {
20
+ return this.http.request({ method: "POST", path: "/broadcasts", body: toWire(payload) });
21
+ }
22
+ get(id) {
23
+ return this.http.request({ method: "GET", path: `/broadcasts/${encodeURIComponent(id)}` });
24
+ }
25
+ list(options) {
26
+ return this.http.request({ method: "GET", path: "/broadcasts", query: listQuery(options) });
27
+ }
28
+ update(id, payload) {
29
+ return this.http.request({
30
+ method: "PATCH",
31
+ path: `/broadcasts/${encodeURIComponent(id)}`,
32
+ body: toWire(payload),
33
+ });
34
+ }
35
+ remove(id) {
36
+ return this.http.request({ method: "DELETE", path: `/broadcasts/${encodeURIComponent(id)}` });
37
+ }
38
+ /** POST /broadcasts/:id/send — omit scheduledAt to send now. */
39
+ send(id, options = {}) {
40
+ return this.http.request({
41
+ method: "POST",
42
+ path: `/broadcasts/${encodeURIComponent(id)}/send`,
43
+ body: { scheduled_at: options.scheduledAt },
44
+ });
45
+ }
46
+ cancel(id) {
47
+ return this.http.request({
48
+ method: "POST",
49
+ path: `/broadcasts/${encodeURIComponent(id)}/cancel`,
50
+ });
51
+ }
52
+ }
53
+ //# 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,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,20 @@
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): Promise<Result<List<ContactListItem>>>;
19
+ }
20
+ //# 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;AA8BrB,+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;IAIjE,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,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;CAGpE"}
@@ -0,0 +1,64 @@
1
+ import { listQuery } from "../query.js";
2
+ function normalize(address) {
3
+ return typeof address === "string" ? { id: address } : address;
4
+ }
5
+ /** Contact path: email wins over id. */
6
+ function contactPath(addr) {
7
+ return `/contacts/${encodeURIComponent(addr.email ?? addr.id ?? "")}`;
8
+ }
9
+ function createBody(o) {
10
+ return {
11
+ email: o.email,
12
+ first_name: o.firstName,
13
+ last_name: o.lastName,
14
+ unsubscribed: o.unsubscribed,
15
+ properties: o.properties,
16
+ };
17
+ }
18
+ function updateBody(o) {
19
+ return {
20
+ first_name: o.firstName,
21
+ last_name: o.lastName,
22
+ unsubscribed: o.unsubscribed,
23
+ properties: o.properties,
24
+ };
25
+ }
26
+ /** Per-contact topic subscriptions (opt in/out of a topic). */
27
+ export class ContactTopics {
28
+ http;
29
+ constructor(http) {
30
+ this.http = http;
31
+ }
32
+ update(options) {
33
+ const key = encodeURIComponent(options.email ?? options.id ?? "");
34
+ return this.http.request({
35
+ method: "PATCH",
36
+ path: `/contacts/${key}/topics`,
37
+ body: options.topics,
38
+ });
39
+ }
40
+ }
41
+ export class Contacts {
42
+ http;
43
+ topics;
44
+ constructor(http) {
45
+ this.http = http;
46
+ this.topics = new ContactTopics(http);
47
+ }
48
+ create(payload) {
49
+ return this.http.request({ method: "POST", path: "/contacts", body: createBody(payload) });
50
+ }
51
+ get(address) {
52
+ return this.http.request({ method: "GET", path: contactPath(normalize(address)) });
53
+ }
54
+ update(options) {
55
+ return this.http.request({ method: "PATCH", path: contactPath(options), body: updateBody(options) });
56
+ }
57
+ remove(address) {
58
+ return this.http.request({ method: "DELETE", path: contactPath(normalize(address)) });
59
+ }
60
+ list(options) {
61
+ return this.http.request({ method: "GET", path: "/contacts", query: listQuery(options) });
62
+ }
63
+ }
64
+ //# sourceMappingURL=contacts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contacts.js","sourceRoot":"","sources":["../../src/resources/contacts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { Result } from "../error.js";
2
+ import type { HttpClient, RequestOptions } from "../http.js";
3
+ import type { CancelEmailResponse, CreateEmailResponse, Email, SendEmailOptions } from "../types.js";
4
+ export declare class Emails {
5
+ private readonly http;
6
+ constructor(http: HttpClient);
7
+ /** POST /emails — supports an Idempotency-Key. */
8
+ send(payload: SendEmailOptions, options?: RequestOptions): Promise<Result<CreateEmailResponse>>;
9
+ /** Alias of {@link send}, mirroring Resend. */
10
+ create(payload: SendEmailOptions, options?: RequestOptions): Promise<Result<CreateEmailResponse>>;
11
+ /** GET /emails/:id */
12
+ get(id: string): Promise<Result<Email>>;
13
+ /** POST /emails/:id/cancel — only scheduled, unsent emails. */
14
+ cancel(id: string): Promise<Result<CancelEmailResponse>>;
15
+ }
16
+ export declare class Batch {
17
+ private readonly http;
18
+ constructor(http: HttpClient);
19
+ /** POST /emails/batch — 1–100 emails in one call; supports an Idempotency-Key. */
20
+ send(payload: SendEmailOptions[], options?: RequestOptions): Promise<Result<{
21
+ data: CreateEmailResponse[];
22
+ }>>;
23
+ /** Alias of {@link send}, mirroring Resend. */
24
+ create(payload: SendEmailOptions[], options?: RequestOptions): Promise<Result<{
25
+ data: CreateEmailResponse[];
26
+ }>>;
27
+ }
28
+ //# sourceMappingURL=emails.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emails.d.ts","sourceRoot":"","sources":["../../src/resources/emails.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,EACL,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAiBrB,qBAAa,MAAM;IACL,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C,kDAAkD;IAClD,IAAI,CACF,OAAO,EAAE,gBAAgB,EACzB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IASvC,+CAA+C;IAC/C,MAAM,CACJ,OAAO,EAAE,gBAAgB,EACzB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAIvC,sBAAsB;IACtB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAIvC,+DAA+D;IAC/D,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;CAMzD;AAED,qBAAa,KAAK;IACJ,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C,kFAAkF;IAClF,IAAI,CACF,OAAO,EAAE,gBAAgB,EAAE,EAC3B,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,MAAM,CAAC;QAAE,IAAI,EAAE,mBAAmB,EAAE,CAAA;KAAE,CAAC,CAAC;IASnD,+CAA+C;IAC/C,MAAM,CACJ,OAAO,EAAE,gBAAgB,EAAE,EAC3B,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,MAAM,CAAC;QAAE,IAAI,EAAE,mBAAmB,EAAE,CAAA;KAAE,CAAC,CAAC;CAGpD"}
@@ -0,0 +1,64 @@
1
+ function toWire(o) {
2
+ return {
3
+ from: o.from,
4
+ to: o.to,
5
+ subject: o.subject,
6
+ html: o.html,
7
+ text: o.text,
8
+ cc: o.cc,
9
+ bcc: o.bcc,
10
+ reply_to: o.replyTo,
11
+ scheduled_at: o.scheduledAt,
12
+ tags: o.tags,
13
+ };
14
+ }
15
+ export class Emails {
16
+ http;
17
+ constructor(http) {
18
+ this.http = http;
19
+ }
20
+ /** POST /emails — supports an Idempotency-Key. */
21
+ send(payload, options = {}) {
22
+ return this.http.request({
23
+ method: "POST",
24
+ path: "/emails",
25
+ body: toWire(payload),
26
+ idempotencyKey: options.idempotencyKey,
27
+ });
28
+ }
29
+ /** Alias of {@link send}, mirroring Resend. */
30
+ create(payload, options = {}) {
31
+ return this.send(payload, options);
32
+ }
33
+ /** GET /emails/:id */
34
+ get(id) {
35
+ return this.http.request({ method: "GET", path: `/emails/${encodeURIComponent(id)}` });
36
+ }
37
+ /** POST /emails/:id/cancel — only scheduled, unsent emails. */
38
+ cancel(id) {
39
+ return this.http.request({
40
+ method: "POST",
41
+ path: `/emails/${encodeURIComponent(id)}/cancel`,
42
+ });
43
+ }
44
+ }
45
+ export class Batch {
46
+ http;
47
+ constructor(http) {
48
+ this.http = http;
49
+ }
50
+ /** POST /emails/batch — 1–100 emails in one call; supports an Idempotency-Key. */
51
+ send(payload, options = {}) {
52
+ return this.http.request({
53
+ method: "POST",
54
+ path: "/emails/batch",
55
+ body: payload.map(toWire),
56
+ idempotencyKey: options.idempotencyKey,
57
+ });
58
+ }
59
+ /** Alias of {@link send}, mirroring Resend. */
60
+ create(payload, options = {}) {
61
+ return this.send(payload, options);
62
+ }
63
+ }
64
+ //# sourceMappingURL=emails.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emails.js","sourceRoot":"","sources":["../../src/resources/emails.ts"],"names":[],"mappings":"AASA,SAAS,MAAM,CAAC,CAAmB;IACjC,OAAO;QACL,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,GAAG,EAAE,CAAC,CAAC,GAAG;QACV,QAAQ,EAAE,CAAC,CAAC,OAAO;QACnB,YAAY,EAAE,CAAC,CAAC,WAAW;QAC3B,IAAI,EAAE,CAAC,CAAC,IAAI;KACb,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,MAAM;IACY;IAA7B,YAA6B,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;IAAG,CAAC;IAEjD,kDAAkD;IAClD,IAAI,CACF,OAAyB,EACzB,UAA0B,EAAE;QAE5B,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;YACvB,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC;YACrB,cAAc,EAAE,OAAO,CAAC,cAAc;SACvC,CAAC,CAAC;IACL,CAAC;IAED,+CAA+C;IAC/C,MAAM,CACJ,OAAyB,EACzB,UAA0B,EAAE;QAE5B,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IAED,sBAAsB;IACtB,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACzF,CAAC;IAED,+DAA+D;IAC/D,MAAM,CAAC,EAAU;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;YACvB,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,WAAW,kBAAkB,CAAC,EAAE,CAAC,SAAS;SACjD,CAAC,CAAC;IACL,CAAC;CACF;AAED,MAAM,OAAO,KAAK;IACa;IAA7B,YAA6B,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;IAAG,CAAC;IAEjD,kFAAkF;IAClF,IAAI,CACF,OAA2B,EAC3B,UAA0B,EAAE;QAE5B,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;YACvB,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;YACzB,cAAc,EAAE,OAAO,CAAC,cAAc;SACvC,CAAC,CAAC;IACL,CAAC;IAED,+CAA+C;IAC/C,MAAM,CACJ,OAA2B,EAC3B,UAA0B,EAAE;QAE5B,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;CACF"}
@@ -0,0 +1,17 @@
1
+ import type { Result } from "../error.js";
2
+ import type { HttpClient } from "../http.js";
3
+ import type { CreateSegmentOptions, List, ListOptions, RemoveSegmentResponse, Segment, UpdateSegmentOptions } from "../types.js";
4
+ /**
5
+ * Dynamic segments — a saved filter over the team's contacts (MillionSend
6
+ * extension, no Resend equivalent). `get` returns a live `contact_count`.
7
+ */
8
+ export declare class Segments {
9
+ private readonly http;
10
+ constructor(http: HttpClient);
11
+ create(payload: CreateSegmentOptions): Promise<Result<Segment>>;
12
+ get(id: string): Promise<Result<Segment>>;
13
+ list(options?: ListOptions): Promise<Result<List<Segment>>>;
14
+ update(id: string, payload: UpdateSegmentOptions): Promise<Result<Segment>>;
15
+ remove(id: string): Promise<Result<RemoveSegmentResponse>>;
16
+ }
17
+ //# sourceMappingURL=segments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segments.d.ts","sourceRoot":"","sources":["../../src/resources/segments.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,oBAAoB,EACpB,IAAI,EACJ,WAAW,EACX,qBAAqB,EACrB,OAAO,EACP,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAErB;;;GAGG;AACH,qBAAa,QAAQ;IACP,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C,MAAM,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAQ/D,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAIzC,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAI3D,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAQ3E,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;CAG3D"}
@@ -0,0 +1,35 @@
1
+ import { listQuery } from "../query.js";
2
+ /**
3
+ * Dynamic segments — a saved filter over the team's contacts (MillionSend
4
+ * extension, no Resend equivalent). `get` returns a live `contact_count`.
5
+ */
6
+ export class Segments {
7
+ http;
8
+ constructor(http) {
9
+ this.http = http;
10
+ }
11
+ create(payload) {
12
+ return this.http.request({
13
+ method: "POST",
14
+ path: "/segments",
15
+ body: { name: payload.name, filter: payload.filter },
16
+ });
17
+ }
18
+ get(id) {
19
+ return this.http.request({ method: "GET", path: `/segments/${encodeURIComponent(id)}` });
20
+ }
21
+ list(options) {
22
+ return this.http.request({ method: "GET", path: "/segments", query: listQuery(options) });
23
+ }
24
+ update(id, payload) {
25
+ return this.http.request({
26
+ method: "PATCH",
27
+ path: `/segments/${encodeURIComponent(id)}`,
28
+ body: { name: payload.name, filter: payload.filter },
29
+ });
30
+ }
31
+ remove(id) {
32
+ return this.http.request({ method: "DELETE", path: `/segments/${encodeURIComponent(id)}` });
33
+ }
34
+ }
35
+ //# sourceMappingURL=segments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segments.js","sourceRoot":"","sources":["../../src/resources/segments.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAUxC;;;GAGG;AACH,MAAM,OAAO,QAAQ;IACU;IAA7B,YAA6B,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;IAAG,CAAC;IAEjD,MAAM,CAAC,OAA6B;QAClC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;YACvB,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;SACrD,CAAC,CAAC;IACL,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,aAAa,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAC3F,CAAC;IAED,IAAI,CAAC,OAAqB;QACxB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC5F,CAAC;IAED,MAAM,CAAC,EAAU,EAAE,OAA6B;QAC9C,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;YACvB,MAAM,EAAE,OAAO;YACf,IAAI,EAAE,aAAa,kBAAkB,CAAC,EAAE,CAAC,EAAE;YAC3C,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;SACrD,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,EAAU;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9F,CAAC;CACF"}
@@ -0,0 +1,16 @@
1
+ import type { Result } from "../error.js";
2
+ import type { HttpClient } from "../http.js";
3
+ import type { CreateTopicOptions, RemoveTopicResponse, Topic, TopicId } from "../types.js";
4
+ /** Subscription topics — granular unsubscribe categories for a team. */
5
+ export declare class Topics {
6
+ private readonly http;
7
+ constructor(http: HttpClient);
8
+ create(payload: CreateTopicOptions): Promise<Result<TopicId>>;
9
+ get(id: string): Promise<Result<Topic>>;
10
+ /** GET /topics — a bare `{ data }` list (topics are unpaginated). */
11
+ list(): Promise<Result<{
12
+ data: Topic[];
13
+ }>>;
14
+ remove(id: string): Promise<Result<RemoveTopicResponse>>;
15
+ }
16
+ //# sourceMappingURL=topics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"topics.d.ts","sourceRoot":"","sources":["../../src/resources/topics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3F,wEAAwE;AACxE,qBAAa,MAAM;IACL,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAE7C,MAAM,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAY7D,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAIvC,qEAAqE;IACrE,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;QAAE,IAAI,EAAE,KAAK,EAAE,CAAA;KAAE,CAAC,CAAC;IAI1C,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;CAGzD"}
@@ -0,0 +1,29 @@
1
+ /** Subscription topics — granular unsubscribe categories for a team. */
2
+ export class Topics {
3
+ http;
4
+ constructor(http) {
5
+ this.http = http;
6
+ }
7
+ create(payload) {
8
+ return this.http.request({
9
+ method: "POST",
10
+ path: "/topics",
11
+ body: {
12
+ name: payload.name,
13
+ description: payload.description,
14
+ default_subscription: payload.defaultSubscription,
15
+ },
16
+ });
17
+ }
18
+ get(id) {
19
+ return this.http.request({ method: "GET", path: `/topics/${encodeURIComponent(id)}` });
20
+ }
21
+ /** GET /topics — a bare `{ data }` list (topics are unpaginated). */
22
+ list() {
23
+ return this.http.request({ method: "GET", path: "/topics" });
24
+ }
25
+ remove(id) {
26
+ return this.http.request({ method: "DELETE", path: `/topics/${encodeURIComponent(id)}` });
27
+ }
28
+ }
29
+ //# sourceMappingURL=topics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"topics.js","sourceRoot":"","sources":["../../src/resources/topics.ts"],"names":[],"mappings":"AAIA,wEAAwE;AACxE,MAAM,OAAO,MAAM;IACY;IAA7B,YAA6B,IAAgB;QAAhB,SAAI,GAAJ,IAAI,CAAY;IAAG,CAAC;IAEjD,MAAM,CAAC,OAA2B;QAChC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;YACvB,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,SAAS;YACf,IAAI,EAAE;gBACJ,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,oBAAoB,EAAE,OAAO,CAAC,mBAAmB;aAClD;SACF,CAAC,CAAC;IACL,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACzF,CAAC;IAED,qEAAqE;IACrE,IAAI;QACF,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,CAAC,EAAU;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5F,CAAC;CACF"}
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Public request/response types. Inputs are camelCase (mapped to the wire's
3
+ * snake_case by each resource); responses are the wire shape verbatim, so the
4
+ * `object`/`created_at`/`first_name` fields read exactly as the API returns.
5
+ */
6
+ export type Recipients = string | string[];
7
+ export interface Tag {
8
+ name: string;
9
+ value: string;
10
+ }
11
+ export interface ListOptions {
12
+ limit?: number;
13
+ /** Keyset cursor: return items after this id. Mutually exclusive with `before`. */
14
+ after?: string;
15
+ before?: string;
16
+ }
17
+ export interface List<T> {
18
+ object: "list";
19
+ data: T[];
20
+ has_more: boolean;
21
+ }
22
+ export interface SendEmailOptions {
23
+ from: string;
24
+ to: Recipients;
25
+ subject: string;
26
+ html?: string;
27
+ text?: string;
28
+ cc?: Recipients;
29
+ bcc?: Recipients;
30
+ replyTo?: Recipients;
31
+ /** ISO 8601 with offset; up to 30 days ahead. */
32
+ scheduledAt?: string;
33
+ tags?: Tag[];
34
+ }
35
+ export interface CreateEmailResponse {
36
+ id: string;
37
+ }
38
+ export interface Email {
39
+ object: "email";
40
+ id: string;
41
+ from: string;
42
+ to: string[];
43
+ cc: string[] | null;
44
+ bcc: string[] | null;
45
+ reply_to: string[] | null;
46
+ subject: string;
47
+ html: string | null;
48
+ text: string | null;
49
+ created_at: string;
50
+ scheduled_at: string | null;
51
+ message_id: string;
52
+ last_event: string;
53
+ }
54
+ export interface CancelEmailResponse {
55
+ object: "email";
56
+ id: string;
57
+ }
58
+ export interface BatchResponse {
59
+ data: CreateEmailResponse[];
60
+ }
61
+ export interface CreateContactOptions {
62
+ email: string;
63
+ firstName?: string;
64
+ lastName?: string;
65
+ unsubscribed?: boolean;
66
+ properties?: Record<string, string | number | boolean | null>;
67
+ }
68
+ /** Address a contact by id or email (email wins if both are given). */
69
+ export interface ContactAddress {
70
+ id?: string;
71
+ email?: string;
72
+ }
73
+ export interface UpdateContactOptions extends ContactAddress {
74
+ firstName?: string | null;
75
+ lastName?: string | null;
76
+ unsubscribed?: boolean;
77
+ properties?: Record<string, string | number | boolean | null>;
78
+ }
79
+ export interface ContactId {
80
+ object: "contact";
81
+ id: string;
82
+ }
83
+ export interface Contact {
84
+ object: "contact";
85
+ id: string;
86
+ email: string;
87
+ first_name: string | null;
88
+ last_name: string | null;
89
+ created_at: string;
90
+ unsubscribed: boolean;
91
+ properties: Record<string, string>;
92
+ }
93
+ export interface ContactListItem {
94
+ id: string;
95
+ email: string;
96
+ first_name: string | null;
97
+ last_name: string | null;
98
+ created_at: string;
99
+ unsubscribed: boolean;
100
+ }
101
+ export interface RemoveContactResponse {
102
+ object: "contact";
103
+ contact: string;
104
+ deleted: true;
105
+ }
106
+ export type TopicSubscription = "opt_in" | "opt_out";
107
+ export interface ContactTopicUpdate {
108
+ id: string;
109
+ subscription: TopicSubscription;
110
+ }
111
+ export interface UpdateContactTopicsOptions extends ContactAddress {
112
+ topics: ContactTopicUpdate[];
113
+ }
114
+ export interface UpdateContactTopicsResponse {
115
+ id: string;
116
+ }
117
+ export interface CreateTopicOptions {
118
+ name: string;
119
+ description?: string;
120
+ defaultSubscription: TopicSubscription;
121
+ }
122
+ export interface Topic {
123
+ id: string;
124
+ name: string;
125
+ description?: string;
126
+ default_subscription: TopicSubscription;
127
+ created_at: string;
128
+ }
129
+ export interface TopicId {
130
+ id: string;
131
+ }
132
+ export interface RemoveTopicResponse {
133
+ id: string;
134
+ object: "topic";
135
+ deleted: true;
136
+ }
137
+ export interface CreateBroadcastOptions {
138
+ name?: string;
139
+ segmentId?: string;
140
+ from: string;
141
+ subject: string;
142
+ html?: string;
143
+ text?: string;
144
+ replyTo?: Recipients;
145
+ topicId?: string | null;
146
+ }
147
+ export interface UpdateBroadcastOptions {
148
+ name?: string;
149
+ segmentId?: string;
150
+ from?: string;
151
+ subject?: string;
152
+ html?: string;
153
+ text?: string;
154
+ replyTo?: Recipients;
155
+ topicId?: string | null;
156
+ }
157
+ export interface SendBroadcastOptions {
158
+ /** ISO 8601 with offset; omit to send now. */
159
+ scheduledAt?: string;
160
+ }
161
+ export interface BroadcastId {
162
+ id: string;
163
+ }
164
+ export interface BroadcastListItem {
165
+ id: string;
166
+ name: string | null;
167
+ segment_id: string | null;
168
+ status: string;
169
+ created_at: string;
170
+ scheduled_at: string | null;
171
+ sent_at: string | null;
172
+ }
173
+ export interface Broadcast extends BroadcastListItem {
174
+ object: "broadcast";
175
+ from: string;
176
+ subject: string;
177
+ reply_to: string[] | null;
178
+ preview_text: string | null;
179
+ topic_id: string | null;
180
+ html: string | null;
181
+ text: string | null;
182
+ }
183
+ export interface CancelBroadcastResponse {
184
+ object: "broadcast";
185
+ id: string;
186
+ }
187
+ export interface RemoveBroadcastResponse {
188
+ object: "broadcast";
189
+ id: string;
190
+ deleted: true;
191
+ }
192
+ export type SegmentMatch = "all" | "any";
193
+ export interface SegmentCondition {
194
+ field: string;
195
+ op: string;
196
+ value?: string | null;
197
+ }
198
+ export interface SegmentFilter {
199
+ match: SegmentMatch;
200
+ conditions: SegmentCondition[];
201
+ }
202
+ export interface CreateSegmentOptions {
203
+ name: string;
204
+ filter: SegmentFilter;
205
+ }
206
+ export interface UpdateSegmentOptions {
207
+ name?: string;
208
+ filter?: SegmentFilter;
209
+ }
210
+ export interface Segment {
211
+ object: "segment";
212
+ id: string;
213
+ name: string;
214
+ filter: SegmentFilter;
215
+ created_at: string;
216
+ /** Present on `get` only — the live count of matching contacts. */
217
+ contact_count?: number;
218
+ }
219
+ export interface RemoveSegmentResponse {
220
+ object: "segment";
221
+ id: string;
222
+ deleted: true;
223
+ }
224
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Public request/response types. Inputs are camelCase (mapped to the wire's
3
+ * snake_case by each resource); responses are the wire shape verbatim, so the
4
+ * `object`/`created_at`/`first_name` fields read exactly as the API returns.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
package/package.json CHANGED
@@ -1,13 +1,38 @@
1
1
  {
2
2
  "name": "millionsend",
3
- "version": "0.0.1",
4
- "description": "Official Node.js SDK for MillionSend — the open-source email platform. Under active development; API coming soon.",
5
- "main": "index.js",
6
- "types": "index.d.ts",
7
- "files": ["index.js", "index.d.ts", "README.md", "LICENSE"],
8
- "keywords": ["email", "millionsend", "ses", "transactional-email"],
9
- "homepage": "https://github.com/MillionSend",
10
- "repository": { "type": "git", "url": "git+https://github.com/MillionSend/millionsend-node.git" },
3
+ "version": "0.2.0",
4
+ "description": "Official MillionSend SDK for Node.js — a Resend-compatible email API you can self-host.",
5
+ "type": "module",
11
6
  "license": "MIT",
12
- "engines": { "node": ">=18" }
7
+ "author": "MillionSend",
8
+ "homepage": "https://github.com/MillionSend/millionsend-node#readme",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/MillionSend/millionsend-node.git"
12
+ },
13
+ "keywords": ["millionsend", "resend", "email", "ses", "sdk", "transactional", "broadcast"],
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/index.d.ts",
17
+ "import": "./dist/index.js"
18
+ }
19
+ },
20
+ "main": "./dist/index.js",
21
+ "module": "./dist/index.js",
22
+ "types": "./dist/index.d.ts",
23
+ "files": ["dist", "README.md", "LICENSE"],
24
+ "engines": {
25
+ "node": ">=18"
26
+ },
27
+ "scripts": {
28
+ "build": "tsc -p tsconfig.build.json",
29
+ "typecheck": "tsc --noEmit",
30
+ "test": "vitest run",
31
+ "prepack": "pnpm build"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^22.20.1",
35
+ "typescript": "^5.9.3",
36
+ "vitest": "^3.2.4"
37
+ }
13
38
  }
package/index.d.ts DELETED
@@ -1,4 +0,0 @@
1
- export declare class MillionSend {
2
- constructor(apiKey?: string);
3
- }
4
- export default MillionSend;
package/index.js DELETED
@@ -1,14 +0,0 @@
1
- // MillionSend Node.js SDK — under active development.
2
- // The published API will mirror the shape you already know:
3
- // const millionsend = new MillionSend(process.env.MILLIONSEND_API_KEY);
4
- // await millionsend.emails.send({ from, to, subject, html });
5
- // Follow https://github.com/MillionSend for progress.
6
- class MillionSend {
7
- constructor() {
8
- throw new Error(
9
- 'The MillionSend SDK is under active development — this placeholder release only reserves the package name. Follow https://github.com/MillionSend for the first working release.'
10
- );
11
- }
12
- }
13
- module.exports = { MillionSend };
14
- module.exports.default = MillionSend;