@ainsleydev/payload-helper 0.0.40 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +227 -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/collections/index.d.ts +3 -0
  8. package/dist/collections/index.js +4 -0
  9. package/dist/collections/index.js.map +1 -0
  10. package/dist/common/index.d.ts +1 -0
  11. package/dist/common/index.js +3 -0
  12. package/dist/common/index.js.map +1 -0
  13. package/dist/email/ForgotPasswordEmail.d.ts +38 -0
  14. package/dist/email/ForgotPasswordEmail.js +61 -0
  15. package/dist/email/ForgotPasswordEmail.js.map +1 -0
  16. package/dist/email/ForgotPasswordEmail.test.d.ts +1 -0
  17. package/dist/email/ForgotPasswordEmail.test.js +202 -0
  18. package/dist/email/ForgotPasswordEmail.test.js.map +1 -0
  19. package/dist/email/VerifyAccountEmail.d.ts +38 -0
  20. package/dist/email/VerifyAccountEmail.js +61 -0
  21. package/dist/email/VerifyAccountEmail.js.map +1 -0
  22. package/dist/email/VerifyAccountEmail.test.d.ts +1 -0
  23. package/dist/email/VerifyAccountEmail.test.js +212 -0
  24. package/dist/email/VerifyAccountEmail.test.js.map +1 -0
  25. package/dist/endpoints/index.d.ts +1 -0
  26. package/dist/endpoints/index.js +3 -0
  27. package/dist/endpoints/index.js.map +1 -0
  28. package/dist/globals/index.d.ts +5 -0
  29. package/dist/globals/index.js +6 -0
  30. package/dist/globals/index.js.map +1 -0
  31. package/dist/index.d.ts +15 -10
  32. package/dist/index.js +14 -66
  33. package/dist/index.js.map +1 -1
  34. package/dist/plugin/email.d.ts +10 -0
  35. package/dist/plugin/email.js +98 -0
  36. package/dist/plugin/email.js.map +1 -0
  37. package/dist/plugin/email.test.js +265 -0
  38. package/dist/plugin/email.test.js.map +1 -0
  39. package/dist/plugin.d.ts +9 -0
  40. package/dist/plugin.js +78 -0
  41. package/dist/plugin.js.map +1 -0
  42. package/dist/types.d.ts +134 -0
  43. package/dist/types.js +3 -1
  44. package/dist/types.js.map +1 -1
  45. package/dist/util/index.d.ts +4 -0
  46. package/dist/util/index.js +6 -0
  47. package/dist/util/index.js.map +1 -0
  48. package/package.json +47 -14
  49. package/dist/plugin/icon.d.ts +0 -6
  50. package/dist/plugin/icon.js +0 -26
  51. package/dist/plugin/icon.js.map +0 -1
  52. package/dist/plugin/logo.d.ts +0 -6
  53. package/dist/plugin/logo.js +0 -26
  54. package/dist/plugin/logo.js.map +0 -1
package/README.md CHANGED
@@ -48,6 +48,157 @@ export default buildConfig({
48
48
  })
