payload-plugin-newsletter 0.1.1 → 0.3.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 (44) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +61 -2
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/collections/NewsletterSettings.d.ts +4 -0
  5. package/dist/collections/NewsletterSettings.d.ts.map +1 -0
  6. package/dist/collections/Subscribers.d.ts.map +1 -1
  7. package/dist/endpoints/preferences.d.ts.map +1 -1
  8. package/dist/endpoints/subscribe.d.ts.map +1 -1
  9. package/dist/endpoints/unsubscribe.d.ts.map +1 -1
  10. package/dist/endpoints/verify-magic-link.d.ts.map +1 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/src/collections/NewsletterSettings.js +390 -0
  13. package/dist/src/collections/NewsletterSettings.js.map +1 -0
  14. package/dist/src/collections/Subscribers.js +4 -39
  15. package/dist/src/collections/Subscribers.js.map +1 -1
  16. package/dist/src/components/MagicLinkVerify.js +1 -1
  17. package/dist/src/components/MagicLinkVerify.js.map +1 -1
  18. package/dist/src/endpoints/preferences.js +16 -4
  19. package/dist/src/endpoints/preferences.js.map +1 -1
  20. package/dist/src/endpoints/subscribe.js +14 -3
  21. package/dist/src/endpoints/subscribe.js.map +1 -1
  22. package/dist/src/endpoints/unsubscribe.js +10 -2
  23. package/dist/src/endpoints/unsubscribe.js.map +1 -1
  24. package/dist/src/endpoints/verify-magic-link.js +13 -3
  25. package/dist/src/endpoints/verify-magic-link.js.map +1 -1
  26. package/dist/src/index.js +18 -12
  27. package/dist/src/index.js.map +1 -1
  28. package/dist/src/templates/NewsletterTemplate.js.map +1 -1
  29. package/dist/src/templates/WelcomeTemplate.js.map +1 -1
  30. package/dist/src/types/index.js.map +1 -1
  31. package/dist/src/utils/access.js +56 -0
  32. package/dist/src/utils/access.js.map +1 -0
  33. package/dist/templates/NewsletterTemplate.d.ts.map +1 -1
  34. package/dist/templates/WelcomeTemplate.d.ts.map +1 -1
  35. package/dist/types/index.d.ts +16 -0
  36. package/dist/types/index.d.ts.map +1 -1
  37. package/dist/utils/access.d.ts +15 -0
  38. package/dist/utils/access.d.ts.map +1 -0
  39. package/package.json +7 -3
  40. package/CLAUDE.md +0 -110
  41. package/dist/globals/EmailSettings.d.ts +0 -4
  42. package/dist/globals/EmailSettings.d.ts.map +0 -1
  43. package/dist/src/globals/EmailSettings.js +0 -252
  44. package/dist/src/globals/EmailSettings.js.map +0 -1
