@latte-macchiat-io/latte-payload 1.0.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 (253) hide show
  1. package/.claude/settings.local.json +9 -0
  2. package/.env.example +29 -0
  3. package/.github/workflows/ci.yml +160 -0
  4. package/.github/workflows/publish.yml +126 -0
  5. package/.nvmrc +1 -0
  6. package/.prettierignore +2 -0
  7. package/.prettierrc +11 -0
  8. package/CHANGELOG.md +87 -0
  9. package/README.md +364 -0
  10. package/TESTING_AND_DOCUMENTATION_SETUP.md +348 -0
  11. package/dist/access/adminAccessOnly.d.ts +25 -0
  12. package/dist/access/adminAccessOnly.d.ts.map +1 -0
  13. package/dist/access/adminAccessOnly.js +11 -0
  14. package/dist/access/adminAccessOnly.js.map +1 -0
  15. package/dist/access/admins.d.ts +72 -0
  16. package/dist/access/admins.d.ts.map +1 -0
  17. package/dist/access/admins.js +76 -0
  18. package/dist/access/admins.js.map +1 -0
  19. package/dist/access/anyone.d.ts +35 -0
  20. package/dist/access/anyone.d.ts.map +1 -0
  21. package/dist/access/anyone.js +34 -0
  22. package/dist/access/anyone.js.map +1 -0
  23. package/dist/access/authenticated.d.ts +63 -0
  24. package/dist/access/authenticated.d.ts.map +1 -0
  25. package/dist/access/authenticated.js +68 -0
  26. package/dist/access/authenticated.js.map +1 -0
  27. package/dist/access/authenticatedAccessOnly.d.ts +13 -0
  28. package/dist/access/authenticatedAccessOnly.d.ts.map +1 -0
  29. package/dist/access/authenticatedAccessOnly.js +11 -0
  30. package/dist/access/authenticatedAccessOnly.js.map +1 -0
  31. package/dist/access/index.d.ts +7 -0
  32. package/dist/access/index.d.ts.map +1 -0
  33. package/dist/access/index.js +7 -0
  34. package/dist/access/index.js.map +1 -0
  35. package/dist/access/publicReadAuthenticatedAccess.d.ts +13 -0
  36. package/dist/access/publicReadAuthenticatedAccess.d.ts.map +1 -0
  37. package/dist/access/publicReadAuthenticatedAccess.js +12 -0
  38. package/dist/access/publicReadAuthenticatedAccess.js.map +1 -0
  39. package/dist/collections/ContactMessages/hooks/sendEmailNotification.d.ts +31 -0
  40. package/dist/collections/ContactMessages/hooks/sendEmailNotification.d.ts.map +1 -0
  41. package/dist/collections/ContactMessages/hooks/sendEmailNotification.js +29 -0
  42. package/dist/collections/ContactMessages/hooks/sendEmailNotification.js.map +1 -0
  43. package/dist/collections/ContactMessages/index.d.ts +27 -0
  44. package/dist/collections/ContactMessages/index.d.ts.map +1 -0
  45. package/dist/collections/ContactMessages/index.js +81 -0
  46. package/dist/collections/ContactMessages/index.js.map +1 -0
  47. package/dist/collections/EmailTemplates/index.d.ts +26 -0
  48. package/dist/collections/EmailTemplates/index.d.ts.map +1 -0
  49. package/dist/collections/EmailTemplates/index.js +74 -0
  50. package/dist/collections/EmailTemplates/index.js.map +1 -0
  51. package/dist/collections/Media/index.d.ts +3 -0
  52. package/dist/collections/Media/index.d.ts.map +1 -0
  53. package/dist/collections/Media/index.js +22 -0
  54. package/dist/collections/Media/index.js.map +1 -0
  55. package/dist/collections/QueuedEmails/components/HtmlViewer.d.ts +3 -0
  56. package/dist/collections/QueuedEmails/components/HtmlViewer.d.ts.map +1 -0
  57. package/dist/collections/QueuedEmails/components/HtmlViewer.js +11 -0
  58. package/dist/collections/QueuedEmails/components/HtmlViewer.js.map +1 -0
  59. package/dist/collections/QueuedEmails/components/RetryEmailButtons.d.ts +2 -0
  60. package/dist/collections/QueuedEmails/components/RetryEmailButtons.d.ts.map +1 -0
  61. package/dist/collections/QueuedEmails/components/RetryEmailButtons.js +79 -0
  62. package/dist/collections/QueuedEmails/components/RetryEmailButtons.js.map +1 -0
  63. package/dist/collections/QueuedEmails/index.d.ts +3 -0
  64. package/dist/collections/QueuedEmails/index.d.ts.map +1 -0
  65. package/dist/collections/QueuedEmails/index.js +245 -0
  66. package/dist/collections/QueuedEmails/index.js.map +1 -0
  67. package/dist/collections/Users/auth-emails/forgot-password-email.d.ts +51 -0
  68. package/dist/collections/Users/auth-emails/forgot-password-email.d.ts.map +1 -0
  69. package/dist/collections/Users/auth-emails/forgot-password-email.js +90 -0
  70. package/dist/collections/Users/auth-emails/forgot-password-email.js.map +1 -0
  71. package/dist/collections/Users/auth-emails/verify-email.d.ts +51 -0
  72. package/dist/collections/Users/auth-emails/verify-email.d.ts.map +1 -0
  73. package/dist/collections/Users/auth-emails/verify-email.js +80 -0
  74. package/dist/collections/Users/auth-emails/verify-email.js.map +1 -0
  75. package/dist/collections/Users/hooks/ensureFirstUserIsAdmin.d.ts +3 -0
  76. package/dist/collections/Users/hooks/ensureFirstUserIsAdmin.d.ts.map +1 -0
  77. package/dist/collections/Users/hooks/ensureFirstUserIsAdmin.js +19 -0
  78. package/dist/collections/Users/hooks/ensureFirstUserIsAdmin.js.map +1 -0
  79. package/dist/collections/Users/index.d.ts +76 -0
  80. package/dist/collections/Users/index.d.ts.map +1 -0
  81. package/dist/collections/Users/index.js +116 -0
  82. package/dist/collections/Users/index.js.map +1 -0
  83. package/dist/collections/index.d.ts +10 -0
  84. package/dist/collections/index.d.ts.map +1 -0
  85. package/dist/collections/index.js +14 -0
  86. package/dist/collections/index.js.map +1 -0
  87. package/dist/components/index.d.ts +3 -0
  88. package/dist/components/index.d.ts.map +1 -0
  89. package/dist/components/index.js +4 -0
  90. package/dist/components/index.js.map +1 -0
  91. package/dist/forms/states.d.ts +8 -0
  92. package/dist/forms/states.d.ts.map +1 -0
  93. package/dist/forms/states.js +16 -0
  94. package/dist/forms/states.js.map +1 -0
  95. package/dist/forms/translate-errors.d.ts +8 -0
  96. package/dist/forms/translate-errors.d.ts.map +1 -0
  97. package/dist/forms/translate-errors.js +11 -0
  98. package/dist/forms/translate-errors.js.map +1 -0
  99. package/dist/forms/validators.d.ts +10 -0
  100. package/dist/forms/validators.d.ts.map +1 -0
  101. package/dist/forms/validators.js +23 -0
  102. package/dist/forms/validators.js.map +1 -0
  103. package/dist/globals/PrivacyPolicy/hooks/revalidate-cache.d.ts +2 -0
  104. package/dist/globals/PrivacyPolicy/hooks/revalidate-cache.d.ts.map +1 -0
  105. package/dist/globals/PrivacyPolicy/hooks/revalidate-cache.js +5 -0
  106. package/dist/globals/PrivacyPolicy/hooks/revalidate-cache.js.map +1 -0
  107. package/dist/globals/PrivacyPolicy/index.d.ts +3 -0
  108. package/dist/globals/PrivacyPolicy/index.d.ts.map +1 -0
  109. package/dist/globals/PrivacyPolicy/index.js +31 -0
  110. package/dist/globals/PrivacyPolicy/index.js.map +1 -0
  111. package/dist/globals/TermsOfUse/hooks/revalidate-cache.d.ts +2 -0
  112. package/dist/globals/TermsOfUse/hooks/revalidate-cache.d.ts.map +1 -0
  113. package/dist/globals/TermsOfUse/hooks/revalidate-cache.js +5 -0
  114. package/dist/globals/TermsOfUse/hooks/revalidate-cache.js.map +1 -0
  115. package/dist/globals/TermsOfUse/index.d.ts +3 -0
  116. package/dist/globals/TermsOfUse/index.d.ts.map +1 -0
  117. package/dist/globals/TermsOfUse/index.js +31 -0
  118. package/dist/globals/TermsOfUse/index.js.map +1 -0
  119. package/dist/globals/index.d.ts +3 -0
  120. package/dist/globals/index.d.ts.map +1 -0
  121. package/dist/globals/index.js +3 -0
  122. package/dist/globals/index.js.map +1 -0
  123. package/dist/index.d.ts +13 -0
  124. package/dist/index.d.ts.map +1 -0
  125. package/dist/index.js +20 -0
  126. package/dist/index.js.map +1 -0
  127. package/dist/tasks/index.d.ts +2 -0
  128. package/dist/tasks/index.d.ts.map +1 -0
  129. package/dist/tasks/index.js +2 -0
  130. package/dist/tasks/index.js.map +1 -0
  131. package/dist/tasks/process-email-queue.d.ts +46 -0
  132. package/dist/tasks/process-email-queue.d.ts.map +1 -0
  133. package/dist/tasks/process-email-queue.js +199 -0
  134. package/dist/tasks/process-email-queue.js.map +1 -0
  135. package/dist/types/index.d.ts +14 -0
  136. package/dist/types/index.d.ts.map +1 -0
  137. package/dist/types/index.js +2 -0
  138. package/dist/types/index.js.map +1 -0
  139. package/dist/types/slug.d.ts +2 -0
  140. package/dist/types/slug.d.ts.map +1 -0
  141. package/dist/types/slug.js +11 -0
  142. package/dist/types/slug.js.map +1 -0
  143. package/dist/utils/database-dates.d.ts +3 -0
  144. package/dist/utils/database-dates.d.ts.map +1 -0
  145. package/dist/utils/database-dates.js +6 -0
  146. package/dist/utils/database-dates.js.map +1 -0
  147. package/dist/utils/email/generate-email-html.d.ts +23 -0
  148. package/dist/utils/email/generate-email-html.d.ts.map +1 -0
  149. package/dist/utils/email/generate-email-html.js +42 -0
  150. package/dist/utils/email/generate-email-html.js.map +1 -0
  151. package/dist/utils/email/get-email-template.d.ts +8 -0
  152. package/dist/utils/email/get-email-template.d.ts.map +1 -0
  153. package/dist/utils/email/get-email-template.js +14 -0
  154. package/dist/utils/email/get-email-template.js.map +1 -0
  155. package/dist/utils/email/index.d.ts +4 -0
  156. package/dist/utils/email/index.d.ts.map +1 -0
  157. package/dist/utils/email/index.js +4 -0
  158. package/dist/utils/email/index.js.map +1 -0
  159. package/dist/utils/email/queue-email.d.ts +29 -0
  160. package/dist/utils/email/queue-email.d.ts.map +1 -0
  161. package/dist/utils/email/queue-email.js +79 -0
  162. package/dist/utils/email/queue-email.js.map +1 -0
  163. package/dist/utils/get-global.d.ts +6 -0
  164. package/dist/utils/get-global.d.ts.map +1 -0
  165. package/dist/utils/get-global.js +20 -0
  166. package/dist/utils/get-global.js.map +1 -0
  167. package/dist/utils/id-from-payload.d.ts +4 -0
  168. package/dist/utils/id-from-payload.d.ts.map +1 -0
  169. package/dist/utils/id-from-payload.js +10 -0
  170. package/dist/utils/id-from-payload.js.map +1 -0
  171. package/dist/utils/index.d.ts +4 -0
  172. package/dist/utils/index.d.ts.map +1 -0
  173. package/dist/utils/index.js +4 -0
  174. package/dist/utils/index.js.map +1 -0
  175. package/dist/utils/migrations.d.ts +2 -0
  176. package/dist/utils/migrations.d.ts.map +1 -0
  177. package/dist/utils/migrations.js +18 -0
  178. package/dist/utils/migrations.js.map +1 -0
  179. package/dist/utils/payload-client.d.ts +10 -0
  180. package/dist/utils/payload-client.d.ts.map +1 -0
  181. package/dist/utils/payload-client.js +14 -0
  182. package/dist/utils/payload-client.js.map +1 -0
  183. package/dist/utils/slugify.d.ts +8 -0
  184. package/dist/utils/slugify.d.ts.map +1 -0
  185. package/dist/utils/slugify.js +15 -0
  186. package/dist/utils/slugify.js.map +1 -0
  187. package/eslint.config.mjs +90 -0
  188. package/package.json +139 -0
  189. package/pnpm-workspace.yaml +4 -0
  190. package/src/access/adminAccessOnly.ts +13 -0
  191. package/src/access/admins.ts +78 -0
  192. package/src/access/anyone.ts +35 -0
  193. package/src/access/authenticated.ts +70 -0
  194. package/src/access/authenticatedAccessOnly.ts +13 -0
  195. package/src/access/index.ts +6 -0
  196. package/src/access/publicReadAuthenticatedAccess.ts +14 -0
  197. package/src/collections/ContactMessages/hooks/sendEmailNotification.ts +58 -0
  198. package/src/collections/ContactMessages/index.ts +100 -0
  199. package/src/collections/EmailTemplates/index.ts +89 -0
  200. package/src/collections/Media/index.ts +24 -0
  201. package/src/collections/QueuedEmails/components/HtmlViewer.tsx +16 -0
  202. package/src/collections/QueuedEmails/components/RetryEmailButtons.tsx +115 -0
  203. package/src/collections/QueuedEmails/index.ts +246 -0
  204. package/src/collections/Users/auth-emails/forgot-password-email.ts +135 -0
  205. package/src/collections/Users/auth-emails/verify-email.ts +123 -0
  206. package/src/collections/Users/hooks/ensureFirstUserIsAdmin.ts +22 -0
  207. package/src/collections/Users/index.ts +201 -0
  208. package/src/collections/index.ts +23 -0
  209. package/src/components/index.ts +3 -0
  210. package/src/forms/states.ts +23 -0
  211. package/src/forms/translate-errors.ts +13 -0
  212. package/src/forms/validators.ts +33 -0
  213. package/src/globals/PrivacyPolicy/hooks/revalidate-cache.ts +5 -0
  214. package/src/globals/PrivacyPolicy/index.ts +33 -0
  215. package/src/globals/TermsOfUse/hooks/revalidate-cache.ts +5 -0
  216. package/src/globals/TermsOfUse/index.ts +33 -0
  217. package/src/globals/index.ts +2 -0
  218. package/src/index.ts +26 -0
  219. package/src/tasks/index.ts +7 -0
  220. package/src/tasks/process-email-queue.ts +261 -0
  221. package/src/types/index.ts +15 -0
  222. package/src/types/slug.ts +11 -0
  223. package/src/utils/database-dates.ts +6 -0
  224. package/src/utils/email/generate-email-html.ts +63 -0
  225. package/src/utils/email/get-email-template.ts +18 -0
  226. package/src/utils/email/index.ts +3 -0
  227. package/src/utils/email/queue-email.ts +109 -0
  228. package/src/utils/get-global.ts +25 -0
  229. package/src/utils/id-from-payload.ts +11 -0
  230. package/src/utils/index.ts +3 -0
  231. package/src/utils/migrations.ts +18 -0
  232. package/src/utils/payload-client.ts +16 -0
  233. package/src/utils/slugify.ts +21 -0
  234. package/tests/fixtures/email-template.html +58 -0
  235. package/tests/fixtures/sample-data.ts +56 -0
  236. package/tests/helpers/create-test-user.ts +37 -0
  237. package/tests/helpers/init-payload.ts +59 -0
  238. package/tests/setup.integration.ts +9 -0
  239. package/tests/setup.ts +4 -0
  240. package/tests/unit/access/adminAccessOnly.spec.ts +117 -0
  241. package/tests/unit/access/admins.spec.ts +68 -0
  242. package/tests/unit/access/anyone.spec.ts +28 -0
  243. package/tests/unit/access/authenticated.spec.ts +53 -0
  244. package/tests/unit/access/authenticatedAccessOnly.spec.ts +112 -0
  245. package/tests/unit/access/publicReadAuthenticatedAccess.spec.ts +112 -0
  246. package/tests/unit/forms/validators.spec.ts +348 -0
  247. package/tests/unit/utils/database-dates.spec.ts +97 -0
  248. package/tests/unit/utils/id-from-payload.spec.ts +142 -0
  249. package/tests/unit/utils/slugify.spec.ts +185 -0
  250. package/tsconfig.json +31 -0
  251. package/typedoc.json +40 -0
  252. package/vitest.config.ts +31 -0
  253. package/vitest.integration.config.ts +27 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translate-errors.d.ts","sourceRoot":"","sources":["../../src/forms/translate-errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,wBAAsB,mBAAmB,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC;;;;;GAQlG"}