49
49
  ```
50
50
 
51
+ ## Available Exports
52
+
53
+ The payload-helper package exports a variety of utilities, collections, globals, and components that you can use directly in your Payload projects.
54
+
55
+ ### Collections
56
+
57
+ Pre-built Payload collections ready to use:
58
+
59
+ ```typescript
60
+ import { Media, Redirects, imageSizes, imageSizesWithAvif } from '@ainsleydev/payload-helper'
61
+
62
+ // Use in your Payload config
63
+ export default buildConfig({
64
+ collections: [
65
+ Media({ includeAvif: true, additionalFields: [...] }),
66
+ Redirects(),
67
+ ],
68
+ })
69
+ ```
70
+
71
+ **Subpath imports** (optional):
72
+ ```typescript
73
+ import { Media, Redirects } from '@ainsleydev/payload-helper/collections'
74
+ ```
75
+
76
+ ### Globals
77
+
78
+ Pre-configured global types for common website needs:
79
+
80
+ ```typescript
81
+ import { Settings, Navigation, countries, languages } from '@ainsleydev/payload-helper'
82
+
83
+ export default buildConfig({
84
+ globals: [
85
+ Settings({ additionalTabs: [...] }),
86
+ Navigation({ includeFooter: true }),
87
+ ],
88
+ })
89
+ ```
90
+
91
+ **Subpath imports** (optional):
92
+ ```typescript
93
+ import { Settings, Navigation } from '@ainsleydev/payload-helper/globals'
94
+ ```
95
+
96
+ ### Utilities
97
+
98
+ Helpful utility functions for validation, field operations, and Lexical conversion:
99
+
100
+ ```typescript
101
+ import {
102
+ env,
103
+ fieldHasName,
104
+ validateURL,
105
+ validatePostcode,
106
+ htmlToLexical,
107
+ lexicalToHtml,
108
+ } from '@ainsleydev/payload-helper'
109
+
110
+ // Use in field validation
111
+ {
112
+ name: 'website',
113
+ type: 'text',
114
+ validate: validateURL,
115
+ }
116
+
117
+ // Convert HTML to Lexical format
118
+ const lexicalData = await htmlToLexical('<p>Hello world</p>')
119
+
120
+ // Convert Lexical to HTML
121
+ const html = await lexicalToHtml(lexicalData)
122
+ ```
123
+
124
+ **Subpath imports** (optional):
125
+ ```typescript
126
+ import { validateURL, htmlToLexical } from '@ainsleydev/payload-helper/util'
127
+ ```
128
+
129
+ ### Common/Reusable Fields
130
+
131
+ Reusable field definitions:
132
+
133
+ ```typescript
134
+ import { SEOFields } from '@ainsleydev/payload-helper'
135
+ import { seoPlugin } from '@payloadcms/plugin-seo'
136
+
137
+ export default buildConfig({
138
+ plugins: [
139
+ seoPlugin({
140
+ collections: ['pages'],
141
+ fields: SEOFields,
142
+ }),
143
+ ],
144
+ })
145
+ ```
146
+
147
+ **Subpath imports** (optional):
148
+ ```typescript
149
+ import { SEOFields } from '@ainsleydev/payload-helper/common'
150
+ ```
151
+
152
+ ### Endpoints
153
+
154
+ Custom API endpoints:
155
+
156
+ ```typescript
157
+ import { findBySlug } from '@ainsleydev/payload-helper'
158
+
159
+ // Use in your collection config
160
+ export const Pages: CollectionConfig = {
161
+ slug: 'pages',
162
+ endpoints: [findBySlug],
163
+ }
164
+ ```
165
+
166
+ **Subpath imports** (optional):
167
+ ```typescript
168
+ import { findBySlug } from '@ainsleydev/payload-helper/endpoints'
169
+ ```
170
+
171
+ ### Email Components
172
+
173
+ Customizable email templates for authentication flows:
174
+
175
+ ```typescript
176
+ import { ForgotPasswordEmail, VerifyAccountEmail } from '@ainsleydev/payload-helper'
177
+ import type { ForgotPasswordEmailProps, VerifyAccountEmailProps } from '@ainsleydev/payload-helper'
178
+
179
+ // Use directly in custom email handlers
180
+ const emailHtml = ForgotPasswordEmail({
181
+ resetPasswordToken: 'token123',
182
+ frontEndUrl: 'https://yoursite.com',
183
+ // ...other props
184
+ })
185
+ ```
186
+
187
+ ### Schema Utilities
188
+
189
+ For projects that need JSON schema generation (e.g., Go type generation):
190
+
191
+ ```typescript
192
+ import { fieldMapper, schemas, addGoJSONSchema } from '@ainsleydev/payload-helper'
193
+ import type { SchemaOptions } from '@ainsleydev/payload-helper'
194
+
195
+ // Apply Go schema mappings
196
+ const config = fieldMapper(sanitizedConfig, {
197
+ useWebKitMedia: true,
198
+ assignRelationships: true,
199
+ })
200
+ ```
201
+
51
202
  ## Configuration
52
203
 
53
204
  ### Admin configuration
@@ -91,6 +242,82 @@ payloadHelper({
91
242
  })
92
243
  ```
93
244
 
