@nilovonjs/connect 0.1.1 → 0.1.4

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 CHANGED
@@ -1,63 +1,177 @@
1
1
  # @nilovonjs/connect
2
2
 
3
- Official TypeScript SDK for Nilovon Connect.
3
+ Official TypeScript SDK for the Nilovon Connect API.
4
4
 
5
- - Homepage: `https://connect.nilovon.com`
6
- - API host: `https://api.connect.nilovon.com`
7
- - API reference: `https://api.connect.nilovon.com/v1`
5
+ - Homepage: https://connect.nilovon.com
6
+ - API host: https://api.connect.nilovon.com
7
+ - Documentation: https://docs.connect.nilovon.com
8
8
 
9
9
  ## Installation
10
10
 
11
11
  ```bash
12
12
  npm install @nilovonjs/connect
13
+ # or
14
+ pnpm add @nilovonjs/connect
15
+ # or
16
+ yarn add @nilovonjs/connect
17
+ # or
18
+ bun add @nilovonjs/connect
13
19
  ```
14
20
 
15
21
  ## Quick Start
16
22
 
17
23
  ```ts
18
- import { createClient } from "@nilovonjs/connect";
24
+ import { NilovonConnect } from "@nilovonjs/connect";
19
25
 
20
- const connect = createClient({
21
- apiKey: "sk_live_...",
22
- });
26
+ const client = new NilovonConnect({ apiKey: "nk_..." });
27
+ // or simply:
28
+ // const client = new NilovonConnect("nk_...");
23
29
 
24
- await connect.message.send({
25
- channelType: "email",
26
- emailDomainId: "dom_...",
30
+ // Send an email
31
+ await client.emails.send({
27
32
  to: "user@example.com",
28
- subject: "Hello from Connect",
29
- body: "<p>Your first message</p>",
33
+ from: "hello@yourdomain.com",
34
+ subject: "Welcome!",
35
+ html: "<h1>Hello</h1><p>Welcome to our platform.</p>",
36
+ });
37
+
38
+ // Create a campaign
39
+ await client.campaigns.create({
40
+ name: "Weekly Newsletter",
41
+ subject: "This week's updates",
42
+ fromEmail: "news@yourdomain.com",
30
43
  });
44
+
45
+ // List contacts
46
+ const { items } = await client.contacts.list({ limit: 50 });
31
47
  ```
32
48
 
33
49
  ## Configuration
34
50
 
35
- | Option | Required | Description |
36
- | -------- | -------- | ------------------------- |
37
- | `apiKey` | Yes | API key from your dashboard |
51
+ | Option | Required | Default | Description |
52
+ | --------- | -------- | ---------------------------------- | ------------------------- |
53
+ | `apiKey` | Yes | — | API key from your dashboard |
54
+ | `baseUrl` | No | `https://api.connect.nilovon.com` | Custom API base URL |
38
55
 
39
- ## API Surface
56
+ ## Resources
40
57
 
41
- - `connect.message`: `send`, `list`, `get`
42
- - `connect.contact`: `create`, `list`, `get`, `update`, `delete`, `bulkCreate`
43
- - `connect.template`: `create`, `list`, `get`, `update`, `delete`
44
- - `connect.webhook`: `create`, `list`, `get`, `update`, `delete`, `test`, `listEvents`
45
- - `connect.emailDomain`: `list`, `get`, `add`, `verify`, `delete`, `setDefault`
46
- - `connect.phoneNumber`: `list`, `get`, `searchAvailable`, `purchase`, `release`, `update`
47
- - `connect.segment`: `create`, `list`, `get`, `update`, `delete`
58
+ ### Emails
48
59
 