@@ -0,0 +1,11 @@
1
+ import { getTranslations } from 'next-intl/server';
2
+ // Utility to translate error keys using i18n
3
+ export async function translateFormErrors(errors) {
4
+ const t = await getTranslations();
5
+ const translate = (messages) => messages?.map((msg) => t(msg)) ?? [];
6
+ return {
7
+ fieldErrors: Object.fromEntries(Object.entries(errors.fieldErrors).map(([field, msgs]) => [field, translate(msgs)])),
8
+ formErrors: translate(errors.formErrors),
9
+ };
10
+ }
11
+ //# sourceMappingURL=translate-errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translate-errors.js","sourceRoot":"","sources":["../../src/forms/translate-errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGnD,6CAA6C;AAC7C,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAyB,MAAiC;IACjG,MAAM,CAAC,GAAG,MAAM,eAAe,EAAE,CAAC;IAClC,MAAM,SAAS,GAAG,CAAC,QAAmB,EAAE,EAAE,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAEhF,OAAO;QACL,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,IAAgB,CAAC,CAAC,CAAC,CAAC;QAChI,UAAU,EAAE,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC;KACzC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { z } from 'zod';
2
+ export declare const requiredString: (message: string) => z.ZodString;
3
+ export declare const requiredPasswordString: (minLength: number, requiredMessage: string, minLengthMessage: string) => z.ZodPipeline<z.ZodString, z.ZodString>;
4
+ export declare const requiredEmailString: ({ required, email }: {
5
+ required: string;
6
+ email: string;
7
+ }) => z.ZodPipeline<z.ZodString, z.ZodString>;
8
+ export declare const validHoneyPot: (message: string) => z.ZodEffects<z.ZodString, string, string>;
9
+ export declare const requiredCheckbox: (message: string) => z.ZodEffects<z.ZodBoolean, boolean, boolean>;
10
+ //# sourceMappingURL=validators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../src/forms/validators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,gBAI/B,CAAC;AAEhB,eAAO,MAAM,sBAAsB,GAAI,WAAW,MAAM,EAAE,iBAAiB,MAAM,EAAE,kBAAkB,MAAM,4CAOtG,CAAC;AAEN,eAAO,MAAM,mBAAmB,GAAI,qBAAqB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,4CAK7C,CAAC;AAEhD,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,8CAGP,CAAC;AAEvC,eAAO,MAAM,gBAAgB,GAAI,SAAS,MAAM,iDAGvB,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { z } from 'zod';
2
+ export const requiredString = (message) => z
3
+ .string({ errorMap: () => ({ message }) }) // Same error message for all errors
4
+ .trim()
5
+ .nonempty();
6
+ export const requiredPasswordString = (minLength, requiredMessage, minLengthMessage) => z
7
+ .string({ errorMap: () => ({ message: requiredMessage }) }) // Same error message for all errors
8
+ .trim()
9
+ .nonempty()
10
+ .pipe(z.string().min(minLength, { message: minLengthMessage }) // Ensure password is at least 12 characters long
11
+ );
12
+ export const requiredEmailString = ({ required, email }) => z
13
+ .string() // Same error message for all errors
14
+ .trim()
15
+ .nonempty({ message: required })
16
+ .pipe(z.string().email({ message: email })); // “email” runs only if nonempty passed
17
+ export const validHoneyPot = (message) => z
18
+ .string({ errorMap: () => ({ message }) }) // Same error message for all errors
19
+ .refine((val) => val.length === 0); // Must be empty
20
+ export const requiredCheckbox = (message) => z
21
+ .boolean({ errorMap: () => ({ message }) }) // Same error message for all errors
22
+ .refine((val) => val); // Must be true
23
+ //# sourceMappingURL=validators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/forms/validators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,OAAe,EAAE,EAAE,CAChD,CAAC;KACE,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,oCAAoC;KAC9E,IAAI,EAAE;KACN,QAAQ,EAAE,CAAC;AAEhB,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,SAAiB,EAAE,eAAuB,EAAE,gBAAwB,EAAE,EAAE,CAC7G,CAAC;KACE,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC,CAAC,oCAAoC;KAC/F,IAAI,EAAE;KACN,QAAQ,EAAE;KACV,IAAI,CACH,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAC,iDAAiD;CAC3G,CAAC;AAEN,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAuC,EAAE,EAAE,CAC9F,CAAC;KACE,MAAM,EAAE,CAAC,oCAAoC;KAC7C,IAAI,EAAE;KACN,QAAQ,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;KAC/B,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,uCAAuC;AAExF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,OAAe,EAAE,EAAE,CAC/C,CAAC;KACE,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,oCAAoC;KAC9E,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,gBAAgB;AAExD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAe,EAAE,EAAE,CAClD,CAAC;KACE,OAAO,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,oCAAoC;KAC/E,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe"}
@@ -0,0 +1,2 @@
1
+ export declare const revalidateCache: () => Promise<void>;
2
+ //# sourceMappingURL=revalidate-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revalidate-cache.d.ts","sourceRoot":"","sources":["../../../../src/globals/PrivacyPolicy/hooks/revalidate-cache.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe,qBAE3B,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { revalidatePath } from 'next/cache';
2
+ export const revalidateCache = async () => {
3
+ revalidatePath('/', 'layout');
4
+ };
5
+ //# sourceMappingURL=revalidate-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revalidate-cache.js","sourceRoot":"","sources":["../../../../src/globals/PrivacyPolicy/hooks/revalidate-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,IAAI,EAAE;IACxC,cAAc,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAChC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { GlobalConfig } from 'payload';
2
+ export declare const PrivacyPolicy: GlobalConfig;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/globals/PrivacyPolicy/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAK5C,eAAO,MAAM,aAAa,EAAE,YA2B3B,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { revalidateCache } from './hooks/revalidate-cache';
2
+ import { authenticatedAccessOnly } from '../../access/authenticatedAccessOnly';
3
+ export const PrivacyPolicy = {
4
+ slug: 'privacy-policy',
5
+ label: { fr: 'Politique de confidentialité', nl: 'Privacybeleid', en: 'Privacy Policy' },
6
+ admin: {
7
+ group: { fr: 'Légal', nl: 'Juridisch', en: 'Legal' },
8
+ hideAPIURL: true,
9
+ },
10
+ access: authenticatedAccessOnly,
11
+ hooks: {
12
+ afterChange: [revalidateCache],
13
+ },
14
+ fields: [
15
+ {
16
+ name: 'title',
17
+ label: { fr: 'Titre', nl: 'Titel', en: 'Title' },
18
+ type: 'text',
19
+ required: true,
20
+ localized: true,
21
+ },
22
+ {
23
+ name: 'content',
24
+ label: { fr: 'Contenu', nl: 'Inhoud', en: 'Content' },
25
+ type: 'richText',
26
+ required: true,
27
+ localized: true,
28
+ },
29
+ ],
30
+ };
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/globals/PrivacyPolicy/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAE/E,MAAM,CAAC,MAAM,aAAa,GAAiB;IACzC,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,EAAE,EAAE,EAAE,8BAA8B,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE,gBAAgB,EAAE;IACxF,KAAK,EAAE;QACL,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE;QACpD,UAAU,EAAE,IAAI;KACjB;IACD,MAAM,EAAE,uBAAuB;IAC/B,KAAK,EAAE;QACL,WAAW,EAAE,CAAC,eAAe,CAAC;KAC/B;IACD,MAAM,EAAE;QACN;YACE,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE;YAChD,IAAI,EAAE,MAAM;YACZ,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,IAAI;SAChB;QACD;YACE,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE;YACrD,IAAI,EAAE,UAAU;YAChB,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,IAAI;SAChB;KACF;CACF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const revalidateCache: () => Promise<void>;
2
+ //# sourceMappingURL=revalidate-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revalidate-cache.d.ts","sourceRoot":"","sources":["../../../../src/globals/TermsOfUse/hooks/revalidate-cache.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe,qBAE3B,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { revalidatePath } from 'next/cache';
2
+ export const revalidateCache = async () => {
3
+ revalidatePath('/', 'layout');
4
+ };
5
+ //# sourceMappingURL=revalidate-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revalidate-cache.js","sourceRoot":"","sources":["../../../../src/globals/TermsOfUse/hooks/revalidate-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,IAAI,EAAE;IACxC,cAAc,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAChC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { GlobalConfig } from 'payload';
2
+ export declare const TermsOfUse: GlobalConfig;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/globals/TermsOfUse/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAK5C,eAAO,MAAM,UAAU,EAAE,YA2BxB,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { revalidateCache } from './hooks/revalidate-cache';
2
+ import { authenticatedAccessOnly } from '../../access/authenticatedAccessOnly';
3
+ export const TermsOfUse = {
4
+ slug: 'terms-of-use',
5
+ label: { fr: "Conditions d'utilisation", nl: 'Gebruiksvoorwaarden', en: 'Terms of Use' },
6
+ admin: {
7
+ group: { fr: 'Légal', nl: 'Juridisch', en: 'Legal' },
8
+ hideAPIURL: true,
9
+ },
10
+ access: authenticatedAccessOnly,
11
+ hooks: {
12
+ afterChange: [revalidateCache],
13
+ },
14
+ fields: [
15
+ {
16
+ name: 'title',
17
+ label: { fr: 'Titre', nl: 'Titel', en: 'Title' },
18
+ type: 'text',
19
+ required: true,
20
+ localized: true,
21
+ },
22
+ {
23
+ name: 'content',
24
+ label: { fr: 'Contenu', nl: 'Inhoud', en: 'Content' },
25
+ type: 'richText',
26
+ required: true,
27
+ localized: true,
28
+ },
29
+ ],
30
+ };
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/globals/TermsOfUse/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAE/E,MAAM,CAAC,MAAM,UAAU,GAAiB;IACtC,IAAI,EAAE,cAAc;IACpB,KAAK,EAAE,EAAE,EAAE,EAAE,0BAA0B,EAAE,EAAE,EAAE,qBAAqB,EAAE,EAAE,EAAE,cAAc,EAAE;IACxF,KAAK,EAAE;QACL,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE;QACpD,UAAU,EAAE,IAAI;KACjB;IACD,MAAM,EAAE,uBAAuB;IAC/B,KAAK,EAAE;QACL,WAAW,EAAE,CAAC,eAAe,CAAC;KAC/B;IACD,MAAM,EAAE;QACN;YACE,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE;YAChD,IAAI,EAAE,MAAM;YACZ,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,IAAI;SAChB;QACD;YACE,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE;YACrD,IAAI,EAAE,UAAU;YAChB,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,IAAI;SAChB;KACF;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { PrivacyPolicy } from './PrivacyPolicy';
2
+ export { TermsOfUse } from './TermsOfUse';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/globals/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { PrivacyPolicy } from './PrivacyPolicy';
2
+ export { TermsOfUse } from './TermsOfUse';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/globals/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @latte-macchiat-io/latte-payload
3
+ *
4
+ * Reusable Payload CMS collections, utilities, and components for Latte projects
5
+ */
6
+ export * from './collections';
7
+ export * from './globals';
8
+ export * from './access';
9
+ export * from './tasks';
10
+ export * from './utils';
11
+ export * from './components';
12
+ export * from './types';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,cAAc,eAAe,CAAC;AAG9B,cAAc,WAAW,CAAC;AAG1B,cAAc,UAAU,CAAC;AAGzB,cAAc,SAAS,CAAC;AAGxB,cAAc,SAAS,CAAC;AAGxB,cAAc,cAAc,CAAC;AAG7B,cAAc,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @latte-macchiat-io/latte-payload
3
+ *
4
+ * Reusable Payload CMS collections, utilities, and components for Latte projects
5
+ */
6
+ // Collections
7
+ export * from './collections';
8
+ // Globals
9
+ export * from './globals';
10
+ // Access Control
11
+ export * from './access';
12
+ // Tasks
13
+ export * from './tasks';
14
+ // Utilities
15
+ export * from './utils';
16
+ // Components
17
+ export * from './components';
18
+ // Types
19
+ export * from './types';
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc;AACd,cAAc,eAAe,CAAC;AAE9B,UAAU;AACV,cAAc,WAAW,CAAC;AAE1B,iBAAiB;AACjB,cAAc,UAAU,CAAC;AAEzB,QAAQ;AACR,cAAc,SAAS,CAAC;AAExB,YAAY;AACZ,cAAc,SAAS,CAAC;AAExB,aAAa;AACb,cAAc,cAAc,CAAC;AAE7B,QAAQ;AACR,cAAc,SAAS,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { processEmailQueueTaskConfig, createProcessEmailQueueTask, processEmailQueueName, processEmailQueueAutoRunConfig, type ProcessEmailQueueConfig, } from './process-email-queue';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tasks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,EAC3B,qBAAqB,EACrB,8BAA8B,EAC9B,KAAK,uBAAuB,GAC7B,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { processEmailQueueTaskConfig, createProcessEmailQueueTask, processEmailQueueName, processEmailQueueAutoRunConfig, } from './process-email-queue';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tasks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,EAC3B,qBAAqB,EACrB,8BAA8B,GAE/B,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { TaskConfig } from 'payload';
2
+ export declare const processEmailQueueName = "process-email-queue";
3
+ export declare const processEmailQueueAutoRunConfig: {
4
+ queue: string;
5
+ cron: string;
6
+ };
7
+ export interface ProcessEmailQueueConfig {
8
+ /**
9
+ * Timezone for email timestamps
10
+ * @default 'Europe/Brussels'
11
+ */
12
+ timezone?: string;
13
+ /**
14
+ * Maximum number of emails to process per run
15
+ * @default 100
16
+ */
17
+ maxEmailsPerRun?: number;
18
+ /**
19
+ * Delay between sending emails in milliseconds (for rate limiting)
20
+ * @default 1000 (1 second - respects Resend's 2 requests/second limit)
21
+ */
22
+ delayBetweenEmails?: number;
23
+ /**
24
+ * Default "from" email address
25
+ * Falls back to process.env.SMTP_FROM_ADDRESS
26
+ */
27
+ defaultFromAddress?: string;
28
+ /**
29
+ * Optional error reporter (e.g., Sentry)
30
+ */
31
+ errorReporter?: {
32
+ captureException: (error: Error, context?: any) => void;
33
+ };
34
+ }
35
+ /**
36
+ * Create process-email-queue task with custom configuration
37
+ *
38
+ * @param config - Optional configuration
39
+ * @returns TaskConfig for process-email-queue
40
+ */
41
+ export declare function createProcessEmailQueueTask(config?: ProcessEmailQueueConfig): TaskConfig<'process-email-queue'>;
42
+ /**
43
+ * Default process-email-queue task
44
+ */
45
+ export declare const processEmailQueueTaskConfig: TaskConfig<"process-email-queue">;
46
+ //# sourceMappingURL=process-email-queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-email-queue.d.ts","sourceRoot":"","sources":["../../src/tasks/process-email-queue.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAGrC,eAAO,MAAM,qBAAqB,wBAAwB,CAAC;AAE3D,eAAO,MAAM,8BAA8B;;;CAG1C,CAAC;AAKF,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;OAEG;IACH,aAAa,CAAC,EAAE;QAEd,gBAAgB,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;KACzD,CAAC;CACH;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,CAAC,EAAE,uBAAuB,GAAG,UAAU,CAAC,qBAAqB,CAAC,CAyM/G;AAED;;GAEG;AACH,eAAO,MAAM,2BAA2B,mCAAgC,CAAC"}
@@ -0,0 +1,199 @@
1
+ import { TZDate } from '@date-fns/tz';
2
+ import { toDatabaseTZDate } from '../utils';
3
+ export const processEmailQueueName = 'process-email-queue';
4
+ export const processEmailQueueAutoRunConfig = {
5
+ queue: processEmailQueueName,
6
+ cron: '* * * * *', // Every minute
7
+ };
8
+ // Utility function to add delay between emails to respect rate limits
9
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
10
+ /**
11
+ * Create process-email-queue task with custom configuration
12
+ *
13
+ * @param config - Optional configuration
14
+ * @returns TaskConfig for process-email-queue
15
+ */
16
+ export function createProcessEmailQueueTask(config) {
17
+ const timezone = config?.timezone || 'Europe/Brussels';
18
+ const maxEmailsPerRun = config?.maxEmailsPerRun || 100;
19
+ const delayBetweenEmails = config?.delayBetweenEmails || 1000;
20
+ return {
21
+ slug: 'process-email-queue',
22
+ label: 'Process Email Queue',
23
+ retries: {
24
+ attempts: 3,
25
+ backoff: { delay: 2000, type: 'exponential' },
26
+ },
27
+ inputSchema: undefined, // No input - auto-triggered by cron
28
+ outputSchema: [
29
+ {
30
+ name: 'processedCount',
31
+ type: 'number',
32
+ required: true,
33
+ },
34
+ {
35
+ name: 'sentCount',
36
+ type: 'number',
37
+ required: true,
38
+ },
39
+ {
40
+ name: 'failedCount',
41
+ type: 'number',
42
+ required: true,
43
+ },
44
+ ],
45
+ // Auto-enqueue to run following the cron schedule
46
+ schedule: [
47
+ {
48
+ queue: processEmailQueueAutoRunConfig.queue,
49
+ cron: processEmailQueueAutoRunConfig.cron,
50
+ },
51
+ ],
52
+ handler: async ({ req }) => {
53
+ const { payload } = req;
54
+ payload.logger.info(`[(Task)ProcessEmailQueue] Task started`);
55
+ let processedCount = 0;
56
+ let sentCount = 0;
57
+ let failedCount = 0;
58
+ try {
59
+ // Find all emails that need to be sent (pending or failed with retries remaining)
60
+ // Note: We can't directly compare attemptCount < maxAttempts in the query,
61
+ // so we fetch all pending/failed emails and filter them in code
62
+ const allPendingOrFailed = await payload.find({
63
+ collection: 'queued-emails',
64
+ where: {
65
+ or: [
66
+ {
67
+ status: { equals: 'pending' },
68
+ },
69
+ {
70
+ status: { equals: 'failed' },
71
+ },
72
+ ],
73
+ },
74
+ sort: 'createdAt', // Process oldest emails first
75
+ limit: 200, // Fetch more to filter down to maxEmailsPerRun eligible
76
+ pagination: false,
77
+ });
78
+ // Filter emails that still have retries remaining
79
+ const emailsToSend = {
80
+ docs: allPendingOrFailed.docs.filter((email) => email.attemptCount < email.maxAttempts).slice(0, maxEmailsPerRun),
81
+ };
82
+ payload.logger.info(`[(Task)ProcessEmailQueue] Found ${emailsToSend.docs.length} emails to process`);
83
+ if (emailsToSend.docs.length === 0) {
84
+ return {
85
+ output: {
86
+ processedCount: 0,
87
+ sentCount: 0,
88
+ failedCount: 0,
89
+ },
90
+ };
91
+ }
92
+ // Process each email
93
+ for (const email of emailsToSend.docs) {
94
+ processedCount++;
95
+ try {
96
+ payload.logger.info(`[(Task)ProcessEmailQueue] Processing email ${email.id} (${email.code}) to ${email.recipient} (attempt ${email.attemptCount + 1}/${email.maxAttempts})`);
97
+ // Mark as sending to prevent duplicate processing
98
+ await payload.update({
99
+ collection: 'queued-emails',
100
+ id: email.id,
101
+ data: {
102
+ status: 'sending',
103
+ lastAttemptAt: toDatabaseTZDate(TZDate.tz(timezone)),
104
+ },
105
+ });
106
+ // Parse CC if it exists
107
+ const ccArray = email.cc ? email.cc.split(',').map((e) => e.trim()) : undefined;
108
+ const fromAddress = config?.defaultFromAddress || process.env.SMTP_FROM_ADDRESS;
109
+ // Send the email using Payload's email service
110
+ await payload.sendEmail({
111
+ from: fromAddress,
112
+ to: email.recipient,
113
+ cc: ccArray,
114
+ subject: email.subject,
115
+ html: email.htmlBody,
116
+ });
117
+ // Mark as sent
118
+ await payload.update({
119
+ collection: 'queued-emails',
120
+ id: email.id,
121
+ data: {
122
+ status: 'sent',
123
+ sentAt: toDatabaseTZDate(TZDate.tz(timezone)),
124
+ attemptCount: email.attemptCount + 1,
125
+ lastError: null,
126
+ },
127
+ });
128
+ sentCount++;
129
+ payload.logger.info(`[(Task)ProcessEmailQueue] Successfully sent email ${email.id} to ${email.recipient}`);
130
+ // Add delay between emails to respect rate limits
131
+ // Only delay if there are more emails to process
132
+ if (processedCount < emailsToSend.docs.length) {
133
+ await sleep(delayBetweenEmails);
134
+ }
135
+ }
136
+ catch (error) {
137
+ failedCount++;
138
+ const errorMessage = error instanceof Error ? error.message : String(error);
139
+ const now = toDatabaseTZDate(TZDate.tz(timezone));
140
+ const newAttemptCount = email.attemptCount + 1;
141
+ payload.logger.error(`[(Task)ProcessEmailQueue] Failed to send email ${email.id} to ${email.recipient}: ${errorMessage}`);
142
+ // Append to error history
143
+ const errorHistory = email.errorHistory || [];
144
+ errorHistory.push({
145
+ timestamp: now,
146
+ timestamp_tz: timezone,
147
+ attemptNumber: newAttemptCount,
148
+ error: errorMessage,
149
+ });
150
+ // Update email status to failed with error message
151
+ await payload.update({
152
+ collection: 'queued-emails',
153
+ id: email.id,
154
+ data: {
155
+ status: 'failed',
156
+ attemptCount: newAttemptCount,
157
+ lastError: errorMessage,
158
+ lastAttemptAt: now,
159
+ errorHistory: errorHistory,
160
+ },
161
+ });
162
+ // Report to error tracker if configured
163
+ if (config?.errorReporter && error instanceof Error) {
164
+ config.errorReporter.captureException(error, {
165
+ extra: {
166
+ emailId: email.id,
167
+ emailCode: email.code,
168
+ recipient: email.recipient,
169
+ attemptCount: newAttemptCount,
170
+ maxAttempts: email.maxAttempts,
171
+ },
172
+ });
173
+ }
174
+ }
175
+ }
176
+ payload.logger.info(`[(Task)ProcessEmailQueue] Task completed - Processed: ${processedCount}, Sent: ${sentCount}, Failed: ${failedCount}`);
177
+ return {
178
+ output: {
179
+ processedCount,
180
+ sentCount,
181
+ failedCount,
182
+ },
183
+ };
184
+ }
185
+ catch (error) {
186
+ payload.logger.error(`[(Task)ProcessEmailQueue] Critical error: ${error}`);
187
+ if (config?.errorReporter && error instanceof Error) {
188
+ config.errorReporter.captureException(error);
189
+ }
190
+ throw error;
191
+ }
192
+ },
193
+ };
194
+ }
195
+ /**
196
+ * Default process-email-queue task
197
+ */
198
+ export const processEmailQueueTaskConfig = createProcessEmailQueueTask();
199
+ //# sourceMappingURL=process-email-queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-email-queue.js","sourceRoot":"","sources":["../../src/tasks/process-email-queue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Supported locales for the Latte Payload package
3
+ * Extend this type if you need additional locales
4
+ */
5
+ export type Locale = 'en' | 'fr' | 'nl';
6
+ /**
7
+ * Email template codes
8
+ */
9
+ export type EmailTemplateCode = 'verify-email' | 'password-lost' | string;
10
+ /**
11
+ * Queued email status
12
+ */
13
+ export type QueuedEmailStatus = 'pending' | 'sending' | 'sent' | 'failed';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAExC;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,cAAc,GAAG,eAAe,GAAG,MAAM,CAAC;AAE1E;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export declare const slugField: import("payload").RowField;
2
+ //# sourceMappingURL=slug.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slug.d.ts","sourceRoot":"","sources":["../../src/types/slug.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,SAAS,4BAOpB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { slugField as payLoadSlugField } from 'payload';
2
+ import { slugify } from '../utils/slugify';
3
+ export const slugField = payLoadSlugField({
4
+ name: 'slug',
5
+ useAsSlug: 'name',
6
+ position: 'sidebar',
7
+ required: true,
8
+ localized: true,
9
+ slugify: ({ valueToSlugify, req }) => slugify(valueToSlugify, { locale: req.locale ?? undefined }),
10
+ });
11
+ //# sourceMappingURL=slug.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slug.js","sourceRoot":"","sources":["../../src/types/slug.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,IAAI,gBAAgB,EAAE,MAAM,SAAS,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,MAAM,CAAC,MAAM,SAAS,GAAG,gBAAgB,CAAC;IACxC,IAAI,EAAE,MAAM;IACZ,SAAS,EAAE,MAAM;IACjB,QAAQ,EAAE,SAAS;IACnB,QAAQ,EAAE,IAAI;IACd,SAAS,EAAE,IAAI;IACf,OAAO,EAAE,CAAC,EAAE,cAAc,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;CACnG,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { TZDate } from '@date-fns/tz';
2
+ export declare function toDatabaseTZDate(date: TZDate | string): string;
3
+ //# sourceMappingURL=database-dates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-dates.d.ts","sourceRoot":"","sources":["../../src/utils/database-dates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAG9D"}
@@ -0,0 +1,6 @@
1
+ export function toDatabaseTZDate(date) {
2
+ if (typeof date === 'string')
3
+ return date;
4
+ return date.toISOString();
5
+ }
6
+ //# sourceMappingURL=database-dates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-dates.js","sourceRoot":"","sources":["../../src/utils/database-dates.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gBAAgB,CAAC,IAAqB;IACpD,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC1C,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;AAC5B,CAAC"}