245
+ ### Email configuration
246
+
247
+ Configure branded email templates for Payload authentication flows. Automatically applies to all collections with `auth` enabled.
248
+
249
+ ```typescript
250
+ payloadHelper({
251
+ siteName: 'My Site',
252
+ email: {
253
+ frontEndUrl: 'https://your-site.com', // Optional, defaults to Payload's serverURL
254
+ theme: {
255
+ branding: {
256
+ companyName: 'My Company',
257
+ logoUrl: 'https://your-site.com/logo.png',
258
+ },
259
+ colours: {
260
+ background: {
261
+ accent: '#ff5043',
262
+ },
263
+ },
264
+ },
265
+ forgotPassword: {
266
+ heading: 'Reset your password',
267
+ bodyText: 'Click the button below to reset your password.',
268
+ buttonText: 'Reset Password',
269
+ },
270
+ verifyAccount: {
271
+ heading: 'Welcome aboard',
272
+ bodyText: 'Please verify your email address.',
273
+ buttonText: 'Verify Email',
274
+ },
275
+ },
276
+ })
277
+ ```
278
+
279
+ #### Previewing emails
280
+
281
+ Preview your emails with your actual branding directly from your Payload configuration:
282
+
283
+ ```bash
284
+ npx payload-helper preview-emails
285
+ ```
286
+
287
+ This command will:
288
+ - Read your `payload.config.ts` to extract your email theme configuration
289
+ - Generate preview templates with your actual branding
290
+ - Launch a preview server at http://localhost:3000
291
+
292
+ You can optionally specify a custom port:
293
+
294
+ ```bash
295
+ npx payload-helper preview-emails --port 3001
296
+ ```
297
+
298
+ The preview will show both ForgotPassword and VerifyAccount emails using your configured theme, frontEndUrl, and content overrides.
299
+
300
+ ## Utilities
301
+
302
+ ### Environment Variables
303
+
304
+ The package exports an `env` utility object that provides access to environment variables required by Payload Helper.
305
+
306
+ ```typescript
307
+ import { env } from '@ainsleydev/payload-helper'
308
+
309
+ // Access environment variables
310
+ const spaces = {
311
+ key: env.DO_SPACES_KEY,
312
+ secret: env.DO_SPACES_SECRET,
313
+ endpoint: env.DO_SPACES_ENDPOINT,
314
+ region: env.DO_SPACES_REGION,
315
+ bucket: env.DO_SPACES_BUCKET,
316
+ }
317
+ ```
318
+
319
+ **Note:** When using ESM modules, always import utilities from the main package entry point as shown above. Direct imports to subpaths (e.g., `@ainsleydev/payload-helper/dist/util/env`) are not supported.
320
+
94
321
  ## Open Source
95
322
 
96
323
  ainsley.dev permits the use of any HTML, SCSS and Javascript found within the repository for use
package/dist/cli/bin.js CHANGED
@@ -1,9 +1,29 @@
1
1
  #!/usr/bin/env node
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
2
4
  import { Command } from 'commander';
5
+ import { getPayload } from 'payload';
6
+ import { previewEmails } from './commands/preview-emails.js';
3
7
  const program = new Command();
8
+ const filename = fileURLToPath(import.meta.url);
9
+ const dirname = path.dirname(filename);
4
10
  program.command('generate-types').description('Generate JSON schema types for Payload CMS');
11
+ program.command('preview-emails').description('Preview email templates with your Payload configuration').option('-p, --port <number>', 'Port to run preview server on', '3000').action(async (options)=>{
12
+ const payload = await getPayloadInstance();
13
+ await previewEmails({
14
+ payload,
15
+ port: Number.parseInt(options.port, 10)
16
+ });
17
+ });
5
18
  export const bin = async ()=>{
6
19
  await program.parseAsync(process.argv);
7
20
  };
21
+ const getPayloadInstance = async ()=>{
22
+ const configPath = path.join(process.cwd(), 'src/payload.config.ts');
23
+ const config = (await import(configPath)).default;
24
+ return await getPayload({
25
+ config
26
+ });
27
+ };
8
28
 