49
- ## Error Handling
60
+ ```ts
61
+ // Send a single email
62
+ await client.emails.send({
63
+ to: "user@example.com",
64
+ from: "hello@yourdomain.com",
65
+ subject: "Hello",
66
+ html: "<p>Content here</p>",
67
+ replyTo: "support@yourdomain.com",
68
+ scheduledAt: "2025-01-01T10:00:00Z", // optional
69
+ });
70
+
71
+ // Get a message by ID
72
+ const message = await client.emails.get("msg_...");
73
+
74
+ // List messages
75
+ const { items } = await client.emails.list({ limit: 20, status: "sent" });
76
+ ```
77
+
78
+ ### Contacts
79
+
80
+ ```ts
81
+ await client.contacts.create({ email: "user@example.com", name: "Jane Doe", tags: ["vip"] });
82
+ await client.contacts.get("contact_id");
83
+ await client.contacts.list({ search: "jane", limit: 50 });
84
+ await client.contacts.update("contact_id", { name: "Jane Smith" });
85
+ await client.contacts.delete("contact_id");
86
+ ```
50
87
 
51
- The SDK throws `ORPCError` for API errors.
88
+ ### Campaigns
89
+
90
+ ```ts
91
+ await client.campaigns.create({ name: "Launch Announcement", subject: "We launched!", fromEmail: "hi@example.com" });
92
+ await client.campaigns.update({ id: "camp_id", bodyHtml: "<h1>Hello</h1>" });
93
+ await client.campaigns.schedule("camp_id"); // send now
94
+ await client.campaigns.schedule("camp_id", "2025-06-01T09:00:00Z"); // schedule
95
+ await client.campaigns.pause("camp_id");
96
+ await client.campaigns.resume("camp_id");
97
+ await client.campaigns.duplicate("camp_id");
98
+ await client.campaigns.delete("camp_id");
99
+ ```
100
+
101
+ ### Domains
102
+
103
+ ```ts
104
+ await client.domains.create("mail.yourdomain.com");
105
+ await client.domains.list();
106
+ await client.domains.verify("domain_id");
107
+ await client.domains.delete("domain_id");
108
+ ```
109
+
110
+ ### Templates
111
+
112
+ ```ts
113
+ await client.templates.create({ name: "Welcome", channelType: "email", body: "<p>Hello {{name}}</p>" });
114
+ await client.templates.list({ channelType: "email" });
115
+ await client.templates.update("tmpl_id", { subject: "Updated subject" });
116
+ await client.templates.delete("tmpl_id");
117
+ ```
118
+
119
+ ### Webhooks
120
+
121
+ ```ts
122
+ await client.webhooks.create({ url: "https://yourdomain.com/webhook", events: ["message.sent"] });
123
+ await client.webhooks.list();
124
+ await client.webhooks.update("wh_id", { isActive: false });
125
+ await client.webhooks.delete("wh_id");
126
+ ```
127
+
128
+ ## Webhook Verification
129
+
130
+ Verify incoming webhook signatures using HMAC-SHA256:
131
+
132
+ ```ts
133
+ import { NilovonConnect } from "@nilovonjs/connect";
134
+
135
+ const isValid = await NilovonConnect.verifyWebhook(
136
+ "your_webhook_secret",
137
+ requestBody,
138
+ request.headers["x-webhook-signature"],
139
+ );
140
+
141
+ if (!isValid) {
142
+ return new Response("Invalid signature", { status: 401 });
143
+ }
144
+ ```
145
+
146
+ ## Advanced: Raw Client
147
+
148
+ For advanced usage, access the underlying oRPC client directly:
149
+
150
+ ```ts
151
+ const client = new NilovonConnect("nk_...");
152
+
153
+ // Use the raw oRPC client
154
+ const result = await client.raw.message.send({ ... });
155
+ ```
156
+
157
+ ## Error Handling
52
158
 
53
159
  ```ts
54
160
  import { ORPCError } from "@orpc/client";
55
161
 
56
162
  try {
57
- await connect.contact.get({ id: "nonexistent" });
163
+ await client.contacts.get("nonexistent");
58
164
  } catch (error) {
59
165
  if (error instanceof ORPCError) {
60
166
  console.error(error.code, error.message);
61
167
  }
62
168
  }
63
169
  ```
