@ainsleydev/payload-helper 0.0.40 → 0.1.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.
Files changed (36) hide show
  1. package/README.md +76 -0
  2. package/dist/cli/bin.js +20 -0
  3. package/dist/cli/bin.js.map +1 -1
  4. package/dist/cli/commands/preview-emails.d.ts +5 -0
  5. package/dist/cli/commands/preview-emails.js +123 -0
  6. package/dist/cli/commands/preview-emails.js.map +1 -0
  7. package/dist/email/ForgotPasswordEmail.d.ts +38 -0
  8. package/dist/email/ForgotPasswordEmail.js +61 -0
  9. package/dist/email/ForgotPasswordEmail.js.map +1 -0
  10. package/dist/email/ForgotPasswordEmail.test.d.ts +1 -0
  11. package/dist/email/ForgotPasswordEmail.test.js +202 -0
  12. package/dist/email/ForgotPasswordEmail.test.js.map +1 -0
  13. package/dist/email/VerifyAccountEmail.d.ts +38 -0
  14. package/dist/email/VerifyAccountEmail.js +61 -0
  15. package/dist/email/VerifyAccountEmail.js.map +1 -0
  16. package/dist/email/VerifyAccountEmail.test.d.ts +1 -0
  17. package/dist/email/VerifyAccountEmail.test.js +212 -0
  18. package/dist/email/VerifyAccountEmail.test.js.map +1 -0
  19. package/dist/index.d.ts +6 -1
  20. package/dist/index.js +13 -0
  21. package/dist/index.js.map +1 -1
  22. package/dist/plugin/email.d.ts +10 -0
  23. package/dist/plugin/email.js +98 -0
  24. package/dist/plugin/email.js.map +1 -0
  25. package/dist/plugin/email.test.js +265 -0
  26. package/dist/plugin/email.test.js.map +1 -0
  27. package/dist/types.d.ts +134 -0
  28. package/dist/types.js +3 -1
  29. package/dist/types.js.map +1 -1
  30. package/package.json +27 -14
  31. package/dist/plugin/icon.d.ts +0 -6
  32. package/dist/plugin/icon.js +0 -26
  33. package/dist/plugin/icon.js.map +0 -1
  34. package/dist/plugin/logo.d.ts +0 -6
  35. package/dist/plugin/logo.js +0 -26
  36. package/dist/plugin/logo.js.map +0 -1