9
29
  //# sourceMappingURL=bin.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/bin.ts"],"sourcesContent":["#!/usr/bin/env node\nimport chalk from 'chalk';\nimport { Command } from 'commander';\n\nconst program = new Command();\n\nprogram.command('generate-types').description('Generate JSON schema types for Payload CMS');\n\nexport const bin = async () => {\n\tawait program.parseAsync(process.argv);\n};\n"],"names":["Command","program","command","description","bin","parseAsync","process","argv"],"mappings":";AAEA,SAASA,OAAO,QAAQ,YAAY;AAEpC,MAAMC,UAAU,IAAID;AAEpBC,QAAQC,OAAO,CAAC,kBAAkBC,WAAW,CAAC;AAE9C,OAAO,MAAMC,MAAM;IAClB,MAAMH,QAAQI,UAAU,CAACC,QAAQC,IAAI;AACtC,EAAE"}
1
+ {"version":3,"sources":["../../src/cli/bin.ts"],"sourcesContent":["#!/usr/bin/env node\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { Command } from 'commander';\nimport { type Payload, getPayload } from 'payload';\nimport { previewEmails } from './commands/preview-emails.js';\n\nconst program = new Command();\nconst filename = fileURLToPath(import.meta.url);\nconst dirname = path.dirname(filename);\n\nprogram.command('generate-types').description('Generate JSON schema types for Payload CMS');\nprogram\n\t.command('preview-emails')\n\t.description('Preview email templates with your Payload configuration')\n\t.option('-p, --port <number>', 'Port to run preview server on', '3000')\n\t.action(async (options) => {\n\t\tconst payload = await getPayloadInstance();\n\n\t\tawait previewEmails({\n\t\t\tpayload,\n\t\t\tport: Number.parseInt(options.port, 10),\n\t\t});\n\t});\n\nexport const bin = async () => {\n\tawait program.parseAsync(process.argv);\n};\n\nconst getPayloadInstance = async (): Promise<Payload> => {\n\tconst configPath = path.join(process.cwd(), 'src/payload.config.ts');\n\tconst config = (await import(configPath)).default;\n\n\treturn await getPayload({ config });\n};\n"],"names":["path","fileURLToPath","Command","getPayload","previewEmails","program","filename","url","dirname","command","description","option","action","options","payload","getPayloadInstance","port","Number","parseInt","bin","parseAsync","process","argv","configPath","join","cwd","config","default"],"mappings":";AAEA,OAAOA,UAAU,YAAY;AAC7B,SAASC,aAAa,QAAQ,WAAW;AACzC,SAASC,OAAO,QAAQ,YAAY;AACpC,SAAuBC,UAAU,QAAQ,UAAU;AACnD,SAASC,aAAa,QAAQ,+BAA+B;AAE7D,MAAMC,UAAU,IAAIH;AACpB,MAAMI,WAAWL,cAAc,YAAYM,GAAG;AAC9C,MAAMC,UAAUR,KAAKQ,OAAO,CAACF;AAE7BD,QAAQI,OAAO,CAAC,kBAAkBC,WAAW,CAAC;AAC9CL,QACEI,OAAO,CAAC,kBACRC,WAAW,CAAC,2DACZC,MAAM,CAAC,uBAAuB,iCAAiC,QAC/DC,MAAM,CAAC,OAAOC;IACd,MAAMC,UAAU,MAAMC;IAEtB,MAAMX,cAAc;QACnBU;QACAE,MAAMC,OAAOC,QAAQ,CAACL,QAAQG,IAAI,EAAE;IACrC;AACD;AAED,OAAO,MAAMG,MAAM;IAClB,MAAMd,QAAQe,UAAU,CAACC,QAAQC,IAAI;AACtC,EAAE;AAEF,MAAMP,qBAAqB;IAC1B,MAAMQ,aAAavB,KAAKwB,IAAI,CAACH,QAAQI,GAAG,IAAI;IAC5C,MAAMC,SAAS,AAAC,CAAA,MAAM,MAAM,CAACH,WAAU,EAAGI,OAAO;IAEjD,OAAO,MAAMxB,WAAW;QAAEuB;IAAO;AAClC"}
@@ -0,0 +1,5 @@
1
+ import type { Payload } from 'payload';
2
+ export declare const previewEmails: (options: {
3
+ payload: Payload;
4
+ port?: number;
5
+ }) => Promise<void>;
@@ -0,0 +1,123 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { mkdirSync, rmSync, writeFileSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import chalk from 'chalk';
6
+ /**
7
+ * Escapes a string for safe use in template literals.
8
+ */ const escapeForTemplate = (str)=>{
9
+ return str.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$/g, '\\$');
10
+ };
11
+ /**
12
+ * Retrieves the email configuration from the Payload config.
13
+ */ const getEmailConfig = (payload)=>{
14
+ const custom = payload.config.custom;
15
+ const payloadHelperOptions = custom?.payloadHelperOptions;
16
+ return payloadHelperOptions?.email;
17
+ };
18
+ export const previewEmails = async (options)=>{
19
+ const port = options.port || 3000;
20
+ const payload = options.payload;
21
+ console.log(chalk.blue('🔍 Looking for email configuration...'));
22
+ // Get email config from stored plugin options
23
+ const emailConfig = getEmailConfig(payload);
24
+ if (!emailConfig) {
25
+ console.log(chalk.yellow('⚠️ No email configuration found'));
26
+ console.log(chalk.yellow(' Make sure you have configured email in your payloadHelper plugin:\n'));
27
+ console.log(chalk.cyan(` payloadHelper({
28
+ email: {
29
+ theme: { /* ... */ },
30
+ frontEndUrl: 'https://yoursite.com',
31
+ }
32
+ })`));
33
+ console.log(chalk.yellow('\n Using default theme for email previews'));
34
+ } else {
35
+ console.log(chalk.green('✓ Found email configuration'));
36
+ }
37
+ // Create temp directory for preview files
38
+ const tempDir = join(tmpdir(), `payload-helper-preview-${Date.now()}-${process.pid}`);
39
+ mkdirSync(tempDir, {
40
+ recursive: true
41
+ });
42
+ console.log(chalk.blue('📝 Generating preview templates...'));
43
+ // Extract theme and frontEndUrl
44
+ const themeConfig = emailConfig?.theme ? JSON.stringify(emailConfig.theme, null, 2) : '{}';
45
+ const frontEndUrl = emailConfig?.frontEndUrl || 'https://yoursite.com';
46
+ // Safely escape the frontEndUrl for use in template strings
47
+ const escapedFrontEndUrl = escapeForTemplate(frontEndUrl);
48
+ // Generate ForgotPassword preview
49
+ const forgotPasswordContent = emailConfig?.forgotPassword ? JSON.stringify(emailConfig.forgotPassword, null, 3) : 'undefined';
50
+ const forgotPasswordPreview = `import { renderEmail } from '@ainsleydev/email-templates';
51
+ import { ForgotPasswordEmail } from '@ainsleydev/payload-helper';
52
+
53
+ export default async function render() {
54
+ return renderEmail({
55
+ component: ForgotPasswordEmail,
56
+ props: {
57
+ user: { firstName: 'John', email: 'john@example.com' },
58
+ resetUrl: \`${escapedFrontEndUrl}/admin/reset/token123\`,
59
+ content: ${forgotPasswordContent},
60
+ },
61
+ theme: ${themeConfig},
62
+ });
63
+ }
64
+ `;
65
+ // Generate VerifyAccount preview
66
+ const verifyAccountContent = emailConfig?.verifyAccount ? JSON.stringify(emailConfig.verifyAccount, null, 3) : 'undefined';
67
+ const verifyAccountPreview = `import { renderEmail } from '@ainsleydev/email-templates';
68
+ import { VerifyAccountEmail } from '@ainsleydev/payload-helper';
69
+
70
+ export default async function render() {
71
+ return renderEmail({
72
+ component: VerifyAccountEmail,
73
+ props: {
74
+ user: { firstName: 'John', email: 'john@example.com' },
75
+ verifyUrl: \`${escapedFrontEndUrl}/admin/verify/token123\`,
76
+ content: ${verifyAccountContent},
77
+ },
78
+ theme: ${themeConfig},
79
+ });
80
+ }
81
+ `;
82
+ // Write preview files
83
+ writeFileSync(join(tempDir, 'forgot-password-email-preview.tsx'), forgotPasswordPreview);
84
+ writeFileSync(join(tempDir, 'verify-account-email-preview.tsx'), verifyAccountPreview);
85
+ console.log(chalk.green('✓ Preview templates generated'));
86
+ console.log(chalk.blue(`🚀 Starting preview server on http://localhost:${port}...`));
87
+ // Launch email-templates preview
88
+ const previewProcess = spawn('npx', [
89
+ 'email-templates',
90
+ 'preview',
91
+ tempDir,
92
+ `--port=${port}`
93
+ ], {
94
+ stdio: 'inherit',
95
+ shell: true
96
+ });
97
+ // Cleanup on exit
98
+ const cleanup = ()=>{
99
+ console.log(chalk.blue('\n🧹 Cleaning up...'));
100
+ try {
101
+ rmSync(tempDir, {
102
+ recursive: true,
103
+ force: true
104
+ });
105
+ console.log(chalk.green('✓ Cleanup complete'));
106
+ } catch (error) {
107
+ console.error(chalk.red('❌ Error during cleanup:'), error);
108
+ }
109
+ };
110
+ previewProcess.on('exit', (code)=>{
111
+ cleanup();
112
+ process.exit(code || 0);
113
+ });
114
+ // Handle Ctrl+C
115
+ process.on('SIGINT', ()=>{
116
+ previewProcess.kill('SIGINT');
117
+ });
118
+ process.on('SIGTERM', ()=>{
119
+ previewProcess.kill('SIGTERM');
120
+ });
121
+ };
122
+
123
+ //# sourceMappingURL=preview-emails.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/cli/commands/preview-emails.ts"],"sourcesContent":["import { spawn } from 'node:child_process';\nimport { mkdirSync, rmSync, writeFileSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport chalk from 'chalk';\nimport type { Payload } from 'payload';\nimport type { PayloadHelperPluginConfig } from '../../types.js';\n\n/**\n * Escapes a string for safe use in template literals.\n */\nconst escapeForTemplate = (str: string): string => {\n\treturn str.replace(/\\\\/g, '\\\\\\\\').replace(/`/g, '\\\\`').replace(/\\$/g, '\\\\$');\n};\n\n/**\n * Retrieves the email configuration from the Payload config.\n */\nconst getEmailConfig = (payload: Payload): PayloadHelperPluginConfig['email'] | undefined => {\n\tconst custom = payload.config.custom as Record<string, unknown> | undefined;\n\tconst payloadHelperOptions = custom?.payloadHelperOptions as\n\t\t| PayloadHelperPluginConfig\n\t\t| undefined;\n\treturn payloadHelperOptions?.email;\n};\n\nexport const previewEmails = async (options: { payload: Payload; port?: number }) => {\n\tconst port = options.port || 3000;\n\tconst payload = options.payload;\n\n\tconsole.log(chalk.blue('🔍 Looking for email configuration...'));\n\n\t// Get email config from stored plugin options\n\tconst emailConfig = getEmailConfig(payload);\n\n\tif (!emailConfig) {\n\t\tconsole.log(chalk.yellow('⚠️ No email configuration found'));\n\t\tconsole.log(\n\t\t\tchalk.yellow(' Make sure you have configured email in your payloadHelper plugin:\\n'),\n\t\t);\n\t\tconsole.log(\n\t\t\tchalk.cyan(` payloadHelper({\n email: {\n theme: { /* ... */ },\n frontEndUrl: 'https://yoursite.com',\n }\n })`),\n\t\t);\n\t\tconsole.log(chalk.yellow('\\n Using default theme for email previews'));\n\t} else {\n\t\tconsole.log(chalk.green('✓ Found email configuration'));\n\t}\n\n\t// Create temp directory for preview files\n\tconst tempDir = join(tmpdir(), `payload-helper-preview-${Date.now()}-${process.pid}`);\n\tmkdirSync(tempDir, { recursive: true });\n\n\tconsole.log(chalk.blue('📝 Generating preview templates...'));\n\n\t// Extract theme and frontEndUrl\n\tconst themeConfig = emailConfig?.theme ? JSON.stringify(emailConfig.theme, null, 2) : '{}';\n\tconst frontEndUrl = emailConfig?.frontEndUrl || 'https://yoursite.com';\n\n\t// Safely escape the frontEndUrl for use in template strings\n\tconst escapedFrontEndUrl = escapeForTemplate(frontEndUrl);\n\n\t// Generate ForgotPassword preview\n\tconst forgotPasswordContent = emailConfig?.forgotPassword\n\t\t? JSON.stringify(emailConfig.forgotPassword, null, 3)\n\t\t: 'undefined';\n\n\tconst forgotPasswordPreview = `import { renderEmail } from '@ainsleydev/email-templates';\nimport { ForgotPasswordEmail } from '@ainsleydev/payload-helper';\n\nexport default async function render() {\n\treturn renderEmail({\n\t\tcomponent: ForgotPasswordEmail,\n\t\tprops: {\n\t\t\tuser: { firstName: 'John', email: 'john@example.com' },\n\t\t\tresetUrl: \\`${escapedFrontEndUrl}/admin/reset/token123\\`,\n\t\t\tcontent: ${forgotPasswordContent},\n\t\t},\n\t\ttheme: ${themeConfig},\n\t});\n}\n`;\n\n\t// Generate VerifyAccount preview\n\tconst verifyAccountContent = emailConfig?.verifyAccount\n\t\t? JSON.stringify(emailConfig.verifyAccount, null, 3)\n\t\t: 'undefined';\n\n\tconst verifyAccountPreview = `import { renderEmail } from '@ainsleydev/email-templates';\nimport { VerifyAccountEmail } from '@ainsleydev/payload-helper';\n\nexport default async function render() {\n\treturn renderEmail({\n\t\tcomponent: VerifyAccountEmail,\n\t\tprops: {\n\t\t\tuser: { firstName: 'John', email: 'john@example.com' },\n\t\t\tverifyUrl: \\`${escapedFrontEndUrl}/admin/verify/token123\\`,\n\t\t\tcontent: ${verifyAccountContent},\n\t\t},\n\t\ttheme: ${themeConfig},\n\t});\n}\n`;\n\n\t// Write preview files\n\twriteFileSync(join(tempDir, 'forgot-password-email-preview.tsx'), forgotPasswordPreview);\n\twriteFileSync(join(tempDir, 'verify-account-email-preview.tsx'), verifyAccountPreview);\n\n\tconsole.log(chalk.green('✓ Preview templates generated'));\n\tconsole.log(chalk.blue(`🚀 Starting preview server on http://localhost:${port}...`));\n\n\t// Launch email-templates preview\n\tconst previewProcess = spawn('npx', ['email-templates', 'preview', tempDir, `--port=${port}`], {\n\t\tstdio: 'inherit',\n\t\tshell: true,\n\t});\n\n\t// Cleanup on exit\n\tconst cleanup = () => {\n\t\tconsole.log(chalk.blue('\\n🧹 Cleaning up...'));\n\t\ttry {\n\t\t\trmSync(tempDir, { recursive: true, force: true });\n\t\t\tconsole.log(chalk.green('✓ Cleanup complete'));\n\t\t} catch (error) {\n\t\t\tconsole.error(chalk.red('❌ Error during cleanup:'), error);\n\t\t}\n\t};\n\n\tpreviewProcess.on('exit', (code) => {\n\t\tcleanup();\n\t\tprocess.exit(code || 0);\n\t});\n\n\t// Handle Ctrl+C\n\tprocess.on('SIGINT', () => {\n\t\tpreviewProcess.kill('SIGINT');\n\t});\n\n\tprocess.on('SIGTERM', () => {\n\t\tpreviewProcess.kill('SIGTERM');\n\t});\n};\n"],"names":["spawn","mkdirSync","rmSync","writeFileSync","tmpdir","join","chalk","escapeForTemplate","str","replace","getEmailConfig","payload","custom","config","payloadHelperOptions","email","previewEmails","options","port","console","log","blue","emailConfig","yellow","cyan","green","tempDir","Date","now","process","pid","recursive","themeConfig","theme","JSON","stringify","frontEndUrl","escapedFrontEndUrl","forgotPasswordContent","forgotPassword","forgotPasswordPreview","verifyAccountContent","verifyAccount","verifyAccountPreview","previewProcess","stdio","shell","cleanup","force","error","red","on","code","exit","kill"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { Media, imageSizes, imageSizesWithAvif } from './Media.js';
2
+ export type { MediaArgs } from './Media.js';
3
+ export { Redirects } from './Redirects.js';
@@ -0,0 +1,4 @@
1
+ export { Media, imageSizes, imageSizesWithAvif } from './Media.js';
2
+ export { Redirects } from './Redirects.js';
3
+
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/collections/index.ts"],"sourcesContent":["export { Media, imageSizes, imageSizesWithAvif } from './Media.js';\nexport type { MediaArgs } from './Media.js';\nexport { Redirects } from './Redirects.js';\n"],"names":["Media","imageSizes","imageSizesWithAvif","Redirects"],"mappings":"AAAA,SAASA,KAAK,EAAEC,UAAU,EAAEC,kBAAkB,QAAQ,aAAa;AAEnE,SAASC,SAAS,QAAQ,iBAAiB"}
@@ -0,0 +1 @@
1
+ export { SEOFields } from './SEO.js';
@@ -0,0 +1,3 @@
1
+ export { SEOFields } from './SEO.js';
2
+
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/common/index.ts"],"sourcesContent":["export { SEOFields } from './SEO.js';\n"],"names":["SEOFields"],"mappings":"AAAA,SAASA,SAAS,QAAQ,WAAW"}
@@ -0,0 +1,38 @@
1
+ import type { EmailTheme } from '@ainsleydev/email-templates';
2
+ import * as React from 'react';
3
+ /**
4
+ * Props for the ForgotPasswordEmail component.
5
+ */
6
+ export interface ForgotPasswordEmailProps {
7
+ /**
8
+ * The email theme (required by renderEmail).
9
+ */
10
+ theme: EmailTheme;
11
+ /**
12
+ * The user object containing user information.
13
+ */
14
+ user: {
15
+ firstName?: string;
16
+ email?: string;
17
+ };
18
+ /**
19
+ * The URL for resetting the password.
20
+ */
21
+ resetUrl: string;
22
+ /**
23
+ * Optional content overrides.
24
+ */
25
+ content?: {
26
+ previewText?: string;
27
+ heading?: string;
28
+ bodyText?: string;
29
+ buttonText?: string;
30
+ };
31
+ }
32
+ /**
33
+ * Email template for password reset requests in Payload CMS.
34
+ *
35
+ * @param props - The component props
36
+ * @returns The rendered email component
37
+ */
38
+ export declare const ForgotPasswordEmail: ({ theme, user, resetUrl, content, }: ForgotPasswordEmailProps) => React.JSX.Element;
@@ -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 password reset requests in Payload CMS.
6
+ *
7
+ * @param props - The component props
8
+ * @returns The rendered email component
9
+ */ export const ForgotPasswordEmail = ({ theme, user, resetUrl, content })=>{
10
+ const userName = user.firstName || user.email || 'there';
11
+ const previewText = content?.previewText || 'Reset your password';
12
+ const heading = content?.heading || `Hello, ${userName}!`;
13
+ const bodyText = content?.bodyText || 'We received a request to reset your password, please click the button below. If you did not request a password reset, you can safely ignore this email.';
14
+ const buttonText = content?.buttonText || 'Reset Password';
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: resetUrl,
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=ForgotPasswordEmail.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/email/ForgotPasswordEmail.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 ForgotPasswordEmail component.\n */\nexport interface ForgotPasswordEmailProps {\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 resetting the password.\n\t */\n\tresetUrl: 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 password reset requests in Payload CMS.\n *\n * @param props - The component props\n * @returns The rendered email component\n */\nexport const ForgotPasswordEmail = ({\n\ttheme,\n\tuser,\n\tresetUrl,\n\tcontent,\n}: ForgotPasswordEmailProps) => {\n\tconst userName = user.firstName || user.email || 'there';\n\tconst previewText = content?.previewText || 'Reset your password';\n\tconst heading = content?.heading || `Hello, ${userName}!`;\n\tconst bodyText =\n\t\tcontent?.bodyText ||\n\t\t'We received a request to reset your password, please click the button below. If you did not request a password reset, you can safely ignore this email.';\n\tconst buttonText = content?.buttonText || 'Reset Password';\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={resetUrl}\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","ForgotPasswordEmail","theme","user","resetUrl","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,sBAAsB,CAAC,EACnCC,KAAK,EACLC,IAAI,EACJC,QAAQ,EACRC,OAAO,EACmB;IAC1B,MAAMC,WAAWH,KAAKI,SAAS,IAAIJ,KAAKK,KAAK,IAAI;IACjD,MAAMC,cAAcJ,SAASI,eAAe;IAC5C,MAAMC,UAAUL,SAASK,WAAW,CAAC,OAAO,EAAEJ,SAAS,CAAC,CAAC;IACzD,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 {};