170
+
171
+ ## TypeScript
172
+
173
+ The SDK is fully typed. Import types as needed:
174
+
175
+ ```ts
176
+ import type { SendEmailParams, ContactParams, CreateCampaignParams } from "@nilovonjs/connect";
177
+ ```
package/dist/index.cjs CHANGED
@@ -20,6 +20,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ Campaigns: () => Campaigns,
24
+ Contacts: () => Contacts,
25
+ Domains: () => Domains,
26
+ Emails: () => Emails,
27
+ NilovonConnect: () => NilovonConnect,
28
+ Templates: () => Templates,
29
+ Webhooks: () => Webhooks,
23
30
  createClient: () => createClient
24
31
  });
25
32
  module.exports = __toCommonJS(index_exports);
@@ -27,18 +34,278 @@ module.exports = __toCommonJS(index_exports);
27
34
  // src/client.ts
28
35
  var import_client = require("@orpc/client");
29
36
  var import_fetch = require("@orpc/client/fetch");
30
- var BASE_URL = "https://api.connect.nilovon.com";
37
+
38
+ // src/resources/emails.ts
39
+ var Emails = class {
40
+ constructor(client) {
41
+ this.client = client;
42
+ }
43
+ /** Send a single email. Returns the created message. */
44
+ async send(params) {
45
+ return this.client.message.send({
46
+ channelType: "email",
47
+ to: params.to,
48
+ from: params.from,
49
+ subject: params.subject,
50
+ body: params.html ?? params.text ?? "",
51
+ emailDomainId: params.emailDomainId,
52
+ smtpConnectionId: params.smtpConnectionId
53
+ });
54
+ }
55
+ /** Get a message by ID. */
56
+ async get(id) {
57
+ return this.client.message.get({ id });
58
+ }
59
+ /** List messages with pagination. */
60
+ async list(params) {
61
+ return this.client.message.list({
62
+ limit: params?.limit ?? 20,
63
+ offset: params?.offset ?? 0,
64
+ status: params?.status,
65
+ channelType: params?.channelType
66
+ });
67
+ }
68
+ };
69
+
70
+ // src/resources/contacts.ts
71
+ var Contacts = class {
72
+ constructor(client) {
73
+ this.client = client;
74
+ }
75
+ /** Create a new contact. */
76
+ async create(params) {
77
+ return this.client.contact.create(params);
78
+ }
79
+ /** Get a contact by ID. */
80
+ async get(id) {
81
+ return this.client.contact.get({ id });
82
+ }
83
+ /** List contacts with pagination. */
84
+ async list(params) {
85
+ return this.client.contact.list({
86
+ limit: params?.limit ?? 20,
87
+ offset: params?.offset ?? 0,
88
+ query: params?.query
89
+ });
90
+ }
91
+ /** Update a contact. */
92
+ async update(id, params) {
93
+ return this.client.contact.update({ id, ...params });
94
+ }
95
+ /** Delete a contact. */
96
+ async delete(id) {
97
+ return this.client.contact.delete({ id });
98
+ }
99
+ };
100
+
101
+ // src/resources/domains.ts
102
+ var Domains = class {
103
+ constructor(client) {
104
+ this.client = client;
105
+ }
106
+ /** List all email domains. */
107
+ async list() {
108
+ return this.client.emailDomain.list({});
109
+ }
110
+ /** Get a domain by ID. */
111
+ async get(id) {
112
+ return this.client.emailDomain.get({ id });
113
+ }
114
+ /** Add a new email domain. */
115
+ async create(domain, region = "us-east-2") {
116
+ return this.client.emailDomain.add({ domain, region });
117
+ }
118
+ /** Verify a domain's DNS records. */
119
+ async verify(id) {
120
+ return this.client.emailDomain.verify({ id });
121
+ }
122
+ /** Delete an email domain. */
123
+ async delete(id) {
124
+ return this.client.emailDomain.delete({ id });
125
+ }
126
+ };
127
+
128
+ // src/resources/campaigns.ts
129
+ var Campaigns = class {
130
+ constructor(client) {
131
+ this.client = client;
132
+ }
133
+ /** Create a draft campaign. */
134
+ async create(params) {
135
+ return this.client.campaign.create(params);
136
+ }
137
+ /** Get a campaign by ID. */
138
+ async get(id) {
139
+ return this.client.campaign.get({ id });
140
+ }
141
+ /** List campaigns with optional status filter. */
142
+ async list(params) {
143
+ return this.client.campaign.list({
144
+ limit: params?.limit ?? 20,
145
+ offset: params?.offset ?? 0,
146
+ status: params?.status
147
+ });
148
+ }
149
+ /** Update a draft or scheduled campaign. */
150
+ async update(params) {
151
+ return this.client.campaign.update(params);
152
+ }
153
+ /** Delete a campaign. */
154
+ async delete(id) {
155
+ return this.client.campaign.delete({ id });
156
+ }
157
+ /** Schedule or send a campaign immediately. */
158
+ async schedule(id, scheduledAt) {
159
+ return this.client.campaign.schedule({ id, scheduledAt });
160
+ }
161
+ /** Pause a running campaign. */
162
+ async pause(id) {
163
+ return this.client.campaign.pause({ id });
164
+ }
165
+ /** Resume a paused campaign. */
166
+ async resume(id) {
167
+ return this.client.campaign.resume({ id });
168
+ }
169
+ /** Duplicate a campaign as a new draft. */
170
+ async duplicate(id) {
171
+ return this.client.campaign.duplicate({ id });
172
+ }
173
+ };
174
+
175
+ // src/resources/templates.ts
176
+ var Templates = class {
177
+ constructor(client) {
178
+ this.client = client;
179
+ }
180
+ /** Create a template. */
181
+ async create(params) {
182
+ return this.client.template.create(params);
183
+ }
184
+ /** Get a template by ID. */
185
+ async get(id) {
186
+ return this.client.template.get({ id });
187
+ }
188
+ /** List templates with optional filters. */
189
+ async list(params) {
190
+ return this.client.template.list({
191
+ limit: params?.limit ?? 20,
192
+ offset: params?.offset ?? 0,
193
+ channelType: params?.channelType,
194
+ isActive: params?.isActive
195
+ });
196
+ }
197
+ /** Update a template. */
198
+ async update(id, params) {
199
+ return this.client.template.update({ id, ...params });
200
+ }
201
+ /** Delete (deactivate) a template. */
202
+ async delete(id) {
203
+ return this.client.template.delete({ id });
204
+ }
205
+ };
206
+
207
+ // src/resources/webhooks.ts
208
+ var Webhooks = class {
209
+ constructor(client) {
210
+ this.client = client;
211
+ }
212
+ /** Create a webhook. */
213
+ async create(params) {
214
+ return this.client.webhook.create(params);
215
+ }
216
+ /** Get a webhook by ID. */
217
+ async get(id) {
218
+ return this.client.webhook.get({ id });
219
+ }
220
+ /** List webhooks. */
221
+ async list(params) {
222
+ return this.client.webhook.list({
223
+ limit: params?.limit ?? 20,
224
+ offset: params?.offset ?? 0
225
+ });
226
+ }
227
+ /** Update a webhook. */
228
+ async update(id, params) {
229
+ return this.client.webhook.update({ id, ...params });
230
+ }
231
+ /** Delete a webhook. */
232
+ async delete(id) {
233
+ return this.client.webhook.delete({ id });
234
+ }
235
+ /**
236
+ * Verify an incoming webhook signature.
237
+ * Returns true if the signature matches.
238
+ */
239
+ static async verify(secret, body, signature) {
240
+ const encoder = new TextEncoder();
241
+ const key = await crypto.subtle.importKey(
242
+ "raw",
243
+ encoder.encode(secret),
244
+ { name: "HMAC", hash: "SHA-256" },
245
+ false,
246
+ ["sign"]
247
+ );
248
+ const sig = await crypto.subtle.sign("HMAC", key, encoder.encode(body));
249
+ const bytes = new Uint8Array(sig);
250
+ let hex = "";
251
+ for (const b of bytes) hex += b.toString(16).padStart(2, "0");
252
+ return signature === `sha256=${hex}`;
253
+ }
254
+ };
255
+
256
+ // src/client.ts
257
+ var DEFAULT_BASE_URL = "https://api.connect.nilovon.com";
258
+ var NilovonConnect = class {
259
+ /** Email sending and management. */
260
+ emails;
261
+ /** Contact management (CRUD). */
262
+ contacts;
263
+ /** Email domain management. */
264
+ domains;
265
+ /** Campaign management. */
266
+ campaigns;
267
+ /** Template management. */
268
+ templates;
269
+ /** Webhook management and verification. */
270
+ webhooks;
271
+ /** The underlying oRPC client for advanced usage. */
272
+ raw;
273
+ constructor(configOrApiKey) {
274
+ const config = typeof configOrApiKey === "string" ? { apiKey: configOrApiKey } : configOrApiKey;
275
+ const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
276
+ const link = new import_fetch.RPCLink({
277
+ url: `${baseUrl}/rpc`,
278
+ headers: () => ({
279
+ Authorization: `Bearer ${config.apiKey}`
280
+ })
281
+ });
282
+ this.raw = (0, import_client.createORPCClient)(link);
283
+ this.emails = new Emails(this.raw);
284
+ this.contacts = new Contacts(this.raw);
285
+ this.domains = new Domains(this.raw);
286
+ this.campaigns = new Campaigns(this.raw);
287
+ this.templates = new Templates(this.raw);
288
+ this.webhooks = new Webhooks(this.raw);
289
+ }
290
+ /**
291
+ * Verify an incoming webhook signature.
292
+ * Convenience static method that delegates to Webhooks.verify().
293
+ */
294
+ static verifyWebhook = Webhooks.verify;
295
+ };
31
296
  function createClient(config) {
32
- const link = new import_fetch.RPCLink({
33
- url: `${BASE_URL}/rpc`,
34
- headers: () => ({
35
- Authorization: `Bearer ${config.apiKey}`
36
- })
37
- });
38
- return (0, import_client.createORPCClient)(link);
297
+ const client = new NilovonConnect(config);
298
+ return client.raw;
39
299
  }