@@ -0,0 +1,61 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { BaseEmail, Button, Heading, Section, Text } from '@ainsleydev/email-templates';
3
+ import * as React from 'react';
4
+ /**
5
+ * Email template for account verification in Payload CMS.
6
+ *
7
+ * @param props - The component props
8
+ * @returns The rendered email component
9
+ */ export const VerifyAccountEmail = ({ theme, user, verifyUrl, content })=>{
10
+ const userName = user.firstName || user.email || 'there';
11
+ const previewText = content?.previewText || 'Verify your email';
12
+ const heading = content?.heading || `Welcome, ${userName}!`;
13
+ const bodyText = content?.bodyText || 'Please verify your email by clicking the button below. If you did not request a password reset, you can safely ignore this email.';
14
+ const buttonText = content?.buttonText || 'Verify Email';
15
+ return /*#__PURE__*/ _jsxs(BaseEmail, {
16
+ theme: theme,
17
+ previewText: previewText,
18
+ children: [
19
+ /*#__PURE__*/ _jsx(Heading, {
20
+ style: {
21
+ color: theme.colours.text.heading,
22
+ fontSize: '24px',
23
+ fontWeight: 'bold',
24
+ marginBottom: '20px'
25
+ },
26
+ children: heading
27
+ }),
28
+ /*#__PURE__*/ _jsx(Text, {
29
+ style: {
30
+ color: theme.colours.text.body,
31
+ fontSize: '16px',
32
+ lineHeight: '24px',
33
+ marginBottom: '30px'
34
+ },
35
+ children: bodyText
36
+ }),
37
+ /*#__PURE__*/ _jsx(Section, {
38
+ style: {
39
+ textAlign: 'center',
40
+ marginBottom: '30px'
41
+ },
42
+ children: /*#__PURE__*/ _jsx(Button, {
43
+ href: verifyUrl,
44
+ style: {
45
+ backgroundColor: theme.colours.background.accent,
46
+ color: theme.colours.text.heading,
47
+ padding: '12px 32px',
48
+ borderRadius: '5px',
49
+ fontSize: '16px',
50
+ fontWeight: 'bold',
51
+ textDecoration: 'none',
52
+ display: 'inline-block'
53
+ },
54
+ children: buttonText
55
+ })
56
+ })
57
+ ]
58
+ });
59
+ };
60
+
61
+ //# sourceMappingURL=VerifyAccountEmail.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/email/VerifyAccountEmail.tsx"],"sourcesContent":["import { BaseEmail, Button, Heading, Section, Text } from '@ainsleydev/email-templates';\nimport type { EmailTheme } from '@ainsleydev/email-templates';\nimport * as React from 'react';\n\n/**\n * Props for the VerifyAccountEmail component.\n */\nexport interface VerifyAccountEmailProps {\n\t/**\n\t * The email theme (required by renderEmail).\n\t */\n\ttheme: EmailTheme;\n\n\t/**\n\t * The user object containing user information.\n\t */\n\tuser: {\n\t\tfirstName?: string;\n\t\temail?: string;\n\t};\n\n\t/**\n\t * The URL for verifying the account.\n\t */\n\tverifyUrl: string;\n\n\t/**\n\t * Optional content overrides.\n\t */\n\tcontent?: {\n\t\tpreviewText?: string;\n\t\theading?: string;\n\t\tbodyText?: string;\n\t\tbuttonText?: string;\n\t};\n}\n\n/**\n * Email template for account verification in Payload CMS.\n *\n * @param props - The component props\n * @returns The rendered email component\n */\nexport const VerifyAccountEmail = ({\n\ttheme,\n\tuser,\n\tverifyUrl,\n\tcontent,\n}: VerifyAccountEmailProps) => {\n\tconst userName = user.firstName || user.email || 'there';\n\tconst previewText = content?.previewText || 'Verify your email';\n\tconst heading = content?.heading || `Welcome, ${userName}!`;\n\tconst bodyText =\n\t\tcontent?.bodyText ||\n\t\t'Please verify your email by clicking the button below. If you did not request a password reset, you can safely ignore this email.';\n\tconst buttonText = content?.buttonText || 'Verify Email';\n\n\treturn (\n\t\t<BaseEmail theme={theme} previewText={previewText}>\n\t\t\t<Heading\n\t\t\t\tstyle={{\n\t\t\t\t\tcolor: theme.colours.text.heading,\n\t\t\t\t\tfontSize: '24px',\n\t\t\t\t\tfontWeight: 'bold',\n\t\t\t\t\tmarginBottom: '20px',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{heading}\n\t\t\t</Heading>\n\t\t\t<Text\n\t\t\t\tstyle={{\n\t\t\t\t\tcolor: theme.colours.text.body,\n\t\t\t\t\tfontSize: '16px',\n\t\t\t\t\tlineHeight: '24px',\n\t\t\t\t\tmarginBottom: '30px',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{bodyText}\n\t\t\t</Text>\n\t\t\t<Section style={{ textAlign: 'center', marginBottom: '30px' }}>\n\t\t\t\t<Button\n\t\t\t\t\thref={verifyUrl}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tbackgroundColor: theme.colours.background.accent,\n\t\t\t\t\t\tcolor: theme.colours.text.heading,\n\t\t\t\t\t\tpadding: '12px 32px',\n\t\t\t\t\t\tborderRadius: '5px',\n\t\t\t\t\t\tfontSize: '16px',\n\t\t\t\t\t\tfontWeight: 'bold',\n\t\t\t\t\t\ttextDecoration: 'none',\n\t\t\t\t\t\tdisplay: 'inline-block',\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{buttonText}\n\t\t\t\t</Button>\n\t\t\t</Section>\n\t\t</BaseEmail>\n\t);\n};\n"],"names":["BaseEmail","Button","Heading","Section","Text","React","VerifyAccountEmail","theme","user","verifyUrl","content","userName","firstName","email","previewText","heading","bodyText","buttonText","style","color","colours","text","fontSize","fontWeight","marginBottom","body","lineHeight","textAlign","href","backgroundColor","background","accent","padding","borderRadius","textDecoration","display"],"mappings":";AAAA,SAASA,SAAS,EAAEC,MAAM,EAAEC,OAAO,EAAEC,OAAO,EAAEC,IAAI,QAAQ,8BAA8B;AAExF,YAAYC,WAAW,QAAQ;AAmC/B;;;;;CAKC,GACD,OAAO,MAAMC,qBAAqB,CAAC,EAClCC,KAAK,EACLC,IAAI,EACJC,SAAS,EACTC,OAAO,EACkB;IACzB,MAAMC,WAAWH,KAAKI,SAAS,IAAIJ,KAAKK,KAAK,IAAI;IACjD,MAAMC,cAAcJ,SAASI,eAAe;IAC5C,MAAMC,UAAUL,SAASK,WAAW,CAAC,SAAS,EAAEJ,SAAS,CAAC,CAAC;IAC3D,MAAMK,WACLN,SAASM,YACT;IACD,MAAMC,aAAaP,SAASO,cAAc;IAE1C,qBACC,MAACjB;QAAUO,OAAOA;QAAOO,aAAaA;;0BACrC,KAACZ;gBACAgB,OAAO;oBACNC,OAAOZ,MAAMa,OAAO,CAACC,IAAI,CAACN,OAAO;oBACjCO,UAAU;oBACVC,YAAY;oBACZC,cAAc;gBACf;0BAECT;;0BAEF,KAACX;gBACAc,OAAO;oBACNC,OAAOZ,MAAMa,OAAO,CAACC,IAAI,CAACI,IAAI;oBAC9BH,UAAU;oBACVI,YAAY;oBACZF,cAAc;gBACf;0BAECR;;0BAEF,KAACb;gBAAQe,OAAO;oBAAES,WAAW;oBAAUH,cAAc;gBAAO;0BAC3D,cAAA,KAACvB;oBACA2B,MAAMnB;oBACNS,OAAO;wBACNW,iBAAiBtB,MAAMa,OAAO,CAACU,UAAU,CAACC,MAAM;wBAChDZ,OAAOZ,MAAMa,OAAO,CAACC,IAAI,CAACN,OAAO;wBACjCiB,SAAS;wBACTC,cAAc;wBACdX,UAAU;wBACVC,YAAY;wBACZW,gBAAgB;wBAChBC,SAAS;oBACV;8BAEClB;;;;;AAKN,EAAE"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,212 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { describe, expect, test, vi } from 'vitest';
3
+ import { VerifyAccountEmail } from './VerifyAccountEmail.js';
4
+ // Mock the email templates module
5
+ vi.mock('@ainsleydev/email-templates', ()=>({
6
+ BaseEmail: ({ children })=>children,
7
+ Button: ({ children, href })=>/*#__PURE__*/ _jsx("a", {
8
+ href: href,
9
+ children: children
10
+ }),
11
+ Heading: ({ children })=>/*#__PURE__*/ _jsx("h1", {
12
+ children: children
13
+ }),
14
+ Section: ({ children })=>/*#__PURE__*/ _jsx("section", {
15
+ children: children
16
+ }),
17
+ Text: ({ children })=>/*#__PURE__*/ _jsx("p", {
18
+ children: children
19
+ })
20
+ }));
21
+ const mockTheme = {
22
+ colours: {
23
+ text: {
24
+ heading: '#000000',
25
+ body: '#333333',
26
+ action: '#007bff',
27
+ negative: '#ffffff'
28
+ },
29
+ background: {
30
+ white: '#ffffff',
31
+ dark: '#000000',
32
+ darker: '#0f0f0f',
33
+ highlight: '#f5f5f5',
34
+ accent: '#007bff'
35
+ },
36
+ border: {
37
+ light: '#e0e0e0',
38
+ medium: '#cccccc',
39
+ dark: '#000000',
40
+ inverse: '#ffffff'
41
+ }
42
+ },
43
+ branding: {
44
+ companyName: 'Test Company',
45
+ logoUrl: 'https://example.com/logo.png',
46
+ logoWidth: 120,
47
+ websiteUrl: 'https://example.com'
48
+ }
49
+ };
50
+ describe('VerifyAccountEmail', ()=>{
51
+ test('should render with default content when no overrides provided', ()=>{
52
+ const props = {
53
+ theme: mockTheme,
54
+ user: {
55
+ firstName: 'John',
56
+ email: 'john@example.com'
57
+ },
58
+ verifyUrl: 'https://example.com/verify/token123'
59
+ };
60
+ const result = VerifyAccountEmail(props);
61
+ // Component should render without errors
62
+ expect(result).toBeDefined();
63
+ });
64
+ test('should use firstName when available', ()=>{
65
+ const props = {
66
+ theme: mockTheme,
67
+ user: {
68
+ firstName: 'Jane',
69
+ email: 'jane@example.com'
70
+ },
71
+ verifyUrl: 'https://example.com/verify/token123'
72
+ };
73
+ const result = VerifyAccountEmail(props);
74
+ // The userName should be set to firstName
75
+ // This is tested through the default heading which uses userName
76
+ expect(result).toBeDefined();
77
+ });
78
+ test('should use email when firstName is not available', ()=>{
79
+ const props = {
80
+ theme: mockTheme,
81
+ user: {
82
+ email: 'john@example.com'
83
+ },
84
+ verifyUrl: 'https://example.com/verify/token123'
85
+ };
86
+ const result = VerifyAccountEmail(props);
87
+ // The userName should be set to email
88
+ expect(result).toBeDefined();
89
+ });
90
+ test('should use "there" when neither firstName nor email is available', ()=>{
91
+ const props = {
92
+ theme: mockTheme,
93
+ user: {},
94
+ verifyUrl: 'https://example.com/verify/token123'
95
+ };
96
+ const result = VerifyAccountEmail(props);
97
+ // The userName should default to "there"
98
+ expect(result).toBeDefined();
99
+ });
100
+ test('should use custom content overrides when provided', ()=>{
101
+ const props = {
102
+ theme: mockTheme,
103
+ user: {
104
+ firstName: 'John'
105
+ },
106
+ verifyUrl: 'https://example.com/verify/token123',
107
+ content: {
108
+ previewText: 'Custom preview text',
109
+ heading: 'Custom Welcome Heading',
110
+ bodyText: 'Custom verification message',
111
+ buttonText: 'Custom Verify Button'
112
+ }
113
+ };
114
+ const result = VerifyAccountEmail(props);
115
+ // Component should use custom content
116
+ expect(result).toBeDefined();
117
+ });
118
+ test('should use partial content overrides with defaults', ()=>{
119
+ const props = {
120
+ theme: mockTheme,
121
+ user: {
122
+ firstName: 'John'
123
+ },
124
+ verifyUrl: 'https://example.com/verify/token123',
125
+ content: {
126
+ buttonText: 'Confirm Email'
127
+ }
128
+ };
129
+ const result = VerifyAccountEmail(props);
130
+ // Component should use custom button text and defaults for others
131
+ expect(result).toBeDefined();
132
+ });
133
+ test('should pass verifyUrl to the button', ()=>{
134
+ const verifyUrl = 'https://example.com/verify/xyz789abc';
135
+ const props = {
136
+ theme: mockTheme,
137
+ user: {
138
+ firstName: 'John'
139
+ },
140
+ verifyUrl
141
+ };
142
+ const result = VerifyAccountEmail(props);
143
+ // The verifyUrl should be used in the button href
144
+ expect(result).toBeDefined();
145
+ });
146
+ test('should apply theme colors correctly', ()=>{
147
+ const customTheme = {
148
+ colours: {
149
+ text: {
150
+ heading: '#ff0000',
151
+ body: '#00ff00',
152
+ action: '#0000ff',
153
+ negative: '#ffffff'
154
+ },
155
+ background: {
156
+ white: '#ffffff',
157
+ dark: '#000000',
158
+ darker: '#0f0f0f',
159
+ highlight: '#f5f5f5',
160
+ accent: '#0000ff'
161
+ },
162
+ border: {
163
+ light: '#e0e0e0',
164
+ medium: '#cccccc',
165
+ dark: '#000000',
166
+ inverse: '#ffffff'
167
+ }
168
+ },
169
+ branding: {
170
+ companyName: 'Custom Company',
171
+ logoUrl: 'https://custom.com/logo.png',
172
+ logoWidth: 150,
173
+ websiteUrl: 'https://custom.com'
174
+ }
175
+ };
176
+ const props = {
177
+ theme: customTheme,
178
+ user: {
179
+ firstName: 'John'
180
+ },
181
+ verifyUrl: 'https://example.com/verify/token123'
182
+ };
183
+ const result = VerifyAccountEmail(props);
184
+ // Component should use custom theme colors
185
+ expect(result).toBeDefined();
186
+ });
187
+ test('should handle empty content object', ()=>{
188
+ const props = {
189
+ theme: mockTheme,
190
+ user: {
191
+ firstName: 'John'
192
+ },
193
+ verifyUrl: 'https://example.com/verify/token123',
194
+ content: {}
195
+ };
196
+ const result = VerifyAccountEmail(props);
197
+ // Should use all defaults when content is empty object
198
+ expect(result).toBeDefined();
199
+ });
200
+ test('should render with minimal props', ()=>{
201
+ const props = {
202
+ theme: mockTheme,
203
+ user: {},
204
+ verifyUrl: 'https://example.com/verify/token123'
205
+ };
206
+ const result = VerifyAccountEmail(props);
207
+ // Should handle minimal props gracefully
208
+ expect(result).toBeDefined();
209
+ });
210
+ });
211
+
212
+ //# sourceMappingURL=VerifyAccountEmail.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/email/VerifyAccountEmail.test.tsx"],"sourcesContent":["import type { EmailTheme } from '@ainsleydev/email-templates';\nimport { describe, expect, test, vi } from 'vitest';\nimport { VerifyAccountEmail } from './VerifyAccountEmail.js';\nimport type { VerifyAccountEmailProps } from './VerifyAccountEmail.js';\n\n// Mock the email templates module\nvi.mock('@ainsleydev/email-templates', () => ({\n\tBaseEmail: ({ children }: { children: React.ReactNode }) => children,\n\tButton: ({ children, href }: { children: React.ReactNode; href: string }) => (\n\t\t<a href={href}>{children}</a>\n\t),\n\tHeading: ({ children }: { children: React.ReactNode }) => <h1>{children}</h1>,\n\tSection: ({ children }: { children: React.ReactNode }) => <section>{children}</section>,\n\tText: ({ children }: { children: React.ReactNode }) => <p>{children}</p>,\n}));\n\nconst mockTheme: EmailTheme = {\n\tcolours: {\n\t\ttext: {\n\t\t\theading: '#000000',\n\t\t\tbody: '#333333',\n\t\t\taction: '#007bff',\n\t\t\tnegative: '#ffffff',\n\t\t},\n\t\tbackground: {\n\t\t\twhite: '#ffffff',\n\t\t\tdark: '#000000',\n\t\t\tdarker: '#0f0f0f',\n\t\t\thighlight: '#f5f5f5',\n\t\t\taccent: '#007bff',\n\t\t},\n\t\tborder: {\n\t\t\tlight: '#e0e0e0',\n\t\t\tmedium: '#cccccc',\n\t\t\tdark: '#000000',\n\t\t\tinverse: '#ffffff',\n\t\t},\n\t},\n\tbranding: {\n\t\tcompanyName: 'Test Company',\n\t\tlogoUrl: 'https://example.com/logo.png',\n\t\tlogoWidth: 120,\n\t\twebsiteUrl: 'https://example.com',\n\t},\n};\n\ndescribe('VerifyAccountEmail', () => {\n\ttest('should render with default content when no overrides provided', () => {\n\t\tconst props: VerifyAccountEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'John',\n\t\t\t\temail: 'john@example.com',\n\t\t\t},\n\t\t\tverifyUrl: 'https://example.com/verify/token123',\n\t\t};\n\n\t\tconst result = VerifyAccountEmail(props);\n\n\t\t// Component should render without errors\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should use firstName when available', () => {\n\t\tconst props: VerifyAccountEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'Jane',\n\t\t\t\temail: 'jane@example.com',\n\t\t\t},\n\t\t\tverifyUrl: 'https://example.com/verify/token123',\n\t\t};\n\n\t\tconst result = VerifyAccountEmail(props);\n\n\t\t// The userName should be set to firstName\n\t\t// This is tested through the default heading which uses userName\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should use email when firstName is not available', () => {\n\t\tconst props: VerifyAccountEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\temail: 'john@example.com',\n\t\t\t},\n\t\t\tverifyUrl: 'https://example.com/verify/token123',\n\t\t};\n\n\t\tconst result = VerifyAccountEmail(props);\n\n\t\t// The userName should be set to email\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should use \"there\" when neither firstName nor email is available', () => {\n\t\tconst props: VerifyAccountEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {},\n\t\t\tverifyUrl: 'https://example.com/verify/token123',\n\t\t};\n\n\t\tconst result = VerifyAccountEmail(props);\n\n\t\t// The userName should default to \"there\"\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should use custom content overrides when provided', () => {\n\t\tconst props: VerifyAccountEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'John',\n\t\t\t},\n\t\t\tverifyUrl: 'https://example.com/verify/token123',\n\t\t\tcontent: {\n\t\t\t\tpreviewText: 'Custom preview text',\n\t\t\t\theading: 'Custom Welcome Heading',\n\t\t\t\tbodyText: 'Custom verification message',\n\t\t\t\tbuttonText: 'Custom Verify Button',\n\t\t\t},\n\t\t};\n\n\t\tconst result = VerifyAccountEmail(props);\n\n\t\t// Component should use custom content\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should use partial content overrides with defaults', () => {\n\t\tconst props: VerifyAccountEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'John',\n\t\t\t},\n\t\t\tverifyUrl: 'https://example.com/verify/token123',\n\t\t\tcontent: {\n\t\t\t\tbuttonText: 'Confirm Email',\n\t\t\t\t// Other fields should use defaults\n\t\t\t},\n\t\t};\n\n\t\tconst result = VerifyAccountEmail(props);\n\n\t\t// Component should use custom button text and defaults for others\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should pass verifyUrl to the button', () => {\n\t\tconst verifyUrl = 'https://example.com/verify/xyz789abc';\n\t\tconst props: VerifyAccountEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'John',\n\t\t\t},\n\t\t\tverifyUrl,\n\t\t};\n\n\t\tconst result = VerifyAccountEmail(props);\n\n\t\t// The verifyUrl should be used in the button href\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should apply theme colors correctly', () => {\n\t\tconst customTheme: EmailTheme = {\n\t\t\tcolours: {\n\t\t\t\ttext: {\n\t\t\t\t\theading: '#ff0000',\n\t\t\t\t\tbody: '#00ff00',\n\t\t\t\t\taction: '#0000ff',\n\t\t\t\t\tnegative: '#ffffff',\n\t\t\t\t},\n\t\t\t\tbackground: {\n\t\t\t\t\twhite: '#ffffff',\n\t\t\t\t\tdark: '#000000',\n\t\t\t\t\tdarker: '#0f0f0f',\n\t\t\t\t\thighlight: '#f5f5f5',\n\t\t\t\t\taccent: '#0000ff',\n\t\t\t\t},\n\t\t\t\tborder: {\n\t\t\t\t\tlight: '#e0e0e0',\n\t\t\t\t\tmedium: '#cccccc',\n\t\t\t\t\tdark: '#000000',\n\t\t\t\t\tinverse: '#ffffff',\n\t\t\t\t},\n\t\t\t},\n\t\t\tbranding: {\n\t\t\t\tcompanyName: 'Custom Company',\n\t\t\t\tlogoUrl: 'https://custom.com/logo.png',\n\t\t\t\tlogoWidth: 150,\n\t\t\t\twebsiteUrl: 'https://custom.com',\n\t\t\t},\n\t\t};\n\n\t\tconst props: VerifyAccountEmailProps = {\n\t\t\ttheme: customTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'John',\n\t\t\t},\n\t\t\tverifyUrl: 'https://example.com/verify/token123',\n\t\t};\n\n\t\tconst result = VerifyAccountEmail(props);\n\n\t\t// Component should use custom theme colors\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should handle empty content object', () => {\n\t\tconst props: VerifyAccountEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {\n\t\t\t\tfirstName: 'John',\n\t\t\t},\n\t\t\tverifyUrl: 'https://example.com/verify/token123',\n\t\t\tcontent: {},\n\t\t};\n\n\t\tconst result = VerifyAccountEmail(props);\n\n\t\t// Should use all defaults when content is empty object\n\t\texpect(result).toBeDefined();\n\t});\n\n\ttest('should render with minimal props', () => {\n\t\tconst props: VerifyAccountEmailProps = {\n\t\t\ttheme: mockTheme,\n\t\t\tuser: {},\n\t\t\tverifyUrl: 'https://example.com/verify/token123',\n\t\t};\n\n\t\tconst result = VerifyAccountEmail(props);\n\n\t\t// Should handle minimal props gracefully\n\t\texpect(result).toBeDefined();\n\t});\n});\n"],"names":["describe","expect","test","vi","VerifyAccountEmail","mock","BaseEmail","children","Button","href","a","Heading","h1","Section","section","Text","p","mockTheme","colours","text","heading","body","action","negative","background","white","dark","darker","highlight","accent","border","light","medium","inverse","branding","companyName","logoUrl","logoWidth","websiteUrl","props","theme","user","firstName","email","verifyUrl","result","toBeDefined","content","previewText","bodyText","buttonText","customTheme"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -9,4 +9,9 @@ import type { PayloadHelperPluginConfig } from './types.js';
9
9
  export declare const payloadHelper: (pluginOptions: PayloadHelperPluginConfig) => (incomingConfig: Config) => Config;
