lumail 0.1.0 → 0.1.2
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 +257 -0
- package/dist/cli.js +80 -15
- package/dist/client.d.ts +9 -0
- package/dist/errors.d.ts +27 -0
- package/dist/index.cjs +60 -17
- package/dist/index.d.ts +19 -0
- package/dist/index.js +42 -9
- package/dist/resources/campaigns.d.ts +12 -0
- package/dist/resources/emails.d.ts +8 -0
- package/dist/resources/events.d.ts +7 -0
- package/dist/resources/subscribers.d.ts +15 -0
- package/dist/resources/tags.d.ts +10 -0
- package/dist/resources/tools.d.ts +12 -0
- package/dist/types.d.ts +327 -0
- package/package.json +6 -2
package/README.md
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
# Lumail
|
|
2
|
+
|
|
3
|
+
TypeScript SDK and CLI for the [Lumail](https://lumail.io) email marketing platform.
|
|
4
|
+
|
|
5
|
+
Manage subscribers, send campaigns, trigger transactional emails, and more — all from code.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install lumail
|
|
11
|
+
# or
|
|
12
|
+
pnpm add lumail
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { Lumail } from "lumail";
|
|
19
|
+
|
|
20
|
+
const lumail = new Lumail({
|
|
21
|
+
apiKey: "lum_your_api_key", // Get yours at lumail.io/settings
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Add a subscriber
|
|
25
|
+
const { subscriber } = await lumail.subscribers.create({
|
|
26
|
+
email: "john@example.com",
|
|
27
|
+
name: "John Doe",
|
|
28
|
+
tags: ["newsletter", "welcome"],
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Send a transactional email
|
|
32
|
+
await lumail.emails.send({
|
|
33
|
+
to: "john@example.com",
|
|
34
|
+
from: "hello@yourdomain.com",
|
|
35
|
+
subject: "Welcome!",
|
|
36
|
+
content: "Thanks for signing up.",
|
|
37
|
+
contentType: "MARKDOWN",
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Authentication
|
|
42
|
+
|
|
43
|
+
Get your API key from your [Lumail settings page](https://lumail.io/settings), then pass it to the constructor:
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
const lumail = new Lumail({ apiKey: "lum_..." });
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Resources
|
|
50
|
+
|
|
51
|
+
### Subscribers
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
// List subscribers (with cursor pagination)
|
|
55
|
+
const { subscribers, nextCursor } = await lumail.subscribers.list({
|
|
56
|
+
tag: "newsletter",
|
|
57
|
+
status: "SUBSCRIBED",
|
|
58
|
+
limit: 50,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Get a subscriber by ID or email
|
|
62
|
+
const { subscriber } = await lumail.subscribers.get("john@example.com");
|
|
63
|
+
|
|
64
|
+
// Create a subscriber
|
|
65
|
+
const { subscriber } = await lumail.subscribers.create({
|
|
66
|
+
email: "john@example.com",
|
|
67
|
+
name: "John Doe",
|
|
68
|
+
phone: "+1234567890",
|
|
69
|
+
tags: ["newsletter"],
|
|
70
|
+
fields: { company: "Acme" },
|
|
71
|
+
triggerWorkflows: true,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Update a subscriber
|
|
75
|
+
await lumail.subscribers.update("john@example.com", {
|
|
76
|
+
name: "John D.",
|
|
77
|
+
fields: { company: "New Corp" },
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Delete a subscriber
|
|
81
|
+
await lumail.subscribers.delete("john@example.com");
|
|
82
|
+
|
|
83
|
+
// Unsubscribe
|
|
84
|
+
await lumail.subscribers.unsubscribe("john@example.com");
|
|
85
|
+
|
|
86
|
+
// Manage tags
|
|
87
|
+
await lumail.subscribers.addTags("john@example.com", ["vip", "early-adopter"]);
|
|
88
|
+
await lumail.subscribers.removeTags("john@example.com", ["early-adopter"]);
|
|
89
|
+
|
|
90
|
+
// List subscriber events
|
|
91
|
+
const { events } = await lumail.subscribers.listEvents("john@example.com", {
|
|
92
|
+
eventTypes: ["EMAIL_OPENED", "EMAIL_CLICKED"],
|
|
93
|
+
order: "desc",
|
|
94
|
+
take: 20,
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Campaigns
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
// List campaigns
|
|
102
|
+
const { campaigns } = await lumail.campaigns.list({
|
|
103
|
+
status: "DRAFT",
|
|
104
|
+
limit: 10,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Create a campaign
|
|
108
|
+
const { campaign } = await lumail.campaigns.create({
|
|
109
|
+
subject: "March Newsletter",
|
|
110
|
+
name: "march-2026",
|
|
111
|
+
preview: "What's new this month",
|
|
112
|
+
contentType: "MARKDOWN",
|
|
113
|
+
content: "# Hello\n\nHere's what's new...",
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Get a campaign
|
|
117
|
+
const { campaign } = await lumail.campaigns.get("campaign_id");
|
|
118
|
+
|
|
119
|
+
// Update a campaign
|
|
120
|
+
await lumail.campaigns.update("campaign_id", {
|
|
121
|
+
subject: "Updated Subject",
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Send immediately
|
|
125
|
+
await lumail.campaigns.send("campaign_id");
|
|
126
|
+
|
|
127
|
+
// Schedule for later
|
|
128
|
+
await lumail.campaigns.send("campaign_id", {
|
|
129
|
+
scheduledAt: "2026-04-10T09:00:00Z",
|
|
130
|
+
timezone: "Europe/Paris",
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Delete a campaign
|
|
134
|
+
await lumail.campaigns.delete("campaign_id");
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Emails
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
// Send a transactional email
|
|
141
|
+
await lumail.emails.send({
|
|
142
|
+
to: "user@example.com",
|
|
143
|
+
from: "noreply@yourdomain.com",
|
|
144
|
+
subject: "Your invoice",
|
|
145
|
+
content: "<h1>Invoice #123</h1><p>Amount: $99</p>",
|
|
146
|
+
contentType: "HTML",
|
|
147
|
+
replyTo: "support@yourdomain.com",
|
|
148
|
+
transactional: true,
|
|
149
|
+
tracking: { open: true, links: true },
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Verify an email address
|
|
153
|
+
const result = await lumail.emails.verify({
|
|
154
|
+
email: "check@example.com",
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
if (!result.success) {
|
|
158
|
+
console.log(result.code, result.error, result.suggestion);
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Tags
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
// List all tags
|
|
166
|
+
const { tags } = await lumail.tags.list();
|
|
167
|
+
|
|
168
|
+
// Create a tag
|
|
169
|
+
const { tag } = await lumail.tags.create({ name: "vip" });
|
|
170
|
+
|
|
171
|
+
// Get a tag (includes subscriber count)
|
|
172
|
+
const { tag } = await lumail.tags.get("vip");
|
|
173
|
+
|
|
174
|
+
// Update a tag
|
|
175
|
+
await lumail.tags.update("vip", { name: "VIP Customers" });
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Events
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
// Create a custom event
|
|
182
|
+
await lumail.events.create({
|
|
183
|
+
eventType: "SUBSCRIBER_PAYMENT",
|
|
184
|
+
subscriber: "john@example.com",
|
|
185
|
+
data: { amount: 99, currency: "USD", plan: "pro" },
|
|
186
|
+
});
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Tools (v2)
|
|
190
|
+
|
|
191
|
+
AI-powered tools for email marketing.
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
// List available tools
|
|
195
|
+
const { tools } = await lumail.tools.list();
|
|
196
|
+
|
|
197
|
+
// Get tool details
|
|
198
|
+
const { tool } = await lumail.tools.get("generate-subject-line");
|
|
199
|
+
|
|
200
|
+
// Run a tool
|
|
201
|
+
const result = await lumail.tools.run("generate-subject-line", {
|
|
202
|
+
topic: "Spring sale announcement",
|
|
203
|
+
tone: "excited",
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Error Handling
|
|
208
|
+
|
|
209
|
+
The SDK throws typed errors you can catch individually:
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
import {
|
|
213
|
+
Lumail,
|
|
214
|
+
LumailAuthenticationError,
|
|
215
|
+
LumailValidationError,
|
|
216
|
+
LumailNotFoundError,
|
|
217
|
+
LumailRateLimitError,
|
|
218
|
+
LumailPaymentRequiredError,
|
|
219
|
+
} from "lumail";
|
|
220
|
+
|
|
221
|
+
try {
|
|
222
|
+
await lumail.subscribers.get("unknown@example.com");
|
|
223
|
+
} catch (error) {
|
|
224
|
+
if (error instanceof LumailNotFoundError) {
|
|
225
|
+
console.log("Subscriber not found");
|
|
226
|
+
} else if (error instanceof LumailAuthenticationError) {
|
|
227
|
+
console.log("Invalid API key");
|
|
228
|
+
} else if (error instanceof LumailRateLimitError) {
|
|
229
|
+
console.log(`Rate limited, retry after ${error.retryAfter}ms`);
|
|
230
|
+
} else if (error instanceof LumailValidationError) {
|
|
231
|
+
console.log(`Bad request: ${error.message}`);
|
|
232
|
+
} else if (error instanceof LumailPaymentRequiredError) {
|
|
233
|
+
console.log("Plan limit reached — upgrade at lumail.io/billing");
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
All errors extend `LumailError` which includes `status` and `code` properties.
|
|
239
|
+
|
|
240
|
+
The client automatically retries idempotent requests (GET, PUT, DELETE) on rate-limit (429) and network errors with exponential backoff.
|
|
241
|
+
|
|
242
|
+
## CLI
|
|
243
|
+
|
|
244
|
+
The package also ships a CLI:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
npx lumail --help
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Requirements
|
|
251
|
+
|
|
252
|
+
- Node.js 18+ (uses native `fetch`)
|
|
253
|
+
- An API key from [lumail.io](https://lumail.io)
|
|
254
|
+
|
|
255
|
+
## License
|
|
256
|
+
|
|
257
|
+
MIT
|
package/dist/cli.js
CHANGED
|
@@ -5,15 +5,29 @@ var __getProtoOf = Object.getPrototypeOf;
|
|
|
5
5
|
var __defProp = Object.defineProperty;
|
|
6
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
function __accessProp(key) {
|
|
9
|
+
return this[key];
|
|
10
|
+
}
|
|
11
|
+
var __toESMCache_node;
|
|
12
|
+
var __toESMCache_esm;
|
|
8
13
|
var __toESM = (mod, isNodeMode, target) => {
|
|
14
|
+
var canCache = mod != null && typeof mod === "object";
|
|
15
|
+
if (canCache) {
|
|
16
|
+
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
17
|
+
var cached = cache.get(mod);
|
|
18
|
+
if (cached)
|
|
19
|
+
return cached;
|
|
20
|
+
}
|
|
9
21
|
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
10
22
|
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
11
23
|
for (let key of __getOwnPropNames(mod))
|
|
12
24
|
if (!__hasOwnProp.call(to, key))
|
|
13
25
|
__defProp(to, key, {
|
|
14
|
-
get: (
|
|
26
|
+
get: __accessProp.bind(mod, key),
|
|
15
27
|
enumerable: true
|
|
16
28
|
});
|
|
29
|
+
if (canCache)
|
|
30
|
+
cache.set(mod, to);
|
|
17
31
|
return to;
|
|
18
32
|
};
|
|
19
33
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
@@ -991,8 +1005,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
991
1005
|
this._exitCallback = (err) => {
|
|
992
1006
|
if (err.code !== "commander.executeSubCommandAsync") {
|
|
993
1007
|
throw err;
|
|
994
|
-
} else {
|
|
995
|
-
}
|
|
1008
|
+
} else {}
|
|
996
1009
|
};
|
|
997
1010
|
}
|
|
998
1011
|
return this;
|
|
@@ -2260,6 +2273,19 @@ class LumailPaymentRequiredError extends LumailError {
|
|
|
2260
2273
|
}
|
|
2261
2274
|
}
|
|
2262
2275
|
|
|
2276
|
+
class LumailConfirmationRequiredError extends LumailError {
|
|
2277
|
+
confirmationCode;
|
|
2278
|
+
action;
|
|
2279
|
+
instruction;
|
|
2280
|
+
constructor(message, confirmationCode, action, instruction) {
|
|
2281
|
+
super(message, 403, "CONFIRMATION_REQUIRED");
|
|
2282
|
+
this.name = "LumailConfirmationRequiredError";
|
|
2283
|
+
this.confirmationCode = confirmationCode;
|
|
2284
|
+
this.action = action;
|
|
2285
|
+
this.instruction = instruction;
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
|
|
2263
2289
|
// ../../src/lib/lumail-sdk/client.ts
|
|
2264
2290
|
var DEFAULT_BASE_URL = "https://lumail.io/api";
|
|
2265
2291
|
var DEFAULT_TIMEOUT = 30000;
|
|
@@ -2295,11 +2321,7 @@ class LumailClient {
|
|
|
2295
2321
|
signal
|
|
2296
2322
|
});
|
|
2297
2323
|
if (response.ok) {
|
|
2298
|
-
|
|
2299
|
-
if (data.success === false) {
|
|
2300
|
-
throw new LumailError(data.message ?? "Request failed", response.status, data.code);
|
|
2301
|
-
}
|
|
2302
|
-
return data;
|
|
2324
|
+
return await response.json();
|
|
2303
2325
|
}
|
|
2304
2326
|
if (response.status === 429 && isIdempotent && attempt < maxRetries) {
|
|
2305
2327
|
await sleep(parseRetryAfter(response, RETRY_DELAYS[attempt]));
|
|
@@ -2336,8 +2358,7 @@ class LumailClient {
|
|
|
2336
2358
|
let body = {};
|
|
2337
2359
|
try {
|
|
2338
2360
|
body = await response.json();
|
|
2339
|
-
} catch {
|
|
2340
|
-
}
|
|
2361
|
+
} catch {}
|
|
2341
2362
|
const message = body.message ?? body.error ?? response.statusText;
|
|
2342
2363
|
const code = body.code;
|
|
2343
2364
|
switch (response.status) {
|
|
@@ -2345,6 +2366,12 @@ class LumailClient {
|
|
|
2345
2366
|
return new LumailAuthenticationError(message);
|
|
2346
2367
|
case 402:
|
|
2347
2368
|
return new LumailPaymentRequiredError(message);
|
|
2369
|
+
case 403: {
|
|
2370
|
+
if (body.error === "CONFIRMATION_REQUIRED") {
|
|
2371
|
+
return new LumailConfirmationRequiredError(message, body.confirmationCode, body.action, body.instruction);
|
|
2372
|
+
}
|
|
2373
|
+
return new LumailValidationError(message);
|
|
2374
|
+
}
|
|
2348
2375
|
case 404:
|
|
2349
2376
|
return new LumailNotFoundError(message);
|
|
2350
2377
|
case 429: {
|
|
@@ -2444,6 +2471,11 @@ class Subscribers {
|
|
|
2444
2471
|
constructor(client) {
|
|
2445
2472
|
this.client = client;
|
|
2446
2473
|
}
|
|
2474
|
+
async list(params) {
|
|
2475
|
+
return this.client.request("GET", "/v1/subscribers", {
|
|
2476
|
+
params
|
|
2477
|
+
});
|
|
2478
|
+
}
|
|
2447
2479
|
async create(params) {
|
|
2448
2480
|
return this.client.request("POST", "/v1/subscribers", {
|
|
2449
2481
|
body: params
|
|
@@ -2511,8 +2543,21 @@ class Tools {
|
|
|
2511
2543
|
async get(toolName) {
|
|
2512
2544
|
return this.client.request("GET", `/v2/tools/${encodeURIComponent(toolName)}`);
|
|
2513
2545
|
}
|
|
2514
|
-
async run(toolName, params) {
|
|
2515
|
-
|
|
2546
|
+
async run(toolName, params, options) {
|
|
2547
|
+
const { autoConfirm = true } = options ?? {};
|
|
2548
|
+
const endpoint = `/v2/tools/${encodeURIComponent(toolName)}`;
|
|
2549
|
+
try {
|
|
2550
|
+
return await this.client.request("POST", endpoint, {
|
|
2551
|
+
body: params ?? {}
|
|
2552
|
+
});
|
|
2553
|
+
} catch (error) {
|
|
2554
|
+
if (autoConfirm && error instanceof LumailConfirmationRequiredError) {
|
|
2555
|
+
return this.client.request("POST", endpoint, {
|
|
2556
|
+
body: { ...params, confirmationCode: error.confirmationCode }
|
|
2557
|
+
});
|
|
2558
|
+
}
|
|
2559
|
+
throw error;
|
|
2560
|
+
}
|
|
2516
2561
|
}
|
|
2517
2562
|
}
|
|
2518
2563
|
|
|
@@ -2664,7 +2709,7 @@ function fmtCell(v) {
|
|
|
2664
2709
|
return s;
|
|
2665
2710
|
}
|
|
2666
2711
|
function stripAnsi(s) {
|
|
2667
|
-
return s.replace(
|
|
2712
|
+
return s.replace(new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, "g"), "");
|
|
2668
2713
|
}
|
|
2669
2714
|
function printTable(rows) {
|
|
2670
2715
|
const cols = Object.keys(rows[0] ?? {});
|
|
@@ -2753,6 +2798,26 @@ API key is valid.`));
|
|
|
2753
2798
|
|
|
2754
2799
|
// ../../src/cli/commands/subscribers.ts
|
|
2755
2800
|
var subscribersCommand = new Command("subscribers").description("Manage subscribers");
|
|
2801
|
+
subscribersCommand.command("list").description("List subscribers with optional filters").option("--tag <tag>", "Filter by tag name").option("--status <status>", "Filter by status (all, SUBSCRIBED, UNSUBSCRIBED, etc.)", "all").option("--limit <n>", "Max number of subscribers to return", "50").option("--cursor <id>", "Cursor for pagination (subscriber ID)").option("--query <q>", "Search by name or email").action(async (opts) => {
|
|
2802
|
+
try {
|
|
2803
|
+
const limit = Number(opts.limit);
|
|
2804
|
+
if (!Number.isFinite(limit) || limit < 1) {
|
|
2805
|
+
console.error("Error: --limit must be a positive integer");
|
|
2806
|
+
process.exit(1);
|
|
2807
|
+
}
|
|
2808
|
+
const lumail = getLumail();
|
|
2809
|
+
const result = await lumail.subscribers.list({
|
|
2810
|
+
tag: opts.tag,
|
|
2811
|
+
status: opts.status,
|
|
2812
|
+
limit,
|
|
2813
|
+
cursor: opts.cursor,
|
|
2814
|
+
query: opts.query
|
|
2815
|
+
});
|
|
2816
|
+
output(result);
|
|
2817
|
+
} catch (error) {
|
|
2818
|
+
handleError(error);
|
|
2819
|
+
}
|
|
2820
|
+
});
|
|
2756
2821
|
subscribersCommand.command("create").description("Create or update a subscriber").requiredOption("--email <email>", "Email address").option("--name <name>", "Subscriber name").option("--tags <tags...>", "Tags to add").action(async (opts) => {
|
|
2757
2822
|
try {
|
|
2758
2823
|
const lumail = getLumail();
|
|
@@ -3041,7 +3106,7 @@ import { homedir as homedir2 } from "os";
|
|
|
3041
3106
|
import { join as join2 } from "path";
|
|
3042
3107
|
var SKILL_URL = "https://raw.githubusercontent.com/Melvynx/lumail-opensource/main/skills/lumail/SKILL.md";
|
|
3043
3108
|
var SKILLS_DIR = join2(homedir2(), ".claude", "skills", "lumail");
|
|
3044
|
-
function prompt(question) {
|
|
3109
|
+
async function prompt(question) {
|
|
3045
3110
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
3046
3111
|
return new Promise((resolve) => {
|
|
3047
3112
|
rl.question(question, (answer) => {
|
|
@@ -3097,7 +3162,7 @@ Installing Lumail skill...`));
|
|
|
3097
3162
|
console.log(import_picocolors3.default.green("Skill installed to ~/.claude/skills/lumail/"));
|
|
3098
3163
|
} catch {
|
|
3099
3164
|
console.log(import_picocolors3.default.yellow("Could not download skill from GitHub."));
|
|
3100
|
-
console.log(import_picocolors3.default.dim(
|
|
3165
|
+
console.log(import_picocolors3.default.dim(`Manual install: curl -o ~/.claude/skills/lumail/SKILL.md --create-dirs ${SKILL_URL}`));
|
|
3101
3166
|
}
|
|
3102
3167
|
setToken(token);
|
|
3103
3168
|
console.log(import_picocolors3.default.green("API key saved."));
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RequestOptions } from "./types";
|
|
2
|
+
export declare class LumailClient {
|
|
3
|
+
private readonly apiKey;
|
|
4
|
+
private readonly baseUrl;
|
|
5
|
+
constructor(apiKey: string, baseUrl?: string);
|
|
6
|
+
request<T>(method: string, path: string, options?: RequestOptions): Promise<T>;
|
|
7
|
+
private buildUrl;
|
|
8
|
+
private handleErrorResponse;
|
|
9
|
+
}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare class LumailError extends Error {
|
|
2
|
+
readonly status: number;
|
|
3
|
+
readonly code: string | undefined;
|
|
4
|
+
constructor(message: string, status: number, code?: string);
|
|
5
|
+
}
|
|
6
|
+
export declare class LumailAuthenticationError extends LumailError {
|
|
7
|
+
constructor(message?: string);
|
|
8
|
+
}
|
|
9
|
+
export declare class LumailRateLimitError extends LumailError {
|
|
10
|
+
readonly retryAfter: number | null;
|
|
11
|
+
constructor(message?: string, retryAfter?: number | null);
|
|
12
|
+
}
|
|
13
|
+
export declare class LumailValidationError extends LumailError {
|
|
14
|
+
constructor(message: string);
|
|
15
|
+
}
|
|
16
|
+
export declare class LumailNotFoundError extends LumailError {
|
|
17
|
+
constructor(message?: string);
|
|
18
|
+
}
|
|
19
|
+
export declare class LumailPaymentRequiredError extends LumailError {
|
|
20
|
+
constructor(message?: string);
|
|
21
|
+
}
|
|
22
|
+
export declare class LumailConfirmationRequiredError extends LumailError {
|
|
23
|
+
readonly confirmationCode: number;
|
|
24
|
+
readonly action: string;
|
|
25
|
+
readonly instruction: string;
|
|
26
|
+
constructor(message: string, confirmationCode: number, action: string, instruction: string);
|
|
27
|
+
}
|
package/dist/index.cjs
CHANGED
|
@@ -2,27 +2,37 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
4
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
-
|
|
5
|
+
function __accessProp(key) {
|
|
6
|
+
return this[key];
|
|
7
|
+
}
|
|
6
8
|
var __toCommonJS = (from) => {
|
|
7
|
-
var entry = __moduleCache.get(from), desc;
|
|
9
|
+
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
8
10
|
if (entry)
|
|
9
11
|
return entry;
|
|
10
12
|
entry = __defProp({}, "__esModule", { value: true });
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function")
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (var key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(entry, key))
|
|
16
|
+
__defProp(entry, key, {
|
|
17
|
+
get: __accessProp.bind(from, key),
|
|
18
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
19
|
+
});
|
|
20
|
+
}
|
|
16
21
|
__moduleCache.set(from, entry);
|
|
17
22
|
return entry;
|
|
18
23
|
};
|
|
24
|
+
var __moduleCache;
|
|
25
|
+
var __returnValue = (v) => v;
|
|
26
|
+
function __exportSetter(name, newValue) {
|
|
27
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
28
|
+
}
|
|
19
29
|
var __export = (target, all) => {
|
|
20
30
|
for (var name in all)
|
|
21
31
|
__defProp(target, name, {
|
|
22
32
|
get: all[name],
|
|
23
33
|
enumerable: true,
|
|
24
34
|
configurable: true,
|
|
25
|
-
set: (
|
|
35
|
+
set: __exportSetter.bind(all, name)
|
|
26
36
|
});
|
|
27
37
|
};
|
|
28
38
|
|
|
@@ -34,6 +44,7 @@ __export(exports_lumail_sdk, {
|
|
|
34
44
|
LumailPaymentRequiredError: () => LumailPaymentRequiredError,
|
|
35
45
|
LumailNotFoundError: () => LumailNotFoundError,
|
|
36
46
|
LumailError: () => LumailError,
|
|
47
|
+
LumailConfirmationRequiredError: () => LumailConfirmationRequiredError,
|
|
37
48
|
LumailAuthenticationError: () => LumailAuthenticationError,
|
|
38
49
|
Lumail: () => Lumail
|
|
39
50
|
});
|
|
@@ -88,6 +99,19 @@ class LumailPaymentRequiredError extends LumailError {
|
|
|
88
99
|
}
|
|
89
100
|
}
|
|
90
101
|
|
|
102
|
+
class LumailConfirmationRequiredError extends LumailError {
|
|
103
|
+
confirmationCode;
|
|
104
|
+
action;
|
|
105
|
+
instruction;
|
|
106
|
+
constructor(message, confirmationCode, action, instruction) {
|
|
107
|
+
super(message, 403, "CONFIRMATION_REQUIRED");
|
|
108
|
+
this.name = "LumailConfirmationRequiredError";
|
|
109
|
+
this.confirmationCode = confirmationCode;
|
|
110
|
+
this.action = action;
|
|
111
|
+
this.instruction = instruction;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
91
115
|
// ../../src/lib/lumail-sdk/client.ts
|
|
92
116
|
var DEFAULT_BASE_URL = "https://lumail.io/api";
|
|
93
117
|
var DEFAULT_TIMEOUT = 30000;
|
|
@@ -123,11 +147,7 @@ class LumailClient {
|
|
|
123
147
|
signal
|
|
124
148
|
});
|
|
125
149
|
if (response.ok) {
|
|
126
|
-
|
|
127
|
-
if (data.success === false) {
|
|
128
|
-
throw new LumailError(data.message ?? "Request failed", response.status, data.code);
|
|
129
|
-
}
|
|
130
|
-
return data;
|
|
150
|
+
return await response.json();
|
|
131
151
|
}
|
|
132
152
|
if (response.status === 429 && isIdempotent && attempt < maxRetries) {
|
|
133
153
|
await sleep(parseRetryAfter(response, RETRY_DELAYS[attempt]));
|
|
@@ -164,8 +184,7 @@ class LumailClient {
|
|
|
164
184
|
let body = {};
|
|
165
185
|
try {
|
|
166
186
|
body = await response.json();
|
|
167
|
-
} catch {
|
|
168
|
-
}
|
|
187
|
+
} catch {}
|
|
169
188
|
const message = body.message ?? body.error ?? response.statusText;
|
|
170
189
|
const code = body.code;
|
|
171
190
|
switch (response.status) {
|
|
@@ -173,6 +192,12 @@ class LumailClient {
|
|
|
173
192
|
return new LumailAuthenticationError(message);
|
|
174
193
|
case 402:
|
|
175
194
|
return new LumailPaymentRequiredError(message);
|
|
195
|
+
case 403: {
|
|
196
|
+
if (body.error === "CONFIRMATION_REQUIRED") {
|
|
197
|
+
return new LumailConfirmationRequiredError(message, body.confirmationCode, body.action, body.instruction);
|
|
198
|
+
}
|
|
199
|
+
return new LumailValidationError(message);
|
|
200
|
+
}
|
|
176
201
|
case 404:
|
|
177
202
|
return new LumailNotFoundError(message);
|
|
178
203
|
case 429: {
|
|
@@ -272,6 +297,11 @@ class Subscribers {
|
|
|
272
297
|
constructor(client) {
|
|
273
298
|
this.client = client;
|
|
274
299
|
}
|
|
300
|
+
async list(params) {
|
|
301
|
+
return this.client.request("GET", "/v1/subscribers", {
|
|
302
|
+
params
|
|
303
|
+
});
|
|
304
|
+
}
|
|
275
305
|
async create(params) {
|
|
276
306
|
return this.client.request("POST", "/v1/subscribers", {
|
|
277
307
|
body: params
|
|
@@ -339,8 +369,21 @@ class Tools {
|
|
|
339
369
|
async get(toolName) {
|
|
340
370
|
return this.client.request("GET", `/v2/tools/${encodeURIComponent(toolName)}`);
|
|
341
371
|
}
|
|
342
|
-
async run(toolName, params) {
|
|
343
|
-
|
|
372
|
+
async run(toolName, params, options) {
|
|
373
|
+
const { autoConfirm = true } = options ?? {};
|
|
374
|
+
const endpoint = `/v2/tools/${encodeURIComponent(toolName)}`;
|
|
375
|
+
try {
|
|
376
|
+
return await this.client.request("POST", endpoint, {
|
|
377
|
+
body: params ?? {}
|
|
378
|
+
});
|
|
379
|
+
} catch (error) {
|
|
380
|
+
if (autoConfirm && error instanceof LumailConfirmationRequiredError) {
|
|
381
|
+
return this.client.request("POST", endpoint, {
|
|
382
|
+
body: { ...params, confirmationCode: error.confirmationCode }
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
throw error;
|
|
386
|
+
}
|
|
344
387
|
}
|
|
345
388
|
}
|
|
346
389
|
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Campaigns } from "./resources/campaigns";
|
|
2
|
+
import { Emails } from "./resources/emails";
|
|
3
|
+
import { Events } from "./resources/events";
|
|
4
|
+
import { Subscribers } from "./resources/subscribers";
|
|
5
|
+
import { Tags } from "./resources/tags";
|
|
6
|
+
import { Tools } from "./resources/tools";
|
|
7
|
+
import type { LumailOptions } from "./types";
|
|
8
|
+
export declare class Lumail {
|
|
9
|
+
readonly subscribers: Subscribers;
|
|
10
|
+
readonly campaigns: Campaigns;
|
|
11
|
+
readonly emails: Emails;
|
|
12
|
+
readonly tags: Tags;
|
|
13
|
+
readonly events: Events;
|
|
14
|
+
readonly tools: Tools;
|
|
15
|
+
constructor(options: LumailOptions);
|
|
16
|
+
}
|
|
17
|
+
export { LumailAuthenticationError, LumailConfirmationRequiredError, LumailError, LumailNotFoundError, LumailPaymentRequiredError, LumailRateLimitError, LumailValidationError, } from "./errors";
|
|
18
|
+
export type { AddTagsResponse, Campaign, CampaignSender, CampaignStatus, CampaignSummary, ContentType, CreateCampaignParams, CreateCampaignResponse, CreateEventParams, CreateEventResponse, CreateSubscriberParams, CreateSubscriberResponse, CreateTagParams, CreateTagResponse, DeleteCampaignResponse, DeleteSubscriberResponse, EmailContentType, GetCampaignResponse, GetSubscriberResponse, GetTagResponse, ConfirmationRequiredResponse, GetToolResponse, ListCampaignsParams, ListCampaignsResponse, ListEventsParams, ListEventsResponse, ListSubscriberEntry, ListSubscribersParams, ListSubscribersResponse, ListTagsResponse, ListToolsResponse, LumailOptions, RemoveTagsResponse, RunToolResponse, SendCampaignParams, SendCampaignResponse, SendEmailParams, SendEmailResponse, Subscriber, SubscriberEvent, SubscriberEventType, SubscriberStatus, SubscriberTag, Tag, TagWithCount, ToolDefinition, UnsubscribeResponse, UpdateCampaignParams, UpdateCampaignResponse, UpdateSubscriberParams, UpdateSubscriberResponse, UpdateTagParams, UpdateTagResponse, VerifyEmailParams, VerifyEmailResponse, } from "./types";
|
|
19
|
+
export type { RunToolOptions } from "./resources/tools";
|
package/dist/index.js
CHANGED
|
@@ -47,6 +47,19 @@ class LumailPaymentRequiredError extends LumailError {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
class LumailConfirmationRequiredError extends LumailError {
|
|
51
|
+
confirmationCode;
|
|
52
|
+
action;
|
|
53
|
+
instruction;
|
|
54
|
+
constructor(message, confirmationCode, action, instruction) {
|
|
55
|
+
super(message, 403, "CONFIRMATION_REQUIRED");
|
|
56
|
+
this.name = "LumailConfirmationRequiredError";
|
|
57
|
+
this.confirmationCode = confirmationCode;
|
|
58
|
+
this.action = action;
|
|
59
|
+
this.instruction = instruction;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
50
63
|
// ../../src/lib/lumail-sdk/client.ts
|
|
51
64
|
var DEFAULT_BASE_URL = "https://lumail.io/api";
|
|
52
65
|
var DEFAULT_TIMEOUT = 30000;
|
|
@@ -82,11 +95,7 @@ class LumailClient {
|
|
|
82
95
|
signal
|
|
83
96
|
});
|
|
84
97
|
if (response.ok) {
|
|
85
|
-
|
|
86
|
-
if (data.success === false) {
|
|
87
|
-
throw new LumailError(data.message ?? "Request failed", response.status, data.code);
|
|
88
|
-
}
|
|
89
|
-
return data;
|
|
98
|
+
return await response.json();
|
|
90
99
|
}
|
|
91
100
|
if (response.status === 429 && isIdempotent && attempt < maxRetries) {
|
|
92
101
|
await sleep(parseRetryAfter(response, RETRY_DELAYS[attempt]));
|
|
@@ -123,8 +132,7 @@ class LumailClient {
|
|
|
123
132
|
let body = {};
|
|
124
133
|
try {
|
|
125
134
|
body = await response.json();
|
|
126
|
-
} catch {
|
|
127
|
-
}
|
|
135
|
+
} catch {}
|
|
128
136
|
const message = body.message ?? body.error ?? response.statusText;
|
|
129
137
|
const code = body.code;
|
|
130
138
|
switch (response.status) {
|
|
@@ -132,6 +140,12 @@ class LumailClient {
|
|
|
132
140
|
return new LumailAuthenticationError(message);
|
|
133
141
|
case 402:
|
|
134
142
|
return new LumailPaymentRequiredError(message);
|
|
143
|
+
case 403: {
|
|
144
|
+
if (body.error === "CONFIRMATION_REQUIRED") {
|
|
145
|
+
return new LumailConfirmationRequiredError(message, body.confirmationCode, body.action, body.instruction);
|
|
146
|
+
}
|
|
147
|
+
return new LumailValidationError(message);
|
|
148
|
+
}
|
|
135
149
|
case 404:
|
|
136
150
|
return new LumailNotFoundError(message);
|
|
137
151
|
case 429: {
|
|
@@ -231,6 +245,11 @@ class Subscribers {
|
|
|
231
245
|
constructor(client) {
|
|
232
246
|
this.client = client;
|
|
233
247
|
}
|
|
248
|
+
async list(params) {
|
|
249
|
+
return this.client.request("GET", "/v1/subscribers", {
|
|
250
|
+
params
|
|
251
|
+
});
|
|
252
|
+
}
|
|
234
253
|
async create(params) {
|
|
235
254
|
return this.client.request("POST", "/v1/subscribers", {
|
|
236
255
|
body: params
|
|
@@ -298,8 +317,21 @@ class Tools {
|
|
|
298
317
|
async get(toolName) {
|
|
299
318
|
return this.client.request("GET", `/v2/tools/${encodeURIComponent(toolName)}`);
|
|
300
319
|
}
|
|
301
|
-
async run(toolName, params) {
|
|
302
|
-
|
|
320
|
+
async run(toolName, params, options) {
|
|
321
|
+
const { autoConfirm = true } = options ?? {};
|
|
322
|
+
const endpoint = `/v2/tools/${encodeURIComponent(toolName)}`;
|
|
323
|
+
try {
|
|
324
|
+
return await this.client.request("POST", endpoint, {
|
|
325
|
+
body: params ?? {}
|
|
326
|
+
});
|
|
327
|
+
} catch (error) {
|
|
328
|
+
if (autoConfirm && error instanceof LumailConfirmationRequiredError) {
|
|
329
|
+
return this.client.request("POST", endpoint, {
|
|
330
|
+
body: { ...params, confirmationCode: error.confirmationCode }
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
throw error;
|
|
334
|
+
}
|
|
303
335
|
}
|
|
304
336
|
}
|
|
305
337
|
|
|
@@ -327,6 +359,7 @@ export {
|
|
|
327
359
|
LumailPaymentRequiredError,
|
|
328
360
|
LumailNotFoundError,
|
|
329
361
|
LumailError,
|
|
362
|
+
LumailConfirmationRequiredError,
|
|
330
363
|
LumailAuthenticationError,
|
|
331
364
|
Lumail
|
|
332
365
|
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { LumailClient } from "../client";
|
|
2
|
+
import type { CreateCampaignParams, CreateCampaignResponse, DeleteCampaignResponse, GetCampaignResponse, ListCampaignsParams, ListCampaignsResponse, SendCampaignParams, SendCampaignResponse, UpdateCampaignParams, UpdateCampaignResponse } from "../types";
|
|
3
|
+
export declare class Campaigns {
|
|
4
|
+
private readonly client;
|
|
5
|
+
constructor(client: LumailClient);
|
|
6
|
+
list(params?: ListCampaignsParams): Promise<ListCampaignsResponse>;
|
|
7
|
+
create(params: CreateCampaignParams): Promise<CreateCampaignResponse>;
|
|
8
|
+
get(campaignId: string): Promise<GetCampaignResponse>;
|
|
9
|
+
update(campaignId: string, params: UpdateCampaignParams): Promise<UpdateCampaignResponse>;
|
|
10
|
+
delete(campaignId: string): Promise<DeleteCampaignResponse>;
|
|
11
|
+
send(campaignId: string, params?: SendCampaignParams): Promise<SendCampaignResponse>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { LumailClient } from "../client";
|
|
2
|
+
import type { SendEmailParams, SendEmailResponse, VerifyEmailParams, VerifyEmailResponse } from "../types";
|
|
3
|
+
export declare class Emails {
|
|
4
|
+
private readonly client;
|
|
5
|
+
constructor(client: LumailClient);
|
|
6
|
+
send(params: SendEmailParams): Promise<SendEmailResponse>;
|
|
7
|
+
verify(params: VerifyEmailParams): Promise<VerifyEmailResponse>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { LumailClient } from "../client";
|
|
2
|
+
import type { CreateEventParams, CreateEventResponse } from "../types";
|
|
3
|
+
export declare class Events {
|
|
4
|
+
private readonly client;
|
|
5
|
+
constructor(client: LumailClient);
|
|
6
|
+
create(params: CreateEventParams): Promise<CreateEventResponse>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { LumailClient } from "../client";
|
|
2
|
+
import type { AddTagsResponse, CreateSubscriberParams, CreateSubscriberResponse, DeleteSubscriberResponse, GetSubscriberResponse, ListEventsParams, ListEventsResponse, ListSubscribersParams, ListSubscribersResponse, RemoveTagsResponse, UnsubscribeResponse, UpdateSubscriberParams, UpdateSubscriberResponse } from "../types";
|
|
3
|
+
export declare class Subscribers {
|
|
4
|
+
private readonly client;
|
|
5
|
+
constructor(client: LumailClient);
|
|
6
|
+
list(params?: ListSubscribersParams): Promise<ListSubscribersResponse>;
|
|
7
|
+
create(params: CreateSubscriberParams): Promise<CreateSubscriberResponse>;
|
|
8
|
+
get(idOrEmail: string): Promise<GetSubscriberResponse>;
|
|
9
|
+
update(idOrEmail: string, params: UpdateSubscriberParams): Promise<UpdateSubscriberResponse>;
|
|
10
|
+
delete(idOrEmail: string): Promise<DeleteSubscriberResponse>;
|
|
11
|
+
unsubscribe(idOrEmail: string): Promise<UnsubscribeResponse>;
|
|
12
|
+
addTags(idOrEmail: string, tags: string[]): Promise<AddTagsResponse>;
|
|
13
|
+
removeTags(idOrEmail: string, tags: string[]): Promise<RemoveTagsResponse>;
|
|
14
|
+
listEvents(idOrEmail: string, params?: ListEventsParams): Promise<ListEventsResponse>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { LumailClient } from "../client";
|
|
2
|
+
import type { CreateTagParams, CreateTagResponse, GetTagResponse, ListTagsResponse, UpdateTagParams, UpdateTagResponse } from "../types";
|
|
3
|
+
export declare class Tags {
|
|
4
|
+
private readonly client;
|
|
5
|
+
constructor(client: LumailClient);
|
|
6
|
+
list(): Promise<ListTagsResponse>;
|
|
7
|
+
create(params: CreateTagParams): Promise<CreateTagResponse>;
|
|
8
|
+
get(idOrName: string): Promise<GetTagResponse>;
|
|
9
|
+
update(idOrName: string, params: UpdateTagParams): Promise<UpdateTagResponse>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { LumailClient } from "../client";
|
|
2
|
+
import type { GetToolResponse, ListToolsResponse, RunToolResponse } from "../types";
|
|
3
|
+
export type RunToolOptions = {
|
|
4
|
+
autoConfirm?: boolean;
|
|
5
|
+
};
|
|
6
|
+
export declare class Tools {
|
|
7
|
+
private readonly client;
|
|
8
|
+
constructor(client: LumailClient);
|
|
9
|
+
list(): Promise<ListToolsResponse>;
|
|
10
|
+
get(toolName: string): Promise<GetToolResponse>;
|
|
11
|
+
run<T = unknown>(toolName: string, params?: Record<string, unknown>, options?: RunToolOptions): Promise<RunToolResponse<T>>;
|
|
12
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
export type LumailOptions = {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
baseUrl?: string;
|
|
4
|
+
};
|
|
5
|
+
export type RequestOptions = {
|
|
6
|
+
params?: Record<string, string | number | boolean | undefined>;
|
|
7
|
+
body?: unknown;
|
|
8
|
+
signal?: AbortSignal;
|
|
9
|
+
};
|
|
10
|
+
export type SubscriberStatus = "PENDING_CONFIRMATION" | "SUBSCRIBED" | "UNSUBSCRIBED" | "BOUNCED" | "BANNED" | "COMPLAINED";
|
|
11
|
+
export type SubscriberTag = {
|
|
12
|
+
id: string;
|
|
13
|
+
name: string;
|
|
14
|
+
};
|
|
15
|
+
export type Subscriber = {
|
|
16
|
+
id: string;
|
|
17
|
+
email: string;
|
|
18
|
+
name: string | null;
|
|
19
|
+
phone: string | null;
|
|
20
|
+
status: SubscriberStatus;
|
|
21
|
+
tags: SubscriberTag[];
|
|
22
|
+
fields: Record<string, string>;
|
|
23
|
+
createdAt?: string;
|
|
24
|
+
updatedAt?: string;
|
|
25
|
+
};
|
|
26
|
+
export type ListSubscribersParams = {
|
|
27
|
+
tag?: string;
|
|
28
|
+
status?: SubscriberStatus | "all";
|
|
29
|
+
limit?: number;
|
|
30
|
+
cursor?: string;
|
|
31
|
+
query?: string;
|
|
32
|
+
};
|
|
33
|
+
export type ListSubscriberEntry = {
|
|
34
|
+
id: string;
|
|
35
|
+
email: string;
|
|
36
|
+
name: string | null;
|
|
37
|
+
status: SubscriberStatus;
|
|
38
|
+
createdAt: string;
|
|
39
|
+
tags: SubscriberTag[];
|
|
40
|
+
};
|
|
41
|
+
export type ListSubscribersResponse = {
|
|
42
|
+
success: true;
|
|
43
|
+
subscribers: ListSubscriberEntry[];
|
|
44
|
+
total: number;
|
|
45
|
+
limit: number;
|
|
46
|
+
nextCursor: string | null;
|
|
47
|
+
};
|
|
48
|
+
export type CreateSubscriberParams = {
|
|
49
|
+
email: string;
|
|
50
|
+
name?: string | null;
|
|
51
|
+
phone?: string | null;
|
|
52
|
+
tags?: string[];
|
|
53
|
+
fields?: Record<string, string | null>;
|
|
54
|
+
replaceTags?: boolean;
|
|
55
|
+
resubscribe?: boolean;
|
|
56
|
+
triggerWorkflows?: boolean;
|
|
57
|
+
ipAddress?: string;
|
|
58
|
+
country?: string;
|
|
59
|
+
};
|
|
60
|
+
export type UpdateSubscriberParams = Omit<CreateSubscriberParams, "email"> & {
|
|
61
|
+
email?: string;
|
|
62
|
+
};
|
|
63
|
+
export type CreateSubscriberResponse = {
|
|
64
|
+
success: true;
|
|
65
|
+
subscriber: Subscriber;
|
|
66
|
+
warnings?: string[];
|
|
67
|
+
};
|
|
68
|
+
export type GetSubscriberResponse = {
|
|
69
|
+
success: true;
|
|
70
|
+
subscriber: Subscriber;
|
|
71
|
+
};
|
|
72
|
+
export type UpdateSubscriberResponse = {
|
|
73
|
+
success: true;
|
|
74
|
+
subscriber: Subscriber;
|
|
75
|
+
warnings?: string[];
|
|
76
|
+
};
|
|
77
|
+
export type DeleteSubscriberResponse = {
|
|
78
|
+
success: true;
|
|
79
|
+
message: string;
|
|
80
|
+
};
|
|
81
|
+
export type UnsubscribeResponse = {
|
|
82
|
+
success: true;
|
|
83
|
+
message: string;
|
|
84
|
+
subscriber: {
|
|
85
|
+
id: string;
|
|
86
|
+
email: string;
|
|
87
|
+
status: SubscriberStatus;
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
export type AddTagsResponse = {
|
|
91
|
+
success: true;
|
|
92
|
+
added: number;
|
|
93
|
+
tags: SubscriberTag[];
|
|
94
|
+
};
|
|
95
|
+
export type RemoveTagsResponse = {
|
|
96
|
+
success: true;
|
|
97
|
+
removed: number;
|
|
98
|
+
tags?: SubscriberTag[];
|
|
99
|
+
message?: string;
|
|
100
|
+
};
|
|
101
|
+
export type SubscriberEventType = "SUBSCRIBED" | "UNSUBSCRIBED" | "TAG_ADDED" | "TAG_REMOVED" | "EMAIL_OPENED" | "EMAIL_CLICKED" | "EMAIL_SENT" | "EMAIL_RECEIVED" | "WORKFLOW_STARTED" | "WORKFLOW_COMPLETED" | "WORKFLOW_CANCELED" | "FIELD_UPDATED" | "EMAIL_BOUNCED" | "EMAIL_COMPLAINED" | "WEBHOOK_EXECUTED" | "SUBSCRIBER_PAYMENT" | "SUBSCRIBER_REFUND";
|
|
102
|
+
export type SubscriberEvent = {
|
|
103
|
+
id: string;
|
|
104
|
+
eventType: SubscriberEventType;
|
|
105
|
+
data: Record<string, unknown> | null;
|
|
106
|
+
subscriberId: string;
|
|
107
|
+
createdAt: string;
|
|
108
|
+
subscriber: {
|
|
109
|
+
id: string;
|
|
110
|
+
email: string;
|
|
111
|
+
name: string | null;
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
export type ListEventsParams = {
|
|
115
|
+
cursor?: string;
|
|
116
|
+
take?: number;
|
|
117
|
+
eventTypes?: SubscriberEventType[];
|
|
118
|
+
order?: "asc" | "desc";
|
|
119
|
+
startDate?: string;
|
|
120
|
+
endDate?: string;
|
|
121
|
+
search?: string;
|
|
122
|
+
};
|
|
123
|
+
export type ListEventsResponse = {
|
|
124
|
+
events: SubscriberEvent[];
|
|
125
|
+
nextCursor: string | null;
|
|
126
|
+
};
|
|
127
|
+
export type CampaignStatus = "DRAFT" | "ARCHIVED" | "SCHEDULED" | "SENDING" | "SENT" | "FAILED";
|
|
128
|
+
export type ContentType = "MAILY" | "PLATE" | "MARKDOWN";
|
|
129
|
+
export type CampaignSummary = {
|
|
130
|
+
id: string;
|
|
131
|
+
campaignId: string;
|
|
132
|
+
name: string;
|
|
133
|
+
subject: string;
|
|
134
|
+
preview: string | null;
|
|
135
|
+
status: CampaignStatus;
|
|
136
|
+
contentType: ContentType;
|
|
137
|
+
sendAt: string | null;
|
|
138
|
+
scheduledAt: string | null;
|
|
139
|
+
recipientCount: number;
|
|
140
|
+
emailsSentCount: number;
|
|
141
|
+
emailsOpenedCount: number;
|
|
142
|
+
emailsClickedCount: number;
|
|
143
|
+
createdAt: string;
|
|
144
|
+
updatedAt: string;
|
|
145
|
+
};
|
|
146
|
+
export type CampaignSender = {
|
|
147
|
+
id: string;
|
|
148
|
+
name: string;
|
|
149
|
+
displayName: string;
|
|
150
|
+
localPart: string;
|
|
151
|
+
replyTo: string | null;
|
|
152
|
+
domain: {
|
|
153
|
+
domain: string;
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
export type Campaign = CampaignSummary & {
|
|
157
|
+
content: unknown;
|
|
158
|
+
replyTo: string | null;
|
|
159
|
+
senderId: string;
|
|
160
|
+
timezone: string | null;
|
|
161
|
+
recipientFilters: unknown[];
|
|
162
|
+
sender: CampaignSender;
|
|
163
|
+
};
|
|
164
|
+
export type ListCampaignsParams = {
|
|
165
|
+
status?: "all" | "DRAFT" | "ARCHIVED" | "SCHEDULED" | "SENT";
|
|
166
|
+
page?: number;
|
|
167
|
+
limit?: number;
|
|
168
|
+
query?: string;
|
|
169
|
+
sortBy?: "name" | "name_desc";
|
|
170
|
+
};
|
|
171
|
+
export type ListCampaignsResponse = {
|
|
172
|
+
success: true;
|
|
173
|
+
campaigns: CampaignSummary[];
|
|
174
|
+
total: number;
|
|
175
|
+
page: number;
|
|
176
|
+
limit: number;
|
|
177
|
+
pageCount: number;
|
|
178
|
+
};
|
|
179
|
+
export type CreateCampaignParams = {
|
|
180
|
+
subject: string;
|
|
181
|
+
name?: string;
|
|
182
|
+
preview?: string | null;
|
|
183
|
+
content?: unknown;
|
|
184
|
+
contentType?: ContentType;
|
|
185
|
+
senderId?: string;
|
|
186
|
+
replyTo?: string | null;
|
|
187
|
+
};
|
|
188
|
+
export type CreateCampaignResponse = {
|
|
189
|
+
success: true;
|
|
190
|
+
campaign: CampaignSummary & {
|
|
191
|
+
content: unknown;
|
|
192
|
+
replyTo: string | null;
|
|
193
|
+
senderId: string;
|
|
194
|
+
};
|
|
195
|
+
campaignId: string;
|
|
196
|
+
};
|
|
197
|
+
export type GetCampaignResponse = {
|
|
198
|
+
success: true;
|
|
199
|
+
campaign: Campaign;
|
|
200
|
+
campaignId: string;
|
|
201
|
+
};
|
|
202
|
+
export type UpdateCampaignParams = Partial<CreateCampaignParams>;
|
|
203
|
+
export type UpdateCampaignResponse = CreateCampaignResponse;
|
|
204
|
+
export type DeleteCampaignResponse = {
|
|
205
|
+
success: true;
|
|
206
|
+
deleted: true;
|
|
207
|
+
campaignId: string;
|
|
208
|
+
};
|
|
209
|
+
export type SendCampaignParams = {
|
|
210
|
+
scheduledAt?: string;
|
|
211
|
+
timezone?: string;
|
|
212
|
+
};
|
|
213
|
+
export type SendCampaignResponse = {
|
|
214
|
+
success: true;
|
|
215
|
+
campaign: {
|
|
216
|
+
id: string;
|
|
217
|
+
campaignId: string;
|
|
218
|
+
status: "SCHEDULED" | "SENDING";
|
|
219
|
+
scheduledAt: string;
|
|
220
|
+
timezone: string;
|
|
221
|
+
};
|
|
222
|
+
campaignId: string;
|
|
223
|
+
};
|
|
224
|
+
export type EmailContentType = "MARKDOWN" | "HTML" | "TIPTAP";
|
|
225
|
+
export type SendEmailParams = {
|
|
226
|
+
to: string;
|
|
227
|
+
from: string;
|
|
228
|
+
subject: string;
|
|
229
|
+
content: string;
|
|
230
|
+
contentType?: EmailContentType;
|
|
231
|
+
preview?: string;
|
|
232
|
+
replyTo?: string;
|
|
233
|
+
transactional?: boolean;
|
|
234
|
+
tracking?: {
|
|
235
|
+
links?: boolean;
|
|
236
|
+
open?: boolean;
|
|
237
|
+
};
|
|
238
|
+
};
|
|
239
|
+
export type SendEmailResponse = {
|
|
240
|
+
success: true;
|
|
241
|
+
message: string;
|
|
242
|
+
qstashMessageId: string;
|
|
243
|
+
};
|
|
244
|
+
export type VerifyEmailParams = {
|
|
245
|
+
email: string;
|
|
246
|
+
};
|
|
247
|
+
export type VerifyEmailResponse = {
|
|
248
|
+
success: boolean;
|
|
249
|
+
error?: string;
|
|
250
|
+
code?: string;
|
|
251
|
+
suggestion?: string;
|
|
252
|
+
warnings?: string[];
|
|
253
|
+
};
|
|
254
|
+
export type Tag = {
|
|
255
|
+
id: string;
|
|
256
|
+
name: string;
|
|
257
|
+
};
|
|
258
|
+
export type TagWithCount = Tag & {
|
|
259
|
+
subscribersCount: number;
|
|
260
|
+
};
|
|
261
|
+
export type ListTagsResponse = {
|
|
262
|
+
success: true;
|
|
263
|
+
tags: Tag[];
|
|
264
|
+
};
|
|
265
|
+
export type CreateTagParams = {
|
|
266
|
+
name: string;
|
|
267
|
+
};
|
|
268
|
+
export type CreateTagResponse = {
|
|
269
|
+
success: true;
|
|
270
|
+
tag: Tag;
|
|
271
|
+
};
|
|
272
|
+
export type GetTagResponse = {
|
|
273
|
+
tag: TagWithCount;
|
|
274
|
+
};
|
|
275
|
+
export type UpdateTagParams = {
|
|
276
|
+
name: string;
|
|
277
|
+
};
|
|
278
|
+
export type UpdateTagResponse = {
|
|
279
|
+
success: true;
|
|
280
|
+
tag: Tag;
|
|
281
|
+
};
|
|
282
|
+
export type CreateEventParams = {
|
|
283
|
+
eventType: SubscriberEventType;
|
|
284
|
+
subscriber: string;
|
|
285
|
+
data: Record<string, unknown>;
|
|
286
|
+
};
|
|
287
|
+
export type CreateEventResponse = {
|
|
288
|
+
success: true;
|
|
289
|
+
event: {
|
|
290
|
+
id: string;
|
|
291
|
+
eventType: SubscriberEventType;
|
|
292
|
+
data: Record<string, unknown>;
|
|
293
|
+
subscriberId: string;
|
|
294
|
+
organizationId: string;
|
|
295
|
+
createdAt: string;
|
|
296
|
+
};
|
|
297
|
+
};
|
|
298
|
+
export type ToolDefinition = {
|
|
299
|
+
name: string;
|
|
300
|
+
description: string;
|
|
301
|
+
category?: string;
|
|
302
|
+
inputSchema?: Record<string, unknown>;
|
|
303
|
+
outputSchema?: Record<string, unknown>;
|
|
304
|
+
};
|
|
305
|
+
export type ListToolsResponse = {
|
|
306
|
+
success: true;
|
|
307
|
+
total: number;
|
|
308
|
+
tools: ToolDefinition[];
|
|
309
|
+
grouped: Record<string, ToolDefinition[]>;
|
|
310
|
+
docs: string;
|
|
311
|
+
};
|
|
312
|
+
export type GetToolResponse = {
|
|
313
|
+
success: true;
|
|
314
|
+
tool: ToolDefinition;
|
|
315
|
+
};
|
|
316
|
+
export type RunToolResponse<T = unknown> = {
|
|
317
|
+
success: true;
|
|
318
|
+
data: T;
|
|
319
|
+
};
|
|
320
|
+
export type ConfirmationRequiredResponse = {
|
|
321
|
+
success: false;
|
|
322
|
+
error: "CONFIRMATION_REQUIRED";
|
|
323
|
+
message: string;
|
|
324
|
+
action: string;
|
|
325
|
+
confirmationCode: number;
|
|
326
|
+
instruction: string;
|
|
327
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lumail",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Lumail SDK and CLI - email marketing platform",
|
|
5
5
|
"author": "Melvyn",
|
|
6
6
|
"license": "MIT",
|
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
"url": "https://github.com/Melvynx/lumail.io.git",
|
|
10
10
|
"directory": "packages/lumail"
|
|
11
11
|
},
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public",
|
|
14
|
+
"provenance": false
|
|
15
|
+
},
|
|
12
16
|
"type": "module",
|
|
13
17
|
"bin": {
|
|
14
18
|
"lumail": "./dist/cli.js"
|
|
@@ -23,7 +27,7 @@
|
|
|
23
27
|
}
|
|
24
28
|
},
|
|
25
29
|
"scripts": {
|
|
26
|
-
"build": "bun run build.ts",
|
|
30
|
+
"build": "rm -rf dist && bun run build.ts && tsc -p tsconfig.build.json",
|
|
27
31
|
"release": "release-it",
|
|
28
32
|
"prepublishOnly": "bun run build"
|
|
29
33
|
},
|