40
300
  // Annotate the CommonJS export names for ESM import in node:
41
301
  0 && (module.exports = {
302
+ Campaigns,
303
+ Contacts,
304
+ Domains,
305
+ Emails,
306
+ NilovonConnect,
307
+ Templates,
308
+ Webhooks,
42
309
  createClient
43
310
  });
44
311
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/client.ts"],"sourcesContent":["export { createClient } from \"./client.js\";\nexport type { ConnectClient, ConnectConfig } from \"./client.js\";\n","import { createORPCClient } from \"@orpc/client\";\nimport { RPCLink } from \"@orpc/client/fetch\";\n\nexport interface ConnectConfig {\n /** API key from the dashboard (used as Bearer token). */\n apiKey: string;\n}\n\nconst BASE_URL = \"https://api.connect.nilovon.com\";\n\n/**\n * Create a fully-typed Connect API client.\n *\n * ```ts\n * import { createClient } from \"@nilovonjs/connect\";\n *\n * const client = createClient({ apiKey: \"sk_live_...\" });\n *\n * const { items } = await client.message.list({ limit: 10, offset: 0 });\n * ```\n */\nexport type ConnectClient = ReturnType<typeof createORPCClient>;\n\nexport function createClient(config: ConnectConfig): ConnectClient {\n const link = new RPCLink({\n url: `${BASE_URL}/rpc`,\n headers: () => ({\n Authorization: `Bearer ${config.apiKey}`,\n }),\n });\n\n return createORPCClient(link);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,oBAAiC;AACjC,mBAAwB;AAOxB,IAAM,WAAW;AAeV,SAAS,aAAa,QAAsC;AACjE,QAAM,OAAO,IAAI,qBAAQ;AAAA,IACvB,KAAK,GAAG,QAAQ;AAAA,IAChB,SAAS,OAAO;AAAA,MACd,eAAe,UAAU,OAAO,MAAM;AAAA,IACxC;AAAA,EACF,CAAC;AAED,aAAO,gCAAiB,IAAI;AAC9B;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/client.ts","../src/resources/emails.ts","../src/resources/contacts.ts","../src/resources/domains.ts","../src/resources/campaigns.ts","../src/resources/templates.ts","../src/resources/webhooks.ts"],"sourcesContent":["export { NilovonConnect } from \"./client\";\nexport type { NilovonConnectConfig } from \"./types\";\nexport type {\n SendEmailParams,\n BatchEmailParams,\n ContactParams,\n CreateCampaignParams,\n UpdateCampaignParams,\n WebhookPayload,\n PaginatedList,\n} from \"./types\";\n\n// Resource classes (for advanced typing)\nexport { Emails } from \"./resources/emails\";\nexport { Contacts } from \"./resources/contacts\";\nexport { Domains } from \"./resources/domains\";\nexport { Campaigns } from \"./resources/campaigns\";\nexport { Templates } from \"./resources/templates\";\nexport { Webhooks } from \"./resources/webhooks\";\n\n// Backward compatibility\nexport { createClient } from \"./client\";\nexport type { ConnectClient, ConnectConfig } from \"./client\";\n","import { createORPCClient } from \"@orpc/client\";\nimport { RPCLink } from \"@orpc/client/fetch\";\nimport type { AppRouterClient } from \"@connect/api/routers/index\";\n\nimport type { NilovonConnectConfig } from \"./types\";\nimport { Emails } from \"./resources/emails\";\nimport { Contacts } from \"./resources/contacts\";\nimport { Domains } from \"./resources/domains\";\nimport { Campaigns } from \"./resources/campaigns\";\nimport { Templates } from \"./resources/templates\";\nimport { Webhooks } from \"./resources/webhooks\";\n\nconst DEFAULT_BASE_URL = \"https://api.connect.nilovon.com\";\n\n/**\n * Main Nilovon Connect SDK client.\n *\n * ```ts\n * const client = new NilovonConnect({ apiKey: \"nk_...\" });\n * // or\n * const client = new NilovonConnect(\"nk_...\");\n *\n * await client.emails.send({ to: \"user@example.com\", from: \"hi@you.com\", subject: \"Hello\", html: \"<p>Hi</p>\" });\n * await client.campaigns.create({ name: \"Weekly newsletter\" });\n * await client.domains.list();\n * ```\n */\nexport class NilovonConnect {\n /** Email sending and management. */\n readonly emails: Emails;\n /** Contact management (CRUD). */\n readonly contacts: Contacts;\n /** Email domain management. */\n readonly domains: Domains;\n /** Campaign management. */\n readonly campaigns: Campaigns;\n /** Template management. */\n readonly templates: Templates;\n /** Webhook management and verification. */\n readonly webhooks: Webhooks;\n\n /** The underlying oRPC client for advanced usage. */\n readonly raw: AppRouterClient;\n\n constructor(configOrApiKey: NilovonConnectConfig | string) {\n const config =\n typeof configOrApiKey === \"string\"\n ? { apiKey: configOrApiKey }\n : configOrApiKey;\n\n const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;\n\n const link = new RPCLink({\n url: `${baseUrl}/rpc`,\n headers: () => ({\n Authorization: `Bearer ${config.apiKey}`,\n }),\n });\n\n this.raw = createORPCClient<AppRouterClient>(link);\n this.emails = new Emails(this.raw);\n this.contacts = new Contacts(this.raw);\n this.domains = new Domains(this.raw);\n this.campaigns = new Campaigns(this.raw);\n this.templates = new Templates(this.raw);\n this.webhooks = new Webhooks(this.raw);\n }\n\n /**\n * Verify an incoming webhook signature.\n * Convenience static method that delegates to Webhooks.verify().\n */\n static verifyWebhook = Webhooks.verify;\n}\n\n/** @deprecated Use `new NilovonConnect(config)` instead. */\nexport type ConnectConfig = NilovonConnectConfig;\n\n/** @deprecated Use `new NilovonConnect(config)` instead. */\nexport type ConnectClient = AppRouterClient;\n\n/** @deprecated Use `new NilovonConnect(config)` instead. */\nexport function createClient(config: NilovonConnectConfig): AppRouterClient {\n const client = new NilovonConnect(config);\n return client.raw;\n}\n","import type { AppRouterClient } from \"@connect/api/routers/index\";\n\nimport type { SendEmailParams } from \"../types\";\n\n/** Email sending and management resource. */\nexport class Emails {\n constructor(private client: AppRouterClient) {}\n\n /** Send a single email. Returns the created message. */\n async send(params: SendEmailParams) {\n return this.client.message.send({\n channelType: \"email\",\n to: params.to,\n from: params.from,\n subject: params.subject,\n body: params.html ?? params.text ?? \"\",\n emailDomainId: params.emailDomainId,\n smtpConnectionId: params.smtpConnectionId,\n });\n }\n\n /** Get a message by ID. */\n async get(id: string) {\n return this.client.message.get({ id });\n }\n\n /** List messages with pagination. */\n async list(params?: { limit?: number; offset?: number; status?: string; channelType?: string }) {\n return this.client.message.list({\n limit: params?.limit ?? 20,\n offset: params?.offset ?? 0,\n status: params?.status as \"queued\" | undefined,\n channelType: params?.channelType as \"email\" | undefined,\n });\n }\n}\n","import type { AppRouterClient } from \"@connect/api/routers/index\";\n\nimport type { ContactParams } from \"../types\";\n\n/** Contact management resource. */\nexport class Contacts {\n constructor(private client: AppRouterClient) {}\n\n /** Create a new contact. */\n async create(params: ContactParams) {\n return this.client.contact.create(params);\n }\n\n /** Get a contact by ID. */\n async get(id: string) {\n return this.client.contact.get({ id });\n }\n\n /** List contacts with pagination. */\n async list(params?: { limit?: number; offset?: number; query?: string }) {\n return this.client.contact.list({\n limit: params?.limit ?? 20,\n offset: params?.offset ?? 0,\n query: params?.query,\n });\n }\n\n /** Update a contact. */\n async update(id: string, params: Partial<ContactParams>) {\n return this.client.contact.update({ id, ...params });\n }\n\n /** Delete a contact. */\n async delete(id: string) {\n return this.client.contact.delete({ id });\n }\n}\n","import type { AppRouterClient } from \"@connect/api/routers/index\";\n\n/** Email domain management resource. */\nexport class Domains {\n constructor(private client: AppRouterClient) {}\n\n /** List all email domains. */\n async list() {\n return this.client.emailDomain.list({});\n }\n\n /** Get a domain by ID. */\n async get(id: string) {\n return this.client.emailDomain.get({ id });\n }\n\n /** Add a new email domain. */\n async create(domain: string, region = \"us-east-2\") {\n return this.client.emailDomain.add({ domain, region });\n }\n\n /** Verify a domain's DNS records. */\n async verify(id: string) {\n return this.client.emailDomain.verify({ id });\n }\n\n /** Delete an email domain. */\n async delete(id: string) {\n return this.client.emailDomain.delete({ id });\n }\n}\n","import type { AppRouterClient } from \"@connect/api/routers/index\";\n\nimport type { CreateCampaignParams, UpdateCampaignParams } from \"../types\";\n\n/** Campaign management resource. */\nexport class Campaigns {\n constructor(private client: AppRouterClient) {}\n\n /** Create a draft campaign. */\n async create(params: CreateCampaignParams) {\n return this.client.campaign.create(params);\n }\n\n /** Get a campaign by ID. */\n async get(id: string) {\n return this.client.campaign.get({ id });\n }\n\n /** List campaigns with optional status filter. */\n async list(params?: { limit?: number; offset?: number; status?: string }) {\n return this.client.campaign.list({\n limit: params?.limit ?? 20,\n offset: params?.offset ?? 0,\n status: params?.status as \"draft\" | undefined,\n });\n }\n\n /** Update a draft or scheduled campaign. */\n async update(params: UpdateCampaignParams) {\n return this.client.campaign.update(params);\n }\n\n /** Delete a campaign. */\n async delete(id: string) {\n return this.client.campaign.delete({ id });\n }\n\n /** Schedule or send a campaign immediately. */\n async schedule(id: string, scheduledAt?: string) {\n return this.client.campaign.schedule({ id, scheduledAt });\n }\n\n /** Pause a running campaign. */\n async pause(id: string) {\n return this.client.campaign.pause({ id });\n }\n\n /** Resume a paused campaign. */\n async resume(id: string) {\n return this.client.campaign.resume({ id });\n }\n\n /** Duplicate a campaign as a new draft. */\n async duplicate(id: string) {\n return this.client.campaign.duplicate({ id });\n }\n}\n","import type { AppRouterClient } from \"@connect/api/routers/index\";\n\n/** Template management resource. */\nexport class Templates {\n constructor(private client: AppRouterClient) {}\n\n /** Create a template. */\n async create(params: {\n name: string;\n channelType: \"email\" | \"sms\";\n body: string;\n subject?: string;\n variables?: Record<string, unknown>;\n isActive?: boolean;\n }) {\n return this.client.template.create(params);\n }\n\n /** Get a template by ID. */\n async get(id: string) {\n return this.client.template.get({ id });\n }\n\n /** List templates with optional filters. */\n async list(params?: {\n limit?: number;\n offset?: number;\n channelType?: \"email\" | \"sms\";\n isActive?: boolean;\n }) {\n return this.client.template.list({\n limit: params?.limit ?? 20,\n offset: params?.offset ?? 0,\n channelType: params?.channelType,\n isActive: params?.isActive,\n });\n }\n\n /** Update a template. */\n async update(\n id: string,\n params: {\n name?: string;\n subject?: string;\n body?: string;\n variables?: Record<string, unknown>;\n isActive?: boolean;\n },\n ) {\n return this.client.template.update({ id, ...params });\n }\n\n /** Delete (deactivate) a template. */\n async delete(id: string) {\n return this.client.template.delete({ id });\n }\n}\n","import type { AppRouterClient } from \"@connect/api/routers/index\";\n\n/** Webhook management and verification resource. */\nexport class Webhooks {\n constructor(private client: AppRouterClient) {}\n\n /** Create a webhook. */\n async create(params: {\n url: string;\n secret: string;\n events: string[];\n description?: string;\n isActive?: boolean;\n }) {\n return this.client.webhook.create(params);\n }\n\n /** Get a webhook by ID. */\n async get(id: string) {\n return this.client.webhook.get({ id });\n }\n\n /** List webhooks. */\n async list(params?: { limit?: number; offset?: number }) {\n return this.client.webhook.list({\n limit: params?.limit ?? 20,\n offset: params?.offset ?? 0,\n });\n }\n\n /** Update a webhook. */\n async update(\n id: string,\n params: {\n url?: string;\n secret?: string;\n events?: string[];\n isActive?: boolean;\n description?: string;\n },\n ) {\n return this.client.webhook.update({ id, ...params });\n }\n\n /** Delete a webhook. */\n async delete(id: string) {\n return this.client.webhook.delete({ id });\n }\n\n /**\n * Verify an incoming webhook signature.\n * Returns true if the signature matches.\n */\n static async verify(\n secret: string,\n body: string,\n signature: string,\n ): Promise<boolean> {\n const encoder = new TextEncoder();\n const key = await crypto.subtle.importKey(\n \"raw\",\n encoder.encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n const sig = await crypto.subtle.sign(\"HMAC\", key, encoder.encode(body));\n const bytes = new Uint8Array(sig);\n let hex = \"\";\n for (const b of bytes) hex += b.toString(16).padStart(2, \"0\");\n return signature === `sha256=${hex}`;\n }\n}\n"],"mappings":"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","names":[]}