10
10
  export type { IconProps } from './admin/components/Icon.js';
11
11
  export type { LogoProps } from './admin/components/Logo.js';
12
- export type { AdminConfig, AdminIconConfig, AdminLogoConfig, PayloadHelperPluginConfig, } from './types.js';
12
+ export { ForgotPasswordEmail } from './email/ForgotPasswordEmail.js';
13
+ export type { ForgotPasswordEmailProps } from './email/ForgotPasswordEmail.js';
14
+ export { VerifyAccountEmail } from './email/VerifyAccountEmail.js';
15
+ export type { VerifyAccountEmailProps } from './email/VerifyAccountEmail.js';
16
+ export { default as env } from './util/env.js';
17
+ export type { AdminConfig, AdminIconConfig, AdminLogoConfig, EmailConfig, EmailContentOverrides, PayloadHelperPluginConfig, } from './types.js';
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { injectAdminIcon, injectAdminLogo } from './plugin/admin.js';
2
+ import { injectEmailTemplates } from './plugin/email.js';
2
3
  import { cacheHookCollections, cacheHookGlobals } from './plugin/hooks.js';
3
4
  /**
4
5
  * Payload Helper Plugin for websites at ainsley.dev
@@ -19,6 +20,10 @@ import { cacheHookCollections, cacheHookGlobals } from './plugin/hooks.js';
19
20
  if (pluginOptions.admin?.icon) {
20
21
  config = injectAdminIcon(config, pluginOptions.admin.icon, pluginOptions.siteName);
21
22
  }
23
+ // Inject email templates for auth-enabled collections if email config is provided
24
+ if (pluginOptions.email) {
25
+ config = injectEmailTemplates(config, pluginOptions.email);
26
+ }
22
27
  // Map collections & add hooks
23
28
  config.collections = (config.collections || []).map((collection)=>{
24
29
  if (collection.upload !== undefined && collection.upload !== true) {
@@ -62,7 +67,15 @@ import { cacheHookCollections, cacheHookGlobals } from './plugin/hooks.js';
62
67
  hooks
63
68
  };
64
69
  });
70
+ // Store plugin options in config.custom for CLI access (e.g., preview-emails command)
71
+ config.custom = {
72
+ ...config.custom,
73
+ payloadHelperOptions: pluginOptions
74
+ };
65
75
  return config;
66
76
  };
77
+ export { ForgotPasswordEmail } from './email/ForgotPasswordEmail.js';
78
+ export { VerifyAccountEmail } from './email/VerifyAccountEmail.js';
79
+ export { default as env } from './util/env.js';
67
80
 
68
81
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { CollectionConfig, Config } from 'payload';\nimport { injectAdminIcon, injectAdminLogo } from './plugin/admin.js';\nimport { cacheHookCollections, cacheHookGlobals } from './plugin/hooks.js';\nimport type { PayloadHelperPluginConfig } from './types.js';\n\n/**\n * Payload Helper Plugin for websites at ainsley.dev\n *\n * @constructor\n * @param pluginOptions\n */\nexport const payloadHelper =\n\t(pluginOptions: PayloadHelperPluginConfig) =>\n\t(incomingConfig: Config): Config => {\n\t\t// TODO: Validate Config\n\n\t\tlet config = incomingConfig;\n\n\t\t// Update typescript generation file\n\t\tconfig.typescript = config.typescript || {};\n\t\tconfig.typescript.outputFile = './src/types/payload.ts';\n\n\t\t// Inject admin Logo component if logo config is provided\n\t\tif (pluginOptions.admin?.logo) {\n\t\t\tconfig = injectAdminLogo(config, pluginOptions.admin.logo, pluginOptions.siteName);\n\t\t}\n\n\t\t// Inject admin Icon component if icon config is provided\n\t\tif (pluginOptions.admin?.icon) {\n\t\t\tconfig = injectAdminIcon(config, pluginOptions.admin.icon, pluginOptions.siteName);\n\t\t}\n\n\t\t// Map collections & add hooks\n\t\tconfig.collections = (config.collections || []).map((collection): CollectionConfig => {\n\t\t\tif (collection.upload !== undefined && collection.upload !== true) {\n\t\t\t\treturn collection;\n\t\t\t}\n\n\t\t\tconst hooks = collection.hooks || {};\n\n\t\t\t// Add afterChange hook only if webServer is defined\n\t\t\tif (pluginOptions.webServer) {\n\t\t\t\thooks.afterChange = [\n\t\t\t\t\t...(hooks.afterChange || []),\n\t\t\t\t\tcacheHookCollections({\n\t\t\t\t\t\tserver: pluginOptions.webServer,\n\t\t\t\t\t\tslug: collection.slug,\n\t\t\t\t\t\tfields: collection.fields,\n\t\t\t\t\t\tisCollection: true,\n\t\t\t\t\t}),\n\t\t\t\t];\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t...collection,\n\t\t\t\thooks,\n\t\t\t};\n\t\t});\n\n\t\t// Map globals & add hooks\n\t\tconfig.globals = (config.globals || []).map((global) => {\n\t\t\tconst hooks = global.hooks || {};\n\n\t\t\t// Add afterChange hook only if webServer is defined\n\t\t\tif (pluginOptions.webServer) {\n\t\t\t\thooks.afterChange = [\n\t\t\t\t\t...(hooks.afterChange || []),\n\t\t\t\t\tcacheHookGlobals({\n\t\t\t\t\t\tserver: pluginOptions.webServer,\n\t\t\t\t\t\tslug: global.slug,\n\t\t\t\t\t\tfields: global.fields,\n\t\t\t\t\t\tisCollection: true,\n\t\t\t\t\t}),\n\t\t\t\t];\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t...global,\n\t\t\t\thooks,\n\t\t\t};\n\t\t});\n\n\t\treturn config;\n\t};\n\nexport type { IconProps } from './admin/components/Icon.js';\nexport type { LogoProps } from './admin/components/Logo.js';\nexport type {\n\tAdminConfig,\n\tAdminIconConfig,\n\tAdminLogoConfig,\n\tPayloadHelperPluginConfig,\n} from './types.js';\n"],"names":["injectAdminIcon","injectAdminLogo","cacheHookCollections","cacheHookGlobals","payloadHelper","pluginOptions","incomingConfig","config","typescript","outputFile","admin","logo","siteName","icon","collections","map","collection","upload","undefined","hooks","webServer","afterChange","server","slug","fields","isCollection","globals","global"],"mappings":"AACA,SAASA,eAAe,EAAEC,eAAe,QAAQ,oBAAoB;AACrE,SAASC,oBAAoB,EAAEC,gBAAgB,QAAQ,oBAAoB;AAG3E;;;;;CAKC,GACD,OAAO,MAAMC,gBACZ,CAACC,gBACD,CAACC;QACA,wBAAwB;QAExB,IAAIC,SAASD;QAEb,oCAAoC;QACpCC,OAAOC,UAAU,GAAGD,OAAOC,UAAU,IAAI,CAAC;QAC1CD,OAAOC,UAAU,CAACC,UAAU,GAAG;QAE/B,yDAAyD;QACzD,IAAIJ,cAAcK,KAAK,EAAEC,MAAM;YAC9BJ,SAASN,gBAAgBM,QAAQF,cAAcK,KAAK,CAACC,IAAI,EAAEN,cAAcO,QAAQ;QAClF;QAEA,yDAAyD;QACzD,IAAIP,cAAcK,KAAK,EAAEG,MAAM;YAC9BN,SAASP,gBAAgBO,QAAQF,cAAcK,KAAK,CAACG,IAAI,EAAER,cAAcO,QAAQ;QAClF;QAEA,8BAA8B;QAC9BL,OAAOO,WAAW,GAAG,AAACP,CAAAA,OAAOO,WAAW,IAAI,EAAE,AAAD,EAAGC,GAAG,CAAC,CAACC;YACpD,IAAIA,WAAWC,MAAM,KAAKC,aAAaF,WAAWC,MAAM,KAAK,MAAM;gBAClE,OAAOD;YACR;YAEA,MAAMG,QAAQH,WAAWG,KAAK,IAAI,CAAC;YAEnC,oDAAoD;YACpD,IAAId,cAAce,SAAS,EAAE;gBAC5BD,MAAME,WAAW,GAAG;uBACfF,MAAME,WAAW,IAAI,EAAE;oBAC3BnB,qBAAqB;wBACpBoB,QAAQjB,cAAce,SAAS;wBAC/BG,MAAMP,WAAWO,IAAI;wBACrBC,QAAQR,WAAWQ,MAAM;wBACzBC,cAAc;oBACf;iBACA;YACF;YAEA,OAAO;gBACN,GAAGT,UAAU;gBACbG;YACD;QACD;QAEA,0BAA0B;QAC1BZ,OAAOmB,OAAO,GAAG,AAACnB,CAAAA,OAAOmB,OAAO,IAAI,EAAE,AAAD,EAAGX,GAAG,CAAC,CAACY;YAC5C,MAAMR,QAAQQ,OAAOR,KAAK,IAAI,CAAC;YAE/B,oDAAoD;YACpD,IAAId,cAAce,SAAS,EAAE;gBAC5BD,MAAME,WAAW,GAAG;uBACfF,MAAME,WAAW,IAAI,EAAE;oBAC3BlB,iBAAiB;wBAChBmB,QAAQjB,cAAce,SAAS;wBAC/BG,MAAMI,OAAOJ,IAAI;wBACjBC,QAAQG,OAAOH,MAAM;wBACrBC,cAAc;oBACf;iBACA;YACF;YAEA,OAAO;gBACN,GAAGE,MAAM;gBACTR;YACD;QACD;QAEA,OAAOZ;IACR,EAAE"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { CollectionConfig, Config } from 'payload';\nimport { injectAdminIcon, injectAdminLogo } from './plugin/admin.js';\nimport { injectEmailTemplates } from './plugin/email.js';\nimport { cacheHookCollections, cacheHookGlobals } from './plugin/hooks.js';\nimport type { PayloadHelperPluginConfig } from './types.js';\n\n/**\n * Payload Helper Plugin for websites at ainsley.dev\n *\n * @constructor\n * @param pluginOptions\n */\nexport const payloadHelper =\n\t(pluginOptions: PayloadHelperPluginConfig) =>\n\t(incomingConfig: Config): Config => {\n\t\t// TODO: Validate Config\n\n\t\tlet config = incomingConfig;\n\n\t\t// Update typescript generation file\n\t\tconfig.typescript = config.typescript || {};\n\t\tconfig.typescript.outputFile = './src/types/payload.ts';\n\n\t\t// Inject admin Logo component if logo config is provided\n\t\tif (pluginOptions.admin?.logo) {\n\t\t\tconfig = injectAdminLogo(config, pluginOptions.admin.logo, pluginOptions.siteName);\n\t\t}\n\n\t\t// Inject admin Icon component if icon config is provided\n\t\tif (pluginOptions.admin?.icon) {\n\t\t\tconfig = injectAdminIcon(config, pluginOptions.admin.icon, pluginOptions.siteName);\n\t\t}\n\n\t\t// Inject email templates for auth-enabled collections if email config is provided\n\t\tif (pluginOptions.email) {\n\t\t\tconfig = injectEmailTemplates(config, pluginOptions.email);\n\t\t}\n\n\t\t// Map collections & add hooks\n\t\tconfig.collections = (config.collections || []).map((collection): CollectionConfig => {\n\t\t\tif (collection.upload !== undefined && collection.upload !== true) {\n\t\t\t\treturn collection;\n\t\t\t}\n\n\t\t\tconst hooks = collection.hooks || {};\n\n\t\t\t// Add afterChange hook only if webServer is defined\n\t\t\tif (pluginOptions.webServer) {\n\t\t\t\thooks.afterChange = [\n\t\t\t\t\t...(hooks.afterChange || []),\n\t\t\t\t\tcacheHookCollections({\n\t\t\t\t\t\tserver: pluginOptions.webServer,\n\t\t\t\t\t\tslug: collection.slug,\n\t\t\t\t\t\tfields: collection.fields,\n\t\t\t\t\t\tisCollection: true,\n\t\t\t\t\t}),\n\t\t\t\t];\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t...collection,\n\t\t\t\thooks,\n\t\t\t};\n\t\t});\n\n\t\t// Map globals & add hooks\n\t\tconfig.globals = (config.globals || []).map((global) => {\n\t\t\tconst hooks = global.hooks || {};\n\n\t\t\t// Add afterChange hook only if webServer is defined\n\t\t\tif (pluginOptions.webServer) {\n\t\t\t\thooks.afterChange = [\n\t\t\t\t\t...(hooks.afterChange || []),\n\t\t\t\t\tcacheHookGlobals({\n\t\t\t\t\t\tserver: pluginOptions.webServer,\n\t\t\t\t\t\tslug: global.slug,\n\t\t\t\t\t\tfields: global.fields,\n\t\t\t\t\t\tisCollection: true,\n\t\t\t\t\t}),\n\t\t\t\t];\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t...global,\n\t\t\t\thooks,\n\t\t\t};\n\t\t});\n\n\t\t// Store plugin options in config.custom for CLI access (e.g., preview-emails command)\n\t\tconfig.custom = {\n\t\t\t...config.custom,\n\t\t\tpayloadHelperOptions: pluginOptions,\n\t\t};\n\n\t\treturn config;\n\t};\n\nexport type { IconProps } from './admin/components/Icon.js';\nexport type { LogoProps } from './admin/components/Logo.js';\nexport { ForgotPasswordEmail } from './email/ForgotPasswordEmail.js';\nexport type { ForgotPasswordEmailProps } from './email/ForgotPasswordEmail.js';\nexport { VerifyAccountEmail } from './email/VerifyAccountEmail.js';\nexport type { VerifyAccountEmailProps } from './email/VerifyAccountEmail.js';\nexport { default as env } from './util/env.js';\nexport type {\n\tAdminConfig,\n\tAdminIconConfig,\n\tAdminLogoConfig,\n\tEmailConfig,\n\tEmailContentOverrides,\n\tPayloadHelperPluginConfig,\n} from './types.js';\n"],"names":["injectAdminIcon","injectAdminLogo","injectEmailTemplates","cacheHookCollections","cacheHookGlobals","payloadHelper","pluginOptions","incomingConfig","config","typescript","outputFile","admin","logo","siteName","icon","email","collections","map","collection","upload","undefined","hooks","webServer","afterChange","server","slug","fields","isCollection","globals","global","custom","payloadHelperOptions","ForgotPasswordEmail","VerifyAccountEmail","default","env"],"mappings":"AACA,SAASA,eAAe,EAAEC,eAAe,QAAQ,oBAAoB;AACrE,SAASC,oBAAoB,QAAQ,oBAAoB;AACzD,SAASC,oBAAoB,EAAEC,gBAAgB,QAAQ,oBAAoB;AAG3E;;;;;CAKC,GACD,OAAO,MAAMC,gBACZ,CAACC,gBACD,CAACC;QACA,wBAAwB;QAExB,IAAIC,SAASD;QAEb,oCAAoC;QACpCC,OAAOC,UAAU,GAAGD,OAAOC,UAAU,IAAI,CAAC;QAC1CD,OAAOC,UAAU,CAACC,UAAU,GAAG;QAE/B,yDAAyD;QACzD,IAAIJ,cAAcK,KAAK,EAAEC,MAAM;YAC9BJ,SAASP,gBAAgBO,QAAQF,cAAcK,KAAK,CAACC,IAAI,EAAEN,cAAcO,QAAQ;QAClF;QAEA,yDAAyD;QACzD,IAAIP,cAAcK,KAAK,EAAEG,MAAM;YAC9BN,SAASR,gBAAgBQ,QAAQF,cAAcK,KAAK,CAACG,IAAI,EAAER,cAAcO,QAAQ;QAClF;QAEA,kFAAkF;QAClF,IAAIP,cAAcS,KAAK,EAAE;YACxBP,SAASN,qBAAqBM,QAAQF,cAAcS,KAAK;QAC1D;QAEA,8BAA8B;QAC9BP,OAAOQ,WAAW,GAAG,AAACR,CAAAA,OAAOQ,WAAW,IAAI,EAAE,AAAD,EAAGC,GAAG,CAAC,CAACC;YACpD,IAAIA,WAAWC,MAAM,KAAKC,aAAaF,WAAWC,MAAM,KAAK,MAAM;gBAClE,OAAOD;YACR;YAEA,MAAMG,QAAQH,WAAWG,KAAK,IAAI,CAAC;YAEnC,oDAAoD;YACpD,IAAIf,cAAcgB,SAAS,EAAE;gBAC5BD,MAAME,WAAW,GAAG;uBACfF,MAAME,WAAW,IAAI,EAAE;oBAC3BpB,qBAAqB;wBACpBqB,QAAQlB,cAAcgB,SAAS;wBAC/BG,MAAMP,WAAWO,IAAI;wBACrBC,QAAQR,WAAWQ,MAAM;wBACzBC,cAAc;oBACf;iBACA;YACF;YAEA,OAAO;gBACN,GAAGT,UAAU;gBACbG;YACD;QACD;QAEA,0BAA0B;QAC1Bb,OAAOoB,OAAO,GAAG,AAACpB,CAAAA,OAAOoB,OAAO,IAAI,EAAE,AAAD,EAAGX,GAAG,CAAC,CAACY;YAC5C,MAAMR,QAAQQ,OAAOR,KAAK,IAAI,CAAC;YAE/B,oDAAoD;YACpD,IAAIf,cAAcgB,SAAS,EAAE;gBAC5BD,MAAME,WAAW,GAAG;uBACfF,MAAME,WAAW,IAAI,EAAE;oBAC3BnB,iBAAiB;wBAChBoB,QAAQlB,cAAcgB,SAAS;wBAC/BG,MAAMI,OAAOJ,IAAI;wBACjBC,QAAQG,OAAOH,MAAM;wBACrBC,cAAc;oBACf;iBACA;YACF;YAEA,OAAO;gBACN,GAAGE,MAAM;gBACTR;YACD;QACD;QAEA,sFAAsF;QACtFb,OAAOsB,MAAM,GAAG;YACf,GAAGtB,OAAOsB,MAAM;YAChBC,sBAAsBzB;QACvB;QAEA,OAAOE;IACR,EAAE;AAIH,SAASwB,mBAAmB,QAAQ,iCAAiC;AAErE,SAASC,kBAAkB,QAAQ,gCAAgC;AAEnE,SAASC,WAAWC,GAAG,QAAQ,gBAAgB"}
@@ -0,0 +1,10 @@
1
+ import type { Config } from 'payload';
2
+ import type { EmailConfig } from '../types.js';
3
+ /**
4
+ * Injects email templates into all auth-enabled collections in the Payload config.
5
+ *
6
+ * @param config - The Payload configuration object
7
+ * @param emailConfig - The email configuration from plugin options
8
+ * @returns The modified Payload configuration with email templates injected
9
+ */
10
+ export declare const injectEmailTemplates: (config: Config, emailConfig: EmailConfig) => Config;
@@ -0,0 +1,98 @@
1
+ import { renderEmail } from '@ainsleydev/email-templates';
2
+ import { ForgotPasswordEmail } from '../email/ForgotPasswordEmail.js';
3
+ import { VerifyAccountEmail } from '../email/VerifyAccountEmail.js';
4
+ /**
5
+ * Injects email templates into all auth-enabled collections in the Payload config.
6
+ *
7
+ * @param config - The Payload configuration object
8
+ * @param emailConfig - The email configuration from plugin options
9
+ * @returns The modified Payload configuration with email templates injected
10
+ */ export const injectEmailTemplates = (config, emailConfig)=>{
11
+ // Get the website URL for branding, defaulting to Payload's serverUrl
12
+ const websiteUrl = emailConfig.frontEndUrl || config.serverURL || '';
13
+ // Merge user theme with websiteUrl for branding
14
+ const themeOverride = {
15
+ ...emailConfig.theme,
16
+ branding: {
17
+ ...emailConfig.theme?.branding,
18
+ websiteUrl
19
+ }
20
+ };
21
+ // Find all collections with auth enabled
22
+ const collectionsWithAuth = config.collections?.filter((collection)=>collection.auth) || [];
23
+ // If no collections with auth, return config unchanged
24
+ if (collectionsWithAuth.length === 0) {
25
+ return config;
26
+ }
27
+ // Inject email templates into each auth-enabled collection
28
+ const updatedCollections = config.collections?.map((collection)=>{
29
+ // Skip collections without auth
30
+ if (!collection.auth) {
31
+ return collection;
32
+ }
33
+ // Clone the collection to avoid mutation
34
+ const updatedCollection = {
35
+ ...collection
36
+ };
37
+ // Ensure auth is an object (it could be true or an object)
38
+ if (typeof updatedCollection.auth === 'boolean') {
39
+ updatedCollection.auth = {};
40
+ } else {
41
+ updatedCollection.auth = {
42
+ ...updatedCollection.auth
43
+ };
44
+ }
45
+ // Inject forgotPassword email template
46
+ const currentForgotPassword = updatedCollection.auth.forgotPassword;
47
+ updatedCollection.auth.forgotPassword = {
48
+ ...typeof currentForgotPassword === 'object' ? currentForgotPassword : {},
49
+ generateEmailHTML: async (args)=>{
50
+ const token = args?.token || '';
51
+ const user = args?.user || {};
52
+ const resetUrl = `${config.serverURL}/admin/reset/${token}`;
53
+ return renderEmail({
54
+ component: ForgotPasswordEmail,
55
+ props: {
56
+ user: {
57
+ firstName: user?.firstName,
58
+ email: user?.email
59
+ },
60
+ resetUrl,
61
+ content: emailConfig.forgotPassword
62
+ },
63
+ theme: themeOverride
64
+ });
65
+ }
66
+ };
67
+ // Inject verify email template
68
+ const currentVerify = updatedCollection.auth.verify;
69
+ updatedCollection.auth.verify = {
70
+ ...typeof currentVerify === 'object' ? currentVerify : {},
71
+ generateEmailHTML: async (args)=>{
72
+ const token = args?.token || '';
73
+ const user = args?.user || {};
74
+ // For verify emails, the token is used in the verification URL
75
+ const verifyUrl = `${config.serverURL}/admin/${collection.slug}/verify/${token}`;
76
+ return renderEmail({
77
+ component: VerifyAccountEmail,
78
+ props: {
79
+ user: {
80
+ firstName: user?.firstName,
81
+ email: user?.email
82
+ },
83
+ verifyUrl,
84
+ content: emailConfig.verifyAccount
85
+ },
86
+ theme: themeOverride
87
+ });
88
+ }
89
+ };
90
+ return updatedCollection;
91
+ });
92
+ return {
93
+ ...config,
94
+ collections: updatedCollections
95
+ };
96
+ };
97
+
98
+ //# sourceMappingURL=email.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/plugin/email.ts"],"sourcesContent":["import { renderEmail } from '@ainsleydev/email-templates';\nimport type { Config } from 'payload';\n\nimport { ForgotPasswordEmail } from '../email/ForgotPasswordEmail.js';\nimport { VerifyAccountEmail } from '../email/VerifyAccountEmail.js';\nimport type { EmailConfig } from '../types.js';\n\n/**\n * Injects email templates into all auth-enabled collections in the Payload config.\n *\n * @param config - The Payload configuration object\n * @param emailConfig - The email configuration from plugin options\n * @returns The modified Payload configuration with email templates injected\n */\nexport const injectEmailTemplates = (config: Config, emailConfig: EmailConfig): Config => {\n\t// Get the website URL for branding, defaulting to Payload's serverUrl\n\tconst websiteUrl = emailConfig.frontEndUrl || config.serverURL || '';\n\n\t// Merge user theme with websiteUrl for branding\n\tconst themeOverride = {\n\t\t...emailConfig.theme,\n\t\tbranding: {\n\t\t\t...emailConfig.theme?.branding,\n\t\t\twebsiteUrl,\n\t\t},\n\t};\n\n\t// Find all collections with auth enabled\n\tconst collectionsWithAuth = config.collections?.filter((collection) => collection.auth) || [];\n\n\t// If no collections with auth, return config unchanged\n\tif (collectionsWithAuth.length === 0) {\n\t\treturn config;\n\t}\n\n\t// Inject email templates into each auth-enabled collection\n\tconst updatedCollections = config.collections?.map((collection) => {\n\t\t// Skip collections without auth\n\t\tif (!collection.auth) {\n\t\t\treturn collection;\n\t\t}\n\n\t\t// Clone the collection to avoid mutation\n\t\tconst updatedCollection = { ...collection };\n\n\t\t// Ensure auth is an object (it could be true or an object)\n\t\tif (typeof updatedCollection.auth === 'boolean') {\n\t\t\tupdatedCollection.auth = {};\n\t\t} else {\n\t\t\tupdatedCollection.auth = { ...updatedCollection.auth };\n\t\t}\n\n\t\t// Inject forgotPassword email template\n\t\tconst currentForgotPassword = updatedCollection.auth.forgotPassword;\n\t\tupdatedCollection.auth.forgotPassword = {\n\t\t\t...(typeof currentForgotPassword === 'object' ? currentForgotPassword : {}),\n\t\t\tgenerateEmailHTML: async (args) => {\n\t\t\t\tconst token = args?.token || '';\n\t\t\t\tconst user = args?.user || {};\n\t\t\t\tconst resetUrl = `${config.serverURL}/admin/reset/${token}`;\n\n\t\t\t\treturn renderEmail({\n\t\t\t\t\tcomponent: ForgotPasswordEmail,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\tfirstName: user?.firstName,\n\t\t\t\t\t\t\temail: user?.email,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tresetUrl,\n\t\t\t\t\t\tcontent: emailConfig.forgotPassword,\n\t\t\t\t\t},\n\t\t\t\t\ttheme: themeOverride,\n\t\t\t\t});\n\t\t\t},\n\t\t};\n\n\t\t// Inject verify email template\n\t\tconst currentVerify = updatedCollection.auth.verify;\n\t\tupdatedCollection.auth.verify = {\n\t\t\t...(typeof currentVerify === 'object' ? currentVerify : {}),\n\t\t\tgenerateEmailHTML: async (args) => {\n\t\t\t\tconst token = args?.token || '';\n\t\t\t\tconst user = args?.user || {};\n\t\t\t\t// For verify emails, the token is used in the verification URL\n\t\t\t\tconst verifyUrl = `${config.serverURL}/admin/${collection.slug}/verify/${token}`;\n\n\t\t\t\treturn renderEmail({\n\t\t\t\t\tcomponent: VerifyAccountEmail,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\tfirstName: user?.firstName,\n\t\t\t\t\t\t\temail: user?.email,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tverifyUrl,\n\t\t\t\t\t\tcontent: emailConfig.verifyAccount,\n\t\t\t\t\t},\n\t\t\t\t\ttheme: themeOverride,\n\t\t\t\t});\n\t\t\t},\n\t\t};\n\n\t\treturn updatedCollection;\n\t});\n\n\treturn {\n\t\t...config,\n\t\tcollections: updatedCollections,\n\t};\n};\n"],"names":["renderEmail","ForgotPasswordEmail","VerifyAccountEmail","injectEmailTemplates","config","emailConfig","websiteUrl","frontEndUrl","serverURL","themeOverride","theme","branding","collectionsWithAuth","collections","filter","collection","auth","length","updatedCollections","map","updatedCollection","currentForgotPassword","forgotPassword","generateEmailHTML","args","token","user","resetUrl","component","props","firstName","email","content","currentVerify","verify","verifyUrl","slug","verifyAccount"],"mappings":"AAAA,SAASA,WAAW,QAAQ,8BAA8B;AAG1D,SAASC,mBAAmB,QAAQ,kCAAkC;AACtE,SAASC,kBAAkB,QAAQ,iCAAiC;AAGpE;;;;;;CAMC,GACD,OAAO,MAAMC,uBAAuB,CAACC,QAAgBC;IACpD,sEAAsE;IACtE,MAAMC,aAAaD,YAAYE,WAAW,IAAIH,OAAOI,SAAS,IAAI;IAElE,gDAAgD;IAChD,MAAMC,gBAAgB;QACrB,GAAGJ,YAAYK,KAAK;QACpBC,UAAU;YACT,GAAGN,YAAYK,KAAK,EAAEC,QAAQ;YAC9BL;QACD;IACD;IAEA,yCAAyC;IACzC,MAAMM,sBAAsBR,OAAOS,WAAW,EAAEC,OAAO,CAACC,aAAeA,WAAWC,IAAI,KAAK,EAAE;IAE7F,uDAAuD;IACvD,IAAIJ,oBAAoBK,MAAM,KAAK,GAAG;QACrC,OAAOb;IACR;IAEA,2DAA2D;IAC3D,MAAMc,qBAAqBd,OAAOS,WAAW,EAAEM,IAAI,CAACJ;QACnD,gCAAgC;QAChC,IAAI,CAACA,WAAWC,IAAI,EAAE;YACrB,OAAOD;QACR;QAEA,yCAAyC;QACzC,MAAMK,oBAAoB;YAAE,GAAGL,UAAU;QAAC;QAE1C,2DAA2D;QAC3D,IAAI,OAAOK,kBAAkBJ,IAAI,KAAK,WAAW;YAChDI,kBAAkBJ,IAAI,GAAG,CAAC;QAC3B,OAAO;YACNI,kBAAkBJ,IAAI,GAAG;gBAAE,GAAGI,kBAAkBJ,IAAI;YAAC;QACtD;QAEA,uCAAuC;QACvC,MAAMK,wBAAwBD,kBAAkBJ,IAAI,CAACM,cAAc;QACnEF,kBAAkBJ,IAAI,CAACM,cAAc,GAAG;YACvC,GAAI,OAAOD,0BAA0B,WAAWA,wBAAwB,CAAC,CAAC;YAC1EE,mBAAmB,OAAOC;gBACzB,MAAMC,QAAQD,MAAMC,SAAS;gBAC7B,MAAMC,OAAOF,MAAME,QAAQ,CAAC;gBAC5B,MAAMC,WAAW,GAAGvB,OAAOI,SAAS,CAAC,aAAa,EAAEiB,OAAO;gBAE3D,OAAOzB,YAAY;oBAClB4B,WAAW3B;oBACX4B,OAAO;wBACNH,MAAM;4BACLI,WAAWJ,MAAMI;4BACjBC,OAAOL,MAAMK;wBACd;wBACAJ;wBACAK,SAAS3B,YAAYiB,cAAc;oBACpC;oBACAZ,OAAOD;gBACR;YACD;QACD;QAEA,+BAA+B;QAC/B,MAAMwB,gBAAgBb,kBAAkBJ,IAAI,CAACkB,MAAM;QACnDd,kBAAkBJ,IAAI,CAACkB,MAAM,GAAG;YAC/B,GAAI,OAAOD,kBAAkB,WAAWA,gBAAgB,CAAC,CAAC;YAC1DV,mBAAmB,OAAOC;gBACzB,MAAMC,QAAQD,MAAMC,SAAS;gBAC7B,MAAMC,OAAOF,MAAME,QAAQ,CAAC;gBAC5B,+DAA+D;gBAC/D,MAAMS,YAAY,GAAG/B,OAAOI,SAAS,CAAC,OAAO,EAAEO,WAAWqB,IAAI,CAAC,QAAQ,EAAEX,OAAO;gBAEhF,OAAOzB,YAAY;oBAClB4B,WAAW1B;oBACX2B,OAAO;wBACNH,MAAM;4BACLI,WAAWJ,MAAMI;4BACjBC,OAAOL,MAAMK;wBACd;wBACAI;wBACAH,SAAS3B,YAAYgC,aAAa;oBACnC;oBACA3B,OAAOD;gBACR;YACD;QACD;QAEA,OAAOW;IACR;IAEA,OAAO;QACN,GAAGhB,MAAM;QACTS,aAAaK;IACd;AACD,EAAE"}