@@ -0,0 +1,4 @@
1
+ import type { CollectionConfig } from 'payload';
2
+ import type { NewsletterPluginConfig } from '../types';
3
+ export declare const createNewsletterSettingsCollection: (pluginConfig: NewsletterPluginConfig) => CollectionConfig;
4
+ //# sourceMappingURL=NewsletterSettings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NewsletterSettings.d.ts","sourceRoot":"","sources":["../../src/collections/NewsletterSettings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAC/C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAA;AAGtD,eAAO,MAAM,kCAAkC,GAC7C,cAAc,sBAAsB,KACnC,gBAiXF,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Subscribers.d.ts","sourceRoot":"","sources":["../../src/collections/Subscribers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAgI,MAAM,SAAS,CAAA;AAC7K,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAA;AAEtD,eAAO,MAAM,2BAA2B,GACtC,cAAc,sBAAsB,KACnC,gBAgVF,CAAA"}
1
+ {"version":3,"file":"Subscribers.d.ts","sourceRoot":"","sources":["../../src/collections/Subscribers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAgE,MAAM,SAAS,CAAA;AAC7G,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAA;AAGtD,eAAO,MAAM,2BAA2B,GACtC,cAAc,sBAAsB,KACnC,gBA4SF,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"preferences.d.ts","sourceRoot":"","sources":["../../src/endpoints/preferences.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,SAAS,CAAA;AACvD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAA;AAGtD,eAAO,MAAM,yBAAyB,GACpC,QAAQ,sBAAsB,KAC7B,QA6DF,CAAA;AAED,eAAO,MAAM,+BAA+B,GAC1C,QAAQ,sBAAsB,KAC7B,QAwEF,CAAA"}
1
+ {"version":3,"file":"preferences.d.ts","sourceRoot":"","sources":["../../src/endpoints/preferences.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,SAAS,CAAA;AACvD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAA;AAGtD,eAAO,MAAM,yBAAyB,GACpC,QAAQ,sBAAsB,KAC7B,QAmEF,CAAA;AAED,eAAO,MAAM,+BAA+B,GAC1C,QAAQ,sBAAsB,KAC7B,QA8EF,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"subscribe.d.ts","sourceRoot":"","sources":["../../src/endpoints/subscribe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,SAAS,CAAA;AACvD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAA;AAStD,eAAO,MAAM,uBAAuB,GAClC,QAAQ,sBAAsB,KAC7B,QAgKF,CAAA"}
1
+ {"version":3,"file":"subscribe.d.ts","sourceRoot":"","sources":["../../src/endpoints/subscribe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,SAAS,CAAA;AACvD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAA;AAQtD,eAAO,MAAM,uBAAuB,GAClC,QAAQ,sBAAsB,KAC7B,QAgLF,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"unsubscribe.d.ts","sourceRoot":"","sources":["../../src/endpoints/unsubscribe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,SAAS,CAAA;AACvD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAA;AAGtD,eAAO,MAAM,yBAAyB,GACpC,QAAQ,sBAAsB,KAC7B,QA4GF,CAAA"}
1
+ {"version":3,"file":"unsubscribe.d.ts","sourceRoot":"","sources":["../../src/endpoints/unsubscribe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,SAAS,CAAA;AACvD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAA;AAGtD,eAAO,MAAM,yBAAyB,GACpC,QAAQ,sBAAsB,KAC7B,QAoHF,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"verify-magic-link.d.ts","sourceRoot":"","sources":["../../src/endpoints/verify-magic-link.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,SAAS,CAAA;AACvD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAA;AAMtD,eAAO,MAAM,6BAA6B,GACxC,QAAQ,sBAAsB,KAC7B,QAsGF,CAAA"}
1
+ {"version":3,"file":"verify-magic-link.d.ts","sourceRoot":"","sources":["../../src/endpoints/verify-magic-link.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,SAAS,CAAA;AACvD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAA;AAMtD,eAAO,MAAM,6BAA6B,GACxC,QAAQ,sBAAsB,KAC7B,QAkHF,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAA;AAQrD,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,WAAW;QACnB,sBAAsB,CAAC,EAAE,GAAG,CAAA;KAC7B;CACF;AAED,eAAO,MAAM,gBAAgB,GAAI,cAAc,sBAAsB,MAAM,gBAAgB,MAAM,KAAG,MA4HnG,CAAA;AAED,OAAO,EAAE,gBAAgB,IAAI,OAAO,EAAE,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAA;AAQrD,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,WAAW;QACnB,sBAAsB,CAAC,EAAE,GAAG,CAAA;KAC7B;CACF;AAED,eAAO,MAAM,gBAAgB,GAAI,cAAc,sBAAsB,MAAM,gBAAgB,MAAM,KAAG,MAiInG,CAAA;AAED,OAAO,EAAE,gBAAgB,IAAI,OAAO,EAAE,CAAA"}
@@ -0,0 +1,390 @@
1
+ import { adminOnly } from '../utils/access';
2
+ export const createNewsletterSettingsCollection = (pluginConfig)=>{
3
+ const slug = pluginConfig.settingsSlug || 'newsletter-settings';
4
+ return {
5
+ slug,
6
+ labels: {
7
+ singular: 'Newsletter Setting',
8
+ plural: 'Newsletter Settings'
9
+ },
10
+ admin: {
11
+ useAsTitle: 'name',
12
+ defaultColumns: [
13
+ 'name',
14
+ 'provider',
15
+ 'active',
16
+ 'updatedAt'
17
+ ],
18
+ group: 'Newsletter',
19
+ description: 'Configure email provider settings and templates'
20
+ },
21
+ fields: [
22
+ {
23
+ name: 'name',
24
+ type: 'text',
25
+ label: 'Configuration Name',
26
+ required: true,
27
+ admin: {
28
+ description: 'A descriptive name for this configuration (e.g., "Production", "Development", "Marketing Emails")'
29
+ }
30
+ },
31
+ {
32
+ name: 'active',
33
+ type: 'checkbox',
34
+ label: 'Active',
35
+ defaultValue: false,
36
+ admin: {
37
+ description: 'Only one configuration can be active at a time'
38
+ }
39
+ },
40
+ {
41
+ type: 'tabs',
42
+ tabs: [
43
+ {
44
+ label: 'Provider Settings',
45
+ fields: [
46
+ {
47
+ name: 'provider',
48
+ type: 'select',
49
+ label: 'Email Provider',
50
+ required: true,
51
+ options: [
52
+ {
53
+ label: 'Resend',
54
+ value: 'resend'
55
+ },
56
+ {
57
+ label: 'Broadcast (Self-Hosted)',
58
+ value: 'broadcast'
59
+ }
60
+ ],
61
+ defaultValue: pluginConfig.providers.default,
62
+ admin: {
63
+ description: 'Choose which email service to use'
64
+ }
65
+ },
66
+ {
67
+ name: 'resendSettings',
68
+ type: 'group',
69
+ label: 'Resend Settings',
70
+ admin: {
71
+ condition: (data)=>data?.provider === 'resend'
72
+ },
73
+ fields: [
74
+ {
75
+ name: 'apiKey',
76
+ type: 'text',
77
+ label: 'API Key',
78
+ required: true,
79
+ admin: {
80
+ description: 'Your Resend API key'
81
+ }
82
+ },
83
+ {
84
+ name: 'audienceIds',
85
+ type: 'array',
86
+ label: 'Audience IDs by Locale',
87
+ fields: [
88
+ {
89
+ name: 'locale',
90
+ type: 'select',
91
+ label: 'Locale',
92
+ required: true,
93
+ options: pluginConfig.i18n?.locales?.map((locale)=>({
94
+ label: locale.toUpperCase(),
95
+ value: locale
96
+ })) || [
97
+ {
98
+ label: 'EN',
99
+ value: 'en'
100
+ }
101
+ ]
102
+ },
103
+ {
104
+ name: 'production',
105
+ type: 'text',
106
+ label: 'Production Audience ID'
107
+ },
108
+ {
109
+ name: 'development',
110
+ type: 'text',
111
+ label: 'Development Audience ID'
112
+ }
113
+ ]
114
+ }
115
+ ]
116
+ },
117
+ {
118
+ name: 'broadcastSettings',
119
+ type: 'group',
120
+ label: 'Broadcast Settings',
121
+ admin: {
122
+ condition: (data)=>data?.provider === 'broadcast'
123
+ },
124
+ fields: [
125
+ {
126
+ name: 'apiUrl',
127
+ type: 'text',
128
+ label: 'API URL',
129
+ required: true,
130
+ admin: {
131
+ description: 'Your Broadcast instance URL'
132
+ }
133
+ },
134
+ {
135
+ name: 'productionToken',
136
+ type: 'text',
137
+ label: 'Production Token',
138
+ admin: {
139
+ description: 'Token for production environment'
140
+ }
141
+ },
142
+ {
143
+ name: 'developmentToken',
144
+ type: 'text',
145
+ label: 'Development Token',
146
+ admin: {
147
+ description: 'Token for development environment'
148
+ }
149
+ }
150
+ ]
151
+ },
152
+ {
153
+ name: 'fromAddress',
154
+ type: 'email',
155
+ label: 'From Address',
156
+ required: true,
157
+ admin: {
158
+ description: 'Default sender email address'
159
+ }
160
+ },
161
+ {
162
+ name: 'fromName',
163
+ type: 'text',
164
+ label: 'From Name',
165
+ required: true,
166
+ admin: {
167
+ description: 'Default sender name'
168
+ }
169
+ },
170
+ {
171
+ name: 'replyTo',
172
+ type: 'email',
173
+ label: 'Reply-To Address',
174
+ admin: {
175
+ description: 'Optional reply-to email address'
176
+ }
177
+ }
178
+ ]
179
+ },
180
+ {
181
+ label: 'Email Templates',
182
+ fields: [
183
+ {
184
+ name: 'emailTemplates',
185
+ type: 'group',
186
+ label: 'Email Templates',
187
+ fields: [
188
+ {
189
+ name: 'welcome',
190
+ type: 'group',
191
+ label: 'Welcome Email',
192
+ fields: [
193
+ {
194
+ name: 'enabled',
195
+ type: 'checkbox',
196
+ label: 'Send Welcome Email',
197
+ defaultValue: true
198
+ },
199
+ {
200
+ name: 'subject',
201
+ type: 'text',
202
+ label: 'Subject Line',
203
+ defaultValue: 'Welcome to {{fromName}}!',
204
+ admin: {
205
+ condition: (data)=>data?.emailTemplates?.welcome?.enabled
206
+ }
207
+ },
208
+ {
209
+ name: 'preheader',
210
+ type: 'text',
211
+ label: 'Preheader Text',
212
+ admin: {
213
+ condition: (data)=>data?.emailTemplates?.welcome?.enabled
214
+ }
215
+ }
216
+ ]
217
+ },
218
+ {
219
+ name: 'magicLink',
220
+ type: 'group',
221
+ label: 'Magic Link Email',
222
+ fields: [
223
+ {
224
+ name: 'subject',
225
+ type: 'text',
226
+ label: 'Subject Line',
227
+ defaultValue: 'Sign in to {{fromName}}'
228
+ },
229
+ {
230
+ name: 'preheader',
231
+ type: 'text',
232
+ label: 'Preheader Text',
233
+ defaultValue: 'Click the link to access your preferences'
234
+ },
235
+ {
236
+ name: 'expirationTime',
237
+ type: 'select',
238
+ label: 'Link Expiration',
239
+ defaultValue: '7d',
240
+ options: [
241
+ {
242
+ label: '1 hour',
243
+ value: '1h'
244
+ },
245
+ {
246
+ label: '24 hours',
247
+ value: '24h'
248
+ },
249
+ {
250
+ label: '7 days',
251
+ value: '7d'
252
+ },
253
+ {
254
+ label: '30 days',
255
+ value: '30d'
256
+ }
257
+ ]
258
+ }
259
+ ]
260
+ }
261
+ ]
262
+ }
263
+ ]
264
+ },
265
+ {
266
+ label: 'Subscription Settings',
267
+ fields: [
268
+ {
269
+ name: 'subscriptionSettings',
270
+ type: 'group',
271
+ label: 'Subscription Settings',
272
+ fields: [
273
+ {
274
+ name: 'requireDoubleOptIn',
275
+ type: 'checkbox',
276
+ label: 'Require Double Opt-In',
277
+ defaultValue: false,
278
+ admin: {
279
+ description: 'Require email confirmation before activating subscriptions'
280
+ }
281
+ },
282
+ {
283
+ name: 'allowedDomains',
284
+ type: 'array',
285
+ label: 'Allowed Email Domains',
286
+ admin: {
287
+ description: 'Leave empty to allow all domains'
288
+ },
289
+ fields: [
290
+ {
291
+ name: 'domain',
292
+ type: 'text',
293
+ label: 'Domain',
294
+ required: true,
295
+ admin: {
296
+ placeholder: 'example.com'
297
+ }
298
+ }
299
+ ]
300
+ },
301
+ {
302
+ name: 'maxSubscribersPerIP',
303
+ type: 'number',
304
+ label: 'Max Subscribers per IP',
305
+ defaultValue: 10,
306
+ min: 1,
307
+ admin: {
308
+ description: 'Maximum number of subscriptions allowed from a single IP address'
309
+ }
310
+ }
311
+ ]
312
+ }
313
+ ]
314
+ }
315
+ ]
316
+ }
317
+ ],
318
+ hooks: {
319
+ beforeChange: [
320
+ async ({ data, req, operation })=>{
321
+ // Verify admin access for settings changes
322
+ if (!req.user || req.user.collection !== 'users') {
323
+ throw new Error('Only administrators can modify newsletter settings');
324
+ }
325
+ // If setting this config as active, deactivate all others
326
+ if (data?.active && operation !== 'create') {
327
+ await req.payload.update({
328
+ collection: slug,
329
+ where: {
330
+ id: {
331
+ not_equals: data.id
332
+ }
333
+ },
334
+ data: {
335
+ active: false
336
+ }
337
+ });
338
+ }
339
+ // For new configs, ensure only one is active
340
+ if (operation === 'create' && data?.active) {
341
+ const existingActive = await req.payload.find({
342
+ collection: slug,
343
+ where: {
344
+ active: {
345
+ equals: true
346
+ }
347
+ }
348
+ });
349
+ if (existingActive.docs.length > 0) {
350
+ // Deactivate existing active configs
351
+ for (const doc of existingActive.docs){
352
+ await req.payload.update({
353
+ collection: slug,
354
+ id: doc.id,
355
+ data: {
356
+ active: false
357
+ }
358
+ });
359
+ }
360
+ }
361
+ }
362
+ return data;
363
+ }
364
+ ],
365
+ afterChange: [
366
+ async ({ doc, req })=>{
367
+ // Reinitialize email service when settings change
368
+ if (req.payload.newsletterEmailService && doc.active) {
369
+ try {
370
+ // TODO: Implement email service reinitialization
371
+ console.warn('Newsletter settings updated, reinitializing service...');
372
+ } catch (error) {
373
+ console.error('Failed to reinitialize email service:', error);
374
+ }
375
+ }
376
+ return doc;
377
+ }
378
+ ]
379
+ },
380
+ access: {
381
+ read: ()=>true,
382
+ create: adminOnly(pluginConfig),
383
+ update: adminOnly(pluginConfig),
384
+ delete: adminOnly(pluginConfig)
385
+ },
386
+ timestamps: true
387
+ };
388
+ };
389
+
390
+ //# sourceMappingURL=NewsletterSettings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/collections/NewsletterSettings.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\nimport type { NewsletterPluginConfig } from '../types'\nimport { adminOnly } from '../utils/access'\n\nexport const createNewsletterSettingsCollection = (\n pluginConfig: NewsletterPluginConfig\n): CollectionConfig => {\n const slug = pluginConfig.settingsSlug || 'newsletter-settings'\n \n return {\n slug,\n labels: {\n singular: 'Newsletter Setting',\n plural: 'Newsletter Settings',\n },\n admin: {\n useAsTitle: 'name',\n defaultColumns: ['name', 'provider', 'active', 'updatedAt'],\n group: 'Newsletter',\n description: 'Configure email provider settings and templates',\n },\n fields: [\n {\n name: 'name',\n type: 'text',\n label: 'Configuration Name',\n required: true,\n admin: {\n description: 'A descriptive name for this configuration (e.g., \"Production\", \"Development\", \"Marketing Emails\")',\n },\n },\n {\n name: 'active',\n type: 'checkbox',\n label: 'Active',\n defaultValue: false,\n admin: {\n description: 'Only one configuration can be active at a time',\n },\n },\n {\n type: 'tabs',\n tabs: [\n {\n label: 'Provider Settings',\n fields: [\n {\n name: 'provider',\n type: 'select',\n label: 'Email Provider',\n required: true,\n options: [\n { label: 'Resend', value: 'resend' },\n { label: 'Broadcast (Self-Hosted)', value: 'broadcast' },\n ],\n defaultValue: pluginConfig.providers.default,\n admin: {\n description: 'Choose which email service to use',\n },\n },\n {\n name: 'resendSettings',\n type: 'group',\n label: 'Resend Settings',\n admin: {\n condition: (data) => data?.provider === 'resend',\n },\n fields: [\n {\n name: 'apiKey',\n type: 'text',\n label: 'API Key',\n required: true,\n admin: {\n description: 'Your Resend API key',\n },\n },\n {\n name: 'audienceIds',\n type: 'array',\n label: 'Audience IDs by Locale',\n fields: [\n {\n name: 'locale',\n type: 'select',\n label: 'Locale',\n required: true,\n options: pluginConfig.i18n?.locales?.map(locale => ({\n label: locale.toUpperCase(),\n value: locale,\n })) || [\n { label: 'EN', value: 'en' },\n ],\n },\n {\n name: 'production',\n type: 'text',\n label: 'Production Audience ID',\n },\n {\n name: 'development',\n type: 'text',\n label: 'Development Audience ID',\n },\n ],\n },\n ],\n },\n {\n name: 'broadcastSettings',\n type: 'group',\n label: 'Broadcast Settings',\n admin: {\n condition: (data) => data?.provider === 'broadcast',\n },\n fields: [\n {\n name: 'apiUrl',\n type: 'text',\n label: 'API URL',\n required: true,\n admin: {\n description: 'Your Broadcast instance URL',\n },\n },\n {\n name: 'productionToken',\n type: 'text',\n label: 'Production Token',\n admin: {\n description: 'Token for production environment',\n },\n },\n {\n name: 'developmentToken',\n type: 'text',\n label: 'Development Token',\n admin: {\n description: 'Token for development environment',\n },\n },\n ],\n },\n {\n name: 'fromAddress',\n type: 'email',\n label: 'From Address',\n required: true,\n admin: {\n description: 'Default sender email address',\n },\n },\n {\n name: 'fromName',\n type: 'text',\n label: 'From Name',\n required: true,\n admin: {\n description: 'Default sender name',\n },\n },\n {\n name: 'replyTo',\n type: 'email',\n label: 'Reply-To Address',\n admin: {\n description: 'Optional reply-to email address',\n },\n },\n ],\n },\n {\n label: 'Email Templates',\n fields: [\n {\n name: 'emailTemplates',\n type: 'group',\n label: 'Email Templates',\n fields: [\n {\n name: 'welcome',\n type: 'group',\n label: 'Welcome Email',\n fields: [\n {\n name: 'enabled',\n type: 'checkbox',\n label: 'Send Welcome Email',\n defaultValue: true,\n },\n {\n name: 'subject',\n type: 'text',\n label: 'Subject Line',\n defaultValue: 'Welcome to {{fromName}}!',\n admin: {\n condition: (data) => data?.emailTemplates?.welcome?.enabled,\n },\n },\n {\n name: 'preheader',\n type: 'text',\n label: 'Preheader Text',\n admin: {\n condition: (data) => data?.emailTemplates?.welcome?.enabled,\n },\n },\n ],\n },\n {\n name: 'magicLink',\n type: 'group',\n label: 'Magic Link Email',\n fields: [\n {\n name: 'subject',\n type: 'text',\n label: 'Subject Line',\n defaultValue: 'Sign in to {{fromName}}',\n },\n {\n name: 'preheader',\n type: 'text',\n label: 'Preheader Text',\n defaultValue: 'Click the link to access your preferences',\n },\n {\n name: 'expirationTime',\n type: 'select',\n label: 'Link Expiration',\n defaultValue: '7d',\n options: [\n { label: '1 hour', value: '1h' },\n { label: '24 hours', value: '24h' },\n { label: '7 days', value: '7d' },\n { label: '30 days', value: '30d' },\n ],\n },\n ],\n },\n ],\n },\n ],\n },\n {\n label: 'Subscription Settings',\n fields: [\n {\n name: 'subscriptionSettings',\n type: 'group',\n label: 'Subscription Settings',\n fields: [\n {\n name: 'requireDoubleOptIn',\n type: 'checkbox',\n label: 'Require Double Opt-In',\n defaultValue: false,\n admin: {\n description: 'Require email confirmation before activating subscriptions',\n },\n },\n {\n name: 'allowedDomains',\n type: 'array',\n label: 'Allowed Email Domains',\n admin: {\n description: 'Leave empty to allow all domains',\n },\n fields: [\n {\n name: 'domain',\n type: 'text',\n label: 'Domain',\n required: true,\n admin: {\n placeholder: 'example.com',\n },\n },\n ],\n },\n {\n name: 'maxSubscribersPerIP',\n type: 'number',\n label: 'Max Subscribers per IP',\n defaultValue: 10,\n min: 1,\n admin: {\n description: 'Maximum number of subscriptions allowed from a single IP address',\n },\n },\n ],\n },\n ],\n },\n ],\n },\n ],\n hooks: {\n beforeChange: [\n async ({ data, req, operation }) => {\n // Verify admin access for settings changes\n if (!req.user || req.user.collection !== 'users') {\n throw new Error('Only administrators can modify newsletter settings')\n }\n \n // If setting this config as active, deactivate all others\n if (data?.active && operation !== 'create') {\n await req.payload.update({\n collection: slug,\n where: {\n id: {\n not_equals: data.id,\n },\n },\n data: {\n active: false,\n },\n // Keep overrideAccess: true for admin operations after verification\n })\n }\n \n // For new configs, ensure only one is active\n if (operation === 'create' && data?.active) {\n const existingActive = await req.payload.find({\n collection: slug,\n where: {\n active: {\n equals: true,\n },\n },\n // Keep overrideAccess: true for admin operations\n })\n \n if (existingActive.docs.length > 0) {\n // Deactivate existing active configs\n for (const doc of existingActive.docs) {\n await req.payload.update({\n collection: slug,\n id: doc.id,\n data: {\n active: false,\n },\n // Keep overrideAccess: true for admin operations\n })\n }\n }\n }\n \n return data\n },\n ],\n afterChange: [\n async ({ doc, req }) => {\n // Reinitialize email service when settings change\n if ((req.payload as any).newsletterEmailService && doc.active) {\n try {\n // TODO: Implement email service reinitialization\n console.warn('Newsletter settings updated, reinitializing service...')\n } catch (error) {\n console.error('Failed to reinitialize email service:', error)\n }\n }\n \n return doc\n },\n ],\n },\n access: {\n read: () => true, // Settings can be read publicly for validation\n create: adminOnly(pluginConfig),\n update: adminOnly(pluginConfig),\n delete: adminOnly(pluginConfig),\n },\n timestamps: true,\n }\n}"],"names":["adminOnly","createNewsletterSettingsCollection","pluginConfig","slug","settingsSlug","labels","singular","plural","admin","useAsTitle","defaultColumns","group","description","fields","name","type","label","required","defaultValue","tabs","options","value","providers","default","condition","data","provider","i18n","locales","map","locale","toUpperCase","emailTemplates","welcome","enabled","placeholder","min","hooks","beforeChange","req","operation","user","collection","Error","active","payload","update","where","id","not_equals","existingActive","find","equals","docs","length","doc","afterChange","newsletterEmailService","console","warn","error","access","read","create","delete","timestamps"],"mappings":"AAEA,SAASA,SAAS,QAAQ,kBAAiB;AAE3C,OAAO,MAAMC,qCAAqC,CAChDC;IAEA,MAAMC,OAAOD,aAAaE,YAAY,IAAI;IAE1C,OAAO;QACLD;QACAE,QAAQ;YACNC,UAAU;YACVC,QAAQ;QACV;QACAC,OAAO;YACLC,YAAY;YACZC,gBAAgB;gBAAC;gBAAQ;gBAAY;gBAAU;aAAY;YAC3DC,OAAO;YACPC,aAAa;QACf;QACAC,QAAQ;YACN;gBACEC,MAAM;gBACNC,MAAM;gBACNC,OAAO;gBACPC,UAAU;gBACVT,OAAO;oBACLI,aAAa;gBACf;YACF;YACA;gBACEE,MAAM;gBACNC,MAAM;gBACNC,OAAO;gBACPE,cAAc;gBACdV,OAAO;oBACLI,aAAa;gBACf;YACF;YACA;gBACEG,MAAM;gBACNI,MAAM;oBACJ;wBACEH,OAAO;wBACPH,QAAQ;4BACN;gCACEC,MAAM;gCACNC,MAAM;gCACNC,OAAO;gCACPC,UAAU;gCACVG,SAAS;oCACP;wCAAEJ,OAAO;wCAAUK,OAAO;oCAAS;oCACnC;wCAAEL,OAAO;wCAA2BK,OAAO;oCAAY;iCACxD;gCACDH,cAAchB,aAAaoB,SAAS,CAACC,OAAO;gCAC5Cf,OAAO;oCACLI,aAAa;gCACf;4BACF;4BACA;gCACEE,MAAM;gCACNC,MAAM;gCACNC,OAAO;gCACPR,OAAO;oCACLgB,WAAW,CAACC,OAASA,MAAMC,aAAa;gCAC1C;gCACAb,QAAQ;oCACN;wCACEC,MAAM;wCACNC,MAAM;wCACNC,OAAO;wCACPC,UAAU;wCACVT,OAAO;4CACLI,aAAa;wCACf;oCACF;oCACA;wCACEE,MAAM;wCACNC,MAAM;wCACNC,OAAO;wCACPH,QAAQ;4CACN;gDACEC,MAAM;gDACNC,MAAM;gDACNC,OAAO;gDACPC,UAAU;gDACVG,SAASlB,aAAayB,IAAI,EAAEC,SAASC,IAAIC,CAAAA,SAAW,CAAA;wDAClDd,OAAOc,OAAOC,WAAW;wDACzBV,OAAOS;oDACT,CAAA,MAAO;oDACL;wDAAEd,OAAO;wDAAMK,OAAO;oDAAK;iDAC5B;4CACH;4CACA;gDACEP,MAAM;gDACNC,MAAM;gDACNC,OAAO;4CACT;4CACA;gDACEF,MAAM;gDACNC,MAAM;gDACNC,OAAO;4CACT;yCACD;oCACH;iCACD;4BACH;4BACA;gCACEF,MAAM;gCACNC,MAAM;gCACNC,OAAO;gCACPR,OAAO;oCACLgB,WAAW,CAACC,OAASA,MAAMC,aAAa;gCAC1C;gCACAb,QAAQ;oCACN;wCACEC,MAAM;wCACNC,MAAM;wCACNC,OAAO;wCACPC,UAAU;wCACVT,OAAO;4CACLI,aAAa;wCACf;oCACF;oCACA;wCACEE,MAAM;wCACNC,MAAM;wCACNC,OAAO;wCACPR,OAAO;4CACLI,aAAa;wCACf;oCACF;oCACA;wCACEE,MAAM;wCACNC,MAAM;wCACNC,OAAO;wCACPR,OAAO;4CACLI,aAAa;wCACf;oCACF;iCACD;4BACH;4BACA;gCACEE,MAAM;gCACNC,MAAM;gCACNC,OAAO;gCACPC,UAAU;gCACVT,OAAO;oCACLI,aAAa;gCACf;4BACF;4BACA;gCACEE,MAAM;gCACNC,MAAM;gCACNC,OAAO;gCACPC,UAAU;gCACVT,OAAO;oCACLI,aAAa;gCACf;4BACF;4BACA;gCACEE,MAAM;gCACNC,MAAM;gCACNC,OAAO;gCACPR,OAAO;oCACLI,aAAa;gCACf;4BACF;yBACD;oBACH;oBACA;wBACEI,OAAO;wBACPH,QAAQ;4BACN;gCACEC,MAAM;gCACNC,MAAM;gCACNC,OAAO;gCACPH,QAAQ;oCACN;wCACEC,MAAM;wCACNC,MAAM;wCACNC,OAAO;wCACPH,QAAQ;4CACN;gDACEC,MAAM;gDACNC,MAAM;gDACNC,OAAO;gDACPE,cAAc;4CAChB;4CACA;gDACEJ,MAAM;gDACNC,MAAM;gDACNC,OAAO;gDACPE,cAAc;gDACdV,OAAO;oDACLgB,WAAW,CAACC,OAASA,MAAMO,gBAAgBC,SAASC;gDACtD;4CACF;4CACA;gDACEpB,MAAM;gDACNC,MAAM;gDACNC,OAAO;gDACPR,OAAO;oDACLgB,WAAW,CAACC,OAASA,MAAMO,gBAAgBC,SAASC;gDACtD;4CACF;yCACD;oCACH;oCACA;wCACEpB,MAAM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"}
@@ -1,3 +1,4 @@
1
+ import { adminOnly, adminOrSelf } from '../utils/access';
1
2
  export const createSubscribersCollection = (pluginConfig)=>{
2
3
  const slug = pluginConfig.subscribersSlug || 'subscribers';
3
4
  // Default fields for the subscribers collection
@@ -296,45 +297,9 @@ export const createSubscribersCollection = (pluginConfig)=>{
296
297
  },
297
298
  access: {
298
299
  create: ()=>true,
299
- read: ({ req })=>{
300
- const user = req.user;
301
- // Admins can read all
302
- if (user) {
303
- return true;
304
- }
305
- // Magic link authenticated subscribers can read their own data
306
- const subscriberId = req.user?.subscriberId;
307
- if (subscriberId) {
308
- return {
309
- id: {
310
- equals: subscriberId
311
- }
312
- };
313
- }
314
- return false;
315
- },
316
- update: ({ req })=>{
317
- const user = req.user;
318
- // Admins can update all
319
- if (user?.collection === 'users') {
320
- return true;
321
- }
322
- // Subscribers can update their own preferences
323
- const subscriberId = req.user?.subscriberId;
324
- if (subscriberId) {
325
- return {
326
- id: {
327
- equals: subscriberId
328
- }
329
- };
330
- }
331
- return false;
332
- },
333
- delete: ({ req })=>{
334
- const user = req.user;
335
- // Only admins can delete
336
- return Boolean(user?.collection === 'users');
337
- }
300
+ read: adminOrSelf(pluginConfig),
301
+ update: adminOrSelf(pluginConfig),
302
+ delete: adminOnly(pluginConfig)
338
303
  },
339
304
  timestamps: true
340
305
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/collections/Subscribers.ts"],"sourcesContent":["import type { CollectionConfig, Field, CollectionBeforeChangeHook, CollectionAfterChangeHook, CollectionBeforeDeleteHook, Access, AccessArgs, PayloadRequest } from 'payload'\nimport type { NewsletterPluginConfig } from '../types'\n\nexport const createSubscribersCollection = (\n pluginConfig: NewsletterPluginConfig\n): CollectionConfig => {\n const slug = pluginConfig.subscribersSlug || 'subscribers'\n \n // Default fields for the subscribers collection\n const defaultFields: Field[] = [\n // Core fields\n {\n name: 'email',\n type: 'email',\n required: true,\n unique: true,\n admin: {\n description: 'Subscriber email address',\n },\n },\n {\n name: 'name',\n type: 'text',\n admin: {\n description: 'Subscriber full name',\n },\n },\n {\n name: 'locale',\n type: 'select',\n options: pluginConfig.i18n?.locales?.map(locale => ({\n label: locale.toUpperCase(),\n value: locale,\n })) || [\n { label: 'EN', value: 'en' },\n ],\n defaultValue: pluginConfig.i18n?.defaultLocale || 'en',\n admin: {\n description: 'Preferred language for communications',\n },\n },\n \n // Authentication fields (hidden from admin UI)\n {\n name: 'magicLinkToken',\n type: 'text',\n hidden: true,\n },\n {\n name: 'magicLinkTokenExpiry',\n type: 'date',\n hidden: true,\n },\n \n // Subscription status\n {\n name: 'subscriptionStatus',\n type: 'select',\n options: [\n { label: 'Active', value: 'active' },\n { label: 'Unsubscribed', value: 'unsubscribed' },\n { label: 'Pending', value: 'pending' },\n ],\n defaultValue: 'pending',\n required: true,\n admin: {\n description: 'Current subscription status',\n },\n },\n {\n name: 'unsubscribedAt',\n type: 'date',\n admin: {\n condition: (data) => data?.subscriptionStatus === 'unsubscribed',\n description: 'When the user unsubscribed',\n readOnly: true,\n },\n },\n \n // Email preferences\n {\n name: 'emailPreferences',\n type: 'group',\n fields: [\n {\n name: 'newsletter',\n type: 'checkbox',\n defaultValue: true,\n label: 'Newsletter',\n admin: {\n description: 'Receive regular newsletter updates',\n },\n },\n {\n name: 'announcements',\n type: 'checkbox',\n defaultValue: true,\n label: 'Announcements',\n admin: {\n description: 'Receive important announcements',\n },\n },\n ],\n admin: {\n description: 'Email communication preferences',\n },\n },\n \n // Source tracking\n {\n name: 'source',\n type: 'text',\n admin: {\n description: 'Where the subscriber signed up from',\n },\n },\n ]\n\n // Add UTM tracking fields if enabled\n if (pluginConfig.features?.utmTracking?.enabled) {\n const utmFields = pluginConfig.features.utmTracking.fields || [\n 'source',\n 'medium',\n 'campaign',\n 'content',\n 'term',\n ]\n \n defaultFields.push({\n name: 'utmParameters',\n type: 'group',\n fields: utmFields.map(field => ({\n name: field,\n type: 'text',\n admin: {\n description: `UTM ${field} parameter`,\n },\n })),\n admin: {\n description: 'UTM tracking parameters',\n },\n })\n }\n\n // Add signup metadata\n defaultFields.push({\n name: 'signupMetadata',\n type: 'group',\n fields: [\n {\n name: 'ipAddress',\n type: 'text',\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'userAgent',\n type: 'text',\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'referrer',\n type: 'text',\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'signupPage',\n type: 'text',\n admin: {\n readOnly: true,\n },\n },\n ],\n admin: {\n description: 'Technical information about signup',\n },\n })\n\n // Add lead magnet field if enabled\n if (pluginConfig.features?.leadMagnets?.enabled) {\n defaultFields.push({\n name: 'leadMagnet',\n type: 'relationship',\n relationTo: pluginConfig.features.leadMagnets.collection || 'media',\n admin: {\n description: 'Lead magnet downloaded at signup',\n },\n })\n }\n\n // Allow field customization\n let fields = defaultFields\n if (pluginConfig.fields?.overrides) {\n fields = pluginConfig.fields.overrides({ defaultFields })\n }\n if (pluginConfig.fields?.additional) {\n fields = [...fields, ...pluginConfig.fields.additional]\n }\n\n const subscribersCollection: CollectionConfig = {\n slug,\n labels: {\n singular: 'Subscriber',\n plural: 'Subscribers',\n },\n admin: {\n useAsTitle: 'email',\n defaultColumns: ['email', 'name', 'subscriptionStatus', 'createdAt'],\n group: 'Newsletter',\n },\n fields,\n hooks: {\n afterChange: [\n async ({ doc, req, operation, previousDoc }) => {\n // After create logic\n if (operation === 'create') {\n // Add to email service\n const emailService = (req.payload as any).newsletterEmailService\n if (emailService) {\n try {\n await emailService.addContact(doc)\n } catch (error) {\n console.error('Failed to add contact to email service:', error)\n }\n }\n\n // Send welcome email if active\n if (doc.subscriptionStatus === 'active' && emailService) {\n try {\n // TODO: Send welcome email\n } catch (error) {\n console.error('Failed to send welcome email:', error)\n }\n }\n\n // Custom after subscribe hook\n if (pluginConfig.hooks?.afterSubscribe) {\n await pluginConfig.hooks.afterSubscribe({ doc, req })\n }\n }\n \n // After update logic\n if (operation === 'update' && previousDoc) {\n // Update email service if status changed\n const emailService = (req.payload as any).newsletterEmailService\n if (\n doc.subscriptionStatus !== previousDoc.subscriptionStatus &&\n emailService\n ) {\n try {\n await emailService.updateContact(doc)\n } catch (error) {\n console.error('Failed to update contact in email service:', error)\n }\n }\n\n // Handle unsubscribe\n if (\n doc.subscriptionStatus === 'unsubscribed' &&\n previousDoc.subscriptionStatus !== 'unsubscribed'\n ) {\n // Set unsubscribed timestamp\n doc.unsubscribedAt = new Date().toISOString()\n \n // Custom after unsubscribe hook\n if (pluginConfig.hooks?.afterUnsubscribe) {\n await pluginConfig.hooks.afterUnsubscribe({ doc, req })\n }\n }\n }\n },\n ] as CollectionAfterChangeHook[],\n beforeDelete: [\n async ({ id, req }) => {\n // Remove from email service\n const emailService = (req.payload as any).newsletterEmailService\n if (emailService) {\n try {\n const doc = await req.payload.findByID({\n collection: slug,\n id,\n })\n await emailService.removeContact(doc.email)\n } catch (error) {\n console.error('Failed to remove contact from email service:', error)\n }\n }\n },\n ] as CollectionBeforeDeleteHook[],\n },\n access: {\n create: () => true, // Public can subscribe\n read: (({ req }: AccessArgs) => {\n const user = (req as PayloadRequest).user\n // Admins can read all\n if (user) {\n return true\n }\n // Magic link authenticated subscribers can read their own data\n const subscriberId = (req as any).user?.subscriberId\n if (subscriberId) {\n return {\n id: {\n equals: subscriberId,\n },\n }\n }\n return false\n }) as Access,\n update: (({ req }: AccessArgs) => {\n const user = (req as PayloadRequest).user\n // Admins can update all\n if (user?.collection === 'users') {\n return true\n }\n // Subscribers can update their own preferences\n const subscriberId = (req as any).user?.subscriberId\n if (subscriberId) {\n return {\n id: {\n equals: subscriberId,\n },\n }\n }\n return false\n }) as Access,\n delete: (({ req }: AccessArgs) => {\n const user = (req as PayloadRequest).user\n // Only admins can delete\n return Boolean(user?.collection === 'users')\n }) as Access,\n },\n timestamps: true,\n }\n\n return subscribersCollection\n}"],"names":["createSubscribersCollection","pluginConfig","slug","subscribersSlug","defaultFields","name","type","required","unique","admin","description","options","i18n","locales","map","locale","label","toUpperCase","value","defaultValue","defaultLocale","hidden","condition","data","subscriptionStatus","readOnly","fields","features","utmTracking","enabled","utmFields","push","field","leadMagnets","relationTo","collection","overrides","additional","subscribersCollection","labels","singular","plural","useAsTitle","defaultColumns","group","hooks","afterChange","doc","req","operation","previousDoc","emailService","payload","newsletterEmailService","addContact","error","console","afterSubscribe","updateContact","unsubscribedAt","Date","toISOString","afterUnsubscribe","beforeDelete","id","findByID","removeContact","email","access","create","read","user","subscriberId","equals","update","delete","Boolean","timestamps"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/collections/Subscribers.ts"],"sourcesContent":["import type { CollectionConfig, Field, CollectionAfterChangeHook, CollectionBeforeDeleteHook } from 'payload'\nimport type { NewsletterPluginConfig } from '../types'\nimport { adminOnly, adminOrSelf } from '../utils/access'\n\nexport const createSubscribersCollection = (\n pluginConfig: NewsletterPluginConfig\n): CollectionConfig => {\n const slug = pluginConfig.subscribersSlug || 'subscribers'\n \n // Default fields for the subscribers collection\n const defaultFields: Field[] = [\n // Core fields\n {\n name: 'email',\n type: 'email',\n required: true,\n unique: true,\n admin: {\n description: 'Subscriber email address',\n },\n },\n {\n name: 'name',\n type: 'text',\n admin: {\n description: 'Subscriber full name',\n },\n },\n {\n name: 'locale',\n type: 'select',\n options: pluginConfig.i18n?.locales?.map(locale => ({\n label: locale.toUpperCase(),\n value: locale,\n })) || [\n { label: 'EN', value: 'en' },\n ],\n defaultValue: pluginConfig.i18n?.defaultLocale || 'en',\n admin: {\n description: 'Preferred language for communications',\n },\n },\n \n // Authentication fields (hidden from admin UI)\n {\n name: 'magicLinkToken',\n type: 'text',\n hidden: true,\n },\n {\n name: 'magicLinkTokenExpiry',\n type: 'date',\n hidden: true,\n },\n \n // Subscription status\n {\n name: 'subscriptionStatus',\n type: 'select',\n options: [\n { label: 'Active', value: 'active' },\n { label: 'Unsubscribed', value: 'unsubscribed' },\n { label: 'Pending', value: 'pending' },\n ],\n defaultValue: 'pending',\n required: true,\n admin: {\n description: 'Current subscription status',\n },\n },\n {\n name: 'unsubscribedAt',\n type: 'date',\n admin: {\n condition: (data) => data?.subscriptionStatus === 'unsubscribed',\n description: 'When the user unsubscribed',\n readOnly: true,\n },\n },\n \n // Email preferences\n {\n name: 'emailPreferences',\n type: 'group',\n fields: [\n {\n name: 'newsletter',\n type: 'checkbox',\n defaultValue: true,\n label: 'Newsletter',\n admin: {\n description: 'Receive regular newsletter updates',\n },\n },\n {\n name: 'announcements',\n type: 'checkbox',\n defaultValue: true,\n label: 'Announcements',\n admin: {\n description: 'Receive important announcements',\n },\n },\n ],\n admin: {\n description: 'Email communication preferences',\n },\n },\n \n // Source tracking\n {\n name: 'source',\n type: 'text',\n admin: {\n description: 'Where the subscriber signed up from',\n },\n },\n ]\n\n // Add UTM tracking fields if enabled\n if (pluginConfig.features?.utmTracking?.enabled) {\n const utmFields = pluginConfig.features.utmTracking.fields || [\n 'source',\n 'medium',\n 'campaign',\n 'content',\n 'term',\n ]\n \n defaultFields.push({\n name: 'utmParameters',\n type: 'group',\n fields: utmFields.map(field => ({\n name: field,\n type: 'text',\n admin: {\n description: `UTM ${field} parameter`,\n },\n })),\n admin: {\n description: 'UTM tracking parameters',\n },\n })\n }\n\n // Add signup metadata\n defaultFields.push({\n name: 'signupMetadata',\n type: 'group',\n fields: [\n {\n name: 'ipAddress',\n type: 'text',\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'userAgent',\n type: 'text',\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'referrer',\n type: 'text',\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'signupPage',\n type: 'text',\n admin: {\n readOnly: true,\n },\n },\n ],\n admin: {\n description: 'Technical information about signup',\n },\n })\n\n // Add lead magnet field if enabled\n if (pluginConfig.features?.leadMagnets?.enabled) {\n defaultFields.push({\n name: 'leadMagnet',\n type: 'relationship',\n relationTo: pluginConfig.features.leadMagnets.collection || 'media',\n admin: {\n description: 'Lead magnet downloaded at signup',\n },\n })\n }\n\n // Allow field customization\n let fields = defaultFields\n if (pluginConfig.fields?.overrides) {\n fields = pluginConfig.fields.overrides({ defaultFields })\n }\n if (pluginConfig.fields?.additional) {\n fields = [...fields, ...pluginConfig.fields.additional]\n }\n\n const subscribersCollection: CollectionConfig = {\n slug,\n labels: {\n singular: 'Subscriber',\n plural: 'Subscribers',\n },\n admin: {\n useAsTitle: 'email',\n defaultColumns: ['email', 'name', 'subscriptionStatus', 'createdAt'],\n group: 'Newsletter',\n },\n fields,\n hooks: {\n afterChange: [\n async ({ doc, req, operation, previousDoc }) => {\n // After create logic\n if (operation === 'create') {\n // Add to email service\n const emailService = (req.payload as any).newsletterEmailService\n if (emailService) {\n try {\n await emailService.addContact(doc)\n } catch (error) {\n console.error('Failed to add contact to email service:', error)\n }\n }\n\n // Send welcome email if active\n if (doc.subscriptionStatus === 'active' && emailService) {\n try {\n // TODO: Send welcome email\n } catch (error) {\n console.error('Failed to send welcome email:', error)\n }\n }\n\n // Custom after subscribe hook\n if (pluginConfig.hooks?.afterSubscribe) {\n await pluginConfig.hooks.afterSubscribe({ doc, req })\n }\n }\n \n // After update logic\n if (operation === 'update' && previousDoc) {\n // Update email service if status changed\n const emailService = (req.payload as any).newsletterEmailService\n if (\n doc.subscriptionStatus !== previousDoc.subscriptionStatus &&\n emailService\n ) {\n try {\n await emailService.updateContact(doc)\n } catch (error) {\n console.error('Failed to update contact in email service:', error)\n }\n }\n\n // Handle unsubscribe\n if (\n doc.subscriptionStatus === 'unsubscribed' &&\n previousDoc.subscriptionStatus !== 'unsubscribed'\n ) {\n // Set unsubscribed timestamp\n doc.unsubscribedAt = new Date().toISOString()\n \n // Custom after unsubscribe hook\n if (pluginConfig.hooks?.afterUnsubscribe) {\n await pluginConfig.hooks.afterUnsubscribe({ doc, req })\n }\n }\n }\n },\n ] as CollectionAfterChangeHook[],\n beforeDelete: [\n async ({ id, req }) => {\n // Remove from email service\n const emailService = (req.payload as any).newsletterEmailService\n if (emailService) {\n try {\n const doc = await req.payload.findByID({\n collection: slug,\n id,\n })\n await emailService.removeContact(doc.email)\n } catch (error) {\n console.error('Failed to remove contact from email service:', error)\n }\n }\n },\n ] as CollectionBeforeDeleteHook[],\n },\n access: {\n create: () => true, // Public can subscribe\n read: adminOrSelf(pluginConfig),\n update: adminOrSelf(pluginConfig),\n delete: adminOnly(pluginConfig),\n },\n timestamps: true,\n }\n\n return subscribersCollection\n}"],"names":["adminOnly","adminOrSelf","createSubscribersCollection","pluginConfig","slug","subscribersSlug","defaultFields","name","type","required","unique","admin","description","options","i18n","locales","map","locale","label","toUpperCase","value","defaultValue","defaultLocale","hidden","condition","data","subscriptionStatus","readOnly","fields","features","utmTracking","enabled","utmFields","push","field","leadMagnets","relationTo","collection","overrides","additional","subscribersCollection","labels","singular","plural","useAsTitle","defaultColumns","group","hooks","afterChange","doc","req","operation","previousDoc","emailService","payload","newsletterEmailService","addContact","error","console","afterSubscribe","updateContact","unsubscribedAt","Date","toISOString","afterUnsubscribe","beforeDelete","id","findByID","removeContact","email","access","create","read","update","delete","timestamps"],"mappings":"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"}
@@ -47,7 +47,7 @@ export const MagicLinkVerify = ({ token: propToken, onSuccess, onError, apiEndpo
47
47
  } })=>{
48
48
  const [status, setStatus] = useState('verifying');
49
49
  const [error, setError] = useState(null);
50
- const [sessionToken, setSessionToken] = useState(null);
50
+ const [_sessionToken, setSessionToken] = useState(null);
51
51
  const styles = {
52
52
  container: {
53
53
  ...defaultStyles.container,