payload-plugin-newsletter 0.4.4 → 0.6.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 (150) hide show
  1. package/CHANGELOG.md +28 -1
  2. package/ESM_FIX_SUMMARY.md +74 -0
  3. package/dist/client.cjs +899 -0
  4. package/dist/client.cjs.map +1 -0
  5. package/dist/client.d.cts +52 -0
  6. package/dist/client.d.ts +52 -0
  7. package/dist/client.js +867 -0
  8. package/dist/client.js.map +1 -0
  9. package/dist/components.cjs +899 -0
  10. package/dist/components.cjs.map +1 -0
  11. package/dist/components.d.cts +4 -0
  12. package/dist/components.d.ts +4 -0
  13. package/dist/components.js +867 -0
  14. package/dist/components.js.map +1 -0
  15. package/dist/index.cjs +1928 -0
  16. package/dist/index.cjs.map +1 -0
  17. package/dist/index.d.cts +11 -0
  18. package/dist/index.d.ts +6 -5
  19. package/dist/index.js +1891 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/types.cjs +19 -0
  22. package/dist/types.cjs.map +1 -0
  23. package/dist/{types/index.d.ts → types.d.cts} +20 -18
  24. package/dist/types.d.ts +350 -0
  25. package/dist/types.js +1 -0
  26. package/dist/types.js.map +1 -0
  27. package/package.json +40 -17
  28. package/dist/.tsbuildinfo +0 -1
  29. package/dist/collections/NewsletterSettings.d.ts +0 -4
  30. package/dist/collections/NewsletterSettings.d.ts.map +0 -1
  31. package/dist/collections/Subscribers.d.ts +0 -4
  32. package/dist/collections/Subscribers.d.ts.map +0 -1
  33. package/dist/components/MagicLinkVerify.d.ts +0 -27
  34. package/dist/components/MagicLinkVerify.d.ts.map +0 -1
  35. package/dist/components/NewsletterForm.d.ts +0 -5
  36. package/dist/components/NewsletterForm.d.ts.map +0 -1
  37. package/dist/components/PreferencesForm.d.ts +0 -5
  38. package/dist/components/PreferencesForm.d.ts.map +0 -1
  39. package/dist/components/index.d.ts +0 -5
  40. package/dist/components/index.d.ts.map +0 -1
  41. package/dist/endpoints/index.d.ts +0 -4
  42. package/dist/endpoints/index.d.ts.map +0 -1
  43. package/dist/endpoints/preferences.d.ts +0 -5
  44. package/dist/endpoints/preferences.d.ts.map +0 -1
  45. package/dist/endpoints/subscribe.d.ts +0 -4
  46. package/dist/endpoints/subscribe.d.ts.map +0 -1
  47. package/dist/endpoints/unsubscribe.d.ts +0 -4
  48. package/dist/endpoints/unsubscribe.d.ts.map +0 -1
  49. package/dist/endpoints/verify-magic-link.d.ts +0 -4
  50. package/dist/endpoints/verify-magic-link.d.ts.map +0 -1
  51. package/dist/exports/client.d.ts +0 -6
  52. package/dist/exports/client.d.ts.map +0 -1
  53. package/dist/exports/components.d.ts +0 -2
  54. package/dist/exports/components.d.ts.map +0 -1
  55. package/dist/exports/types.d.ts +0 -2
  56. package/dist/exports/types.d.ts.map +0 -1
  57. package/dist/fields/newsletterScheduling.d.ts +0 -4
  58. package/dist/fields/newsletterScheduling.d.ts.map +0 -1
  59. package/dist/hooks/useNewsletterAuth.d.ts +0 -16
  60. package/dist/hooks/useNewsletterAuth.d.ts.map +0 -1
  61. package/dist/index.d.ts.map +0 -1
  62. package/dist/providers/broadcast.d.ts +0 -19
  63. package/dist/providers/broadcast.d.ts.map +0 -1
  64. package/dist/providers/index.d.ts +0 -23
  65. package/dist/providers/index.d.ts.map +0 -1
  66. package/dist/providers/resend.d.ts +0 -20
  67. package/dist/providers/resend.d.ts.map +0 -1
  68. package/dist/providers/types.d.ts +0 -46
  69. package/dist/providers/types.d.ts.map +0 -1
  70. package/dist/src/collections/NewsletterSettings.js +0 -390
  71. package/dist/src/collections/NewsletterSettings.js.map +0 -1
  72. package/dist/src/collections/Subscribers.js +0 -309
  73. package/dist/src/collections/Subscribers.js.map +0 -1
  74. package/dist/src/components/MagicLinkVerify.js +0 -180
  75. package/dist/src/components/MagicLinkVerify.js.map +0 -1
  76. package/dist/src/components/NewsletterForm.js +0 -326
  77. package/dist/src/components/NewsletterForm.js.map +0 -1
  78. package/dist/src/components/PreferencesForm.js +0 -524
  79. package/dist/src/components/PreferencesForm.js.map +0 -1
  80. package/dist/src/components/index.js +0 -5
  81. package/dist/src/components/index.js.map +0 -1
  82. package/dist/src/endpoints/index.js +0 -17
  83. package/dist/src/endpoints/index.js.map +0 -1
  84. package/dist/src/endpoints/preferences.js +0 -136
  85. package/dist/src/endpoints/preferences.js.map +0 -1
  86. package/dist/src/endpoints/subscribe.js +0 -162
  87. package/dist/src/endpoints/subscribe.js.map +0 -1
  88. package/dist/src/endpoints/unsubscribe.js +0 -105
  89. package/dist/src/endpoints/unsubscribe.js.map +0 -1
  90. package/dist/src/endpoints/verify-magic-link.js +0 -103
  91. package/dist/src/endpoints/verify-magic-link.js.map +0 -1
  92. package/dist/src/exports/client.js +0 -7
  93. package/dist/src/exports/client.js.map +0 -1
  94. package/dist/src/exports/components.js +0 -6
  95. package/dist/src/exports/components.js.map +0 -1
  96. package/dist/src/exports/types.js +0 -3
  97. package/dist/src/exports/types.js.map +0 -1
  98. package/dist/src/fields/newsletterScheduling.js +0 -194
  99. package/dist/src/fields/newsletterScheduling.js.map +0 -1
  100. package/dist/src/hooks/useNewsletterAuth.js +0 -112
  101. package/dist/src/hooks/useNewsletterAuth.js.map +0 -1
  102. package/dist/src/index.js +0 -130
  103. package/dist/src/index.js.map +0 -1
  104. package/dist/src/providers/broadcast.js +0 -158
  105. package/dist/src/providers/broadcast.js.map +0 -1
  106. package/dist/src/providers/index.js +0 -63
  107. package/dist/src/providers/index.js.map +0 -1
  108. package/dist/src/providers/resend.js +0 -122
  109. package/dist/src/providers/resend.js.map +0 -1
  110. package/dist/src/providers/types.js +0 -12
  111. package/dist/src/providers/types.js.map +0 -1
  112. package/dist/src/templates/BaseTemplate.js +0 -105
  113. package/dist/src/templates/BaseTemplate.js.map +0 -1
  114. package/dist/src/templates/MagicLinkTemplate.js +0 -178
  115. package/dist/src/templates/MagicLinkTemplate.js.map +0 -1
  116. package/dist/src/templates/NewsletterTemplate.js +0 -150
  117. package/dist/src/templates/NewsletterTemplate.js.map +0 -1
  118. package/dist/src/templates/WelcomeTemplate.js +0 -192
  119. package/dist/src/templates/WelcomeTemplate.js.map +0 -1
  120. package/dist/src/templates/index.js +0 -6
  121. package/dist/src/templates/index.js.map +0 -1
  122. package/dist/src/types/index.js +0 -3
  123. package/dist/src/types/index.js.map +0 -1
  124. package/dist/src/utils/access.js +0 -80
  125. package/dist/src/utils/access.js.map +0 -1
  126. package/dist/src/utils/jwt.js +0 -91
  127. package/dist/src/utils/jwt.js.map +0 -1
  128. package/dist/src/utils/rate-limiter.js +0 -43
  129. package/dist/src/utils/rate-limiter.js.map +0 -1
  130. package/dist/src/utils/validation.js +0 -148
  131. package/dist/src/utils/validation.js.map +0 -1
  132. package/dist/templates/BaseTemplate.d.ts +0 -45
  133. package/dist/templates/BaseTemplate.d.ts.map +0 -1
  134. package/dist/templates/MagicLinkTemplate.d.ts +0 -67
  135. package/dist/templates/MagicLinkTemplate.d.ts.map +0 -1
  136. package/dist/templates/NewsletterTemplate.d.ts +0 -112
  137. package/dist/templates/NewsletterTemplate.d.ts.map +0 -1
  138. package/dist/templates/WelcomeTemplate.d.ts +0 -55
  139. package/dist/templates/WelcomeTemplate.d.ts.map +0 -1
  140. package/dist/templates/index.d.ts +0 -7
  141. package/dist/templates/index.d.ts.map +0 -1
  142. package/dist/types/index.d.ts.map +0 -1
  143. package/dist/utils/access.d.ts +0 -15
  144. package/dist/utils/access.d.ts.map +0 -1
  145. package/dist/utils/jwt.d.ts +0 -32
  146. package/dist/utils/jwt.d.ts.map +0 -1
  147. package/dist/utils/rate-limiter.d.ts +0 -15
  148. package/dist/utils/rate-limiter.d.ts.map +0 -1
  149. package/dist/utils/validation.d.ts +0 -33
  150. package/dist/utils/validation.d.ts.map +0 -1
