lumail 0.1.0 → 0.1.1
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 +253 -0
- package/dist/cli.js +79 -10
- package/dist/client.d.ts +9 -0
- package/dist/errors.d.ts +27 -0
- package/dist/index.cjs +59 -12
- package/dist/index.d.ts +19 -0
- package/dist/index.js +41 -4
- 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 +323 -0
- package/package.json +6 -2
package/README.md
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
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 { isValid } = await lumail.emails.verify({
|
|
154
|
+
email: "check@example.com",
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Tags
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
// List all tags
|
|
162
|
+
const { tags } = await lumail.tags.list();
|
|
163
|
+
|
|
164
|
+
// Create a tag
|
|
165
|
+
const { tag } = await lumail.tags.create({ name: "vip" });
|
|
166
|
+
|
|
167
|
+
// Get a tag (includes subscriber count)
|
|
168
|
+
const { tag } = await lumail.tags.get("vip");
|
|
169
|
+
|
|
170
|
+
// Update a tag
|
|
171
|
+
await lumail.tags.update("vip", { name: "VIP Customers" });
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Events
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
// Create a custom event
|
|
178
|
+
await lumail.events.create({
|
|
179
|
+
eventType: "SUBSCRIBER_PAYMENT",
|
|
180
|
+
subscriber: "john@example.com",
|
|
181
|
+
data: { amount: 99, currency: "USD", plan: "pro" },
|
|
182
|
+
});
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Tools (v2)
|
|
186
|
+
|
|
187
|
+
AI-powered tools for email marketing.
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
// List available tools
|
|
191
|
+
const { tools } = await lumail.tools.list();
|
|
192
|
+
|
|
193
|
+
// Get tool details
|
|
194
|
+
const { tool } = await lumail.tools.get("generate-subject-line");
|
|
195
|
+
|
|
196
|
+
// Run a tool
|
|
197
|
+
const result = await lumail.tools.run("generate-subject-line", {
|
|
198
|
+
topic: "Spring sale announcement",
|
|
199
|
+
tone: "excited",
|
|
200
|
+
});
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Error Handling
|
|
204
|
+
|
|
205
|
+
The SDK throws typed errors you can catch individually:
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
import {
|
|
209
|
+
Lumail,
|
|
210
|
+
LumailAuthenticationError,
|
|
211
|
+
LumailValidationError,
|
|
212
|
+
LumailNotFoundError,
|
|
213
|
+
LumailRateLimitError,
|
|
214
|
+
LumailPaymentRequiredError,
|
|
215
|
+
} from "lumail";
|
|
216
|
+
|
|
217
|
+
try {
|
|
218
|
+
await lumail.subscribers.get("unknown@example.com");
|
|
219
|
+
} catch (error) {
|
|
220
|
+
if (error instanceof LumailNotFoundError) {
|
|
221
|
+
console.log("Subscriber not found");
|
|
222
|
+
} else if (error instanceof LumailAuthenticationError) {
|
|
223
|
+
console.log("Invalid API key");
|
|
224
|
+
} else if (error instanceof LumailRateLimitError) {
|
|
225
|
+
console.log(`Rate limited, retry after ${error.retryAfter}ms`);
|
|
226
|
+
} else if (error instanceof LumailValidationError) {
|
|
227
|
+
console.log(`Bad request: ${error.message}`);
|
|
228
|
+
} else if (error instanceof LumailPaymentRequiredError) {
|
|
229
|
+
console.log("Plan limit reached — upgrade at lumail.io/billing");
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
All errors extend `LumailError` which includes `status` and `code` properties.
|
|
235
|
+
|
|
236
|
+
The client automatically retries idempotent requests (GET, PUT, DELETE) on rate-limit (429) and network errors with exponential backoff.
|
|
237
|
+
|
|
238
|
+
## CLI
|
|
239
|
+
|
|
240
|
+
The package also ships a CLI:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
npx lumail --help
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Requirements
|
|
247
|
+
|
|
248
|
+
- Node.js 18+ (uses native `fetch`)
|
|
249
|
+
- An API key from [lumail.io](https://lumail.io)
|
|
250
|
+
|
|
251
|
+
## License
|
|
252
|
+
|
|
253
|
+
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;
|
|
@@ -2336,8 +2362,7 @@ class LumailClient {
|
|
|
2336
2362
|
let body = {};
|
|
2337
2363
|
try {
|
|
2338
2364
|
body = await response.json();
|
|
2339
|
-
} catch {
|
|
2340
|
-
}
|
|
2365
|
+
} catch {}
|
|
2341
2366
|
const message = body.message ?? body.error ?? response.statusText;
|
|
2342
2367
|
const code = body.code;
|
|
2343
2368
|
switch (response.status) {
|
|
@@ -2345,6 +2370,12 @@ class LumailClient {
|
|
|
2345
2370
|
return new LumailAuthenticationError(message);
|
|
2346
2371
|
case 402:
|
|
2347
2372
|
return new LumailPaymentRequiredError(message);
|
|
2373
|
+
case 403: {
|
|
2374
|
+
if (body.error === "CONFIRMATION_REQUIRED") {
|
|
2375
|
+
return new LumailConfirmationRequiredError(message, body.confirmationCode, body.action, body.instruction);
|
|
2376
|
+
}
|
|
2377
|
+
return new LumailValidationError(message);
|
|
2378
|
+
}
|
|
2348
2379
|
case 404:
|
|
2349
2380
|
return new LumailNotFoundError(message);
|
|
2350
2381
|
case 429: {
|
|
@@ -2444,6 +2475,11 @@ class Subscribers {
|
|
|
2444
2475
|
constructor(client) {
|
|
2445
2476
|
this.client = client;
|
|
2446
2477
|
}
|
|
2478
|
+
async list(params) {
|
|
2479
|
+
return this.client.request("GET", "/v1/subscribers", {
|
|
2480
|
+
params
|
|
2481
|
+
});
|
|
2482
|
+
}
|
|
2447
2483
|
async create(params) {
|
|
2448
2484
|
return this.client.request("POST", "/v1/subscribers", {
|
|
2449
2485
|
body: params
|
|
@@ -2511,8 +2547,21 @@ class Tools {
|
|
|
2511
2547
|
async get(toolName) {
|
|
2512
2548
|
return this.client.request("GET", `/v2/tools/${encodeURIComponent(toolName)}`);
|
|
2513
2549
|
}
|
|
2514
|
-
async run(toolName, params) {
|
|
2515
|
-
|
|
2550
|
+
async run(toolName, params, options) {
|
|
2551
|
+
const { autoConfirm = true } = options ?? {};
|
|
2552
|
+
const endpoint = `/v2/tools/${encodeURIComponent(toolName)}`;
|
|
2553
|
+
try {
|
|
2554
|
+
return await this.client.request("POST", endpoint, {
|
|
2555
|
+
body: params ?? {}
|
|
2556
|
+
});
|
|
2557
|
+
} catch (error) {
|
|
2558
|
+
if (autoConfirm && error instanceof LumailConfirmationRequiredError) {
|
|
2559
|
+
return this.client.request("POST", endpoint, {
|
|
2560
|
+
body: { ...params, confirmationCode: error.confirmationCode }
|
|
2561
|
+
});
|
|
2562
|
+
}
|
|
2563
|
+
throw error;
|
|
2564
|
+
}
|
|
2516
2565
|
}
|
|
2517
2566
|
}
|
|
2518
2567
|
|
|
@@ -2664,7 +2713,7 @@ function fmtCell(v) {
|
|
|
2664
2713
|
return s;
|
|
2665
2714
|
}
|
|
2666
2715
|
function stripAnsi(s) {
|
|
2667
|
-
return s.replace(
|
|
2716
|
+
return s.replace(new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, "g"), "");
|
|
2668
2717
|
}
|
|
2669
2718
|
function printTable(rows) {
|
|
2670
2719
|
const cols = Object.keys(rows[0] ?? {});
|
|
@@ -2753,6 +2802,26 @@ API key is valid.`));
|
|
|
2753
2802
|
|
|
2754
2803
|
// ../../src/cli/commands/subscribers.ts
|
|
2755
2804
|
var subscribersCommand = new Command("subscribers").description("Manage subscribers");
|
|
2805
|
+
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) => {
|
|
2806
|
+
try {
|
|
2807
|
+
const limit = Number(opts.limit);
|
|
2808
|
+
if (!Number.isFinite(limit) || limit < 1) {
|
|
2809
|
+
console.error("Error: --limit must be a positive integer");
|
|
2810
|
+
process.exit(1);
|
|
2811
|
+
}
|
|
2812
|
+
const lumail = getLumail();
|
|
2813
|
+
const result = await lumail.subscribers.list({
|
|
2814
|
+
tag: opts.tag,
|
|
2815
|
+
status: opts.status,
|
|
2816
|
+
limit,
|
|
2817
|
+
cursor: opts.cursor,
|
|
2818
|
+
query: opts.query
|
|
2819
|
+
});
|
|
2820
|
+
output(result);
|
|
2821
|
+
} catch (error) {
|
|
2822
|
+
handleError(error);
|
|
2823
|
+
}
|
|
2824
|
+
});
|
|
2756
2825
|
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
2826
|
try {
|
|
2758
2827
|
const lumail = getLumail();
|
|
@@ -3041,7 +3110,7 @@ import { homedir as homedir2 } from "os";
|
|
|
3041
3110
|
import { join as join2 } from "path";
|
|
3042
3111
|
var SKILL_URL = "https://raw.githubusercontent.com/Melvynx/lumail-opensource/main/skills/lumail/SKILL.md";
|
|
3043
3112
|
var SKILLS_DIR = join2(homedir2(), ".claude", "skills", "lumail");
|
|
3044
|
-
function prompt(question) {
|
|
3113
|
+
async function prompt(question) {
|
|
3045
3114
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
3046
3115
|
return new Promise((resolve) => {
|
|
3047
3116
|
rl.question(question, (answer) => {
|
|
@@ -3097,7 +3166,7 @@ Installing Lumail skill...`));
|
|
|
3097
3166
|
console.log(import_picocolors3.default.green("Skill installed to ~/.claude/skills/lumail/"));
|
|
3098
3167
|
} catch {
|
|
3099
3168
|
console.log(import_picocolors3.default.yellow("Could not download skill from GitHub."));
|
|
3100
|
-
console.log(import_picocolors3.default.dim(
|
|
3169
|
+
console.log(import_picocolors3.default.dim(`Manual install: curl -o ~/.claude/skills/lumail/SKILL.md --create-dirs ${SKILL_URL}`));
|
|
3101
3170
|
}
|
|
3102
3171
|
setToken(token);
|
|
3103
3172
|
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;
|
|
@@ -164,8 +188,7 @@ class LumailClient {
|
|
|
164
188
|
let body = {};
|
|
165
189
|
try {
|
|
166
190
|
body = await response.json();
|
|
167
|
-
} catch {
|
|
168
|
-
}
|
|
191
|
+
} catch {}
|
|
169
192
|
const message = body.message ?? body.error ?? response.statusText;
|
|
170
193
|
const code = body.code;
|
|
171
194
|
switch (response.status) {
|
|
@@ -173,6 +196,12 @@ class LumailClient {
|
|
|
173
196
|
return new LumailAuthenticationError(message);
|
|
174
197
|
case 402:
|
|
175
198
|
return new LumailPaymentRequiredError(message);
|
|
199
|
+
case 403: {
|
|
200
|
+
if (body.error === "CONFIRMATION_REQUIRED") {
|
|
201
|
+
return new LumailConfirmationRequiredError(message, body.confirmationCode, body.action, body.instruction);
|
|
202
|
+
}
|
|
203
|
+
return new LumailValidationError(message);
|
|
204
|
+
}
|
|
176
205
|
case 404:
|
|
177
206
|
return new LumailNotFoundError(message);
|
|
178
207
|
case 429: {
|
|
@@ -272,6 +301,11 @@ class Subscribers {
|
|
|
272
301
|
constructor(client) {
|
|
273
302
|
this.client = client;
|
|
274
303
|
}
|
|
304
|
+
async list(params) {
|
|
305
|
+
return this.client.request("GET", "/v1/subscribers", {
|
|
306
|
+
params
|
|
307
|
+
});
|
|
308
|
+
}
|
|
275
309
|
async create(params) {
|
|
276
310
|
return this.client.request("POST", "/v1/subscribers", {
|
|
277
311
|
body: params
|
|
@@ -339,8 +373,21 @@ class Tools {
|
|
|
339
373
|
async get(toolName) {
|
|
340
374
|
return this.client.request("GET", `/v2/tools/${encodeURIComponent(toolName)}`);
|
|
341
375
|
}
|
|
342
|
-
async run(toolName, params) {
|
|
343
|
-
|
|
376
|
+
async run(toolName, params, options) {
|
|
377
|
+
const { autoConfirm = true } = options ?? {};
|
|
378
|
+
const endpoint = `/v2/tools/${encodeURIComponent(toolName)}`;
|
|
379
|
+
try {
|
|
380
|
+
return await this.client.request("POST", endpoint, {
|
|
381
|
+
body: params ?? {}
|
|
382
|
+
});
|
|
383
|
+
} catch (error) {
|
|
384
|
+
if (autoConfirm && error instanceof LumailConfirmationRequiredError) {
|
|
385
|
+
return this.client.request("POST", endpoint, {
|
|
386
|
+
body: { ...params, confirmationCode: error.confirmationCode }
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
throw error;
|
|
390
|
+
}
|
|
344
391
|
}
|
|
345
392
|
}
|
|
346
393
|
|
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;
|
|
@@ -123,8 +136,7 @@ class LumailClient {
|
|
|
123
136
|
let body = {};
|
|
124
137
|
try {
|
|
125
138
|
body = await response.json();
|
|
126
|
-
} catch {
|
|
127
|
-
}
|
|
139
|
+
} catch {}
|
|
128
140
|
const message = body.message ?? body.error ?? response.statusText;
|
|
129
141
|
const code = body.code;
|
|
130
142
|
switch (response.status) {
|
|
@@ -132,6 +144,12 @@ class LumailClient {
|
|
|
132
144
|
return new LumailAuthenticationError(message);
|
|
133
145
|
case 402:
|
|
134
146
|
return new LumailPaymentRequiredError(message);
|
|
147
|
+
case 403: {
|
|
148
|
+
if (body.error === "CONFIRMATION_REQUIRED") {
|
|
149
|
+
return new LumailConfirmationRequiredError(message, body.confirmationCode, body.action, body.instruction);
|
|
150
|
+
}
|
|
151
|
+
return new LumailValidationError(message);
|
|
152
|
+
}
|
|
135
153
|
case 404:
|
|
136
154
|
return new LumailNotFoundError(message);
|
|
137
155
|
case 429: {
|
|
@@ -231,6 +249,11 @@ class Subscribers {
|
|
|
231
249
|
constructor(client) {
|
|
232
250
|
this.client = client;
|
|
233
251
|
}
|
|
252
|
+
async list(params) {
|
|
253
|
+
return this.client.request("GET", "/v1/subscribers", {
|
|
254
|
+
params
|
|
255
|
+
});
|
|
256
|
+
}
|
|
234
257
|
async create(params) {
|
|
235
258
|
return this.client.request("POST", "/v1/subscribers", {
|
|
236
259
|
body: params
|
|
@@ -298,8 +321,21 @@ class Tools {
|
|
|
298
321
|
async get(toolName) {
|
|
299
322
|
return this.client.request("GET", `/v2/tools/${encodeURIComponent(toolName)}`);
|
|
300
323
|
}
|
|
301
|
-
async run(toolName, params) {
|
|
302
|
-
|
|
324
|
+
async run(toolName, params, options) {
|
|
325
|
+
const { autoConfirm = true } = options ?? {};
|
|
326
|
+
const endpoint = `/v2/tools/${encodeURIComponent(toolName)}`;
|
|
327
|
+
try {
|
|
328
|
+
return await this.client.request("POST", endpoint, {
|
|
329
|
+
body: params ?? {}
|
|
330
|
+
});
|
|
331
|
+
} catch (error) {
|
|
332
|
+
if (autoConfirm && error instanceof LumailConfirmationRequiredError) {
|
|
333
|
+
return this.client.request("POST", endpoint, {
|
|
334
|
+
body: { ...params, confirmationCode: error.confirmationCode }
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
throw error;
|
|
338
|
+
}
|
|
303
339
|
}
|
|
304
340
|
}
|
|
305
341
|
|
|
@@ -327,6 +363,7 @@ export {
|
|
|
327
363
|
LumailPaymentRequiredError,
|
|
328
364
|
LumailNotFoundError,
|
|
329
365
|
LumailError,
|
|
366
|
+
LumailConfirmationRequiredError,
|
|
330
367
|
LumailAuthenticationError,
|
|
331
368
|
Lumail
|
|
332
369
|
};
|
|
@@ -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,323 @@
|
|
|
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
|
+
isValid: boolean;
|
|
249
|
+
};
|
|
250
|
+
export type Tag = {
|
|
251
|
+
id: string;
|
|
252
|
+
name: string;
|
|
253
|
+
};
|
|
254
|
+
export type TagWithCount = Tag & {
|
|
255
|
+
subscribersCount: number;
|
|
256
|
+
};
|
|
257
|
+
export type ListTagsResponse = {
|
|
258
|
+
success: true;
|
|
259
|
+
tags: Tag[];
|
|
260
|
+
};
|
|
261
|
+
export type CreateTagParams = {
|
|
262
|
+
name: string;
|
|
263
|
+
};
|
|
264
|
+
export type CreateTagResponse = {
|
|
265
|
+
success: true;
|
|
266
|
+
tag: Tag;
|
|
267
|
+
};
|
|
268
|
+
export type GetTagResponse = {
|
|
269
|
+
tag: TagWithCount;
|
|
270
|
+
};
|
|
271
|
+
export type UpdateTagParams = {
|
|
272
|
+
name: string;
|
|
273
|
+
};
|
|
274
|
+
export type UpdateTagResponse = {
|
|
275
|
+
success: true;
|
|
276
|
+
tag: Tag;
|
|
277
|
+
};
|
|
278
|
+
export type CreateEventParams = {
|
|
279
|
+
eventType: SubscriberEventType;
|
|
280
|
+
subscriber: string;
|
|
281
|
+
data: Record<string, unknown>;
|
|
282
|
+
};
|
|
283
|
+
export type CreateEventResponse = {
|
|
284
|
+
success: true;
|
|
285
|
+
event: {
|
|
286
|
+
id: string;
|
|
287
|
+
eventType: SubscriberEventType;
|
|
288
|
+
data: Record<string, unknown>;
|
|
289
|
+
subscriberId: string;
|
|
290
|
+
organizationId: string;
|
|
291
|
+
createdAt: string;
|
|
292
|
+
};
|
|
293
|
+
};
|
|
294
|
+
export type ToolDefinition = {
|
|
295
|
+
name: string;
|
|
296
|
+
description: string;
|
|
297
|
+
category?: string;
|
|
298
|
+
inputSchema?: Record<string, unknown>;
|
|
299
|
+
outputSchema?: Record<string, unknown>;
|
|
300
|
+
};
|
|
301
|
+
export type ListToolsResponse = {
|
|
302
|
+
success: true;
|
|
303
|
+
total: number;
|
|
304
|
+
tools: ToolDefinition[];
|
|
305
|
+
grouped: Record<string, ToolDefinition[]>;
|
|
306
|
+
docs: string;
|
|
307
|
+
};
|
|
308
|
+
export type GetToolResponse = {
|
|
309
|
+
success: true;
|
|
310
|
+
tool: ToolDefinition;
|
|
311
|
+
};
|
|
312
|
+
export type RunToolResponse<T = unknown> = {
|
|
313
|
+
success: true;
|
|
314
|
+
data: T;
|
|
315
|
+
};
|
|
316
|
+
export type ConfirmationRequiredResponse = {
|
|
317
|
+
success: false;
|
|
318
|
+
error: "CONFIRMATION_REQUIRED";
|
|
319
|
+
message: string;
|
|
320
|
+
action: string;
|
|
321
|
+
confirmationCode: number;
|
|
322
|
+
instruction: string;
|
|
323
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lumail",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
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
|
},
|