@wrelik/email 0.1.2 → 2.0.0
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/.turbo/turbo-build.log +18 -14
- package/CHANGELOG.md +24 -0
- package/dist/client/index.d.mts +3 -0
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.js +34 -0
- package/dist/client/index.mjs +9 -0
- package/dist/server/index.d.mts +54 -0
- package/dist/server/index.d.ts +54 -0
- package/dist/server/index.js +99 -0
- package/dist/server/index.mjs +70 -0
- package/dist/shared/index.d.mts +18 -0
- package/dist/shared/index.d.ts +18 -0
- package/dist/shared/index.js +18 -0
- package/dist/shared/index.mjs +0 -0
- package/package.json +30 -6
- package/src/client/index.test.ts +7 -0
- package/src/client/index.ts +5 -0
- package/src/server/index.test.ts +116 -0
- package/src/server/index.ts +118 -0
- package/src/shared/index.ts +1 -0
- package/src/shared/types.ts +10 -0
- package/dist/index.d.mts +0 -24
- package/dist/index.d.ts +0 -24
- package/dist/index.js +0 -80
- package/dist/index.mjs +0 -52
- package/dist/unsupported.d.mts +0 -2
- package/dist/unsupported.d.ts +0 -2
- package/dist/unsupported.js +0 -6
- package/dist/unsupported.mjs +0 -4
- package/src/index.ts +0 -73
- package/src/unsupported.ts +0 -4
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
|
|
2
|
-
> @wrelik/email@0.
|
|
3
|
-
> tsup src/index.ts src/
|
|
2
|
+
> @wrelik/email@2.0.0 build /home/runner/work/wrelik-kit/wrelik-kit/packages/email
|
|
3
|
+
> tsup src/server/index.ts src/client/index.ts src/shared/index.ts --format cjs,esm --dts --clean
|
|
4
4
|
|
|
5
|
-
[34mCLI[39m Building entry: src/index.ts, src/
|
|
5
|
+
[34mCLI[39m Building entry: src/client/index.ts, src/server/index.ts, src/shared/index.ts
|
|
6
6
|
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
7
7
|
[34mCLI[39m tsup v8.5.1
|
|
8
8
|
[34mCLI[39m Target: es2022
|
|
9
9
|
[34mCLI[39m Cleaning output folder
|
|
10
10
|
[34mCJS[39m Build start
|
|
11
11
|
[34mESM[39m Build start
|
|
12
|
-
[
|
|
13
|
-
[
|
|
14
|
-
[
|
|
15
|
-
[32mESM[39m
|
|
16
|
-
[
|
|
17
|
-
[
|
|
12
|
+
[32mESM[39m [1mdist/client/index.mjs [22m[32m274.00 B[39m
|
|
13
|
+
[32mESM[39m [1mdist/shared/index.mjs [22m[32m0 B[39m
|
|
14
|
+
[32mESM[39m [1mdist/server/index.mjs [22m[32m1.87 KB[39m
|
|
15
|
+
[32mESM[39m ⚡️ Build success in 77ms
|
|
16
|
+
[32mCJS[39m [1mdist/client/index.js [22m[32m1.28 KB[39m
|
|
17
|
+
[32mCJS[39m [1mdist/server/index.js [22m[32m3.03 KB[39m
|
|
18
|
+
[32mCJS[39m [1mdist/shared/index.js [22m[32m767.00 B[39m
|
|
19
|
+
[32mCJS[39m ⚡️ Build success in 79ms
|
|
18
20
|
[34mDTS[39m Build start
|
|
19
|
-
[32mDTS[39m ⚡️ Build success in
|
|
20
|
-
[32mDTS[39m [1mdist/
|
|
21
|
-
[32mDTS[39m [1mdist/index.d.ts
|
|
22
|
-
[32mDTS[39m [1mdist/
|
|
23
|
-
[32mDTS[39m [1mdist/index.d.mts
|
|
21
|
+
[32mDTS[39m ⚡️ Build success in 2585ms
|
|
22
|
+
[32mDTS[39m [1mdist/client/index.d.ts [22m[32m77.00 B[39m
|
|
23
|
+
[32mDTS[39m [1mdist/server/index.d.ts [22m[32m1.99 KB[39m
|
|
24
|
+
[32mDTS[39m [1mdist/shared/index.d.ts [22m[32m364.00 B[39m
|
|
25
|
+
[32mDTS[39m [1mdist/client/index.d.mts [22m[32m77.00 B[39m
|
|
26
|
+
[32mDTS[39m [1mdist/server/index.d.mts [22m[32m1.99 KB[39m
|
|
27
|
+
[32mDTS[39m [1mdist/shared/index.d.mts [22m[32m364.00 B[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @wrelik/email
|
|
2
2
|
|
|
3
|
+
## 2.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- 818ed58: Refactor runtime packages to strict subpath exports (`/server`, `/client`, `/shared`) with side-effect free entrypoints and hard CI/runtime boundary enforcement.
|
|
8
|
+
|
|
9
|
+
### Minor Changes
|
|
10
|
+
|
|
11
|
+
- Add platform wrapper packages for Clerk (Next/Expo), Next Sentry client instrumentation, and Upstash server SDK access so apps can avoid direct vendor imports while staying inside the `@wrelik/*` boundary.
|
|
12
|
+
|
|
13
|
+
Add temporary deprecated server-side compatibility singleton exports to analytics, email, jobs, and storage to support DRX migration from root-import convenience APIs to runtime subpaths in one cutover.
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- Updated dependencies [818ed58]
|
|
18
|
+
- @wrelik/errors@2.0.0
|
|
19
|
+
|
|
20
|
+
## 0.1.3
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- Updated dependencies [2b9cbf7]
|
|
25
|
+
- @wrelik/errors@0.2.1
|
|
26
|
+
|
|
3
27
|
## 0.1.2
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
|
@@ -0,0 +1,34 @@
|
|
|
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/client/index.ts
|
|
21
|
+
var client_exports = {};
|
|
22
|
+
__export(client_exports, {
|
|
23
|
+
serverOnlyClientStub: () => serverOnlyClientStub
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(client_exports);
|
|
26
|
+
var serverOnlyClientStub = (() => {
|
|
27
|
+
throw new Error(
|
|
28
|
+
"@wrelik/email/client is a server-only adapter stub. Use @wrelik/email/server on the backend and call your backend API from client or Expo apps."
|
|
29
|
+
);
|
|
30
|
+
})();
|
|
31
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
32
|
+
0 && (module.exports = {
|
|
33
|
+
serverOnlyClientStub
|
|
34
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// src/client/index.ts
|
|
2
|
+
var serverOnlyClientStub = (() => {
|
|
3
|
+
throw new Error(
|
|
4
|
+
"@wrelik/email/client is a server-only adapter stub. Use @wrelik/email/server on the backend and call your backend API from client or Expo apps."
|
|
5
|
+
);
|
|
6
|
+
})();
|
|
7
|
+
export {
|
|
8
|
+
serverOnlyClientStub
|
|
9
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { SendEmailOptions, TemplateRenderer } from '../shared/index.mjs';
|
|
2
|
+
|
|
3
|
+
interface EmailTransport {
|
|
4
|
+
emails: {
|
|
5
|
+
send: (input: {
|
|
6
|
+
from: string;
|
|
7
|
+
to: string | string[];
|
|
8
|
+
subject: string;
|
|
9
|
+
html?: string;
|
|
10
|
+
text?: string;
|
|
11
|
+
tags?: Array<{
|
|
12
|
+
name: string;
|
|
13
|
+
value: string;
|
|
14
|
+
}>;
|
|
15
|
+
react: null;
|
|
16
|
+
}) => Promise<{
|
|
17
|
+
data: unknown;
|
|
18
|
+
error: {
|
|
19
|
+
message: string;
|
|
20
|
+
} | null;
|
|
21
|
+
}>;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
declare function createEmailServer(config: {
|
|
25
|
+
apiKey: string;
|
|
26
|
+
defaultFromAddress: string;
|
|
27
|
+
}, options?: {
|
|
28
|
+
transport?: EmailTransport;
|
|
29
|
+
}): {
|
|
30
|
+
sendEmail: ({ to, subject, html, text, from, tags }: SendEmailOptions) => Promise<unknown>;
|
|
31
|
+
defineTemplate<T>(id: string, renderer: TemplateRenderer<T>): void;
|
|
32
|
+
sendTemplate<T>(id: string, to: string | string[], data: T, options?: Partial<SendEmailOptions>): Promise<unknown>;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* @deprecated Temporary DRX compatibility singleton. Prefer createEmailServer(...) and explicit dependency wiring.
|
|
36
|
+
*/
|
|
37
|
+
declare function initEmail(config: {
|
|
38
|
+
apiKey: string;
|
|
39
|
+
defaultFromAddress: string;
|
|
40
|
+
}, options?: Parameters<typeof createEmailServer>[1]): void;
|
|
41
|
+
/**
|
|
42
|
+
* @deprecated Temporary DRX compatibility singleton. Prefer createEmailServer(...).defineTemplate(...)
|
|
43
|
+
*/
|
|
44
|
+
declare function defineTemplate<T>(id: string, renderer: TemplateRenderer<T>): void;
|
|
45
|
+
/**
|
|
46
|
+
* @deprecated Temporary DRX compatibility singleton. Prefer createEmailServer(...).sendEmail(...)
|
|
47
|
+
*/
|
|
48
|
+
declare function sendEmail(input: SendEmailOptions): Promise<unknown>;
|
|
49
|
+
/**
|
|
50
|
+
* @deprecated Temporary DRX compatibility singleton. Prefer createEmailServer(...).sendTemplate(...)
|
|
51
|
+
*/
|
|
52
|
+
declare function sendTemplate<T>(id: string, to: string | string[], data: T, options?: Partial<SendEmailOptions>): Promise<unknown>;
|
|
53
|
+
|
|
54
|
+
export { type EmailTransport, SendEmailOptions, TemplateRenderer, createEmailServer, defineTemplate, initEmail, sendEmail, sendTemplate };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { SendEmailOptions, TemplateRenderer } from '../shared/index.js';
|
|
2
|
+
|
|
3
|
+
interface EmailTransport {
|
|
4
|
+
emails: {
|
|
5
|
+
send: (input: {
|
|
6
|
+
from: string;
|
|
7
|
+
to: string | string[];
|
|
8
|
+
subject: string;
|
|
9
|
+
html?: string;
|
|
10
|
+
text?: string;
|
|
11
|
+
tags?: Array<{
|
|
12
|
+
name: string;
|
|
13
|
+
value: string;
|
|
14
|
+
}>;
|
|
15
|
+
react: null;
|
|
16
|
+
}) => Promise<{
|
|
17
|
+
data: unknown;
|
|
18
|
+
error: {
|
|
19
|
+
message: string;
|
|
20
|
+
} | null;
|
|
21
|
+
}>;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
declare function createEmailServer(config: {
|
|
25
|
+
apiKey: string;
|
|
26
|
+
defaultFromAddress: string;
|
|
27
|
+
}, options?: {
|
|
28
|
+
transport?: EmailTransport;
|
|
29
|
+
}): {
|
|
30
|
+
sendEmail: ({ to, subject, html, text, from, tags }: SendEmailOptions) => Promise<unknown>;
|
|
31
|
+
defineTemplate<T>(id: string, renderer: TemplateRenderer<T>): void;
|
|
32
|
+
sendTemplate<T>(id: string, to: string | string[], data: T, options?: Partial<SendEmailOptions>): Promise<unknown>;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* @deprecated Temporary DRX compatibility singleton. Prefer createEmailServer(...) and explicit dependency wiring.
|
|
36
|
+
*/
|
|
37
|
+
declare function initEmail(config: {
|
|
38
|
+
apiKey: string;
|
|
39
|
+
defaultFromAddress: string;
|
|
40
|
+
}, options?: Parameters<typeof createEmailServer>[1]): void;
|
|
41
|
+
/**
|
|
42
|
+
* @deprecated Temporary DRX compatibility singleton. Prefer createEmailServer(...).defineTemplate(...)
|
|
43
|
+
*/
|
|
44
|
+
declare function defineTemplate<T>(id: string, renderer: TemplateRenderer<T>): void;
|
|
45
|
+
/**
|
|
46
|
+
* @deprecated Temporary DRX compatibility singleton. Prefer createEmailServer(...).sendEmail(...)
|
|
47
|
+
*/
|
|
48
|
+
declare function sendEmail(input: SendEmailOptions): Promise<unknown>;
|
|
49
|
+
/**
|
|
50
|
+
* @deprecated Temporary DRX compatibility singleton. Prefer createEmailServer(...).sendTemplate(...)
|
|
51
|
+
*/
|
|
52
|
+
declare function sendTemplate<T>(id: string, to: string | string[], data: T, options?: Partial<SendEmailOptions>): Promise<unknown>;
|
|
53
|
+
|
|
54
|
+
export { type EmailTransport, SendEmailOptions, TemplateRenderer, createEmailServer, defineTemplate, initEmail, sendEmail, sendTemplate };
|
|
@@ -0,0 +1,99 @@
|
|
|
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/server/index.ts
|
|
21
|
+
var server_exports = {};
|
|
22
|
+
__export(server_exports, {
|
|
23
|
+
createEmailServer: () => createEmailServer,
|
|
24
|
+
defineTemplate: () => defineTemplate,
|
|
25
|
+
initEmail: () => initEmail,
|
|
26
|
+
sendEmail: () => sendEmail,
|
|
27
|
+
sendTemplate: () => sendTemplate
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(server_exports);
|
|
30
|
+
var import_resend = require("resend");
|
|
31
|
+
var import_shared = require("@wrelik/errors/shared");
|
|
32
|
+
function createEmailServer(config, options) {
|
|
33
|
+
const client = options?.transport ?? new import_resend.Resend(config.apiKey);
|
|
34
|
+
const templates = /* @__PURE__ */ new Map();
|
|
35
|
+
const sendEmail2 = async ({ to, subject, html, text, from, tags }) => {
|
|
36
|
+
const result = await client.emails.send({
|
|
37
|
+
from: from ?? config.defaultFromAddress,
|
|
38
|
+
to,
|
|
39
|
+
subject,
|
|
40
|
+
html,
|
|
41
|
+
text,
|
|
42
|
+
tags,
|
|
43
|
+
react: null
|
|
44
|
+
});
|
|
45
|
+
if (result.error) {
|
|
46
|
+
throw new Error(`Failed to send email: ${result.error.message}`);
|
|
47
|
+
}
|
|
48
|
+
return result.data;
|
|
49
|
+
};
|
|
50
|
+
return {
|
|
51
|
+
sendEmail: sendEmail2,
|
|
52
|
+
defineTemplate(id, renderer) {
|
|
53
|
+
templates.set(id, renderer);
|
|
54
|
+
},
|
|
55
|
+
async sendTemplate(id, to, data, options2) {
|
|
56
|
+
const renderer = templates.get(id);
|
|
57
|
+
if (!renderer) {
|
|
58
|
+
throw new import_shared.ValidationError(`Template ${id} not found`);
|
|
59
|
+
}
|
|
60
|
+
const { subject, html, text } = renderer(data);
|
|
61
|
+
return sendEmail2({
|
|
62
|
+
to,
|
|
63
|
+
subject,
|
|
64
|
+
html,
|
|
65
|
+
text,
|
|
66
|
+
...options2
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
var emailSingleton = null;
|
|
72
|
+
function requireEmailSingleton() {
|
|
73
|
+
if (!emailSingleton) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
"@wrelik/email/server compatibility API is not initialized. Call initEmail({ apiKey, defaultFromAddress }) before sendEmail/sendTemplate."
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
return emailSingleton;
|
|
79
|
+
}
|
|
80
|
+
function initEmail(config, options) {
|
|
81
|
+
emailSingleton = createEmailServer(config, options);
|
|
82
|
+
}
|
|
83
|
+
function defineTemplate(id, renderer) {
|
|
84
|
+
requireEmailSingleton().defineTemplate(id, renderer);
|
|
85
|
+
}
|
|
86
|
+
function sendEmail(input) {
|
|
87
|
+
return requireEmailSingleton().sendEmail(input);
|
|
88
|
+
}
|
|
89
|
+
function sendTemplate(id, to, data, options) {
|
|
90
|
+
return requireEmailSingleton().sendTemplate(id, to, data, options);
|
|
91
|
+
}
|
|
92
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
93
|
+
0 && (module.exports = {
|
|
94
|
+
createEmailServer,
|
|
95
|
+
defineTemplate,
|
|
96
|
+
initEmail,
|
|
97
|
+
sendEmail,
|
|
98
|
+
sendTemplate
|
|
99
|
+
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// src/server/index.ts
|
|
2
|
+
import { Resend } from "resend";
|
|
3
|
+
import { ValidationError } from "@wrelik/errors/shared";
|
|
4
|
+
function createEmailServer(config, options) {
|
|
5
|
+
const client = options?.transport ?? new Resend(config.apiKey);
|
|
6
|
+
const templates = /* @__PURE__ */ new Map();
|
|
7
|
+
const sendEmail2 = async ({ to, subject, html, text, from, tags }) => {
|
|
8
|
+
const result = await client.emails.send({
|
|
9
|
+
from: from ?? config.defaultFromAddress,
|
|
10
|
+
to,
|
|
11
|
+
subject,
|
|
12
|
+
html,
|
|
13
|
+
text,
|
|
14
|
+
tags,
|
|
15
|
+
react: null
|
|
16
|
+
});
|
|
17
|
+
if (result.error) {
|
|
18
|
+
throw new Error(`Failed to send email: ${result.error.message}`);
|
|
19
|
+
}
|
|
20
|
+
return result.data;
|
|
21
|
+
};
|
|
22
|
+
return {
|
|
23
|
+
sendEmail: sendEmail2,
|
|
24
|
+
defineTemplate(id, renderer) {
|
|
25
|
+
templates.set(id, renderer);
|
|
26
|
+
},
|
|
27
|
+
async sendTemplate(id, to, data, options2) {
|
|
28
|
+
const renderer = templates.get(id);
|
|
29
|
+
if (!renderer) {
|
|
30
|
+
throw new ValidationError(`Template ${id} not found`);
|
|
31
|
+
}
|
|
32
|
+
const { subject, html, text } = renderer(data);
|
|
33
|
+
return sendEmail2({
|
|
34
|
+
to,
|
|
35
|
+
subject,
|
|
36
|
+
html,
|
|
37
|
+
text,
|
|
38
|
+
...options2
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
var emailSingleton = null;
|
|
44
|
+
function requireEmailSingleton() {
|
|
45
|
+
if (!emailSingleton) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
"@wrelik/email/server compatibility API is not initialized. Call initEmail({ apiKey, defaultFromAddress }) before sendEmail/sendTemplate."
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
return emailSingleton;
|
|
51
|
+
}
|
|
52
|
+
function initEmail(config, options) {
|
|
53
|
+
emailSingleton = createEmailServer(config, options);
|
|
54
|
+
}
|
|
55
|
+
function defineTemplate(id, renderer) {
|
|
56
|
+
requireEmailSingleton().defineTemplate(id, renderer);
|
|
57
|
+
}
|
|
58
|
+
function sendEmail(input) {
|
|
59
|
+
return requireEmailSingleton().sendEmail(input);
|
|
60
|
+
}
|
|
61
|
+
function sendTemplate(id, to, data, options) {
|
|
62
|
+
return requireEmailSingleton().sendTemplate(id, to, data, options);
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
createEmailServer,
|
|
66
|
+
defineTemplate,
|
|
67
|
+
initEmail,
|
|
68
|
+
sendEmail,
|
|
69
|
+
sendTemplate
|
|
70
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface SendEmailOptions {
|
|
2
|
+
to: string | string[];
|
|
3
|
+
subject: string;
|
|
4
|
+
html?: string;
|
|
5
|
+
text?: string;
|
|
6
|
+
from?: string;
|
|
7
|
+
tags?: Array<{
|
|
8
|
+
name: string;
|
|
9
|
+
value: string;
|
|
10
|
+
}>;
|
|
11
|
+
}
|
|
12
|
+
type TemplateRenderer<T> = (data: T) => {
|
|
13
|
+
subject: string;
|
|
14
|
+
html: string;
|
|
15
|
+
text?: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type { SendEmailOptions, TemplateRenderer };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface SendEmailOptions {
|
|
2
|
+
to: string | string[];
|
|
3
|
+
subject: string;
|
|
4
|
+
html?: string;
|
|
5
|
+
text?: string;
|
|
6
|
+
from?: string;
|
|
7
|
+
tags?: Array<{
|
|
8
|
+
name: string;
|
|
9
|
+
value: string;
|
|
10
|
+
}>;
|
|
11
|
+
}
|
|
12
|
+
type TemplateRenderer<T> = (data: T) => {
|
|
13
|
+
subject: string;
|
|
14
|
+
html: string;
|
|
15
|
+
text?: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type { SendEmailOptions, TemplateRenderer };
|
|
@@ -0,0 +1,18 @@
|
|
|
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 __copyProps = (to, from, except, desc) => {
|
|
7
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
+
for (let key of __getOwnPropNames(from))
|
|
9
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
+
}
|
|
12
|
+
return to;
|
|
13
|
+
};
|
|
14
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
+
|
|
16
|
+
// src/shared/index.ts
|
|
17
|
+
var shared_exports = {};
|
|
18
|
+
module.exports = __toCommonJS(shared_exports);
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrelik/email",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -9,12 +9,28 @@
|
|
|
9
9
|
"url": "https://github.com/lwhite702/wrelik-kit.git",
|
|
10
10
|
"directory": "packages/email"
|
|
11
11
|
},
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
|
|
12
|
+
"sideEffects": false,
|
|
13
|
+
"exports": {
|
|
14
|
+
"./server": {
|
|
15
|
+
"types": "./dist/server/index.d.ts",
|
|
16
|
+
"import": "./dist/server/index.mjs",
|
|
17
|
+
"require": "./dist/server/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./client": {
|
|
20
|
+
"types": "./dist/client/index.d.ts",
|
|
21
|
+
"import": "./dist/client/index.mjs",
|
|
22
|
+
"require": "./dist/client/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./shared": {
|
|
25
|
+
"types": "./dist/shared/index.d.ts",
|
|
26
|
+
"import": "./dist/shared/index.mjs",
|
|
27
|
+
"require": "./dist/shared/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./package.json": "./package.json"
|
|
30
|
+
},
|
|
15
31
|
"dependencies": {
|
|
16
32
|
"resend": "^3.2.0",
|
|
17
|
-
"@wrelik/errors": "
|
|
33
|
+
"@wrelik/errors": "2.0.0"
|
|
18
34
|
},
|
|
19
35
|
"devDependencies": {
|
|
20
36
|
"tsup": "^8.0.1",
|
|
@@ -22,9 +38,17 @@
|
|
|
22
38
|
"@wrelik/eslint-config": "0.1.1",
|
|
23
39
|
"@wrelik/tsconfig": "0.1.1"
|
|
24
40
|
},
|
|
41
|
+
"wrelik": {
|
|
42
|
+
"runtimes": [
|
|
43
|
+
"server",
|
|
44
|
+
"client",
|
|
45
|
+
"shared"
|
|
46
|
+
]
|
|
47
|
+
},
|
|
25
48
|
"scripts": {
|
|
26
|
-
"build": "tsup src/index.ts src/
|
|
49
|
+
"build": "tsup src/server/index.ts src/client/index.ts src/shared/index.ts --format cjs,esm --dts --clean",
|
|
27
50
|
"lint": "eslint src/",
|
|
51
|
+
"typecheck": "tsc --noEmit",
|
|
28
52
|
"test": "vitest run --passWithNoTests"
|
|
29
53
|
}
|
|
30
54
|
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { ValidationError } from '@wrelik/errors/shared';
|
|
3
|
+
import { createEmailServer } from './index';
|
|
4
|
+
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
vi.resetModules();
|
|
7
|
+
vi.clearAllMocks();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
describe('@wrelik/email/server', () => {
|
|
11
|
+
it('registers templates and applies default sender in sendTemplate', async () => {
|
|
12
|
+
const send = vi.fn(async () => ({ data: { id: 'msg_1' }, error: null }));
|
|
13
|
+
const email = createEmailServer(
|
|
14
|
+
{ apiKey: 'rk_test', defaultFromAddress: 'hello@wrelik.com' },
|
|
15
|
+
{ transport: { emails: { send } } },
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
email.defineTemplate('welcome', (data: { name: string }) => ({
|
|
19
|
+
subject: `Welcome ${data.name}`,
|
|
20
|
+
html: `<p>${data.name}</p>`,
|
|
21
|
+
text: data.name,
|
|
22
|
+
}));
|
|
23
|
+
|
|
24
|
+
const result = await email.sendTemplate('welcome', 'lee@example.com', { name: 'Lee' });
|
|
25
|
+
|
|
26
|
+
expect(result).toEqual({ id: 'msg_1' });
|
|
27
|
+
expect(send).toHaveBeenCalledWith({
|
|
28
|
+
from: 'hello@wrelik.com',
|
|
29
|
+
to: 'lee@example.com',
|
|
30
|
+
subject: 'Welcome Lee',
|
|
31
|
+
html: '<p>Lee</p>',
|
|
32
|
+
text: 'Lee',
|
|
33
|
+
tags: undefined,
|
|
34
|
+
react: null,
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('throws a validation error when template is missing', async () => {
|
|
39
|
+
const email = createEmailServer(
|
|
40
|
+
{ apiKey: 'rk_test', defaultFromAddress: 'hello@wrelik.com' },
|
|
41
|
+
{ transport: { emails: { send: vi.fn() } } },
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
await expect(email.sendTemplate('missing', 'a@b.com', {})).rejects.toThrow(ValidationError);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('surfaces provider errors from sendEmail', async () => {
|
|
48
|
+
const email = createEmailServer(
|
|
49
|
+
{ apiKey: 'rk_test', defaultFromAddress: 'hello@wrelik.com' },
|
|
50
|
+
{
|
|
51
|
+
transport: {
|
|
52
|
+
emails: {
|
|
53
|
+
send: vi.fn(async () => ({ data: null, error: { message: 'provider down' } })),
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
await expect(
|
|
60
|
+
email.sendEmail({
|
|
61
|
+
to: 'a@b.com',
|
|
62
|
+
subject: 'Hello',
|
|
63
|
+
html: '<p>hi</p>',
|
|
64
|
+
}),
|
|
65
|
+
).rejects.toThrow(/provider down/);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('compatibility singleton throws before initEmail', async () => {
|
|
69
|
+
const mod = await import('./index.js');
|
|
70
|
+
expect(() =>
|
|
71
|
+
mod.sendEmail({
|
|
72
|
+
to: 'a@b.com',
|
|
73
|
+
subject: 'Hello',
|
|
74
|
+
html: '<p>hi</p>',
|
|
75
|
+
}),
|
|
76
|
+
).toThrow(/initEmail/i);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('compatibility singleton delegates after initEmail', async () => {
|
|
80
|
+
const send = vi.fn(async () => ({ data: { id: 'msg_2' }, error: null }));
|
|
81
|
+
const mod = await import('./index.js');
|
|
82
|
+
|
|
83
|
+
mod.initEmail(
|
|
84
|
+
{ apiKey: 'rk_test', defaultFromAddress: 'hello@wrelik.com' },
|
|
85
|
+
{ transport: { emails: { send } } },
|
|
86
|
+
);
|
|
87
|
+
mod.defineTemplate('receipt', (data: { total: number }) => ({
|
|
88
|
+
subject: `Receipt ${data.total}`,
|
|
89
|
+
html: `<p>${data.total}</p>`,
|
|
90
|
+
text: String(data.total),
|
|
91
|
+
}));
|
|
92
|
+
|
|
93
|
+
await mod.sendTemplate('receipt', 'lee@example.com', { total: 42 });
|
|
94
|
+
await mod.sendEmail({ to: 'lee@example.com', subject: 'Ping', text: 'pong' });
|
|
95
|
+
|
|
96
|
+
expect(send).toHaveBeenCalledTimes(2);
|
|
97
|
+
expect(send).toHaveBeenNthCalledWith(1, {
|
|
98
|
+
from: 'hello@wrelik.com',
|
|
99
|
+
to: 'lee@example.com',
|
|
100
|
+
subject: 'Receipt 42',
|
|
101
|
+
html: '<p>42</p>',
|
|
102
|
+
text: '42',
|
|
103
|
+
tags: undefined,
|
|
104
|
+
react: null,
|
|
105
|
+
});
|
|
106
|
+
expect(send).toHaveBeenNthCalledWith(2, {
|
|
107
|
+
from: 'hello@wrelik.com',
|
|
108
|
+
to: 'lee@example.com',
|
|
109
|
+
subject: 'Ping',
|
|
110
|
+
html: undefined,
|
|
111
|
+
text: 'pong',
|
|
112
|
+
tags: undefined,
|
|
113
|
+
react: null,
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
});
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/* eslint-disable no-restricted-imports */
|
|
2
|
+
import { Resend } from 'resend';
|
|
3
|
+
import { ValidationError } from '@wrelik/errors/shared';
|
|
4
|
+
import type { SendEmailOptions, TemplateRenderer } from '../shared';
|
|
5
|
+
export type { SendEmailOptions, TemplateRenderer } from '../shared';
|
|
6
|
+
|
|
7
|
+
export interface EmailTransport {
|
|
8
|
+
emails: {
|
|
9
|
+
send: (input: {
|
|
10
|
+
from: string;
|
|
11
|
+
to: string | string[];
|
|
12
|
+
subject: string;
|
|
13
|
+
html?: string;
|
|
14
|
+
text?: string;
|
|
15
|
+
tags?: Array<{ name: string; value: string }>;
|
|
16
|
+
react: null;
|
|
17
|
+
}) => Promise<{ data: unknown; error: { message: string } | null }>;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function createEmailServer(
|
|
22
|
+
config: { apiKey: string; defaultFromAddress: string },
|
|
23
|
+
options?: { transport?: EmailTransport },
|
|
24
|
+
) {
|
|
25
|
+
const client: EmailTransport = options?.transport ?? new Resend(config.apiKey);
|
|
26
|
+
const templates = new Map<string, TemplateRenderer<unknown>>();
|
|
27
|
+
const sendEmail = async ({ to, subject, html, text, from, tags }: SendEmailOptions) => {
|
|
28
|
+
const result = await client.emails.send({
|
|
29
|
+
from: from ?? config.defaultFromAddress,
|
|
30
|
+
to,
|
|
31
|
+
subject,
|
|
32
|
+
html,
|
|
33
|
+
text,
|
|
34
|
+
tags,
|
|
35
|
+
react: null,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
if (result.error) {
|
|
39
|
+
throw new Error(`Failed to send email: ${result.error.message}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return result.data;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
sendEmail,
|
|
47
|
+
|
|
48
|
+
defineTemplate<T>(id: string, renderer: TemplateRenderer<T>) {
|
|
49
|
+
templates.set(id, renderer as TemplateRenderer<unknown>);
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
async sendTemplate<T>(id: string, to: string | string[], data: T, options?: Partial<SendEmailOptions>) {
|
|
53
|
+
const renderer = templates.get(id);
|
|
54
|
+
if (!renderer) {
|
|
55
|
+
throw new ValidationError(`Template ${id} not found`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const { subject, html, text } = renderer(data);
|
|
59
|
+
return sendEmail({
|
|
60
|
+
to,
|
|
61
|
+
subject,
|
|
62
|
+
html,
|
|
63
|
+
text,
|
|
64
|
+
...options,
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
type EmailServerCompat = ReturnType<typeof createEmailServer>;
|
|
71
|
+
|
|
72
|
+
let emailSingleton: EmailServerCompat | null = null;
|
|
73
|
+
|
|
74
|
+
function requireEmailSingleton(): EmailServerCompat {
|
|
75
|
+
if (!emailSingleton) {
|
|
76
|
+
throw new Error(
|
|
77
|
+
'@wrelik/email/server compatibility API is not initialized. Call initEmail({ apiKey, defaultFromAddress }) before sendEmail/sendTemplate.',
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return emailSingleton;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @deprecated Temporary DRX compatibility singleton. Prefer createEmailServer(...) and explicit dependency wiring.
|
|
86
|
+
*/
|
|
87
|
+
export function initEmail(
|
|
88
|
+
config: { apiKey: string; defaultFromAddress: string },
|
|
89
|
+
options?: Parameters<typeof createEmailServer>[1],
|
|
90
|
+
): void {
|
|
91
|
+
emailSingleton = createEmailServer(config, options);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @deprecated Temporary DRX compatibility singleton. Prefer createEmailServer(...).defineTemplate(...)
|
|
96
|
+
*/
|
|
97
|
+
export function defineTemplate<T>(id: string, renderer: TemplateRenderer<T>): void {
|
|
98
|
+
requireEmailSingleton().defineTemplate(id, renderer);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @deprecated Temporary DRX compatibility singleton. Prefer createEmailServer(...).sendEmail(...)
|
|
103
|
+
*/
|
|
104
|
+
export function sendEmail(input: SendEmailOptions): Promise<unknown> {
|
|
105
|
+
return requireEmailSingleton().sendEmail(input);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* @deprecated Temporary DRX compatibility singleton. Prefer createEmailServer(...).sendTemplate(...)
|
|
110
|
+
*/
|
|
111
|
+
export function sendTemplate<T>(
|
|
112
|
+
id: string,
|
|
113
|
+
to: string | string[],
|
|
114
|
+
data: T,
|
|
115
|
+
options?: Partial<SendEmailOptions>,
|
|
116
|
+
): Promise<unknown> {
|
|
117
|
+
return requireEmailSingleton().sendTemplate(id, to, data, options);
|
|
118
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type { SendEmailOptions, TemplateRenderer } from './types';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface SendEmailOptions {
|
|
2
|
+
to: string | string[];
|
|
3
|
+
subject: string;
|
|
4
|
+
html?: string;
|
|
5
|
+
text?: string;
|
|
6
|
+
from?: string;
|
|
7
|
+
tags?: Array<{ name: string; value: string }>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type TemplateRenderer<T> = (data: T) => { subject: string; html: string; text?: string };
|
package/dist/index.d.mts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import * as resend from 'resend';
|
|
2
|
-
|
|
3
|
-
declare function initEmail(apiKey: string, defaultFromAddress: string): void;
|
|
4
|
-
interface SendEmailOptions {
|
|
5
|
-
to: string | string[];
|
|
6
|
-
subject: string;
|
|
7
|
-
html?: string;
|
|
8
|
-
text?: string;
|
|
9
|
-
from?: string;
|
|
10
|
-
tags?: Array<{
|
|
11
|
-
name: string;
|
|
12
|
-
value: string;
|
|
13
|
-
}>;
|
|
14
|
-
}
|
|
15
|
-
declare function sendEmail({ to, subject, html, text, from, tags }: SendEmailOptions): Promise<resend.CreateEmailResponseSuccess | null>;
|
|
16
|
-
type TemplateRenderer<T> = (data: T) => {
|
|
17
|
-
subject: string;
|
|
18
|
-
html: string;
|
|
19
|
-
text?: string;
|
|
20
|
-
};
|
|
21
|
-
declare function defineTemplate<T>(id: string, renderer: TemplateRenderer<T>): void;
|
|
22
|
-
declare function sendTemplate<T>(id: string, to: string | string[], data: T, options?: Partial<SendEmailOptions>): Promise<resend.CreateEmailResponseSuccess | null>;
|
|
23
|
-
|
|
24
|
-
export { type SendEmailOptions, defineTemplate, initEmail, sendEmail, sendTemplate };
|
package/dist/index.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import * as resend from 'resend';
|
|
2
|
-
|
|
3
|
-
declare function initEmail(apiKey: string, defaultFromAddress: string): void;
|
|
4
|
-
interface SendEmailOptions {
|
|
5
|
-
to: string | string[];
|
|
6
|
-
subject: string;
|
|
7
|
-
html?: string;
|
|
8
|
-
text?: string;
|
|
9
|
-
from?: string;
|
|
10
|
-
tags?: Array<{
|
|
11
|
-
name: string;
|
|
12
|
-
value: string;
|
|
13
|
-
}>;
|
|
14
|
-
}
|
|
15
|
-
declare function sendEmail({ to, subject, html, text, from, tags }: SendEmailOptions): Promise<resend.CreateEmailResponseSuccess | null>;
|
|
16
|
-
type TemplateRenderer<T> = (data: T) => {
|
|
17
|
-
subject: string;
|
|
18
|
-
html: string;
|
|
19
|
-
text?: string;
|
|
20
|
-
};
|
|
21
|
-
declare function defineTemplate<T>(id: string, renderer: TemplateRenderer<T>): void;
|
|
22
|
-
declare function sendTemplate<T>(id: string, to: string | string[], data: T, options?: Partial<SendEmailOptions>): Promise<resend.CreateEmailResponseSuccess | null>;
|
|
23
|
-
|
|
24
|
-
export { type SendEmailOptions, defineTemplate, initEmail, sendEmail, sendTemplate };
|
package/dist/index.js
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
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 index_exports = {};
|
|
22
|
-
__export(index_exports, {
|
|
23
|
-
defineTemplate: () => defineTemplate,
|
|
24
|
-
initEmail: () => initEmail,
|
|
25
|
-
sendEmail: () => sendEmail,
|
|
26
|
-
sendTemplate: () => sendTemplate
|
|
27
|
-
});
|
|
28
|
-
module.exports = __toCommonJS(index_exports);
|
|
29
|
-
var import_resend = require("resend");
|
|
30
|
-
var import_errors = require("@wrelik/errors");
|
|
31
|
-
var client;
|
|
32
|
-
var defaultFrom;
|
|
33
|
-
function initEmail(apiKey, defaultFromAddress) {
|
|
34
|
-
client = new import_resend.Resend(apiKey);
|
|
35
|
-
defaultFrom = defaultFromAddress;
|
|
36
|
-
}
|
|
37
|
-
function getClient() {
|
|
38
|
-
if (!client) throw new Error("Email not initialized");
|
|
39
|
-
return client;
|
|
40
|
-
}
|
|
41
|
-
async function sendEmail({ to, subject, html, text, from, tags }) {
|
|
42
|
-
const result = await getClient().emails.send({
|
|
43
|
-
from: from || defaultFrom,
|
|
44
|
-
to,
|
|
45
|
-
subject,
|
|
46
|
-
html,
|
|
47
|
-
text,
|
|
48
|
-
tags,
|
|
49
|
-
react: null
|
|
50
|
-
});
|
|
51
|
-
if (result.error) {
|
|
52
|
-
throw new Error(`Failed to send email: ${result.error.message}`);
|
|
53
|
-
}
|
|
54
|
-
return result.data;
|
|
55
|
-
}
|
|
56
|
-
var templates = /* @__PURE__ */ new Map();
|
|
57
|
-
function defineTemplate(id, renderer) {
|
|
58
|
-
templates.set(id, renderer);
|
|
59
|
-
}
|
|
60
|
-
async function sendTemplate(id, to, data, options) {
|
|
61
|
-
const renderer = templates.get(id);
|
|
62
|
-
if (!renderer) {
|
|
63
|
-
throw new import_errors.ValidationError(`Template ${id} not found`);
|
|
64
|
-
}
|
|
65
|
-
const { subject, html, text } = renderer(data);
|
|
66
|
-
return sendEmail({
|
|
67
|
-
to,
|
|
68
|
-
subject,
|
|
69
|
-
html,
|
|
70
|
-
text,
|
|
71
|
-
...options
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
75
|
-
0 && (module.exports = {
|
|
76
|
-
defineTemplate,
|
|
77
|
-
initEmail,
|
|
78
|
-
sendEmail,
|
|
79
|
-
sendTemplate
|
|
80
|
-
});
|
package/dist/index.mjs
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
// src/index.ts
|
|
2
|
-
import { Resend } from "resend";
|
|
3
|
-
import { ValidationError } from "@wrelik/errors";
|
|
4
|
-
var client;
|
|
5
|
-
var defaultFrom;
|
|
6
|
-
function initEmail(apiKey, defaultFromAddress) {
|
|
7
|
-
client = new Resend(apiKey);
|
|
8
|
-
defaultFrom = defaultFromAddress;
|
|
9
|
-
}
|
|
10
|
-
function getClient() {
|
|
11
|
-
if (!client) throw new Error("Email not initialized");
|
|
12
|
-
return client;
|
|
13
|
-
}
|
|
14
|
-
async function sendEmail({ to, subject, html, text, from, tags }) {
|
|
15
|
-
const result = await getClient().emails.send({
|
|
16
|
-
from: from || defaultFrom,
|
|
17
|
-
to,
|
|
18
|
-
subject,
|
|
19
|
-
html,
|
|
20
|
-
text,
|
|
21
|
-
tags,
|
|
22
|
-
react: null
|
|
23
|
-
});
|
|
24
|
-
if (result.error) {
|
|
25
|
-
throw new Error(`Failed to send email: ${result.error.message}`);
|
|
26
|
-
}
|
|
27
|
-
return result.data;
|
|
28
|
-
}
|
|
29
|
-
var templates = /* @__PURE__ */ new Map();
|
|
30
|
-
function defineTemplate(id, renderer) {
|
|
31
|
-
templates.set(id, renderer);
|
|
32
|
-
}
|
|
33
|
-
async function sendTemplate(id, to, data, options) {
|
|
34
|
-
const renderer = templates.get(id);
|
|
35
|
-
if (!renderer) {
|
|
36
|
-
throw new ValidationError(`Template ${id} not found`);
|
|
37
|
-
}
|
|
38
|
-
const { subject, html, text } = renderer(data);
|
|
39
|
-
return sendEmail({
|
|
40
|
-
to,
|
|
41
|
-
subject,
|
|
42
|
-
html,
|
|
43
|
-
text,
|
|
44
|
-
...options
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
export {
|
|
48
|
-
defineTemplate,
|
|
49
|
-
initEmail,
|
|
50
|
-
sendEmail,
|
|
51
|
-
sendTemplate
|
|
52
|
-
};
|
package/dist/unsupported.d.mts
DELETED
package/dist/unsupported.d.ts
DELETED
package/dist/unsupported.js
DELETED
package/dist/unsupported.mjs
DELETED
package/src/index.ts
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
// eslint-disable-next-line no-restricted-imports
|
|
2
|
-
import { Resend } from 'resend';
|
|
3
|
-
import { ValidationError } from '@wrelik/errors';
|
|
4
|
-
|
|
5
|
-
let client: Resend;
|
|
6
|
-
let defaultFrom: string;
|
|
7
|
-
|
|
8
|
-
export function initEmail(apiKey: string, defaultFromAddress: string) {
|
|
9
|
-
client = new Resend(apiKey);
|
|
10
|
-
defaultFrom = defaultFromAddress;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function getClient() {
|
|
14
|
-
if (!client) throw new Error('Email not initialized');
|
|
15
|
-
return client;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface SendEmailOptions {
|
|
19
|
-
to: string | string[];
|
|
20
|
-
subject: string;
|
|
21
|
-
html?: string;
|
|
22
|
-
text?: string;
|
|
23
|
-
from?: string;
|
|
24
|
-
tags?: Array<{ name: string; value: string }>;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export async function sendEmail({ to, subject, html, text, from, tags }: SendEmailOptions) {
|
|
28
|
-
const result = await getClient().emails.send({
|
|
29
|
-
from: from || defaultFrom,
|
|
30
|
-
to,
|
|
31
|
-
subject,
|
|
32
|
-
html,
|
|
33
|
-
text,
|
|
34
|
-
tags,
|
|
35
|
-
react: null,
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
if (result.error) {
|
|
39
|
-
throw new Error(`Failed to send email: ${result.error.message}`);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return result.data;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Template Registry
|
|
46
|
-
type TemplateRenderer<T> = (data: T) => { subject: string; html: string; text?: string };
|
|
47
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
48
|
-
const templates = new Map<string, TemplateRenderer<any>>();
|
|
49
|
-
|
|
50
|
-
export function defineTemplate<T>(id: string, renderer: TemplateRenderer<T>) {
|
|
51
|
-
templates.set(id, renderer);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export async function sendTemplate<T>(
|
|
55
|
-
id: string,
|
|
56
|
-
to: string | string[],
|
|
57
|
-
data: T,
|
|
58
|
-
options?: Partial<SendEmailOptions>,
|
|
59
|
-
) {
|
|
60
|
-
const renderer = templates.get(id);
|
|
61
|
-
if (!renderer) {
|
|
62
|
-
throw new ValidationError(`Template ${id} not found`);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const { subject, html, text } = renderer(data);
|
|
66
|
-
return sendEmail({
|
|
67
|
-
to,
|
|
68
|
-
subject,
|
|
69
|
-
html,
|
|
70
|
-
text,
|
|
71
|
-
...options,
|
|
72
|
-
});
|
|
73
|
-
}
|
package/src/unsupported.ts
DELETED