@@ -1,309 +0,0 @@
1
- import { adminOnly, adminOrSelf } from '../utils/access';
2
- export const createSubscribersCollection = (pluginConfig)=>{
3
- const slug = pluginConfig.subscribersSlug || 'subscribers';
4
- // Default fields for the subscribers collection
5
- const defaultFields = [
6
- // Core fields
7
- {
8
- name: 'email',
9
- type: 'email',
10
- required: true,
11
- unique: true,
12
- admin: {
13
- description: 'Subscriber email address'
14
- }
15
- },
16
- {
17
- name: 'name',
18
- type: 'text',
19
- admin: {
20
- description: 'Subscriber full name'
21
- }
22
- },
23
- {
24
- name: 'locale',
25
- type: 'select',
26
- options: pluginConfig.i18n?.locales?.map((locale)=>({
27
- label: locale.toUpperCase(),
28
- value: locale
29
- })) || [
30
- {
31
- label: 'EN',
32
- value: 'en'
33
- }
34
- ],
35
- defaultValue: pluginConfig.i18n?.defaultLocale || 'en',
36
- admin: {
37
- description: 'Preferred language for communications'
38
- }
39
- },
40
- // Authentication fields (hidden from admin UI)
41
- {
42
- name: 'magicLinkToken',
43
- type: 'text',
44
- hidden: true
45
- },
46
- {
47
- name: 'magicLinkTokenExpiry',
48
- type: 'date',
49
- hidden: true
50
- },
51
- // Subscription status
52
- {
53
- name: 'subscriptionStatus',
54
- type: 'select',
55
- options: [
56
- {
57
- label: 'Active',
58
- value: 'active'
59
- },
60
- {
61
- label: 'Unsubscribed',
62
- value: 'unsubscribed'
63
- },
64
- {
65
- label: 'Pending',
66
- value: 'pending'
67
- }
68
- ],
69
- defaultValue: 'pending',
70
- required: true,
71
- admin: {
72
- description: 'Current subscription status'
73
- }
74
- },
75
- {
76
- name: 'unsubscribedAt',
77
- type: 'date',
78
- admin: {
79
- condition: (data)=>data?.subscriptionStatus === 'unsubscribed',
80
- description: 'When the user unsubscribed',
81
- readOnly: true
82
- }
83
- },
84
- // Email preferences
85
- {
86
- name: 'emailPreferences',
87
- type: 'group',
88
- fields: [
89
- {
90
- name: 'newsletter',
91
- type: 'checkbox',
92
- defaultValue: true,
93
- label: 'Newsletter',
94
- admin: {
95
- description: 'Receive regular newsletter updates'
96
- }
97
- },
98
- {
99
- name: 'announcements',
100
- type: 'checkbox',
101
- defaultValue: true,
102
- label: 'Announcements',
103
- admin: {
104
- description: 'Receive important announcements'
105
- }
106
- }
107
- ],
108
- admin: {
109
- description: 'Email communication preferences'
110
- }
111
- },
112
- // Source tracking
113
- {
114
- name: 'source',
115
- type: 'text',
116
- admin: {
117
- description: 'Where the subscriber signed up from'
118
- }
119
- }
120
- ];
121
- // Add UTM tracking fields if enabled
122
- if (pluginConfig.features?.utmTracking?.enabled) {
123
- const utmFields = pluginConfig.features.utmTracking.fields || [
124
- 'source',
125
- 'medium',
126
- 'campaign',
127
- 'content',
128
- 'term'
129
- ];
130
- defaultFields.push({
131
- name: 'utmParameters',
132
- type: 'group',
133
- fields: utmFields.map((field)=>({
134
- name: field,
135
- type: 'text',
136
- admin: {
137
- description: `UTM ${field} parameter`
138
- }
139
- })),
140
- admin: {
141
- description: 'UTM tracking parameters'
142
- }
143
- });
144
- }
145
- // Add signup metadata
146
- defaultFields.push({
147
- name: 'signupMetadata',
148
- type: 'group',
149
- fields: [
150
- {
151
- name: 'ipAddress',
152
- type: 'text',
153
- admin: {
154
- readOnly: true
155
- }
156
- },
157
- {
158
- name: 'userAgent',
159
- type: 'text',
160
- admin: {
161
- readOnly: true
162
- }
163
- },
164
- {
165
- name: 'referrer',
166
- type: 'text',
167
- admin: {
168
- readOnly: true
169
- }
170
- },
171
- {
172
- name: 'signupPage',
173
- type: 'text',
174
- admin: {
175
- readOnly: true
176
- }
177
- }
178
- ],
179
- admin: {
180
- description: 'Technical information about signup'
181
- }
182
- });
183
- // Add lead magnet field if enabled
184
- if (pluginConfig.features?.leadMagnets?.enabled) {
185
- defaultFields.push({
186
- name: 'leadMagnet',
187
- type: 'relationship',
188
- relationTo: pluginConfig.features.leadMagnets.collection || 'media',
189
- admin: {
190
- description: 'Lead magnet downloaded at signup'
191
- }
192
- });
193
- }
194
- // Allow field customization
195
- let fields = defaultFields;
196
- if (pluginConfig.fields?.overrides) {
197
- fields = pluginConfig.fields.overrides({
198
- defaultFields
199
- });
200
- }
201
- if (pluginConfig.fields?.additional) {
202
- fields = [
203
- ...fields,
204
- ...pluginConfig.fields.additional
205
- ];
206
- }
207
- const subscribersCollection = {
208
- slug,
209
- labels: {
210
- singular: 'Subscriber',
211
- plural: 'Subscribers'
212
- },
213
- admin: {
214
- useAsTitle: 'email',
215
- defaultColumns: [
216
- 'email',
217
- 'name',
218
- 'subscriptionStatus',
219
- 'createdAt'
220
- ],
221
- group: 'Newsletter'
222
- },
223
- fields,
224
- hooks: {
225
- afterChange: [
226
- async ({ doc, req, operation, previousDoc })=>{
227
- // After create logic
228
- if (operation === 'create') {
229
- // Add to email service
230
- const emailService = req.payload.newsletterEmailService;
231
- if (emailService) {
232
- try {
233
- await emailService.addContact(doc);
234
- } catch {
235
- // Failed to add contact to email service
236
- }
237
- }
238
- // Send welcome email if active
239
- if (doc.subscriptionStatus === 'active' && emailService) {
240
- try {
241
- // TODO: Send welcome email
242
- } catch {
243
- // Failed to send welcome email
244
- }
245
- }
246
- // Custom after subscribe hook
247
- if (pluginConfig.hooks?.afterSubscribe) {
248
- await pluginConfig.hooks.afterSubscribe({
249
- doc,
250
- req
251
- });
252
- }
253
- }
254
- // After update logic
255
- if (operation === 'update' && previousDoc) {
256
- // Update email service if status changed
257
- const emailService = req.payload.newsletterEmailService;
258
- if (doc.subscriptionStatus !== previousDoc.subscriptionStatus && emailService) {
259
- try {
260
- await emailService.updateContact(doc);
261
- } catch {
262
- // Failed to update contact in email service
263
- }
264
- }
265
- // Handle unsubscribe
266
- if (doc.subscriptionStatus === 'unsubscribed' && previousDoc.subscriptionStatus !== 'unsubscribed') {
267
- // Set unsubscribed timestamp
268
- doc.unsubscribedAt = new Date().toISOString();
269
- // Custom after unsubscribe hook
270
- if (pluginConfig.hooks?.afterUnsubscribe) {
271
- await pluginConfig.hooks.afterUnsubscribe({
272
- doc,
273
- req
274
- });
275
- }
276
- }
277
- }
278
- }
279
- ],
280
- beforeDelete: [
281
- async ({ id, req })=>{
282
- // Remove from email service
283
- const emailService = req.payload.newsletterEmailService;
284
- if (emailService) {
285
- try {
286
- const doc = await req.payload.findByID({
287
- collection: slug,
288
- id
289
- });
290
- await emailService.removeContact(doc.email);
291
- } catch {
292
- // Failed to remove contact from email service
293
- }
294
- }
295
- }
296
- ]
297
- },
298
- access: {
299
- create: ()=>true,
300
- read: adminOrSelf(pluginConfig),
301
- update: adminOrSelf(pluginConfig),
302
- delete: adminOnly(pluginConfig)
303
- },
304
- timestamps: true
305
- };
306
- return subscribersCollection;
307
- };
308
-
309
- //# sourceMappingURL=Subscribers.js.map
@@ -1 +0,0 @@
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 {\n // Failed to add contact to email service\n }\n }\n\n // Send welcome email if active\n if (doc.subscriptionStatus === 'active' && emailService) {\n try {\n // TODO: Send welcome email\n } catch {\n // Failed to send welcome email\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 {\n // Failed to update contact in email service\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 {\n // Failed to remove contact from email service\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","afterSubscribe","updateContact","unsubscribedAt","Date","toISOString","afterUnsubscribe","beforeDelete","id","findByID","removeContact","email","access","create","read","update","delete","timestamps"],"mappings":"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"}
@@ -1,180 +0,0 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import React, { useState, useEffect } from 'react';
4
- const defaultStyles = {
5
- container: {
6
- maxWidth: '400px',
7
- margin: '4rem auto',
8
- padding: '2rem',
9
- textAlign: 'center'
10
- },
11
- heading: {
12
- fontSize: '1.5rem',
13
- fontWeight: '600',
14
- marginBottom: '1rem',
15
- color: '#111827'
16
- },
17
- message: {
18
- fontSize: '1rem',
19
- color: '#6b7280',
20
- marginBottom: '1.5rem'
21
- },
22
- error: {
23
- fontSize: '1rem',
24
- color: '#ef4444',
25
- marginBottom: '1.5rem'
26
- },
27
- button: {
28
- padding: '0.75rem 1.5rem',
29
- fontSize: '1rem',
30
- fontWeight: '500',
31
- color: '#ffffff',
32
- backgroundColor: '#3b82f6',
33
- border: 'none',
34
- borderRadius: '0.375rem',
35
- cursor: 'pointer',
36
- transition: 'background-color 0.2s'
37
- }
38
- };
39
- export const MagicLinkVerify = ({ token: propToken, onSuccess, onError, apiEndpoint = '/api/newsletter/verify-magic-link', className, styles: customStyles = {}, labels = {
40
- verifying: 'Verifying your magic link...',
41
- success: 'Successfully verified! Redirecting...',
42
- error: 'Failed to verify magic link',
43
- expired: 'This magic link has expired. Please request a new one.',
44
- invalid: 'This magic link is invalid. Please request a new one.',
45
- redirecting: 'Redirecting to your preferences...',
46
- tryAgain: 'Try Again'
47
- } })=>{
48
- const [status, setStatus] = useState('verifying');
49
- const [error, setError] = useState(null);
50
- const [_sessionToken, setSessionToken] = useState(null);
51
- const styles = {
52
- container: {
53
- ...defaultStyles.container,
54
- ...customStyles.container
55
- },
56
- heading: {
57
- ...defaultStyles.heading,
58
- ...customStyles.heading
59
- },
60
- message: {
61
- ...defaultStyles.message,
62
- ...customStyles.message
63
- },
64
- error: {
65
- ...defaultStyles.error,
66
- ...customStyles.error
67
- },
68
- button: {
69
- ...defaultStyles.button,
70
- ...customStyles.button
71
- }
72
- };
73
- useEffect(()=>{
74
- // Get token from props or URL
75
- const token = propToken || new URLSearchParams(window.location.search).get('token');
76
- if (token) {
77
- verifyToken(token);
78
- } else {
79
- setStatus('error');
80
- setError(labels.invalid || 'Invalid magic link');
81
- }
82
- }, [
83
- propToken
84
- ]);
85
- const verifyToken = async (token)=>{
86
- try {
87
- const response = await fetch(apiEndpoint, {
88
- method: 'POST',
89
- headers: {
90
- 'Content-Type': 'application/json'
91
- },
92
- body: JSON.stringify({
93
- token
94
- })
95
- });
96
- const data = await response.json();
97
- if (!response.ok) {
98
- if (data.error?.includes('expired')) {
99
- throw new Error(labels.expired);
100
- }
101
- throw new Error(data.error || labels.error);
102
- }
103
- setStatus('success');
104
- setSessionToken(data.sessionToken);
105
- // Store session token
106
- if (typeof window !== 'undefined' && data.sessionToken) {
107
- localStorage.setItem('newsletter_session', data.sessionToken);
108
- }
109
- if (onSuccess) {
110
- onSuccess(data.sessionToken, data.subscriber);
111
- }
112
- } catch (err) {
113
- setStatus('error');
114
- const errorMessage = err instanceof Error ? err.message : labels.error || 'Verification failed';
115
- setError(errorMessage);
116
- if (onError) {
117
- onError(err instanceof Error ? err : new Error(errorMessage));
118
- }
119
- }
120
- };
121
- const handleTryAgain = ()=>{
122
- window.location.href = '/';
123
- };
124
- return /*#__PURE__*/ _jsxs("div", {
125
- className: className,
126
- style: styles.container,
127
- children: [
128
- status === 'verifying' && /*#__PURE__*/ _jsxs(_Fragment, {
129
- children: [
130
- /*#__PURE__*/ _jsx("h2", {
131
- style: styles.heading,
132
- children: "Verifying"
133
- }),
134
- /*#__PURE__*/ _jsx("p", {
135
- style: styles.message,
136
- children: labels.verifying
137
- })
138
- ]
139
- }),
140
- status === 'success' && /*#__PURE__*/ _jsxs(_Fragment, {
141
- children: [
142
- /*#__PURE__*/ _jsx("h2", {
143
- style: styles.heading,
144
- children: "Success!"
145
- }),
146
- /*#__PURE__*/ _jsx("p", {
147
- style: styles.message,
148
- children: labels.success
149
- })
150
- ]
151
- }),
152
- status === 'error' && /*#__PURE__*/ _jsxs(_Fragment, {
153
- children: [
154
- /*#__PURE__*/ _jsx("h2", {
155
- style: styles.heading,
156
- children: "Verification Failed"
157
- }),
158
- /*#__PURE__*/ _jsx("p", {
159
- style: styles.error,
160
- children: error
161
- }),
162
- /*#__PURE__*/ _jsx("button", {
163
- onClick: handleTryAgain,
164
- style: styles.button,
165
- children: labels.tryAgain
166
- })
167
- ]
168
- })
169
- ]
170
- });
171
- };
172
- // Factory function for creating custom magic link verify components
173
- export function createMagicLinkVerify(defaultProps) {
174
- return (props)=>/*#__PURE__*/ _jsx(MagicLinkVerify, {
175
- ...defaultProps,
176
- ...props
177
- });
178
- }
179
-
180
- //# sourceMappingURL=MagicLinkVerify.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/components/MagicLinkVerify.tsx"],"sourcesContent":["'use client'\n\nimport React, { useState, useEffect } from 'react'\n\nexport interface MagicLinkVerifyProps {\n token?: string\n onSuccess?: (sessionToken: string, subscriber: any) => void\n onError?: (error: Error) => void\n apiEndpoint?: string\n className?: string\n styles?: {\n container?: React.CSSProperties\n heading?: React.CSSProperties\n message?: React.CSSProperties\n error?: React.CSSProperties\n button?: React.CSSProperties\n }\n labels?: {\n verifying?: string\n success?: string\n error?: string\n expired?: string\n invalid?: string\n redirecting?: string\n tryAgain?: string\n }\n}\n\nconst defaultStyles = {\n container: {\n maxWidth: '400px',\n margin: '4rem auto',\n padding: '2rem',\n textAlign: 'center' as const,\n },\n heading: {\n fontSize: '1.5rem',\n fontWeight: '600',\n marginBottom: '1rem',\n color: '#111827',\n },\n message: {\n fontSize: '1rem',\n color: '#6b7280',\n marginBottom: '1.5rem',\n },\n error: {\n fontSize: '1rem',\n color: '#ef4444',\n marginBottom: '1.5rem',\n },\n button: {\n padding: '0.75rem 1.5rem',\n fontSize: '1rem',\n fontWeight: '500',\n color: '#ffffff',\n backgroundColor: '#3b82f6',\n border: 'none',\n borderRadius: '0.375rem',\n cursor: 'pointer',\n transition: 'background-color 0.2s',\n },\n}\n\nexport const MagicLinkVerify: React.FC<MagicLinkVerifyProps> = ({\n token: propToken,\n onSuccess,\n onError,\n apiEndpoint = '/api/newsletter/verify-magic-link',\n className,\n styles: customStyles = {},\n labels = {\n verifying: 'Verifying your magic link...',\n success: 'Successfully verified! Redirecting...',\n error: 'Failed to verify magic link',\n expired: 'This magic link has expired. Please request a new one.',\n invalid: 'This magic link is invalid. Please request a new one.',\n redirecting: 'Redirecting to your preferences...',\n tryAgain: 'Try Again',\n },\n}) => {\n const [status, setStatus] = useState<'verifying' | 'success' | 'error'>('verifying')\n const [error, setError] = useState<string | null>(null)\n const [_sessionToken, setSessionToken] = useState<string | null>(null)\n\n const styles = {\n container: { ...defaultStyles.container, ...customStyles.container },\n heading: { ...defaultStyles.heading, ...customStyles.heading },\n message: { ...defaultStyles.message, ...customStyles.message },\n error: { ...defaultStyles.error, ...customStyles.error },\n button: { ...defaultStyles.button, ...customStyles.button },\n }\n\n useEffect(() => {\n // Get token from props or URL\n const token = propToken || new URLSearchParams(window.location.search).get('token')\n \n if (token) {\n verifyToken(token)\n } else {\n setStatus('error')\n setError(labels.invalid || 'Invalid magic link')\n }\n }, [propToken])\n\n const verifyToken = async (token: string) => {\n try {\n const response = await fetch(apiEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ token }),\n })\n\n const data = await response.json()\n\n if (!response.ok) {\n if (data.error?.includes('expired')) {\n throw new Error(labels.expired)\n }\n throw new Error(data.error || labels.error)\n }\n\n setStatus('success')\n setSessionToken(data.sessionToken)\n\n // Store session token\n if (typeof window !== 'undefined' && data.sessionToken) {\n localStorage.setItem('newsletter_session', data.sessionToken)\n }\n\n if (onSuccess) {\n onSuccess(data.sessionToken, data.subscriber)\n }\n } catch (err) {\n setStatus('error')\n const errorMessage = err instanceof Error ? err.message : (labels.error || 'Verification failed')\n setError(errorMessage)\n if (onError) {\n onError(err instanceof Error ? err : new Error(errorMessage))\n }\n }\n }\n\n const handleTryAgain = () => {\n window.location.href = '/'\n }\n\n return (\n <div className={className} style={styles.container}>\n {status === 'verifying' && (\n <>\n <h2 style={styles.heading}>Verifying</h2>\n <p style={styles.message}>{labels.verifying}</p>\n </>\n )}\n\n {status === 'success' && (\n <>\n <h2 style={styles.heading}>Success!</h2>\n <p style={styles.message}>{labels.success}</p>\n </>\n )}\n\n {status === 'error' && (\n <>\n <h2 style={styles.heading}>Verification Failed</h2>\n <p style={styles.error}>{error}</p>\n <button onClick={handleTryAgain} style={styles.button}>\n {labels.tryAgain}\n </button>\n </>\n )}\n </div>\n )\n}\n\n// Factory function for creating custom magic link verify components\nexport function createMagicLinkVerify(\n defaultProps: Partial<MagicLinkVerifyProps>\n): React.FC<MagicLinkVerifyProps> {\n return (props: MagicLinkVerifyProps) => (\n <MagicLinkVerify {...defaultProps} {...props} />\n )\n}"],"names":["React","useState","useEffect","defaultStyles","container","maxWidth","margin","padding","textAlign","heading","fontSize","fontWeight","marginBottom","color","message","error","button","backgroundColor","border","borderRadius","cursor","transition","MagicLinkVerify","token","propToken","onSuccess","onError","apiEndpoint","className","styles","customStyles","labels","verifying","success","expired","invalid","redirecting","tryAgain","status","setStatus","setError","_sessionToken","setSessionToken","URLSearchParams","window","location","search","get","verifyToken","response","fetch","method","headers","body","JSON","stringify","data","json","ok","includes","Error","sessionToken","localStorage","setItem","subscriber","err","errorMessage","handleTryAgain","href","div","style","h2","p","onClick","createMagicLinkVerify","defaultProps","props"],"mappings":"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"}