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,150 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React from 'react';
3
- import { Heading, Button, Markdown } from '@react-email/components';
4
- import { BaseTemplate } from './BaseTemplate';
5
- const newsletterStyles = {
6
- heading: {
7
- fontSize: '32px',
8
- fontWeight: '700',
9
- color: '#1a1a1a',
10
- margin: '0 0 24px 0'
11
- },
12
- markdown: {
13
- h1: {
14
- fontSize: '28px',
15
- fontWeight: '700',
16
- color: '#1a1a1a',
17
- margin: '32px 0 16px 0'
18
- },
19
- h2: {
20
- fontSize: '24px',
21
- fontWeight: '600',
22
- color: '#1a1a1a',
23
- margin: '24px 0 12px 0'
24
- },
25
- h3: {
26
- fontSize: '20px',
27
- fontWeight: '600',
28
- color: '#1a1a1a',
29
- margin: '20px 0 8px 0'
30
- },
31
- p: {
32
- fontSize: '16px',
33
- lineHeight: '24px',
34
- color: '#4a4a4a',
35
- margin: '0 0 16px 0'
36
- },
37
- a: {
38
- color: '#0066cc',
39
- textDecoration: 'underline'
40
- },
41
- ul: {
42
- paddingLeft: '20px',
43
- margin: '0 0 16px 0'
44
- },
45
- ol: {
46
- paddingLeft: '20px',
47
- margin: '0 0 16px 0'
48
- },
49
- li: {
50
- fontSize: '16px',
51
- lineHeight: '24px',
52
- color: '#4a4a4a',
53
- marginBottom: '8px'
54
- },
55
- img: {
56
- maxWidth: '100%',
57
- height: 'auto',
58
- margin: '16px 0'
59
- },
60
- blockquote: {
61
- borderLeft: '4px solid #e6ebf1',
62
- paddingLeft: '16px',
63
- margin: '0 0 16px 0',
64
- fontStyle: 'italic',
65
- color: '#6a6a6a'
66
- },
67
- code: {
68
- backgroundColor: '#f6f8fa',
69
- padding: '2px 4px',
70
- borderRadius: '3px',
71
- fontFamily: 'monospace',
72
- fontSize: '14px'
73
- },
74
- pre: {
75
- backgroundColor: '#f6f8fa',
76
- padding: '16px',
77
- borderRadius: '6px',
78
- overflow: 'auto',
79
- margin: '0 0 16px 0'
80
- }
81
- },
82
- button: {
83
- backgroundColor: '#0066cc',
84
- borderRadius: '6px',
85
- color: '#ffffff',
86
- fontSize: '16px',
87
- fontWeight: '600',
88
- textDecoration: 'none',
89
- textAlign: 'center',
90
- display: 'block',
91
- width: '100%',
92
- padding: '12px 20px',
93
- margin: '32px 0'
94
- }
95
- };
96
- export const NewsletterTemplate = ({ subject, preheader, title, content, ctaButton, footer })=>{
97
- return /*#__PURE__*/ _jsxs(BaseTemplate, {
98
- preview: preheader || subject,
99
- footer: footer,
100
- children: [
101
- title && /*#__PURE__*/ _jsx(Heading, {
102
- style: newsletterStyles.heading,
103
- children: title
104
- }),
105
- /*#__PURE__*/ _jsx(Markdown, {
106
- markdownCustomStyles: newsletterStyles.markdown,
107
- markdownContainerStyles: {
108
- padding: '0'
109
- },
110
- children: content
111
- }),
112
- ctaButton && /*#__PURE__*/ _jsx(Button, {
113
- href: ctaButton.href,
114
- style: newsletterStyles.button,
115
- children: ctaButton.text
116
- })
117
- ]
118
- });
119
- };
120
- // Export a function that creates a custom newsletter template
121
- export function createNewsletterTemplate(customStyles) {
122
- const mergedStyles = {
123
- ...newsletterStyles,
124
- ...customStyles
125
- };
126
- return (props)=>/*#__PURE__*/ _jsxs(BaseTemplate, {
127
- preview: props.preheader || props.subject,
128
- footer: props.footer,
129
- children: [
130
- props.title && /*#__PURE__*/ _jsx(Heading, {
131
- style: mergedStyles.heading,
132
- children: props.title
133
- }),
134
- /*#__PURE__*/ _jsx(Markdown, {
135
- markdownCustomStyles: mergedStyles.markdown,
136
- markdownContainerStyles: {
137
- padding: '0'
138
- },
139
- children: props.content
140
- }),
141
- props.ctaButton && /*#__PURE__*/ _jsx(Button, {
142
- href: props.ctaButton.href,
143
- style: mergedStyles.button,
144
- children: props.ctaButton.text
145
- })
146
- ]
147
- });
148
- }
149
-
150
- //# sourceMappingURL=NewsletterTemplate.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/templates/NewsletterTemplate.tsx"],"sourcesContent":["import React from 'react'\nimport {\n Heading,\n Button,\n Markdown,\n} from '@react-email/components'\nimport { BaseTemplate } from './BaseTemplate'\n\nexport interface NewsletterTemplateProps {\n subject: string\n preheader?: string\n title?: string\n content: string // Markdown content\n ctaButton?: {\n text: string\n href: string\n }\n footer?: {\n unsubscribeUrl?: string\n preferencesUrl?: string\n address?: string\n copyright?: string\n }\n}\n\nconst newsletterStyles = {\n heading: {\n fontSize: '32px',\n fontWeight: '700',\n color: '#1a1a1a',\n margin: '0 0 24px 0',\n },\n markdown: {\n h1: {\n fontSize: '28px',\n fontWeight: '700',\n color: '#1a1a1a',\n margin: '32px 0 16px 0',\n },\n h2: {\n fontSize: '24px',\n fontWeight: '600',\n color: '#1a1a1a',\n margin: '24px 0 12px 0',\n },\n h3: {\n fontSize: '20px',\n fontWeight: '600',\n color: '#1a1a1a',\n margin: '20px 0 8px 0',\n },\n p: {\n fontSize: '16px',\n lineHeight: '24px',\n color: '#4a4a4a',\n margin: '0 0 16px 0',\n },\n a: {\n color: '#0066cc',\n textDecoration: 'underline',\n },\n ul: {\n paddingLeft: '20px',\n margin: '0 0 16px 0',\n },\n ol: {\n paddingLeft: '20px',\n margin: '0 0 16px 0',\n },\n li: {\n fontSize: '16px',\n lineHeight: '24px',\n color: '#4a4a4a',\n marginBottom: '8px',\n },\n img: {\n maxWidth: '100%',\n height: 'auto',\n margin: '16px 0',\n },\n blockquote: {\n borderLeft: '4px solid #e6ebf1',\n paddingLeft: '16px',\n margin: '0 0 16px 0',\n fontStyle: 'italic',\n color: '#6a6a6a',\n },\n code: {\n backgroundColor: '#f6f8fa',\n padding: '2px 4px',\n borderRadius: '3px',\n fontFamily: 'monospace',\n fontSize: '14px',\n },\n pre: {\n backgroundColor: '#f6f8fa',\n padding: '16px',\n borderRadius: '6px',\n overflow: 'auto',\n margin: '0 0 16px 0',\n },\n },\n button: {\n backgroundColor: '#0066cc',\n borderRadius: '6px',\n color: '#ffffff',\n fontSize: '16px',\n fontWeight: '600',\n textDecoration: 'none',\n textAlign: 'center' as const,\n display: 'block',\n width: '100%',\n padding: '12px 20px',\n margin: '32px 0',\n },\n}\n\nexport const NewsletterTemplate: React.FC<NewsletterTemplateProps> = ({\n subject,\n preheader,\n title,\n content,\n ctaButton,\n footer,\n}) => {\n return (\n <BaseTemplate\n preview={preheader || subject}\n footer={footer}\n >\n {title && (\n <Heading style={newsletterStyles.heading}>\n {title}\n </Heading>\n )}\n \n <Markdown\n markdownCustomStyles={newsletterStyles.markdown}\n markdownContainerStyles={{\n padding: '0',\n }}\n >\n {content}\n </Markdown>\n \n {ctaButton && (\n <Button\n href={ctaButton.href}\n style={newsletterStyles.button}\n >\n {ctaButton.text}\n </Button>\n )}\n </BaseTemplate>\n )\n}\n\n// Export a function that creates a custom newsletter template\nexport function createNewsletterTemplate(\n customStyles?: Partial<typeof newsletterStyles>\n): React.FC<NewsletterTemplateProps> {\n const mergedStyles = {\n ...newsletterStyles,\n ...customStyles,\n }\n \n return (props: NewsletterTemplateProps) => (\n <BaseTemplate\n preview={props.preheader || props.subject}\n footer={props.footer}\n >\n {props.title && (\n <Heading style={mergedStyles.heading}>\n {props.title}\n </Heading>\n )}\n \n <Markdown\n markdownCustomStyles={mergedStyles.markdown}\n markdownContainerStyles={{\n padding: '0',\n }}\n >\n {props.content}\n </Markdown>\n \n {props.ctaButton && (\n <Button\n href={props.ctaButton.href}\n style={mergedStyles.button}\n >\n {props.ctaButton.text}\n </Button>\n )}\n </BaseTemplate>\n )\n}"],"names":["React","Heading","Button","Markdown","BaseTemplate","newsletterStyles","heading","fontSize","fontWeight","color","margin","markdown","h1","h2","h3","p","lineHeight","a","textDecoration","ul","paddingLeft","ol","li","marginBottom","img","maxWidth","height","blockquote","borderLeft","fontStyle","code","backgroundColor","padding","borderRadius","fontFamily","pre","overflow","button","textAlign","display","width","NewsletterTemplate","subject","preheader","title","content","ctaButton","footer","preview","style","markdownCustomStyles","markdownContainerStyles","href","text","createNewsletterTemplate","customStyles","mergedStyles","props"],"mappings":";AAAA,OAAOA,WAAW,QAAO;AACzB,SACEC,OAAO,EACPC,MAAM,EACNC,QAAQ,QACH,0BAAyB;AAChC,SAASC,YAAY,QAAQ,iBAAgB;AAmB7C,MAAMC,mBAAmB;IACvBC,SAAS;QACPC,UAAU;QACVC,YAAY;QACZC,OAAO;QACPC,QAAQ;IACV;IACAC,UAAU;QACRC,IAAI;YACFL,UAAU;YACVC,YAAY;YACZC,OAAO;YACPC,QAAQ;QACV;QACAG,IAAI;YACFN,UAAU;YACVC,YAAY;YACZC,OAAO;YACPC,QAAQ;QACV;QACAI,IAAI;YACFP,UAAU;YACVC,YAAY;YACZC,OAAO;YACPC,QAAQ;QACV;QACAK,GAAG;YACDR,UAAU;YACVS,YAAY;YACZP,OAAO;YACPC,QAAQ;QACV;QACAO,GAAG;YACDR,OAAO;YACPS,gBAAgB;QAClB;QACAC,IAAI;YACFC,aAAa;YACbV,QAAQ;QACV;QACAW,IAAI;YACFD,aAAa;YACbV,QAAQ;QACV;QACAY,IAAI;YACFf,UAAU;YACVS,YAAY;YACZP,OAAO;YACPc,cAAc;QAChB;QACAC,KAAK;YACHC,UAAU;YACVC,QAAQ;YACRhB,QAAQ;QACV;QACAiB,YAAY;YACVC,YAAY;YACZR,aAAa;YACbV,QAAQ;YACRmB,WAAW;YACXpB,OAAO;QACT;QACAqB,MAAM;YACJC,iBAAiB;YACjBC,SAAS;YACTC,cAAc;YACdC,YAAY;YACZ3B,UAAU;QACZ;QACA4B,KAAK;YACHJ,iBAAiB;YACjBC,SAAS;YACTC,cAAc;YACdG,UAAU;YACV1B,QAAQ;QACV;IACF;IACA2B,QAAQ;QACNN,iBAAiB;QACjBE,cAAc;QACdxB,OAAO;QACPF,UAAU;QACVC,YAAY;QACZU,gBAAgB;QAChBoB,WAAW;QACXC,SAAS;QACTC,OAAO;QACPR,SAAS;QACTtB,QAAQ;IACV;AACF;AAEA,OAAO,MAAM+B,qBAAwD,CAAC,EACpEC,OAAO,EACPC,SAAS,EACTC,KAAK,EACLC,OAAO,EACPC,SAAS,EACTC,MAAM,EACP;IACC,qBACE,MAAC3C;QACC4C,SAASL,aAAaD;QACtBK,QAAQA;;YAEPH,uBACC,KAAC3C;gBAAQgD,OAAO5C,iBAAiBC,OAAO;0BACrCsC;;0BAIL,KAACzC;gBACC+C,sBAAsB7C,iBAAiBM,QAAQ;gBAC/CwC,yBAAyB;oBACvBnB,SAAS;gBACX;0BAECa;;YAGFC,2BACC,KAAC5C;gBACCkD,MAAMN,UAAUM,IAAI;gBACpBH,OAAO5C,iBAAiBgC,MAAM;0BAE7BS,UAAUO,IAAI;;;;AAKzB,EAAC;AAED,8DAA8D;AAC9D,OAAO,SAASC,yBACdC,YAA+C;IAE/C,MAAMC,eAAe;QACnB,GAAGnD,gBAAgB;QACnB,GAAGkD,YAAY;IACjB;IAEA,OAAO,CAACE,sBACN,MAACrD;YACC4C,SAASS,MAAMd,SAAS,IAAIc,MAAMf,OAAO;YACzCK,QAAQU,MAAMV,MAAM;;gBAEnBU,MAAMb,KAAK,kBACV,KAAC3C;oBAAQgD,OAAOO,aAAalD,OAAO;8BACjCmD,MAAMb,KAAK;;8BAIhB,KAACzC;oBACC+C,sBAAsBM,aAAa7C,QAAQ;oBAC3CwC,yBAAyB;wBACvBnB,SAAS;oBACX;8BAECyB,MAAMZ,OAAO;;gBAGfY,MAAMX,SAAS,kBACd,KAAC5C;oBACCkD,MAAMK,MAAMX,SAAS,CAACM,IAAI;oBAC1BH,OAAOO,aAAanB,MAAM;8BAEzBoB,MAAMX,SAAS,CAACO,IAAI;;;;AAK/B"}
@@ -1,192 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import React from 'react';
3
- import { Heading, Text, Button } from '@react-email/components';
4
- import { BaseTemplate } from './BaseTemplate';
5
- const welcomeStyles = {
6
- heading: {
7
- fontSize: '28px',
8
- fontWeight: '700',
9
- color: '#1a1a1a',
10
- margin: '0 0 16px 0'
11
- },
12
- subheading: {
13
- fontSize: '20px',
14
- fontWeight: '600',
15
- color: '#4a4a4a',
16
- margin: '24px 0 12px 0'
17
- },
18
- text: {
19
- fontSize: '16px',
20
- lineHeight: '24px',
21
- color: '#4a4a4a',
22
- margin: '0 0 16px 0'
23
- },
24
- button: {
25
- backgroundColor: '#0066cc',
26
- borderRadius: '6px',
27
- color: '#ffffff',
28
- fontSize: '16px',
29
- fontWeight: '600',
30
- textDecoration: 'none',
31
- textAlign: 'center',
32
- display: 'block',
33
- width: '200px',
34
- padding: '12px 20px',
35
- margin: '24px 0'
36
- },
37
- list: {
38
- paddingLeft: '20px',
39
- margin: '0 0 16px 0'
40
- },
41
- listItem: {
42
- fontSize: '16px',
43
- lineHeight: '24px',
44
- color: '#4a4a4a',
45
- marginBottom: '8px'
46
- }
47
- };
48
- export const WelcomeTemplate = ({ subscriber, unsubscribeUrl, preferencesUrl })=>{
49
- return /*#__PURE__*/ _jsxs(BaseTemplate, {
50
- preview: `Welcome to our newsletter, ${subscriber.name || 'there'}!`,
51
- footer: {
52
- unsubscribeUrl,
53
- preferencesUrl
54
- },
55
- children: [
56
- /*#__PURE__*/ _jsxs(Heading, {
57
- style: welcomeStyles.heading,
58
- children: [
59
- "Welcome",
60
- subscriber.name ? `, ${subscriber.name}` : '',
61
- "!"
62
- ]
63
- }),
64
- /*#__PURE__*/ _jsx(Text, {
65
- style: welcomeStyles.text,
66
- children: "Thank you for subscribing to our newsletter. We're excited to have you on board!"
67
- }),
68
- /*#__PURE__*/ _jsx(Text, {
69
- style: welcomeStyles.text,
70
- children: "Here's what you can expect from us:"
71
- }),
72
- /*#__PURE__*/ _jsxs("ul", {
73
- style: welcomeStyles.list,
74
- children: [
75
- /*#__PURE__*/ _jsx("li", {
76
- style: welcomeStyles.listItem,
77
- children: "Weekly updates with our latest content"
78
- }),
79
- /*#__PURE__*/ _jsx("li", {
80
- style: welcomeStyles.listItem,
81
- children: "Exclusive insights and tips"
82
- }),
83
- /*#__PURE__*/ _jsx("li", {
84
- style: welcomeStyles.listItem,
85
- children: "Early access to new features and announcements"
86
- })
87
- ]
88
- }),
89
- preferencesUrl && /*#__PURE__*/ _jsxs(_Fragment, {
90
- children: [
91
- /*#__PURE__*/ _jsx(Heading, {
92
- as: "h2",
93
- style: welcomeStyles.subheading,
94
- children: "Customize Your Experience"
95
- }),
96
- /*#__PURE__*/ _jsx(Text, {
97
- style: welcomeStyles.text,
98
- children: "Want to control what types of emails you receive? Visit your preferences page to customize your subscription."
99
- }),
100
- /*#__PURE__*/ _jsx(Button, {
101
- href: preferencesUrl,
102
- style: welcomeStyles.button,
103
- children: "Manage Preferences"
104
- })
105
- ]
106
- }),
107
- /*#__PURE__*/ _jsx(Text, {
108
- style: welcomeStyles.text,
109
- children: "If you have any questions or feedback, feel free to reply to this email. We'd love to hear from you!"
110
- }),
111
- /*#__PURE__*/ _jsxs(Text, {
112
- style: welcomeStyles.text,
113
- children: [
114
- "Best regards,",
115
- /*#__PURE__*/ _jsx("br", {}),
116
- "The Team"
117
- ]
118
- })
119
- ]
120
- });
121
- };
122
- // Export a function that creates a custom welcome template
123
- export function createWelcomeTemplate(customContent, customStyles) {
124
- const mergedStyles = {
125
- ...welcomeStyles,
126
- ...customStyles
127
- };
128
- return (props)=>/*#__PURE__*/ _jsxs(BaseTemplate, {
129
- preview: customContent?.heading || `Welcome to our newsletter, ${props.subscriber.name || 'there'}!`,
130
- footer: {
131
- unsubscribeUrl: props.unsubscribeUrl,
132
- preferencesUrl: props.preferencesUrl
133
- },
134
- children: [
135
- /*#__PURE__*/ _jsx(Heading, {
136
- style: mergedStyles.heading,
137
- children: customContent?.heading || `Welcome${props.subscriber.name ? `, ${props.subscriber.name}` : ''}!`
138
- }),
139
- /*#__PURE__*/ _jsx(Text, {
140
- style: mergedStyles.text,
141
- children: customContent?.intro || 'Thank you for subscribing to our newsletter. We\'re excited to have you on board!'
142
- }),
143
- customContent?.features && customContent.features.length > 0 && /*#__PURE__*/ _jsxs(_Fragment, {
144
- children: [
145
- /*#__PURE__*/ _jsx(Text, {
146
- style: mergedStyles.text,
147
- children: "Here's what you can expect from us:"
148
- }),
149
- /*#__PURE__*/ _jsx("ul", {
150
- style: mergedStyles.list,
151
- children: customContent.features.map((feature, index)=>/*#__PURE__*/ _jsx("li", {
152
- style: mergedStyles.listItem,
153
- children: feature
154
- }, index))
155
- })
156
- ]
157
- }),
158
- props.preferencesUrl && /*#__PURE__*/ _jsxs(_Fragment, {
159
- children: [
160
- /*#__PURE__*/ _jsx(Heading, {
161
- as: "h2",
162
- style: mergedStyles.subheading,
163
- children: "Customize Your Experience"
164
- }),
165
- /*#__PURE__*/ _jsx(Text, {
166
- style: mergedStyles.text,
167
- children: "Want to control what types of emails you receive? Visit your preferences page to customize your subscription."
168
- }),
169
- /*#__PURE__*/ _jsx(Button, {
170
- href: props.preferencesUrl,
171
- style: mergedStyles.button,
172
- children: customContent?.ctaText || 'Manage Preferences'
173
- })
174
- ]
175
- }),
176
- /*#__PURE__*/ _jsx(Text, {
177
- style: mergedStyles.text,
178
- children: customContent?.closing || 'If you have any questions or feedback, feel free to reply to this email. We\'d love to hear from you!'
179
- }),
180
- /*#__PURE__*/ _jsxs(Text, {
181
- style: mergedStyles.text,
182
- children: [
183
- "Best regards,",
184
- /*#__PURE__*/ _jsx("br", {}),
185
- "The Team"
186
- ]
187
- })
188
- ]
189
- });
190
- }
191
-
192
- //# sourceMappingURL=WelcomeTemplate.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/templates/WelcomeTemplate.tsx"],"sourcesContent":["import React from 'react'\nimport {\n Heading,\n Text,\n Button,\n} from '@react-email/components'\nimport { BaseTemplate } from './BaseTemplate'\nimport type { WelcomeEmailProps } from '../types'\n\nconst welcomeStyles = {\n heading: {\n fontSize: '28px',\n fontWeight: '700',\n color: '#1a1a1a',\n margin: '0 0 16px 0',\n },\n subheading: {\n fontSize: '20px',\n fontWeight: '600',\n color: '#4a4a4a',\n margin: '24px 0 12px 0',\n },\n text: {\n fontSize: '16px',\n lineHeight: '24px',\n color: '#4a4a4a',\n margin: '0 0 16px 0',\n },\n button: {\n backgroundColor: '#0066cc',\n borderRadius: '6px',\n color: '#ffffff',\n fontSize: '16px',\n fontWeight: '600',\n textDecoration: 'none',\n textAlign: 'center' as const,\n display: 'block',\n width: '200px',\n padding: '12px 20px',\n margin: '24px 0',\n },\n list: {\n paddingLeft: '20px',\n margin: '0 0 16px 0',\n },\n listItem: {\n fontSize: '16px',\n lineHeight: '24px',\n color: '#4a4a4a',\n marginBottom: '8px',\n },\n}\n\nexport const WelcomeTemplate: React.FC<WelcomeEmailProps> = ({\n subscriber,\n unsubscribeUrl,\n preferencesUrl,\n}) => {\n return (\n <BaseTemplate\n preview={`Welcome to our newsletter, ${subscriber.name || 'there'}!`}\n footer={{\n unsubscribeUrl,\n preferencesUrl,\n }}\n >\n <Heading style={welcomeStyles.heading}>\n Welcome{subscriber.name ? `, ${subscriber.name}` : ''}!\n </Heading>\n \n <Text style={welcomeStyles.text}>\n Thank you for subscribing to our newsletter. We're excited to have you on board!\n </Text>\n \n <Text style={welcomeStyles.text}>\n Here's what you can expect from us:\n </Text>\n \n <ul style={welcomeStyles.list}>\n <li style={welcomeStyles.listItem}>\n Weekly updates with our latest content\n </li>\n <li style={welcomeStyles.listItem}>\n Exclusive insights and tips\n </li>\n <li style={welcomeStyles.listItem}>\n Early access to new features and announcements\n </li>\n </ul>\n \n {preferencesUrl && (\n <>\n <Heading as=\"h2\" style={welcomeStyles.subheading}>\n Customize Your Experience\n </Heading>\n \n <Text style={welcomeStyles.text}>\n Want to control what types of emails you receive? Visit your preferences page to customize your subscription.\n </Text>\n \n <Button\n href={preferencesUrl}\n style={welcomeStyles.button}\n >\n Manage Preferences\n </Button>\n </>\n )}\n \n <Text style={welcomeStyles.text}>\n If you have any questions or feedback, feel free to reply to this email. We'd love to hear from you!\n </Text>\n \n <Text style={welcomeStyles.text}>\n Best regards,<br />\n The Team\n </Text>\n </BaseTemplate>\n )\n}\n\n// Export a function that creates a custom welcome template\nexport function createWelcomeTemplate(\n customContent?: {\n heading?: string\n intro?: string\n features?: string[]\n ctaText?: string\n closing?: string\n },\n customStyles?: Partial<typeof welcomeStyles>\n): React.FC<WelcomeEmailProps> {\n const mergedStyles = {\n ...welcomeStyles,\n ...customStyles,\n }\n \n return (props: WelcomeEmailProps) => (\n <BaseTemplate\n preview={customContent?.heading || `Welcome to our newsletter, ${props.subscriber.name || 'there'}!`}\n footer={{\n unsubscribeUrl: props.unsubscribeUrl,\n preferencesUrl: props.preferencesUrl,\n }}\n >\n <Heading style={mergedStyles.heading}>\n {customContent?.heading || `Welcome${props.subscriber.name ? `, ${props.subscriber.name}` : ''}!`}\n </Heading>\n \n <Text style={mergedStyles.text}>\n {customContent?.intro || 'Thank you for subscribing to our newsletter. We\\'re excited to have you on board!'}\n </Text>\n \n {customContent?.features && customContent.features.length > 0 && (\n <>\n <Text style={mergedStyles.text}>\n Here's what you can expect from us:\n </Text>\n \n <ul style={mergedStyles.list}>\n {customContent.features.map((feature, index) => (\n <li key={index} style={mergedStyles.listItem}>\n {feature}\n </li>\n ))}\n </ul>\n </>\n )}\n \n {props.preferencesUrl && (\n <>\n <Heading as=\"h2\" style={mergedStyles.subheading}>\n Customize Your Experience\n </Heading>\n \n <Text style={mergedStyles.text}>\n Want to control what types of emails you receive? Visit your preferences page to customize your subscription.\n </Text>\n \n <Button\n href={props.preferencesUrl}\n style={mergedStyles.button}\n >\n {customContent?.ctaText || 'Manage Preferences'}\n </Button>\n </>\n )}\n \n <Text style={mergedStyles.text}>\n {customContent?.closing || 'If you have any questions or feedback, feel free to reply to this email. We\\'d love to hear from you!'}\n </Text>\n \n <Text style={mergedStyles.text}>\n Best regards,<br />\n The Team\n </Text>\n </BaseTemplate>\n )\n}"],"names":["React","Heading","Text","Button","BaseTemplate","welcomeStyles","heading","fontSize","fontWeight","color","margin","subheading","text","lineHeight","button","backgroundColor","borderRadius","textDecoration","textAlign","display","width","padding","list","paddingLeft","listItem","marginBottom","WelcomeTemplate","subscriber","unsubscribeUrl","preferencesUrl","preview","name","footer","style","ul","li","as","href","br","createWelcomeTemplate","customContent","customStyles","mergedStyles","props","intro","features","length","map","feature","index","ctaText","closing"],"mappings":"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"}
@@ -1,6 +0,0 @@
1
- export { BaseTemplate, baseStyles } from './BaseTemplate';
2
- export { NewsletterTemplate, createNewsletterTemplate } from './NewsletterTemplate';
3
- export { WelcomeTemplate, createWelcomeTemplate } from './WelcomeTemplate';
4
- export { MagicLinkTemplate, createMagicLinkTemplate } from './MagicLinkTemplate';
5
-
6
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/templates/index.ts"],"sourcesContent":["export { BaseTemplate, baseStyles } from './BaseTemplate'\nexport type { BaseTemplateProps } from './BaseTemplate'\n\nexport { NewsletterTemplate, createNewsletterTemplate } from './NewsletterTemplate'\nexport type { NewsletterTemplateProps } from './NewsletterTemplate'\n\nexport { WelcomeTemplate, createWelcomeTemplate } from './WelcomeTemplate'\n\nexport { MagicLinkTemplate, createMagicLinkTemplate } from './MagicLinkTemplate'"],"names":["BaseTemplate","baseStyles","NewsletterTemplate","createNewsletterTemplate","WelcomeTemplate","createWelcomeTemplate","MagicLinkTemplate","createMagicLinkTemplate"],"mappings":"AAAA,SAASA,YAAY,EAAEC,UAAU,QAAQ,iBAAgB;AAGzD,SAASC,kBAAkB,EAAEC,wBAAwB,QAAQ,uBAAsB;AAGnF,SAASC,eAAe,EAAEC,qBAAqB,QAAQ,oBAAmB;AAE1E,SAASC,iBAAiB,EAAEC,uBAAuB,QAAQ,sBAAqB"}
@@ -1,3 +0,0 @@
1
- export { };
2
-
3
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/types/index.ts"],"sourcesContent":["import type { Field } from 'payload'\n\nexport interface NewsletterPluginConfig {\n /**\n * Enable or disable the plugin\n * @default true\n */\n enabled?: boolean\n\n /**\n * Slug for the subscribers collection\n * @default 'subscribers'\n */\n subscribersSlug?: string\n \n /**\n * Slug for the newsletter settings collection\n * @default 'newsletter-settings'\n */\n settingsSlug?: string\n\n /**\n * Authentication configuration for magic links\n */\n auth?: {\n /**\n * Enable magic link authentication\n * @default true\n */\n enabled?: boolean\n \n /**\n * Token expiration time\n * @default '7d'\n */\n tokenExpiration?: string\n \n /**\n * Path where magic link redirects\n * @default '/newsletter/verify'\n */\n magicLinkPath?: string\n }\n\n /**\n * Access control configuration\n */\n access?: {\n /**\n * Custom function to determine if a user is an admin\n * @param user - The authenticated user object\n * @returns true if the user should have admin access\n */\n isAdmin?: (user: any) => boolean\n }\n\n /**\n * Email provider configuration\n */\n providers: {\n /**\n * Default provider to use\n */\n default: 'resend' | 'broadcast' | string\n \n /**\n * Resend provider configuration\n */\n resend?: ResendProviderConfig\n \n /**\n * Broadcast provider configuration\n */\n broadcast?: BroadcastProviderConfig\n }\n\n /**\n * Field customization options\n */\n fields?: {\n /**\n * Override default fields\n */\n overrides?: (args: { defaultFields: Field[] }) => Field[]\n \n /**\n * Additional custom fields\n */\n additional?: Field[]\n }\n\n /**\n * Email template components\n */\n templates?: {\n /**\n * Welcome email template\n */\n welcome?: React.ComponentType<WelcomeEmailProps>\n \n /**\n * Magic link email template\n */\n magicLink?: React.ComponentType<MagicLinkEmailProps>\n }\n\n /**\n * Plugin hooks\n */\n hooks?: {\n beforeSubscribe?: (args: BeforeSubscribeArgs) => void | Promise<void>\n afterSubscribe?: (args: AfterSubscribeArgs) => void | Promise<void>\n beforeUnsubscribe?: (args: BeforeUnsubscribeArgs) => void | Promise<void>\n afterUnsubscribe?: (args: AfterUnsubscribeArgs) => void | Promise<void>\n }\n\n /**\n * UI component overrides\n */\n components?: {\n signupForm?: React.ComponentType<SignupFormProps>\n preferencesForm?: React.ComponentType<PreferencesFormProps>\n }\n\n /**\n * Feature flags\n */\n features?: {\n /**\n * Lead magnet configuration\n */\n leadMagnets?: {\n enabled?: boolean\n collection?: string\n }\n \n /**\n * Post-signup survey configuration\n */\n surveys?: {\n enabled?: boolean\n questions?: SurveyQuestion[]\n }\n \n /**\n * UTM tracking configuration\n */\n utmTracking?: {\n enabled?: boolean\n fields?: string[]\n }\n \n /**\n * Newsletter scheduling configuration\n */\n newsletterScheduling?: {\n enabled?: boolean\n /**\n * Collections to add newsletter fields to\n * Can be a string for single collection or array for multiple\n * @example 'articles' or ['articles', 'posts', 'updates']\n */\n collections?: string | string[]\n /**\n * Field configuration\n */\n fields?: {\n /**\n * Group name for newsletter fields\n * @default 'newsletterScheduling'\n */\n groupName?: string\n /**\n * Rich text field name to use for content\n * @default 'content'\n */\n contentField?: string\n /**\n * Whether to create a markdown companion field\n * @default true\n */\n createMarkdownField?: boolean\n }\n }\n }\n\n /**\n * Internationalization configuration\n */\n i18n?: {\n defaultLocale?: string\n locales?: string[]\n }\n}\n\nexport interface ResendProviderConfig {\n apiKey: string\n fromAddress?: string\n fromName?: string\n audienceIds?: {\n [locale: string]: {\n production?: string\n development?: string\n }\n }\n}\n\nexport interface BroadcastProviderConfig {\n apiUrl: string\n tokens: {\n production?: string\n development?: string\n }\n fromAddress?: string\n fromName?: string\n}\n\nexport interface EmailProvider {\n send(params: SendEmailParams): Promise<void>\n addContact(contact: Subscriber): Promise<void>\n updateContact(contact: Subscriber): Promise<void>\n removeContact(email: string): Promise<void>\n}\n\nexport interface SendEmailParams {\n to: string | string[]\n subject: string\n html?: string\n text?: string\n react?: React.ReactElement\n}\n\nexport interface Subscriber {\n id: string\n email: string\n name?: string\n locale?: string\n subscriptionStatus: 'active' | 'unsubscribed' | 'pending'\n emailPreferences?: {\n newsletter?: boolean\n announcements?: boolean\n [key: string]: boolean | undefined\n }\n source?: string\n utmParameters?: {\n source?: string\n medium?: string\n campaign?: string\n content?: string\n term?: string\n }\n createdAt: string\n updatedAt: string\n}\n\nexport interface WelcomeEmailProps {\n subscriber: Subscriber\n unsubscribeUrl: string\n preferencesUrl: string\n}\n\nexport interface MagicLinkEmailProps {\n magicLinkUrl: string\n subscriber: Subscriber\n}\n\nexport interface SignupFormProps {\n onSuccess?: (subscriber: Subscriber) => void\n onError?: (error: Error) => void\n showName?: boolean\n showPreferences?: boolean\n leadMagnet?: {\n id: string\n title: string\n description?: string\n }\n className?: string\n styles?: {\n form?: React.CSSProperties\n inputGroup?: React.CSSProperties\n label?: React.CSSProperties\n input?: React.CSSProperties\n button?: React.CSSProperties\n buttonDisabled?: React.CSSProperties\n error?: React.CSSProperties\n success?: React.CSSProperties\n checkbox?: React.CSSProperties\n checkboxInput?: React.CSSProperties\n checkboxLabel?: React.CSSProperties\n }\n apiEndpoint?: string\n buttonText?: string\n loadingText?: string\n successMessage?: string\n placeholders?: {\n email?: string\n name?: string\n }\n labels?: {\n email?: string\n name?: string\n newsletter?: string\n announcements?: string\n }\n}\n\nexport interface PreferencesFormProps {\n subscriber?: Subscriber\n onSuccess?: (subscriber: Subscriber) => void\n onError?: (error: Error) => void\n className?: string\n styles?: {\n container?: React.CSSProperties\n heading?: React.CSSProperties\n form?: React.CSSProperties\n section?: React.CSSProperties\n sectionTitle?: React.CSSProperties\n inputGroup?: React.CSSProperties\n label?: React.CSSProperties\n input?: React.CSSProperties\n select?: React.CSSProperties\n checkbox?: React.CSSProperties\n checkboxInput?: React.CSSProperties\n checkboxLabel?: React.CSSProperties\n buttonGroup?: React.CSSProperties\n button?: React.CSSProperties\n primaryButton?: React.CSSProperties\n secondaryButton?: React.CSSProperties\n dangerButton?: React.CSSProperties\n error?: React.CSSProperties\n success?: React.CSSProperties\n info?: React.CSSProperties\n }\n sessionToken?: string\n apiEndpoint?: string\n showUnsubscribe?: boolean\n locales?: string[]\n labels?: {\n title?: string\n personalInfo?: string\n emailPreferences?: string\n name?: string\n language?: string\n newsletter?: string\n announcements?: string\n saveButton?: string\n unsubscribeButton?: string\n saving?: string\n saved?: string\n unsubscribeConfirm?: string\n }\n}\n\nexport interface BeforeSubscribeArgs {\n data: Partial<Subscriber>\n req: any\n}\n\nexport interface AfterSubscribeArgs {\n doc: Subscriber\n req: any\n}\n\nexport interface BeforeUnsubscribeArgs {\n email: string\n req: any\n}\n\nexport interface AfterUnsubscribeArgs {\n doc: Subscriber\n req: any\n}\n\nexport interface SurveyQuestion {\n id: string\n question: string\n type: 'text' | 'select' | 'multiselect' | 'radio'\n options?: string[]\n required?: boolean\n}"],"names":[],"mappings":"AAqXA,WAMC"}
@@ -1,80 +0,0 @@
1
- /**
2
- * Check if a user is an admin based on the plugin configuration
3
- */ export const isAdmin = (user, config)=>{
4
- if (!user || user.collection !== 'users') {
5
- return false;
6
- }
7
- // If custom admin check is provided, use it
8
- if (config?.access?.isAdmin) {
9
- return config.access.isAdmin(user);
10
- }
11
- // Default checks for common admin patterns
12
- // 1. Check for admin role
13
- if (user.roles?.includes('admin')) {
14
- return true;
15
- }
16
- // 2. Check for isAdmin boolean field
17
- if (user.isAdmin === true) {
18
- return true;
19
- }
20
- // 3. Check for role field with admin value
21
- if (user.role === 'admin') {
22
- return true;
23
- }
24
- // 4. Check for admin collection relationship
25
- if (user.admin === true) {
26
- return true;
27
- }
28
- return false;
29
- };
30
- /**
31
- * Create admin-only access control
32
- */ export const adminOnly = (config)=>({ req })=>{
33
- const user = req.user;
34
- return isAdmin(user, config);
35
- };
36
- /**
37
- * Create admin or owner access control
38
- */ export const adminOrSelf = (config)=>({ req, id })=>{
39
- const user = req.user;
40
- // No user = no access
41
- if (!user) {
42
- // For list operations without ID, return impossible condition
43
- if (!id) {
44
- return {
45
- id: {
46
- equals: 'unauthorized-no-access'
47
- }
48
- };
49
- }
50
- return false;
51
- }
52
- // Admins can access everything
53
- if (isAdmin(user, config)) {
54
- return true;
55
- }
56
- // Synthetic users (subscribers from magic link) can access their own data
57
- if (user.collection === 'subscribers') {
58
- // For list operations, scope to their own data
59
- if (!id) {
60
- return {
61
- id: {
62
- equals: user.id
63
- }
64
- };
65
- }
66
- // For specific document access, check if it's their own
67
- return id === user.id;
68
- }
69
- // Regular users cannot access subscriber data
70
- if (!id) {
71
- return {
72
- id: {
73
- equals: 'unauthorized-no-access'
74
- }
75
- };
76
- }
77
- return false;
78
- };
79
-
80
- //# sourceMappingURL=access.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/utils/access.ts"],"sourcesContent":["import type { Access, AccessArgs } from 'payload'\nimport type { NewsletterPluginConfig } from '../types'\n\n/**\n * Check if a user is an admin based on the plugin configuration\n */\nexport const isAdmin = (user: any, config?: NewsletterPluginConfig): boolean => {\n if (!user || user.collection !== 'users') {\n return false\n }\n\n // If custom admin check is provided, use it\n if (config?.access?.isAdmin) {\n return config.access.isAdmin(user)\n }\n\n // Default checks for common admin patterns\n // 1. Check for admin role\n if (user.roles?.includes('admin')) {\n return true\n }\n\n // 2. Check for isAdmin boolean field\n if (user.isAdmin === true) {\n return true\n }\n\n // 3. Check for role field with admin value\n if (user.role === 'admin') {\n return true\n }\n\n // 4. Check for admin collection relationship\n if (user.admin === true) {\n return true\n }\n\n return false\n}\n\n/**\n * Create admin-only access control\n */\nexport const adminOnly = (config?: NewsletterPluginConfig): Access => \n ({ req }: AccessArgs) => {\n const user = req.user\n return isAdmin(user, config)\n }\n\n/**\n * Create admin or owner access control\n */\nexport const adminOrSelf = (config?: NewsletterPluginConfig): Access => \n ({ req, id }: AccessArgs) => {\n const user = req.user\n \n // No user = no access\n if (!user) {\n // For list operations without ID, return impossible condition\n if (!id) {\n return {\n id: {\n equals: 'unauthorized-no-access',\n },\n }\n }\n return false\n }\n \n // Admins can access everything\n if (isAdmin(user, config)) {\n return true\n }\n \n // Synthetic users (subscribers from magic link) can access their own data\n if (user.collection === 'subscribers') {\n // For list operations, scope to their own data\n if (!id) {\n return {\n id: {\n equals: user.id,\n },\n }\n }\n // For specific document access, check if it's their own\n return id === user.id\n }\n \n // Regular users cannot access subscriber data\n if (!id) {\n return {\n id: {\n equals: 'unauthorized-no-access',\n },\n }\n }\n return false\n }"],"names":["isAdmin","user","config","collection","access","roles","includes","role","admin","adminOnly","req","adminOrSelf","id","equals"],"mappings":"AAGA;;CAEC,GACD,OAAO,MAAMA,UAAU,CAACC,MAAWC;IACjC,IAAI,CAACD,QAAQA,KAAKE,UAAU,KAAK,SAAS;QACxC,OAAO;IACT;IAEA,4CAA4C;IAC5C,IAAID,QAAQE,QAAQJ,SAAS;QAC3B,OAAOE,OAAOE,MAAM,CAACJ,OAAO,CAACC;IAC/B;IAEA,2CAA2C;IAC3C,0BAA0B;IAC1B,IAAIA,KAAKI,KAAK,EAAEC,SAAS,UAAU;QACjC,OAAO;IACT;IAEA,qCAAqC;IACrC,IAAIL,KAAKD,OAAO,KAAK,MAAM;QACzB,OAAO;IACT;IAEA,2CAA2C;IAC3C,IAAIC,KAAKM,IAAI,KAAK,SAAS;QACzB,OAAO;IACT;IAEA,6CAA6C;IAC7C,IAAIN,KAAKO,KAAK,KAAK,MAAM;QACvB,OAAO;IACT;IAEA,OAAO;AACT,EAAC;AAED;;CAEC,GACD,OAAO,MAAMC,YAAY,CAACP,SACxB,CAAC,EAAEQ,GAAG,EAAc;QAClB,MAAMT,OAAOS,IAAIT,IAAI;QACrB,OAAOD,QAAQC,MAAMC;IACvB,EAAC;AAEH;;CAEC,GACD,OAAO,MAAMS,cAAc,CAACT,SAC1B,CAAC,EAAEQ,GAAG,EAAEE,EAAE,EAAc;QACtB,MAAMX,OAAOS,IAAIT,IAAI;QAErB,sBAAsB;QACtB,IAAI,CAACA,MAAM;YACT,8DAA8D;YAC9D,IAAI,CAACW,IAAI;gBACP,OAAO;oBACLA,IAAI;wBACFC,QAAQ;oBACV;gBACF;YACF;YACA,OAAO;QACT;QAEA,+BAA+B;QAC/B,IAAIb,QAAQC,MAAMC,SAAS;YACzB,OAAO;QACT;QAEA,0EAA0E;QAC1E,IAAID,KAAKE,UAAU,KAAK,eAAe;YACrC,+CAA+C;YAC/C,IAAI,CAACS,IAAI;gBACP,OAAO;oBACLA,IAAI;wBACFC,QAAQZ,KAAKW,EAAE;oBACjB;gBACF;YACF;YACA,wDAAwD;YACxD,OAAOA,OAAOX,KAAKW,EAAE;QACvB;QAEA,8CAA8C;QAC9C,IAAI,CAACA,IAAI;YACP,OAAO;gBACLA,IAAI;oBACFC,QAAQ;gBACV;YACF;QACF;QACA,OAAO;IACT,EAAC"}
@@ -1,91 +0,0 @@
1
- import jwt from 'jsonwebtoken';
2
- /**
3
- * Get JWT secret from environment or generate a warning
4
- */ function getJWTSecret() {
5
- const secret = process.env.JWT_SECRET || process.env.PAYLOAD_SECRET;
6
- if (!secret) {
7
- console.warn('WARNING: No JWT_SECRET or PAYLOAD_SECRET found in environment variables. ' + 'Magic link authentication will not work properly. ' + 'Please set JWT_SECRET in your environment.');
8
- // Return a placeholder to prevent crashes during development
9
- return 'INSECURE_DEVELOPMENT_SECRET_PLEASE_SET_JWT_SECRET';
10
- }
11
- return secret;
12
- }
13
- /**
14
- * Generate a magic link token for email authentication
15
- */ export function generateMagicLinkToken(subscriberId, email, config) {
16
- const payload = {
17
- subscriberId,
18
- email,
19
- type: 'magic-link'
20
- };
21
- const expiresIn = config.auth?.tokenExpiration || '7d';
22
- return jwt.sign(payload, getJWTSecret(), {
23
- expiresIn: expiresIn,
24
- issuer: 'payload-newsletter-plugin'
25
- });
26
- }
27
- /**
28
- * Verify a magic link token
29
- */ export function verifyMagicLinkToken(token) {
30
- try {
31
- const payload = jwt.verify(token, getJWTSecret(), {
32
- issuer: 'payload-newsletter-plugin'
33
- });
34
- if (payload.type !== 'magic-link') {
35
- throw new Error('Invalid token type');
36
- }
37
- return payload;
38
- } catch (error) {
39
- if (error instanceof Error && error.name === 'TokenExpiredError') {
40
- throw new Error('Magic link has expired. Please request a new one.');
41
- }
42
- if (error instanceof Error && error.name === 'JsonWebTokenError') {
43
- throw new Error('Invalid magic link token');
44
- }
45
- throw error;
46
- }
47
- }
48
- /**
49
- * Generate a session token after successful magic link verification
50
- */ export function generateSessionToken(subscriberId, email) {
51
- const payload = {
52
- subscriberId,
53
- email,
54
- type: 'session'
55
- };
56
- return jwt.sign(payload, getJWTSecret(), {
57
- expiresIn: '30d',
58
- issuer: 'payload-newsletter-plugin'
59
- });
60
- }
61
- /**
62
- * Verify a session token
63
- */ export function verifySessionToken(token) {
64
- try {
65
- const payload = jwt.verify(token, getJWTSecret(), {
66
- issuer: 'payload-newsletter-plugin'
67
- });
68
- if (payload.type !== 'session') {
69
- throw new Error('Invalid token type');
70
- }
71
- return payload;
72
- } catch (error) {
73
- if (error instanceof Error && error.name === 'TokenExpiredError') {
74
- throw new Error('Session has expired. Please sign in again.');
75
- }
76
- if (error instanceof Error && error.name === 'JsonWebTokenError') {
77
- throw new Error('Invalid session token');
78
- }
79
- throw error;
80
- }
81
- }
82
- /**
83
- * Generate a magic link URL
84
- */ export function generateMagicLinkURL(token, baseURL, config) {
85
- const path = config.auth?.magicLinkPath || '/newsletter/verify';
86
- const url = new URL(path, baseURL);
87
- url.searchParams.set('token', token);
88
- return url.toString();
89
- }
90
-
91
- //# sourceMappingURL=jwt.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/utils/jwt.ts"],"sourcesContent":["import jwt from 'jsonwebtoken'\nimport type { NewsletterPluginConfig } from '../types'\n\nexport interface MagicLinkTokenPayload {\n subscriberId: string\n email: string\n type: 'magic-link'\n}\n\nexport interface SessionTokenPayload {\n subscriberId: string\n email: string\n type: 'session'\n}\n\n/**\n * Get JWT secret from environment or generate a warning\n */\nfunction getJWTSecret(): string {\n const secret = process.env.JWT_SECRET || process.env.PAYLOAD_SECRET\n\n if (!secret) {\n console.warn(\n 'WARNING: No JWT_SECRET or PAYLOAD_SECRET found in environment variables. ' +\n 'Magic link authentication will not work properly. ' +\n 'Please set JWT_SECRET in your environment.'\n )\n // Return a placeholder to prevent crashes during development\n return 'INSECURE_DEVELOPMENT_SECRET_PLEASE_SET_JWT_SECRET'\n }\n\n return secret\n}\n\n/**\n * Generate a magic link token for email authentication\n */\nexport function generateMagicLinkToken(\n subscriberId: string,\n email: string,\n config: NewsletterPluginConfig\n): string {\n const payload: MagicLinkTokenPayload = {\n subscriberId,\n email,\n type: 'magic-link',\n }\n\n const expiresIn = config.auth?.tokenExpiration || '7d'\n\n return jwt.sign(payload, getJWTSecret(), {\n expiresIn: expiresIn,\n issuer: 'payload-newsletter-plugin',\n } as jwt.SignOptions)\n}\n\n/**\n * Verify a magic link token\n */\nexport function verifyMagicLinkToken(token: string): MagicLinkTokenPayload {\n try {\n const payload = jwt.verify(token, getJWTSecret(), {\n issuer: 'payload-newsletter-plugin',\n }) as any\n\n if (payload.type !== 'magic-link') {\n throw new Error('Invalid token type')\n }\n\n return payload as MagicLinkTokenPayload\n } catch (error: unknown) {\n if (error instanceof Error && error.name === 'TokenExpiredError') {\n throw new Error('Magic link has expired. Please request a new one.')\n }\n if (error instanceof Error && error.name === 'JsonWebTokenError') {\n throw new Error('Invalid magic link token')\n }\n throw error\n }\n}\n\n/**\n * Generate a session token after successful magic link verification\n */\nexport function generateSessionToken(\n subscriberId: string,\n email: string\n): string {\n const payload: SessionTokenPayload = {\n subscriberId,\n email,\n type: 'session',\n }\n\n return jwt.sign(payload, getJWTSecret(), {\n expiresIn: '30d',\n issuer: 'payload-newsletter-plugin',\n })\n}\n\n/**\n * Verify a session token\n */\nexport function verifySessionToken(token: string): SessionTokenPayload {\n try {\n const payload = jwt.verify(token, getJWTSecret(), {\n issuer: 'payload-newsletter-plugin',\n }) as any\n\n if (payload.type !== 'session') {\n throw new Error('Invalid token type')\n }\n\n return payload as SessionTokenPayload\n } catch (error: unknown) {\n if (error instanceof Error && error.name === 'TokenExpiredError') {\n throw new Error('Session has expired. Please sign in again.')\n }\n if (error instanceof Error && error.name === 'JsonWebTokenError') {\n throw new Error('Invalid session token')\n }\n throw error\n }\n}\n\n/**\n * Generate a magic link URL\n */\nexport function generateMagicLinkURL(\n token: string,\n baseURL: string,\n config: NewsletterPluginConfig\n): string {\n const path = config.auth?.magicLinkPath || '/newsletter/verify'\n const url = new URL(path, baseURL)\n url.searchParams.set('token', token)\n return url.toString()\n}"],"names":["jwt","getJWTSecret","secret","process","env","JWT_SECRET","PAYLOAD_SECRET","console","warn","generateMagicLinkToken","subscriberId","email","config","payload","type","expiresIn","auth","tokenExpiration","sign","issuer","verifyMagicLinkToken","token","verify","Error","error","name","generateSessionToken","verifySessionToken","generateMagicLinkURL","baseURL","path","magicLinkPath","url","URL","searchParams","set","toString"],"mappings":"AAAA,OAAOA,SAAS,eAAc;AAe9B;;CAEC,GACD,SAASC;IACP,MAAMC,SAASC,QAAQC,GAAG,CAACC,UAAU,IAAIF,QAAQC,GAAG,CAACE,cAAc;IAEnE,IAAI,CAACJ,QAAQ;QACXK,QAAQC,IAAI,CACV,8EACA,uDACA;QAEF,6DAA6D;QAC7D,OAAO;IACT;IAEA,OAAON;AACT;AAEA;;CAEC,GACD,OAAO,SAASO,uBACdC,YAAoB,EACpBC,KAAa,EACbC,MAA8B;IAE9B,MAAMC,UAAiC;QACrCH;QACAC;QACAG,MAAM;IACR;IAEA,MAAMC,YAAYH,OAAOI,IAAI,EAAEC,mBAAmB;IAElD,OAAOjB,IAAIkB,IAAI,CAACL,SAASZ,gBAAgB;QACvCc,WAAWA;QACXI,QAAQ;IACV;AACF;AAEA;;CAEC,GACD,OAAO,SAASC,qBAAqBC,KAAa;IAChD,IAAI;QACF,MAAMR,UAAUb,IAAIsB,MAAM,CAACD,OAAOpB,gBAAgB;YAChDkB,QAAQ;QACV;QAEA,IAAIN,QAAQC,IAAI,KAAK,cAAc;YACjC,MAAM,IAAIS,MAAM;QAClB;QAEA,OAAOV;IACT,EAAE,OAAOW,OAAgB;QACvB,IAAIA,iBAAiBD,SAASC,MAAMC,IAAI,KAAK,qBAAqB;YAChE,MAAM,IAAIF,MAAM;QAClB;QACA,IAAIC,iBAAiBD,SAASC,MAAMC,IAAI,KAAK,qBAAqB;YAChE,MAAM,IAAIF,MAAM;QAClB;QACA,MAAMC;IACR;AACF;AAEA;;CAEC,GACD,OAAO,SAASE,qBACdhB,YAAoB,EACpBC,KAAa;IAEb,MAAME,UAA+B;QACnCH;QACAC;QACAG,MAAM;IACR;IAEA,OAAOd,IAAIkB,IAAI,CAACL,SAASZ,gBAAgB;QACvCc,WAAW;QACXI,QAAQ;IACV;AACF;AAEA;;CAEC,GACD,OAAO,SAASQ,mBAAmBN,KAAa;IAC9C,IAAI;QACF,MAAMR,UAAUb,IAAIsB,MAAM,CAACD,OAAOpB,gBAAgB;YAChDkB,QAAQ;QACV;QAEA,IAAIN,QAAQC,IAAI,KAAK,WAAW;YAC9B,MAAM,IAAIS,MAAM;QAClB;QAEA,OAAOV;IACT,EAAE,OAAOW,OAAgB;QACvB,IAAIA,iBAAiBD,SAASC,MAAMC,IAAI,KAAK,qBAAqB;YAChE,MAAM,IAAIF,MAAM;QAClB;QACA,IAAIC,iBAAiBD,SAASC,MAAMC,IAAI,KAAK,qBAAqB;YAChE,MAAM,IAAIF,MAAM;QAClB;QACA,MAAMC;IACR;AACF;AAEA;;CAEC,GACD,OAAO,SAASI,qBACdP,KAAa,EACbQ,OAAe,EACfjB,MAA8B;IAE9B,MAAMkB,OAAOlB,OAAOI,IAAI,EAAEe,iBAAiB;IAC3C,MAAMC,MAAM,IAAIC,IAAIH,MAAMD;IAC1BG,IAAIE,YAAY,CAACC,GAAG,CAAC,SAASd;IAC9B,OAAOW,IAAII,QAAQ;AACrB"}