@lovable.dev/email-js 0.0.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 +53 -0
- package/dist/index.cjs +81 -0
- package/dist/index.d.cts +35 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +53 -0
- package/package.json +35 -0
package/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# @lovable.dev/email-js
|
|
2
|
+
|
|
3
|
+
Utilities for Lovable email hooks and delivery.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @lovable.dev/email-js
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { parseEmailWebhookPayload, sendLovableEmail } from "@lovable.dev/email-js";
|
|
15
|
+
import { verifyWebhookRequest, type EmailWebhookPayload } from "@lovable.dev/webhooks-js";
|
|
16
|
+
|
|
17
|
+
const apiKey = Deno.env.get("LOVABLE_API_KEY");
|
|
18
|
+
|
|
19
|
+
export async function handleWebhook(req: Request) {
|
|
20
|
+
if (!apiKey) {
|
|
21
|
+
throw new Error("Missing Lovable API key");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const { body } = await verifyWebhookRequest<EmailWebhookPayload>({
|
|
25
|
+
req,
|
|
26
|
+
secret: apiKey,
|
|
27
|
+
});
|
|
28
|
+
const payload = parseEmailWebhookPayload(body);
|
|
29
|
+
if (payload.version !== "1") {
|
|
30
|
+
throw new Error(`Unsupported payload version: ${payload.version}`);
|
|
31
|
+
}
|
|
32
|
+
if (!payload.run_id) {
|
|
33
|
+
throw new Error("Missing run_id");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const apiBaseUrl = payload.data?.api_base_url ?? "https://api.lovable.dev";
|
|
37
|
+
|
|
38
|
+
await sendLovableEmail(
|
|
39
|
+
{
|
|
40
|
+
run_id: payload.run_id,
|
|
41
|
+
to: payload.data?.email ?? "",
|
|
42
|
+
from: "My App <noreply@example.com>",
|
|
43
|
+
subject: "Welcome",
|
|
44
|
+
html: "<p>Hello</p>",
|
|
45
|
+
text: "Hello",
|
|
46
|
+
purpose: "transactional",
|
|
47
|
+
},
|
|
48
|
+
{ apiKey, apiBaseUrl },
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
You can also override the idempotency key (defaults to `run_id`).
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
parseEmailWebhookPayload: () => parseEmailWebhookPayload,
|
|
24
|
+
sendLovableEmail: () => sendLovableEmail
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(src_exports);
|
|
27
|
+
|
|
28
|
+
// src/email.ts
|
|
29
|
+
var DEFAULT_AUTH_HEADER = "Authorization";
|
|
30
|
+
var DEFAULT_API_BASE_URL = "https://api.lovable.dev";
|
|
31
|
+
var DEFAULT_SEND_PATH = "/v1/messaging/email/send";
|
|
32
|
+
function buildAuthHeaderValue(apiKey) {
|
|
33
|
+
return `Bearer ${apiKey}`;
|
|
34
|
+
}
|
|
35
|
+
async function sendLovableEmail(payload, options) {
|
|
36
|
+
const apiKey = options.apiKey;
|
|
37
|
+
if (!apiKey) {
|
|
38
|
+
throw new Error("Missing Lovable API key");
|
|
39
|
+
}
|
|
40
|
+
const authHeader = options.authHeader ?? DEFAULT_AUTH_HEADER;
|
|
41
|
+
const sendUrl = options.sendUrl;
|
|
42
|
+
const apiBaseUrl = options.apiBaseUrl ?? DEFAULT_API_BASE_URL;
|
|
43
|
+
const url = sendUrl || `${apiBaseUrl.replace(/\/$/, "")}${DEFAULT_SEND_PATH}`;
|
|
44
|
+
const idempotencyKey = options.idempotencyKey ?? payload.run_id;
|
|
45
|
+
const headers = {
|
|
46
|
+
[authHeader]: buildAuthHeaderValue(apiKey),
|
|
47
|
+
"Content-Type": "application/json"
|
|
48
|
+
};
|
|
49
|
+
if (idempotencyKey) {
|
|
50
|
+
headers["Idempotency-Key"] = idempotencyKey;
|
|
51
|
+
}
|
|
52
|
+
const response = await fetch(url, {
|
|
53
|
+
method: "POST",
|
|
54
|
+
headers,
|
|
55
|
+
body: JSON.stringify(payload)
|
|
56
|
+
});
|
|
57
|
+
if (!response.ok) {
|
|
58
|
+
const errorText = await response.text();
|
|
59
|
+
const safeErrorText = errorText.length > 500 ? `${errorText.slice(0, 500)}...` : errorText;
|
|
60
|
+
throw new Error(`Email API error: ${response.status} ${safeErrorText}`);
|
|
61
|
+
}
|
|
62
|
+
return await response.json();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// src/webhook.ts
|
|
66
|
+
function parseEmailWebhookPayload(body) {
|
|
67
|
+
const parsed = JSON.parse(body);
|
|
68
|
+
if (!parsed || typeof parsed !== "object") {
|
|
69
|
+
throw new Error("Invalid email webhook payload: missing version or type");
|
|
70
|
+
}
|
|
71
|
+
const payload = parsed;
|
|
72
|
+
if (typeof payload.version !== "string" || typeof payload.type !== "string") {
|
|
73
|
+
throw new Error("Invalid email webhook payload: missing version or type");
|
|
74
|
+
}
|
|
75
|
+
return payload;
|
|
76
|
+
}
|
|
77
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
78
|
+
0 && (module.exports = {
|
|
79
|
+
parseEmailWebhookPayload,
|
|
80
|
+
sendLovableEmail
|
|
81
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { EmailWebhookPayload } from '@lovable.dev/webhooks-js';
|
|
2
|
+
export { EmailWebhookPayload } from '@lovable.dev/webhooks-js';
|
|
3
|
+
|
|
4
|
+
interface EmailSendRequest {
|
|
5
|
+
run_id: string;
|
|
6
|
+
to: string;
|
|
7
|
+
from: string;
|
|
8
|
+
sender_domain?: string;
|
|
9
|
+
subject: string;
|
|
10
|
+
html: string;
|
|
11
|
+
text: string;
|
|
12
|
+
purpose?: string;
|
|
13
|
+
reply_to?: string;
|
|
14
|
+
identity_id?: string;
|
|
15
|
+
test_mode?: boolean;
|
|
16
|
+
}
|
|
17
|
+
interface EmailSendResponse {
|
|
18
|
+
success: boolean;
|
|
19
|
+
message_id?: string;
|
|
20
|
+
workflow_id?: string;
|
|
21
|
+
status?: string;
|
|
22
|
+
}
|
|
23
|
+
interface SendEmailOptions {
|
|
24
|
+
apiKey: string;
|
|
25
|
+
authHeader?: string;
|
|
26
|
+
apiBaseUrl?: string;
|
|
27
|
+
sendUrl?: string;
|
|
28
|
+
idempotencyKey?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
declare function sendLovableEmail(payload: EmailSendRequest, options: SendEmailOptions): Promise<EmailSendResponse>;
|
|
32
|
+
|
|
33
|
+
declare function parseEmailWebhookPayload(body: string): EmailWebhookPayload;
|
|
34
|
+
|
|
35
|
+
export { EmailSendRequest, EmailSendResponse, SendEmailOptions, parseEmailWebhookPayload, sendLovableEmail };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { EmailWebhookPayload } from '@lovable.dev/webhooks-js';
|
|
2
|
+
export { EmailWebhookPayload } from '@lovable.dev/webhooks-js';
|
|
3
|
+
|
|
4
|
+
interface EmailSendRequest {
|
|
5
|
+
run_id: string;
|
|
6
|
+
to: string;
|
|
7
|
+
from: string;
|
|
8
|
+
sender_domain?: string;
|
|
9
|
+
subject: string;
|
|
10
|
+
html: string;
|
|
11
|
+
text: string;
|
|
12
|
+
purpose?: string;
|
|
13
|
+
reply_to?: string;
|
|
14
|
+
identity_id?: string;
|
|
15
|
+
test_mode?: boolean;
|
|
16
|
+
}
|
|
17
|
+
interface EmailSendResponse {
|
|
18
|
+
success: boolean;
|
|
19
|
+
message_id?: string;
|
|
20
|
+
workflow_id?: string;
|
|
21
|
+
status?: string;
|
|
22
|
+
}
|
|
23
|
+
interface SendEmailOptions {
|
|
24
|
+
apiKey: string;
|
|
25
|
+
authHeader?: string;
|
|
26
|
+
apiBaseUrl?: string;
|
|
27
|
+
sendUrl?: string;
|
|
28
|
+
idempotencyKey?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
declare function sendLovableEmail(payload: EmailSendRequest, options: SendEmailOptions): Promise<EmailSendResponse>;
|
|
32
|
+
|
|
33
|
+
declare function parseEmailWebhookPayload(body: string): EmailWebhookPayload;
|
|
34
|
+
|
|
35
|
+
export { EmailSendRequest, EmailSendResponse, SendEmailOptions, parseEmailWebhookPayload, sendLovableEmail };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// src/email.ts
|
|
2
|
+
var DEFAULT_AUTH_HEADER = "Authorization";
|
|
3
|
+
var DEFAULT_API_BASE_URL = "https://api.lovable.dev";
|
|
4
|
+
var DEFAULT_SEND_PATH = "/v1/messaging/email/send";
|
|
5
|
+
function buildAuthHeaderValue(apiKey) {
|
|
6
|
+
return `Bearer ${apiKey}`;
|
|
7
|
+
}
|
|
8
|
+
async function sendLovableEmail(payload, options) {
|
|
9
|
+
const apiKey = options.apiKey;
|
|
10
|
+
if (!apiKey) {
|
|
11
|
+
throw new Error("Missing Lovable API key");
|
|
12
|
+
}
|
|
13
|
+
const authHeader = options.authHeader ?? DEFAULT_AUTH_HEADER;
|
|
14
|
+
const sendUrl = options.sendUrl;
|
|
15
|
+
const apiBaseUrl = options.apiBaseUrl ?? DEFAULT_API_BASE_URL;
|
|
16
|
+
const url = sendUrl || `${apiBaseUrl.replace(/\/$/, "")}${DEFAULT_SEND_PATH}`;
|
|
17
|
+
const idempotencyKey = options.idempotencyKey ?? payload.run_id;
|
|
18
|
+
const headers = {
|
|
19
|
+
[authHeader]: buildAuthHeaderValue(apiKey),
|
|
20
|
+
"Content-Type": "application/json"
|
|
21
|
+
};
|
|
22
|
+
if (idempotencyKey) {
|
|
23
|
+
headers["Idempotency-Key"] = idempotencyKey;
|
|
24
|
+
}
|
|
25
|
+
const response = await fetch(url, {
|
|
26
|
+
method: "POST",
|
|
27
|
+
headers,
|
|
28
|
+
body: JSON.stringify(payload)
|
|
29
|
+
});
|
|
30
|
+
if (!response.ok) {
|
|
31
|
+
const errorText = await response.text();
|
|
32
|
+
const safeErrorText = errorText.length > 500 ? `${errorText.slice(0, 500)}...` : errorText;
|
|
33
|
+
throw new Error(`Email API error: ${response.status} ${safeErrorText}`);
|
|
34
|
+
}
|
|
35
|
+
return await response.json();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// src/webhook.ts
|
|
39
|
+
function parseEmailWebhookPayload(body) {
|
|
40
|
+
const parsed = JSON.parse(body);
|
|
41
|
+
if (!parsed || typeof parsed !== "object") {
|
|
42
|
+
throw new Error("Invalid email webhook payload: missing version or type");
|
|
43
|
+
}
|
|
44
|
+
const payload = parsed;
|
|
45
|
+
if (typeof payload.version !== "string" || typeof payload.type !== "string") {
|
|
46
|
+
throw new Error("Invalid email webhook payload: missing version or type");
|
|
47
|
+
}
|
|
48
|
+
return payload;
|
|
49
|
+
}
|
|
50
|
+
export {
|
|
51
|
+
parseEmailWebhookPayload,
|
|
52
|
+
sendLovableEmail
|
|
53
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lovable.dev/email-js",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Lovable Email JS",
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"keywords": [
|
|
13
|
+
"lovable",
|
|
14
|
+
"email",
|
|
15
|
+
"webhook"
|
|
16
|
+
],
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@lovable.dev/webhooks-js": "^0.0.1"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/node": "^22",
|
|
23
|
+
"rimraf": "^5.0.0",
|
|
24
|
+
"tsup": "^7.2.0",
|
|
25
|
+
"typescript": "^5",
|
|
26
|
+
"vitest": "^3"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --outDir dist",
|
|
30
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
31
|
+
"test": "vitest run",
|
|
32
|
+
"typecheck": "tsc --noEmit",
|
|
33
|
+
"clean": "rimraf dist"
|
|
34
|
+
}
|
|
35
|
+
}
|