@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 +141 -27
- package/dist/index.cjs +275 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +275 -11
- package/dist/index.d.ts +275 -11
- package/dist/index.js +268 -8
- package/dist/index.js.map +1 -1
- package/package.json +11 -9
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:
|
|
6
|
-
- API host:
|
|
7
|
-
-
|
|
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 {
|
|
24
|
+
import { NilovonConnect } from "@nilovonjs/connect";
|
|
19
25
|
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
26
|
+
const client = new NilovonConnect({ apiKey: "nk_..." });
|
|
27
|
+
// or simply:
|
|
28
|
+
// const client = new NilovonConnect("nk_...");
|
|
23
29
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
emailDomainId: "dom_...",
|
|
30
|
+
// Send an email
|
|
31
|
+
await client.emails.send({
|
|
27
32
|
to: "user@example.com",
|
|
28
|
-
|
|
29
|
-
|
|
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
|
|
36
|
-
|
|
|
37
|
-
| `apiKey`
|
|
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
|
-
##
|
|
56
|
+
## Resources
|
|
40
57
|
|
|
41
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
33
|
-
|
|
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
|
package/dist/index.cjs.map
CHANGED
|
@@ -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":[]}
|