ghost 6.53.0 → 6.54.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 (639) hide show
  1. package/components/ghost-storage-base-3.0.0.tgz +0 -0
  2. package/components/tryghost-adapter-base-cache-0.2.0.tgz +0 -0
  3. package/components/tryghost-adapter-base-scheduling-0.2.0.tgz +0 -0
  4. package/components/tryghost-adapter-base-sso-0.1.1.tgz +0 -0
  5. package/components/tryghost-admin-api-schema-0.0.0.tgz +0 -0
  6. package/components/tryghost-custom-field-types-0.0.0.tgz +0 -0
  7. package/components/tryghost-i18n-0.0.0.tgz +0 -0
  8. package/components/tryghost-kg-converters-1.2.3.tgz +0 -0
  9. package/components/tryghost-kg-default-nodes-2.1.3.tgz +0 -0
  10. package/components/tryghost-kg-lexical-html-renderer-1.4.3.tgz +0 -0
  11. package/core/boot.js +9 -6
  12. package/core/built/admin/assets/Combination-CJG7Flp-.js +41 -0
  13. package/core/built/admin/assets/Growth-BTP1LthE.js +3 -0
  14. package/core/built/admin/assets/Newsletters-CSEX0myc.js +1 -0
  15. package/core/built/admin/assets/Overview-BjACEsJF.js +1 -0
  16. package/core/built/admin/assets/{PolarAngleAxis-pciQ0MOy.js → PolarAngleAxis-BGjf7sBu.js} +1 -1
  17. package/core/built/admin/assets/{RadialBarChart-DWmw2PcX.js → RadialBarChart-zeFf9mBz.js} +1 -1
  18. package/core/built/admin/assets/Web-CxxxjCcv.js +2 -0
  19. package/core/built/admin/assets/account-migration-BklF2I_I.js +1 -0
  20. package/core/built/admin/assets/activitypub/{account-migration-BPZG37DJ.js → account-migration-CNovr6W-.js} +13 -13
  21. package/core/built/admin/assets/activitypub/activitypub.js +8 -8
  22. package/core/built/admin/assets/activitypub/{avatar-ZYco0ITb.js → avatar-B3DEDB1l.js} +10 -10
  23. package/core/built/admin/assets/activitypub/{avatar-flipboard-D541lc4F.js → avatar-flipboard-Cqrg0XMx.js} +3 -3
  24. package/core/built/admin/assets/activitypub/{bluesky-sharing-NOHUtHjl.js → bluesky-sharing-Ceslb1_M.js} +38 -37
  25. package/core/built/admin/assets/activitypub/{chunk-KS7C4IRE-B-GOFDPZ.js → chunk-KS7C4IRE-D4HEcEwi.js} +716 -710
  26. package/core/built/admin/assets/activitypub/{content-formatters-bwrp4iEO.js → content-formatters-BpQARh28.js} +229 -181
  27. package/core/built/admin/assets/activitypub/{copy-C7m7ovHw.js → copy-D9UWIAan.js} +2 -2
  28. package/core/built/admin/assets/activitypub/{dist-BqkDUQxJ2.js → dist-ByFmDSNP2.js} +64 -63
  29. package/core/built/admin/assets/activitypub/{dist-B5ira32t.js → dist-DHAjBcV3.js} +5 -5
  30. package/core/built/admin/assets/activitypub/{domain-iqE4YXwD.js → domain-C1qQvJ8C.js} +33 -33
  31. package/core/built/admin/assets/activitypub/{edit-profile-B8MFYh28.js → edit-profile-BcH-jEfM.js} +46 -45
  32. package/core/built/admin/assets/activitypub/{explore-BbdKodp3.js → explore-AxwBh9dI.js} +20 -20
  33. package/core/built/admin/assets/activitypub/{feed-Cl3A5owG.js → feed-BaOlbh7a.js} +15 -15
  34. package/core/built/admin/assets/activitypub/{field-DL6WyR-c.js → field-B7mYYQpN.js} +13 -13
  35. package/core/built/admin/assets/activitypub/{hash-6G3DzwL9.js → hash-BC9Q0N4c.js} +2 -2
  36. package/core/built/admin/assets/activitypub/{inbox-YmhuBice.js → inbox-DQ4ZnC1m.js} +2 -2
  37. package/core/built/admin/assets/activitypub/inbox-vXez-5uJ.js +1221 -0
  38. package/core/built/admin/assets/activitypub/{label-DGbLjDvE.js → label-Chv5T8bw.js} +6 -6
  39. package/core/built/admin/assets/activitypub/layout-CziktJXo.js +1 -0
  40. package/core/built/admin/assets/activitypub/{moderation-qnBtk1zS.js → moderation-DtSM2i1I.js} +32 -31
  41. package/core/built/admin/assets/activitypub/{note-C7ZRoSJv.js → note-Dckp4S-2.js} +21 -21
  42. package/core/built/admin/assets/activitypub/{notifications-DiEA4b1o.js → notifications-CG5T22vg.js} +17 -17
  43. package/core/built/admin/assets/activitypub/{onboarding-_JVgEwgV.js → onboarding-BFDkzeR2.js} +2 -2
  44. package/core/built/admin/assets/activitypub/{onboarding-DG4zu3qM.js → onboarding-D6rcBdPe.js} +5 -5
  45. package/core/built/admin/assets/activitypub/{preferences-B3FtocnP.js → preferences-D_799jdl.js} +1607 -1606
  46. package/core/built/admin/assets/activitypub/{profile-D8ZJfYXB.js → profile-D2JfXBQl.js} +264 -263
  47. package/core/built/admin/assets/activitypub/{reply-C1vggenw.js → reply-CpdMeAO5.js} +2 -2
  48. package/core/built/admin/assets/activitypub/{routes-BOii-V9n.js → routes-CCHe2dQp.js} +1317 -1298
  49. package/core/built/admin/assets/activitypub/{separator-1gNokN5S.js → separator-BI1FLsYM.js} +4 -4
  50. package/core/built/admin/assets/activitypub/{settings--9Sb0nbl.js → settings-kx-9Enkz.js} +14 -14
  51. package/core/built/admin/assets/activitypub/{site-fkMmqv0V.js → site-x4_IjVJ0.js} +10 -10
  52. package/core/built/admin/assets/activitypub/{step-1-QhivSMw2.js → step-1-DIDg4aHb.js} +15 -15
  53. package/core/built/admin/assets/activitypub/{step-2-pMk9YwqD.js → step-2-BfGe8BYt.js} +7 -7
  54. package/core/built/admin/assets/activitypub/{step-3-DvmVC1fo.js → step-3-mE9spAqw.js} +12 -12
  55. package/core/built/admin/assets/activitypub/{tabs-Dc0FEEYD.js → tabs-CyPRQQ1N.js} +241 -237
  56. package/core/built/admin/assets/activitypub/{topic-filter-CuDyM5bD.js → topic-filter-DLHBZT93.js} +4 -4
  57. package/core/built/admin/assets/activitypub/use-activity-pub-queries-VzbN99u_.js +1957 -0
  58. package/core/built/admin/assets/activitypub/{use-navigate-with-base-path-Drx1kdAK.js → use-navigate-with-base-path-CAwXTmqH.js} +165 -175
  59. package/core/built/admin/assets/activitypub/{use-reply-chain-data-BHkCHcW5.js → use-reply-chain-data-BAB6fNGt.js} +8 -8
  60. package/core/built/admin/assets/activitypub/users-BLeiOTHc.js +1464 -0
  61. package/core/built/admin/assets/activitypub/{x-BHCEe-c2.js → x-C8tAnXly.js} +2 -2
  62. package/core/built/admin/assets/{audience-adiFehTD.js → audience-X_XsZivI.js} +1 -1
  63. package/core/built/admin/assets/{automated-emails-UWM02CMr.js → automated-emails-of1MvVsv.js} +1 -1
  64. package/core/built/admin/assets/automations-B7-y3dXt.js +1 -0
  65. package/core/built/admin/assets/automations-DRFjW5fw.js +1 -0
  66. package/core/built/admin/assets/{avatar-flipboard-Lz3F9fNT.js → avatar-flipboard-C6Kj3Awu.js} +1 -1
  67. package/core/built/admin/assets/bluesky-sharing-BbbjWdzs.js +1 -0
  68. package/core/built/admin/assets/box-BWbhXh21.js +1 -0
  69. package/core/built/admin/assets/breadcrumb-B-M9Ip_2.js +1 -0
  70. package/core/built/admin/assets/card-DGoDJzrn.js +1 -0
  71. package/core/built/admin/assets/{chart-ChpW-NzQ.js → chart-BuRT2Y6p.js} +14 -14
  72. package/core/built/admin/assets/chart-helpers-xiSsW8r0.js +1 -0
  73. package/core/built/admin/assets/checkbox-EhJKHFdZ.js +1 -0
  74. package/core/built/admin/assets/{chunk.432.c2caa0b20f03e71d1a35.js → chunk.211.6f7328d63c41536451b3.js} +2025 -2819
  75. package/core/built/admin/assets/{chunk.432.c2caa0b20f03e71d1a35.js.LICENSE.txt → chunk.211.6f7328d63c41536451b3.js.LICENSE.txt} +1 -62
  76. package/core/built/admin/assets/{chunk.831.0703a12e49f51cec3f3a.js → chunk.361.3cdb584b973959e52ccc.js} +78 -85
  77. package/core/built/admin/assets/chunk.524.8365cd9280405c0f6216.js +25 -0
  78. package/core/built/admin/assets/chunk.582.61d078937e6102769f2c.js +27 -0
  79. package/core/built/admin/assets/code-editor-view-CZtJFGhR.js +1 -0
  80. package/core/built/admin/assets/comments-CvyXxOyN.js +1 -0
  81. package/core/built/admin/assets/container-BYz2Ed39.js +1 -0
  82. package/core/built/admin/assets/data-list-16rkJYYi.js +1 -0
  83. package/core/built/admin/assets/date-range-select-CTlyo8zW.js +1 -0
  84. package/core/built/admin/assets/disabled-sources-indicator-qs2GfLvl.js +1 -0
  85. package/core/built/admin/assets/{dist-DJ6c4_De.js → dist-2Tnz2Yfq.js} +1 -1
  86. package/core/built/admin/assets/{dist-CsekE4FL.js → dist-CQJY6SVY.js} +1 -1
  87. package/core/built/admin/assets/dist-CjY-f5Z1.js +1 -0
  88. package/core/built/admin/assets/dist-DGzPJ_bO.js +4 -0
  89. package/core/built/admin/assets/dist-DIC8yz5C.js +1 -0
  90. package/core/built/admin/assets/{dist-BbGrW05X.js → dist-DyViJwIy.js} +1 -1
  91. package/core/built/admin/assets/dist-Ndy-PuGN.js +1 -0
  92. package/core/built/admin/assets/dist-P_ohUlTi.js +1 -0
  93. package/core/built/admin/assets/domain-CPNXKVOV.js +1 -0
  94. package/core/built/admin/assets/dropzone-BmCXnw6J.js +5 -0
  95. package/core/built/admin/assets/edit-profile-SGrJve5M.js +1 -0
  96. package/core/built/admin/assets/editor-BOG2YPUm.js +8 -0
  97. package/core/built/admin/assets/empty-indicator-oX1u1Pkn.js +1 -0
  98. package/core/built/admin/assets/esm-CFX93H5M.js +2 -0
  99. package/core/built/admin/assets/explore-CUYLv9G9.js +1 -0
  100. package/core/built/admin/assets/feed-CPdJMttL.js +1 -0
  101. package/core/built/admin/assets/field-D0XISCK2.js +1 -0
  102. package/core/built/admin/assets/{filter-sources-v39ihhhV.js → filter-sources-Bieps75g.js} +1 -1
  103. package/core/built/admin/assets/filters-CuB-A7ma.js +1 -0
  104. package/core/built/admin/assets/filters-bXkkWro8.js +1 -0
  105. package/core/built/admin/assets/framework-provider-CmtnPXIT.js +4 -0
  106. package/core/built/admin/assets/{ghost-b57f077997b739a8ae9a70772dc016cb.js → ghost-05f9a7182ed56903dba05878a5b8422b.js} +46 -41
  107. package/core/built/admin/assets/ghost-dark-c8d0ab7f515b2010c173e23e9b32ea8a.css +1 -0
  108. package/core/built/admin/assets/gift-link-modal-su8MsRdg.js +1 -0
  109. package/core/built/admin/assets/{gift-links-CY3GwiVi.js → gift-links-nBxJjZiQ.js} +1 -1
  110. package/core/built/admin/assets/growth-Ba6S5FQX.js +1 -0
  111. package/core/built/admin/assets/hooks-BApwwBE0.js +2 -0
  112. package/core/built/admin/assets/{inbox-TEISAmth.js → inbox-Xx1CdnfO.js} +38 -38
  113. package/core/built/admin/assets/index-D8PbzuT9.css +1 -0
  114. package/core/built/admin/assets/index-ukW_0Uie.js +67 -0
  115. package/core/built/admin/assets/inline-EMAm3okk.js +1 -0
  116. package/core/built/admin/assets/input-group-CGOXcy4l.js +1 -0
  117. package/core/built/admin/assets/input-surface-BpAjZXY5.js +1 -0
  118. package/core/built/admin/assets/{react-dom-C6aoWSfl.js → jsx-runtime-DX3WBWVO.js} +1 -1
  119. package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +5 -2
  120. package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +2 -2
  121. package/core/built/admin/assets/{koenig-lexical-Di7b48ED.js → koenig-lexical-B61IALf5.js} +2 -2
  122. package/core/built/admin/assets/kpi-card-BlZaG1Lo.js +1 -0
  123. package/core/built/admin/assets/kpi-card-DCdlyaSS.js +1 -0
  124. package/core/built/admin/assets/kpi-helpers-DpAuS1Nb.js +1 -0
  125. package/core/built/admin/assets/kpi-tabs-Dme44bQS.js +1 -0
  126. package/core/built/admin/assets/label-dSs5aepE.js +1 -0
  127. package/core/built/admin/assets/label-picker-Uq91atex.js +1 -0
  128. package/core/built/admin/assets/{labels-GbxlXWtf.js → labels-Cyayfd-e.js} +1 -1
  129. package/core/built/admin/assets/layout-WUcz6tu1.js +1 -0
  130. package/core/built/admin/assets/limit-service-9fwD33lU.js +20 -0
  131. package/core/built/admin/assets/link-helpers-tOlxmuH5.js +1 -0
  132. package/core/built/admin/assets/list-page-B6ANtzkd.js +1 -0
  133. package/core/built/admin/assets/mailchimp-Ds_NQ04w.svg +9 -0
  134. package/core/built/admin/assets/member-custom-fields-NCzrMuba.js +1 -0
  135. package/core/built/admin/assets/member-detail-DPWDtYnN.js +1 -0
  136. package/core/built/admin/assets/members-B9rO7qr4.js +10 -0
  137. package/core/built/admin/assets/modals-CxRaan1J.js +31 -0
  138. package/core/built/admin/assets/moderation-D8zon60E.js +1 -0
  139. package/core/built/admin/assets/multi-select-combobox-1wYm3nle.js +1 -0
  140. package/core/built/admin/assets/newsletter-DbYMRxRS.js +1 -0
  141. package/core/built/admin/assets/{newsletters-DZm3yLj8.js → newsletters-D1jbtV-h.js} +1 -1
  142. package/core/built/admin/assets/note-PiWPnnrh.js +1 -0
  143. package/core/built/admin/assets/notifications-DEgqqB9G.js +1 -0
  144. package/core/built/admin/assets/nql-lang-B7faUf8D.js +19 -0
  145. package/core/built/admin/assets/{offers-D11QtPXX.js → offers-CrY6nSRR.js} +1 -1
  146. package/core/built/admin/assets/onboarding-route-BzF6HeVn.js +1 -0
  147. package/core/built/admin/assets/overview-DixLeIqY.js +1 -0
  148. package/core/built/admin/assets/page-header-op0eN36I.js +1 -0
  149. package/core/built/admin/assets/{pages-BnObVRrf.js → pages-BbNWFcGj.js} +1 -1
  150. package/core/built/admin/assets/pintura-CXOmq-5H.svg +15 -0
  151. package/core/built/admin/assets/post-analytics-WwRDEnrV.js +1 -0
  152. package/core/built/admin/assets/post-analytics-header-DsMoLx0R.js +1 -0
  153. package/core/built/admin/assets/{post-analytics-provider-DSfBCtnj.js → post-analytics-provider-BJCPLMIb.js} +1 -1
  154. package/core/built/admin/assets/post-share-modal-Dx-MEjhI.js +1 -0
  155. package/core/built/admin/assets/{posts-CwH8VJvB.js → posts-EWpZIjkr.js} +1 -1
  156. package/core/built/admin/assets/preferences-D7-j6A4C.js +5 -0
  157. package/core/built/admin/assets/profile-Dl69QPp0.js +1 -0
  158. package/core/built/admin/assets/{referrers-nxR52jPI.js → referrers-BCfFYSHc.js} +1 -1
  159. package/core/built/admin/assets/router-provider-C1R4AZ2o.js +1 -0
  160. package/core/built/admin/assets/select-C1qDZnW4.js +1 -0
  161. package/core/built/admin/assets/settings-BbmC_Iqq.js +4 -0
  162. package/core/built/admin/assets/settings-H6HxFgfI.js +1 -0
  163. package/core/built/admin/assets/shade-app-B3heOAfz-CGXQwWeO.js +3 -0
  164. package/core/built/admin/assets/share-modal-BJCadJyp.js +1 -0
  165. package/core/built/admin/assets/social-urls-BPL1nADp.js +8 -0
  166. package/core/built/admin/assets/sort-button-DyYlfYp7.js +1 -0
  167. package/core/built/admin/assets/source-icon-_ubRDbg_.js +1 -0
  168. package/core/built/admin/assets/stack-xiN0eQ6Z.js +1 -0
  169. package/core/built/admin/assets/stats-BQZMGMvn.js +1 -0
  170. package/core/built/admin/assets/stats-view-Doei-qCX.js +1 -0
  171. package/core/built/admin/assets/step-1-IKiLBPoC.js +1 -0
  172. package/core/built/admin/assets/step-2-jJ41PsDN.js +1 -0
  173. package/core/built/admin/assets/step-3-CaqFAEqf.js +2 -0
  174. package/core/built/admin/assets/switch-t-WyENU2.js +1 -0
  175. package/core/built/admin/assets/table-DxUL78jU.js +1 -0
  176. package/core/built/admin/assets/tabs-BQcJQ1ke.js +1 -0
  177. package/core/built/admin/assets/tags-CNujGwkT.js +1 -0
  178. package/core/built/admin/assets/text-DwtjwGkh.js +1 -0
  179. package/core/built/admin/assets/textarea-Bjccvh_E.js +1 -0
  180. package/core/built/admin/assets/{tiers-EghDzCKc.js → tiers-BgYLWRJv.js} +1 -1
  181. package/core/built/admin/assets/toggle-group-BeEpQ69p.js +1 -0
  182. package/core/built/admin/assets/topic-filter-Bb5MOD-1.js +1 -0
  183. package/core/built/admin/assets/{use-analytics-data-0l_OHtnR.js → use-analytics-data-Cds6XDjg.js} +1 -1
  184. package/core/built/admin/assets/use-filter-params-DjXkhO54.js +1 -0
  185. package/core/built/admin/assets/use-growth-stats-D8uf98-G.js +1 -0
  186. package/core/built/admin/assets/{use-post-referrers-DwI31Ril.js → use-post-referrers-CRtgyuXB.js} +1 -1
  187. package/core/built/admin/assets/use-reply-chain-data-DbKYX50v.js +1 -0
  188. package/core/built/admin/assets/use-simple-pagination-DC01kpo0.js +1 -0
  189. package/core/built/admin/assets/{use-tinybird-query-DvZBBMG7.js → use-tinybird-query-C7bQRJWw.js} +1 -1
  190. package/core/built/admin/assets/{use-tinybird-token-CQtebkvU.js → use-tinybird-token-Az4tam7_.js} +1 -1
  191. package/core/built/admin/assets/{users-Pc8IRjk9.js → users-CcSCQFcQ.js} +1 -1
  192. package/core/built/admin/assets/virtual-list-Dhuh9fGx.js +1 -0
  193. package/core/built/admin/assets/web-LtHNiNBV.js +1 -0
  194. package/core/built/admin/index.html +22 -22
  195. package/core/frontend/apps/private-blogging/index.js +1 -1
  196. package/core/frontend/apps/private-blogging/lib/middleware.js +1 -1
  197. package/core/frontend/helpers/split.js +2 -1
  198. package/core/frontend/meta/asset-url.js +1 -1
  199. package/core/frontend/meta/author-image.js +1 -1
  200. package/core/frontend/meta/blog-logo.js +1 -1
  201. package/core/frontend/meta/canonical-url.js +1 -1
  202. package/core/frontend/meta/cover-image.js +1 -1
  203. package/core/frontend/meta/get-meta.js +1 -1
  204. package/core/frontend/meta/og-image.js +1 -1
  205. package/core/frontend/meta/paginated-url.js +1 -1
  206. package/core/frontend/meta/twitter-image.js +1 -1
  207. package/core/frontend/meta/url.js +1 -1
  208. package/core/frontend/services/assets-minification/admin-auth-assets.js +1 -1
  209. package/core/frontend/services/llms/handler.js +1 -1
  210. package/core/frontend/services/proxy.js +42 -3
  211. package/core/frontend/services/routing/collection-router.js +1 -1
  212. package/core/frontend/services/routing/controllers/email-post.js +1 -1
  213. package/core/frontend/services/routing/controllers/entry/markdown.js +1 -1
  214. package/core/frontend/services/routing/controllers/entry/markdown.ts +1 -1
  215. package/core/frontend/services/routing/controllers/entry.js +1 -1
  216. package/core/frontend/services/routing/controllers/entry.ts +1 -1
  217. package/core/frontend/services/routing/controllers/previews.js +6 -7
  218. package/core/frontend/services/routing/controllers/unsubscribe.js +7 -3
  219. package/core/frontend/services/routing/email-router.js +1 -1
  220. package/core/frontend/services/routing/events.js +12 -0
  221. package/core/frontend/services/routing/middleware/page-param.js +1 -1
  222. package/core/frontend/services/routing/parent-router.js +1 -1
  223. package/core/frontend/services/routing/preview-router.js +1 -1
  224. package/core/frontend/services/routing/router-manager.js +4 -8
  225. package/core/frontend/services/routing/rss-router.js +1 -1
  226. package/core/frontend/services/routing/static-pages-router.js +1 -1
  227. package/core/frontend/services/routing/static-routes-router.js +1 -1
  228. package/core/frontend/services/routing/taxonomy-router.js +1 -1
  229. package/core/frontend/services/rss/generate-feed.js +1 -1
  230. package/core/frontend/services/sitemap/base-site-map-generator.js +23 -4
  231. package/core/frontend/services/sitemap/site-map-index-generator.js +1 -1
  232. package/core/frontend/services/sitemap/site-map-manager.js +14 -8
  233. package/core/frontend/services/sitemap/utils.js +1 -1
  234. package/core/frontend/services/theme-engine/middleware/update-global-template-options.js +1 -1
  235. package/core/frontend/services/theme-engine/middleware/update-local-template-options.js +1 -1
  236. package/core/frontend/utils/images.js +1 -1
  237. package/core/frontend/web/middleware/admin-toolbar.js +1 -1
  238. package/core/frontend/web/middleware/handle-image-sizes.js +2 -2
  239. package/core/frontend/web/middleware/redirect-ghost-to-admin.js +1 -1
  240. package/core/frontend/web/routers/serve-favicon.js +1 -1
  241. package/core/frontend/web/routers/serve-public-file.js +1 -1
  242. package/core/frontend/web/site.js +5 -5
  243. package/core/server/adapters/cache/AdapterCacheMemoryTTL.js +2 -2
  244. package/core/server/adapters/cache/MemoryCache.js +2 -2
  245. package/core/server/adapters/cache/Redis.js +1 -1
  246. package/core/server/adapters/cache/index.js +1 -1
  247. package/core/server/adapters/lib/redis/AdapterCacheRedis.js +2 -2
  248. package/core/server/adapters/route-settings/FileStore.js +2 -8
  249. package/core/server/adapters/route-settings/FileStore.ts +1 -6
  250. package/core/server/adapters/route-settings/S3RouteSettingsStore.js +206 -0
  251. package/core/server/adapters/route-settings/S3RouteSettingsStore.ts +199 -0
  252. package/core/server/adapters/route-settings/utils.js +13 -0
  253. package/core/server/adapters/route-settings/utils.ts +7 -0
  254. package/core/server/adapters/scheduling/deps.d.ts +0 -2
  255. package/core/server/adapters/scheduling/error-capture.js +76 -0
  256. package/core/server/adapters/scheduling/error-capture.ts +91 -0
  257. package/core/server/adapters/scheduling/utils.js +18 -34
  258. package/core/server/adapters/scheduling/utils.ts +36 -0
  259. package/core/server/adapters/storage/LocalFilesStorage.js +13 -11
  260. package/core/server/adapters/storage/LocalFilesStorage.ts +24 -0
  261. package/core/server/adapters/storage/LocalImagesStorage.js +14 -12
  262. package/core/server/adapters/storage/LocalImagesStorage.ts +24 -0
  263. package/core/server/adapters/storage/LocalMediaStorage.js +13 -11
  264. package/core/server/adapters/storage/LocalMediaStorage.ts +24 -0
  265. package/core/server/adapters/storage/LocalStorageBase.js +107 -167
  266. package/core/server/adapters/storage/LocalStorageBase.ts +342 -0
  267. package/core/server/adapters/storage/S3Storage.js +2 -2
  268. package/core/server/adapters/storage/S3Storage.ts +1 -1
  269. package/core/server/adapters/storage/utils.js +36 -50
  270. package/core/server/adapters/storage/utils.ts +60 -0
  271. package/core/server/api/endpoints/authentication.js +1 -1
  272. package/core/server/api/endpoints/db.js +6 -0
  273. package/core/server/api/endpoints/featurebase.js +1 -1
  274. package/core/server/api/endpoints/files.js +2 -2
  275. package/core/server/api/endpoints/images.js +2 -2
  276. package/core/server/api/endpoints/libraries.d.ts +0 -1
  277. package/core/server/api/endpoints/media.js +8 -5
  278. package/core/server/api/endpoints/member-custom-fields.js +4 -1
  279. package/core/server/api/endpoints/member-custom-fields.ts +4 -1
  280. package/core/server/api/endpoints/members.js +25 -28
  281. package/core/server/api/endpoints/pages.js +6 -1
  282. package/core/server/api/endpoints/posts.js +28 -3
  283. package/core/server/api/endpoints/search-index-public.js +4 -3
  284. package/core/server/api/endpoints/search-index.js +5 -4
  285. package/core/server/api/endpoints/settings-public.js +1 -1
  286. package/core/server/api/endpoints/settings.js +3 -1
  287. package/core/server/api/endpoints/utils/serializers/input/utils/url.js +9 -1
  288. package/core/server/api/endpoints/utils/serializers/output/default.js +7 -0
  289. package/core/server/api/endpoints/utils/serializers/output/files.js +1 -1
  290. package/core/server/api/endpoints/utils/serializers/output/mappers/comments.js +4 -1
  291. package/core/server/api/endpoints/utils/serializers/output/media.js +1 -1
  292. package/core/server/api/endpoints/utils/serializers/output/member-custom-fields.js +7 -4
  293. package/core/server/api/endpoints/utils/serializers/output/member-custom-fields.ts +8 -4
  294. package/core/server/api/endpoints/utils/serializers/output/members.js +27 -106
  295. package/core/server/api/endpoints/utils/serializers/output/pages.js +7 -0
  296. package/core/server/api/endpoints/utils/serializers/output/posts.js +13 -0
  297. package/core/server/api/endpoints/utils/serializers/output/utils/url.js +1 -1
  298. package/core/server/api/endpoints/utils/validators/input/members.js +2 -52
  299. package/core/server/data/db/backup.js +1 -1
  300. package/core/server/data/exporter/export-filename.js +2 -1
  301. package/core/server/data/importer/handlers/image.js +3 -3
  302. package/core/server/data/importer/import-manager.js +6 -4
  303. package/core/server/data/importer/importers/content-file-importer.js +2 -2
  304. package/core/server/data/importer/importers/data/revue-subscriber-importer.js +6 -10
  305. package/core/server/data/importer/importers/json-to-html.js +24 -4
  306. package/core/server/data/migrations/utils/schema.js +4 -2
  307. package/core/server/data/migrations/versions/6.54/2026-07-19-16-59-00-add-content-import-permission.js +10 -0
  308. package/core/server/data/migrations/versions/6.54/2026-07-20-13-59-21-drop-email-tracked-sent-count-from-automation-action-revisions.js +7 -0
  309. package/core/server/data/migrations/versions/6.54/2026-07-21-01-58-20-add-automation-run-steps-poller-index.js +3 -0
  310. package/core/server/data/migrations/versions/6.54/2026-07-21-21-08-15-add-automated-email-recipients-mailgun-message-id-index.js +3 -0
  311. package/core/server/data/migrations/versions/6.54/2026-07-22-10-41-08-add-click-tracking-to-automated-email-recipients.js +13 -0
  312. package/core/server/data/migrations/versions/6.54/2026-07-22-15-10-30-add-email-clicked-count-to-automation-action-revisions.js +7 -0
  313. package/core/server/data/migrations/versions/6.54/2026-07-23-10-24-18-add-automation-action-revision-to-redirects.js +9 -0
  314. package/core/server/data/schema/commands.js +37 -3
  315. package/core/server/data/schema/fixtures/fixtures.json +7 -0
  316. package/core/server/data/schema/lib/default-index-name.js +20 -0
  317. package/core/server/data/schema/schema.js +40 -17
  318. package/core/server/data/seeders/data-generator.js +4 -2
  319. package/core/server/lib/image/image-size.js +7 -23
  320. package/core/server/lib/image/image-utils.js +16 -2
  321. package/core/server/lib/image/index.js +4 -4
  322. package/core/server/lib/lexical.js +3 -3
  323. package/core/server/lib/mobiledoc.js +2 -2
  324. package/core/server/lib/request-external.js +1 -1
  325. package/core/server/lib/validate-password.js +1 -1
  326. package/core/server/models/action.js +9 -0
  327. package/core/server/models/base/plugins/generate-slug.js +1 -1
  328. package/core/server/models/collection.js +1 -1
  329. package/core/server/models/custom-theme-setting.js +1 -1
  330. package/core/server/models/member.js +73 -0
  331. package/core/server/models/newsletter.js +1 -1
  332. package/core/server/models/post.js +19 -5
  333. package/core/server/models/posts-meta.js +1 -1
  334. package/core/server/models/redirect.js +1 -1
  335. package/core/server/models/settings.js +1 -1
  336. package/core/server/models/snippet.js +1 -1
  337. package/core/server/models/tag.js +1 -1
  338. package/core/server/models/user.js +47 -71
  339. package/core/server/models/welcome-email-automated-email.js +1 -1
  340. package/core/server/services/activitypub/activity-pub-service-wrapper.js +1 -1
  341. package/core/server/services/adapter-manager/adapter-manager.js +5 -1
  342. package/core/server/services/adapter-manager/adapter-manager.ts +7 -2
  343. package/core/server/services/adapter-manager/index.js +18 -15
  344. package/core/server/services/adapter-manager/index.ts +23 -17
  345. package/core/server/services/adapter-manager/utils.js +124 -14
  346. package/core/server/services/adapter-manager/utils.ts +130 -14
  347. package/core/server/services/api-version-compatibility/mw-version-rewrites.js +1 -1
  348. package/core/server/services/audience-feedback/index.js +1 -1
  349. package/core/server/services/auth/passwordreset.js +1 -1
  350. package/core/server/services/auth/session/express-session.js +1 -1
  351. package/core/server/services/auth/session/index.js +2 -2
  352. package/core/server/services/auth/session/session-service.js +29 -2
  353. package/core/server/services/automations/automations-api.js +8 -25
  354. package/core/server/services/automations/automations-api.ts +8 -37
  355. package/core/server/services/automations/automations-repository.ts +16 -0
  356. package/core/server/services/automations/database-automations-repository.js +37 -4
  357. package/core/server/services/automations/database-automations-repository.ts +41 -4
  358. package/core/server/services/automations/poll.js +16 -12
  359. package/core/server/services/automations/poll.ts +17 -15
  360. package/core/server/services/automations/service.js +1 -1
  361. package/core/server/services/automations/service.ts +3 -13
  362. package/core/server/services/automations/welcome-email-automation-poll.js +2 -1
  363. package/core/server/services/comments/comments-service-emails.js +4 -1
  364. package/core/server/services/comments/index.js +1 -1
  365. package/core/server/services/custom-redirects/index.js +2 -2
  366. package/core/server/services/email-analytics/email-analytics-service-wrapper.js +14 -13
  367. package/core/server/services/email-analytics/email-analytics-service.js +1 -1
  368. package/core/server/services/email-analytics/events/start-email-analytics-job-event.js +11 -15
  369. package/core/server/services/email-analytics/events/start-email-analytics-job-event.ts +15 -0
  370. package/core/server/services/email-analytics/index.js +2 -3
  371. package/core/server/services/email-analytics/index.ts +1 -2
  372. package/core/server/services/email-analytics/jobs/email-analytics-job-scheduler.js +1 -6
  373. package/core/server/services/email-analytics/jobs/email-analytics-job-scheduler.ts +0 -9
  374. package/core/server/services/email-analytics/jobs/fetch-latest/index.js +1 -1
  375. package/core/server/services/email-analytics/jobs/index.js +0 -2
  376. package/core/server/services/email-service/email-service-wrapper.js +1 -1
  377. package/core/server/services/email-service/email-service.js +20 -4
  378. package/core/server/services/explore-ping/explore-ping-service.js +24 -39
  379. package/core/server/services/explore-ping/explore-ping-service.ts +198 -0
  380. package/core/server/services/explore-ping/index.js +11 -11
  381. package/core/server/services/explore-ping/index.ts +42 -0
  382. package/core/server/services/gifts/gift-reminder-scheduler.js +1 -1
  383. package/core/server/services/gifts/gift-reminder-scheduler.ts +1 -1
  384. package/core/server/services/gifts/gift-service-wrapper.js +1 -1
  385. package/core/server/services/identity-tokens/identity-token-service-wrapper.js +1 -1
  386. package/core/server/services/indexnow-ping/constants.js +30 -0
  387. package/core/server/services/indexnow-ping/constants.ts +32 -0
  388. package/core/server/services/indexnow-ping/index.js +29 -253
  389. package/core/server/services/indexnow-ping/index.ts +37 -0
  390. package/core/server/services/indexnow-ping/indexnow-ping-service.js +229 -0
  391. package/core/server/services/indexnow-ping/indexnow-ping-service.ts +319 -0
  392. package/core/server/services/invites/index.js +1 -1
  393. package/core/server/services/lib/mailgun-client.js +3 -3
  394. package/core/server/services/link-redirection/index.js +2 -2
  395. package/core/server/services/link-redirection/link-redirect-repository.js +1 -1
  396. package/core/server/services/link-redirection/link-redirect.js +12 -13
  397. package/core/server/services/link-redirection/link-redirect.ts +22 -0
  398. package/core/server/services/link-redirection/link-redirects-service.js +1 -1
  399. package/core/server/services/link-tracking/full-post-link.js +2 -2
  400. package/core/server/services/link-tracking/index.js +1 -1
  401. package/core/server/services/mail/ghost-mailer.js +1 -1
  402. package/core/server/services/mail/index.js +1 -1
  403. package/core/server/services/media-inliner/external-media-inliner.js +2 -2
  404. package/core/server/services/media-inliner/service.js +4 -3
  405. package/core/server/services/member-attribution/index.js +1 -1
  406. package/core/server/services/member-welcome-emails/service.js +1 -1
  407. package/core/server/services/members/api.js +8 -2
  408. package/core/server/services/members/import-export/config.js +30 -0
  409. package/core/server/services/members/import-export/config.ts +34 -0
  410. package/core/server/services/members/import-export/csv/index.js +10 -0
  411. package/core/server/services/members/import-export/csv/index.ts +2 -0
  412. package/core/server/services/members/import-export/csv/parse.js +64 -0
  413. package/core/server/services/members/import-export/csv/parse.ts +69 -0
  414. package/core/server/services/members/import-export/csv/serialize.js +13 -0
  415. package/core/server/services/members/import-export/csv/serialize.ts +18 -0
  416. package/core/server/services/members/import-export/export/exporter.js +202 -0
  417. package/core/server/services/members/import-export/export/exporter.ts +325 -0
  418. package/core/server/services/members/import-export/import/completion-email.js +65 -0
  419. package/core/server/services/members/import-export/import/completion-email.ts +119 -0
  420. package/core/server/services/members/import-export/import/importer.js +276 -0
  421. package/core/server/services/members/import-export/import/importer.ts +430 -0
  422. package/core/server/services/members/import-export/import/reader.js +32 -0
  423. package/core/server/services/members/import-export/import/reader.ts +33 -0
  424. package/core/server/services/members/import-export/import/row.js +33 -0
  425. package/core/server/services/members/import-export/import/row.ts +52 -0
  426. package/core/server/services/members/import-export/import/spool.js +30 -0
  427. package/core/server/services/members/import-export/import/spool.ts +38 -0
  428. package/core/server/services/members/import-export/index.js +90 -0
  429. package/core/server/services/members/import-export/index.ts +118 -0
  430. package/core/server/services/members/members-api/controllers/router-controller.js +7 -0
  431. package/core/server/services/members/members-api/members-api.js +4 -2
  432. package/core/server/services/members/members-api/repositories/event-repository.js +13 -2
  433. package/core/server/services/members/members-api/services/member-bread-service.js +42 -19
  434. package/core/server/services/members/middleware.js +1 -1
  435. package/core/server/services/members/service.js +28 -17
  436. package/core/server/services/members/stripe-connect.js +1 -1
  437. package/core/server/services/members-custom-fields/actions.js +3 -0
  438. package/core/server/services/members-custom-fields/actions.ts +6 -2
  439. package/core/server/services/members-custom-fields/config.js +34 -0
  440. package/core/server/services/members-custom-fields/config.ts +38 -0
  441. package/core/server/services/members-custom-fields/definitions-service.js +156 -21
  442. package/core/server/services/members-custom-fields/definitions-service.ts +170 -25
  443. package/core/server/services/members-custom-fields/index.js +16 -3
  444. package/core/server/services/members-custom-fields/index.ts +17 -3
  445. package/core/server/services/members-custom-fields/values-service.js +56 -10
  446. package/core/server/services/members-custom-fields/values-service.ts +62 -10
  447. package/core/server/services/mentions/mention-sending-service.js +22 -2
  448. package/core/server/services/mentions/service.js +21 -5
  449. package/core/server/services/newsletters/index.js +1 -1
  450. package/core/server/services/oembed/oembed-service.js +122 -33
  451. package/core/server/services/oembed/service.js +4 -2
  452. package/core/server/services/offers/service.js +1 -1
  453. package/core/server/services/post-scheduling/index.js +4 -3
  454. package/core/server/services/post-scheduling/index.ts +4 -3
  455. package/core/server/services/post-scheduling/post-scheduling.js +1 -1
  456. package/core/server/services/post-scheduling/post-scheduling.ts +1 -1
  457. package/core/server/services/posts/post-email-handler.js +13 -6
  458. package/core/server/services/posts/post-scheduling.js +1 -1
  459. package/core/server/services/posts/posts-exporter.js +6 -4
  460. package/core/server/services/posts/posts-service-instance.js +1 -1
  461. package/core/server/services/posts/posts-service.js +4 -4
  462. package/core/server/services/posts-public/service.js +1 -1
  463. package/core/server/services/public-config/site.js +1 -1
  464. package/core/server/services/recommendations/recommendation-service-wrapper.js +1 -1
  465. package/core/server/services/recommendations/service/libraries.d.ts +0 -2
  466. package/core/server/services/route-settings/dynamic-routing-service.js +2 -3
  467. package/core/server/services/route-settings/index.js +1 -1
  468. package/core/server/services/route-settings/route-settings-parser.js +134 -124
  469. package/core/server/services/route-settings/route-settings-parser.ts +160 -125
  470. package/core/server/services/route-settings/validation-errors.js +178 -0
  471. package/core/server/services/route-settings/validation-errors.ts +196 -0
  472. package/core/server/services/settings/settings-service.js +2 -2
  473. package/core/server/services/settings-helpers/index.js +1 -1
  474. package/core/server/services/slack-notifications/service.js +1 -1
  475. package/core/server/services/slack-ping/constants.js +16 -0
  476. package/core/server/services/slack-ping/constants.ts +15 -0
  477. package/core/server/services/slack-ping/index.js +26 -204
  478. package/core/server/services/slack-ping/index.ts +35 -0
  479. package/core/server/services/slack-ping/slack-ping-service.js +214 -0
  480. package/core/server/services/slack-ping/slack-ping-service.ts +296 -0
  481. package/core/server/services/staff/index.js +1 -1
  482. package/core/server/services/stats/posts-stats-service.js +1 -1
  483. package/core/server/services/stats/service.js +1 -1
  484. package/core/server/services/stripe/service.js +1 -1
  485. package/core/server/services/tags-public/service.js +1 -1
  486. package/core/server/services/themes/storage.js +9 -0
  487. package/core/server/services/themes/theme-storage.js +1 -1
  488. package/core/server/services/themes/validate.js +1 -1
  489. package/core/server/services/update-check/index.js +1 -1
  490. package/core/server/services/url/lazy-url-service.js +66 -6
  491. package/core/server/services/url/lazy-url-service.ts +73 -6
  492. package/core/server/services/url/url-generator.js +1 -1
  493. package/core/server/services/url/url-service-facade.js +68 -3
  494. package/core/server/services/url/url-service-facade.ts +79 -4
  495. package/core/server/services/url/url-service.js +1 -1
  496. package/core/server/services/url/urls.js +1 -1
  497. package/core/server/services/webhooks/index.js +19 -2
  498. package/core/server/services/webhooks/listen.js +6 -11
  499. package/core/server/services/webhooks/payload.js +1 -3
  500. package/core/server/services/webhooks/serialize.js +16 -1
  501. package/core/server/web/admin/app.js +1 -1
  502. package/core/server/web/admin/middleware/redirect-admin-urls.js +1 -1
  503. package/core/server/web/api/endpoints/admin/routes.js +1 -0
  504. package/core/server/web/api/middleware/cors.js +1 -1
  505. package/core/server/web/api/middleware/upload.js +4 -0
  506. package/core/server/web/gift-preview/controller.js +1 -1
  507. package/core/server/web/shared/middleware/redirect-amp-urls.js +1 -1
  508. package/core/server/web/shared/middleware/uncapitalise.js +2 -2
  509. package/core/server/web/shared/middleware/url-redirects.js +1 -1
  510. package/core/shared/config/defaults.json +10 -2
  511. package/core/shared/config/overrides.json +4 -0
  512. package/core/shared/express.js +6 -1
  513. package/core/shared/labs.js +2 -1
  514. package/core/shared/url-utils.js +19 -15
  515. package/core/shared/url-utils.ts +20 -0
  516. package/ghost.js +0 -1
  517. package/package.json +30 -35
  518. package/pnpm-lock.yaml +681 -2789
  519. package/pnpm-workspace.yaml +31 -17
  520. package/components/tryghost-adapter-base-scheduling-0.0.0.tgz +0 -0
  521. package/components/tryghost-adapter-base-sso-0.0.0.tgz +0 -0
  522. package/core/built/admin/assets/Combination--5EZGaDs.js +0 -43
  523. package/core/built/admin/assets/Growth-C0NoKcHQ.js +0 -3
  524. package/core/built/admin/assets/Newsletters-Ed8kDjdy.js +0 -1
  525. package/core/built/admin/assets/Overview-CArPgRZt.js +0 -1
  526. package/core/built/admin/assets/Web-CjjYoVM3.js +0 -2
  527. package/core/built/admin/assets/account-migration-mfa5mNI9.js +0 -1
  528. package/core/built/admin/assets/activitypub/inbox-B3rjKMTv.js +0 -1221
  529. package/core/built/admin/assets/activitypub/layout-jcurg3rU.js +0 -1
  530. package/core/built/admin/assets/activitypub/use-activity-pub-queries-yqGRcnLn.js +0 -2569
  531. package/core/built/admin/assets/activitypub/users-CfyHIsTG.js +0 -1316
  532. package/core/built/admin/assets/automations-DkUnxNdv.js +0 -1
  533. package/core/built/admin/assets/automations-vjXofmV_.js +0 -1
  534. package/core/built/admin/assets/bluesky-sharing-T-pO3RcP.js +0 -1
  535. package/core/built/admin/assets/breadcrumb-CekPYTCn.js +0 -1
  536. package/core/built/admin/assets/button--i2uMDDn.js +0 -4
  537. package/core/built/admin/assets/card-CSWz_BXq.js +0 -1
  538. package/core/built/admin/assets/chart-helpers-C_4Ka_vT.js +0 -1
  539. package/core/built/admin/assets/chunk.524.8ce2c741473e2f0929dc.js +0 -25
  540. package/core/built/admin/assets/chunk.582.453459d6228d2955408b.js +0 -27
  541. package/core/built/admin/assets/code-editor-view-BfkwQto2.js +0 -1
  542. package/core/built/admin/assets/command-K75Jzs0G.js +0 -1
  543. package/core/built/admin/assets/comments-BEIi1DH-.js +0 -1
  544. package/core/built/admin/assets/container-BNXvlcjA.js +0 -1
  545. package/core/built/admin/assets/data-list-BmK5QMab.js +0 -1
  546. package/core/built/admin/assets/date-range-select-5sKzwbt7.js +0 -1
  547. package/core/built/admin/assets/disabled-sources-indicator-L_ssJTNr.js +0 -1
  548. package/core/built/admin/assets/dist-BBIJuyPg.js +0 -1
  549. package/core/built/admin/assets/dist-BHE0dp6o.js +0 -1
  550. package/core/built/admin/assets/dist-CT46_f_J.js +0 -1
  551. package/core/built/admin/assets/dist-DW0QXQO3.js +0 -1
  552. package/core/built/admin/assets/dist-DxFLceO5.js +0 -1
  553. package/core/built/admin/assets/dist-QcACAOAD.js +0 -1
  554. package/core/built/admin/assets/dist-duxRDcQu.js +0 -177
  555. package/core/built/admin/assets/domain-CLaPZ9Rc.js +0 -1
  556. package/core/built/admin/assets/dropzone-E0bSX4_a.js +0 -5
  557. package/core/built/admin/assets/edit-profile-DqNPKaA4.js +0 -1
  558. package/core/built/admin/assets/editor-CkLXQDRp.js +0 -8
  559. package/core/built/admin/assets/empty-indicator-BTtOlgIo.js +0 -1
  560. package/core/built/admin/assets/esm-TSfGW7nz.js +0 -2
  561. package/core/built/admin/assets/explore-BEstLxKr.js +0 -1
  562. package/core/built/admin/assets/feed-C58p2voG.js +0 -1
  563. package/core/built/admin/assets/field-BSbDUHPv.js +0 -1
  564. package/core/built/admin/assets/filters-BgYv8Gt7.js +0 -1
  565. package/core/built/admin/assets/filters-DvenFkmK.js +0 -1
  566. package/core/built/admin/assets/framework-provider-jQktxm9P.js +0 -4
  567. package/core/built/admin/assets/ghost-dark-8590dea6cd695ff90f27d262c4464538.css +0 -1
  568. package/core/built/admin/assets/gift-link-modal-BPjXkEFt.js +0 -1
  569. package/core/built/admin/assets/growth-D4JNiVTe.js +0 -1
  570. package/core/built/admin/assets/hooks-Cjxexi_I.js +0 -2
  571. package/core/built/admin/assets/index-BacwlcOy.js +0 -67
  572. package/core/built/admin/assets/index-DxRNHH0o.css +0 -1
  573. package/core/built/admin/assets/inline-C22rnPro.js +0 -1
  574. package/core/built/admin/assets/input-group-CKfrILLP.js +0 -1
  575. package/core/built/admin/assets/jsx-runtime-CtMZ-PAS.js +0 -1
  576. package/core/built/admin/assets/kpi-card-DZxQKAIb.js +0 -1
  577. package/core/built/admin/assets/kpi-card-FidQ5zg3.js +0 -1
  578. package/core/built/admin/assets/kpi-helpers-C5T8Vaf1.js +0 -1
  579. package/core/built/admin/assets/kpi-tabs-_VRK6hGV.js +0 -1
  580. package/core/built/admin/assets/label-Cza7hPgn.js +0 -1
  581. package/core/built/admin/assets/label-picker-DgC_zLaw.js +0 -1
  582. package/core/built/admin/assets/layout-BxsXnKFX.js +0 -1
  583. package/core/built/admin/assets/limit-service-CTurluJQ.js +0 -20
  584. package/core/built/admin/assets/link-helpers-C3Gqy2cz.js +0 -1
  585. package/core/built/admin/assets/list-page-BtqCnow_.js +0 -1
  586. package/core/built/admin/assets/member-custom-fields-9uXFBqSt.js +0 -1
  587. package/core/built/admin/assets/member-detail-Dq6ZDIxo.js +0 -1
  588. package/core/built/admin/assets/members-CUWD9jal.js +0 -10
  589. package/core/built/admin/assets/modals-CIdwHVga.js +0 -31
  590. package/core/built/admin/assets/moderation-DTt04UDA.js +0 -1
  591. package/core/built/admin/assets/newsletter-cC8vcc9h.js +0 -1
  592. package/core/built/admin/assets/note-DZU0IY9e.js +0 -1
  593. package/core/built/admin/assets/notifications-NoHpBHJ4.js +0 -1
  594. package/core/built/admin/assets/nql-lang-CvCSOQG3.js +0 -19
  595. package/core/built/admin/assets/onboarding-route-Deg2hNm8.js +0 -1
  596. package/core/built/admin/assets/overview-BQPt_9w3.js +0 -1
  597. package/core/built/admin/assets/page-header-D6bEqPo2.js +0 -1
  598. package/core/built/admin/assets/post-analytics-header-BPw_B2_D.js +0 -1
  599. package/core/built/admin/assets/post-analytics-kp2_--XO.js +0 -1
  600. package/core/built/admin/assets/post-share-modal-Cave3Z4W.js +0 -1
  601. package/core/built/admin/assets/preferences-C7h3j_uy.js +0 -5
  602. package/core/built/admin/assets/profile-B2x4q2oB.js +0 -1
  603. package/core/built/admin/assets/router-provider-5fsX1CYn.js +0 -1
  604. package/core/built/admin/assets/select-PhPjIBBT.js +0 -1
  605. package/core/built/admin/assets/settings-D5P9Gwgo.js +0 -6
  606. package/core/built/admin/assets/settings-zUOzQV5I.js +0 -1
  607. package/core/built/admin/assets/share-modal-EfpfbuWF.js +0 -1
  608. package/core/built/admin/assets/social-urls-DgAF08Xc.js +0 -18
  609. package/core/built/admin/assets/sort-button-WOQYJm2H.js +0 -1
  610. package/core/built/admin/assets/source-icon-hm8Cj-Gx.js +0 -1
  611. package/core/built/admin/assets/stats-CnQDb62m.js +0 -1
  612. package/core/built/admin/assets/stats-view-CCfTJgSe.js +0 -1
  613. package/core/built/admin/assets/step-1-BGlhY4DS.js +0 -1
  614. package/core/built/admin/assets/step-2-D3sDEyFH.js +0 -1
  615. package/core/built/admin/assets/step-3-CvZoUdsc.js +0 -2
  616. package/core/built/admin/assets/switch-CNjkOmwz.js +0 -1
  617. package/core/built/admin/assets/table-C5nZYPnW.js +0 -1
  618. package/core/built/admin/assets/tabs-dtOcExye.js +0 -1
  619. package/core/built/admin/assets/tags-Dhm0FB_g.js +0 -1
  620. package/core/built/admin/assets/textarea-CeKw3wmV.js +0 -1
  621. package/core/built/admin/assets/toggle-group-DfhZIMTW.js +0 -1
  622. package/core/built/admin/assets/topic-filter-Cxe1Il41.js +0 -1
  623. package/core/built/admin/assets/typeof-Ca-duI-z.js +0 -1
  624. package/core/built/admin/assets/use-filter-params-Bub6BqNy.js +0 -1
  625. package/core/built/admin/assets/use-growth-stats-BJORomv0.js +0 -1
  626. package/core/built/admin/assets/use-reply-chain-data-B89YjVoo.js +0 -1
  627. package/core/built/admin/assets/use-simple-pagination-BL2SYXKi.js +0 -1
  628. package/core/built/admin/assets/virtual-list-DNJOSK9I.js +0 -1
  629. package/core/built/admin/assets/web-BHUE3YQc.js +0 -1
  630. package/core/server/adapters/scheduling/scheduling-base.js +0 -5
  631. package/core/server/adapters/sso/SSOBase.js +0 -5
  632. package/core/server/adapters/storage/index.js +0 -17
  633. package/core/server/services/mail/templates/newsletter.html +0 -876
  634. package/core/server/services/members/exporter/query.js +0 -206
  635. package/core/server/services/members/importer/index.js +0 -30
  636. package/core/server/services/members/importer/labels.js +0 -125
  637. package/core/server/services/members/importer/members-csv-importer.js +0 -502
  638. /package/core/server/services/members/{importer → import-export/import}/email-template.js +0 -0
  639. /package/core/server/services/members/{importer/members-csv-importer-stripe-utils.js → import-export/import/stripe-utils.js} +0 -0
@@ -25,6 +25,7 @@ export interface WaitAction {
25
25
  }
26
26
 
27
27
  export interface AutomationEmailStats {
28
+ email_clicked_count: number;
28
29
  email_sent_count: number;
29
30
  email_opened_count: number;
30
31
  opened_rate: number | null;
@@ -81,6 +82,17 @@ export type AutomatedEmailEvents = {
81
82
  automationActionRevisionId: string;
82
83
  };
83
84
 
85
+ export type RecordEmailSentOptions = Readonly<{
86
+ automationActionRevisionId: string;
87
+ mailgunMessageId?: string;
88
+ memberEmail: string;
89
+ memberId: string;
90
+ memberName: string | null;
91
+ memberUuid: string;
92
+ trackClicks: boolean;
93
+ trackOpens: boolean;
94
+ }>;
95
+
84
96
  type AutomationStepBase = {
85
97
  id: string;
86
98
  locked_by: string;
@@ -167,6 +179,10 @@ export interface AutomationsRepository {
167
179
  step: Pick<AutomationStepToRun, 'id' | 'locked_by'>,
168
180
  retryAt: Readonly<Date>
169
181
  ): Promise<boolean>;
182
+ /**
183
+ * Record a sent email and increment its action revision's sent count.
184
+ */
185
+ recordEmailSent(options: RecordEmailSentOptions): Promise<void>;
170
186
  /**
171
187
  * Fetch sent emails by their Mailgun IDs.
172
188
  */
@@ -94,6 +94,29 @@ function createDatabaseAutomationsRepository({ knex, fakeWaitHoursMultiplier })
94
94
  async retryStep(step, retryAt) {
95
95
  return await knex.transaction(trx => retryStep(trx, step, retryAt));
96
96
  },
97
+ async recordEmailSent(options) {
98
+ await knex.transaction(async (trx) => {
99
+ await trx('automation_action_revisions')
100
+ .where('id', options.automationActionRevisionId)
101
+ .update({
102
+ email_sent_count: trx.raw('COALESCE(??, 0) + ?', ['email_sent_count', 1])
103
+ });
104
+ const now = toDatabaseDate(new Date());
105
+ await trx('automated_email_recipients').insert({
106
+ id: (0, bson_objectid_1.default)().toHexString(),
107
+ member_id: options.memberId,
108
+ member_uuid: options.memberUuid,
109
+ member_email: options.memberEmail,
110
+ member_name: options.memberName,
111
+ automation_action_revision_id: options.automationActionRevisionId,
112
+ ...(options.mailgunMessageId ? { mailgun_message_id: options.mailgunMessageId } : {}),
113
+ track_clicks: options.trackClicks,
114
+ track_opens: options.trackOpens,
115
+ created_at: now,
116
+ updated_at: now
117
+ });
118
+ });
119
+ },
97
120
  async getAutomatedEmailRecipientsByMailgunIds(mailgunMessageIds) {
98
121
  if (mailgunMessageIds.length === 0) {
99
122
  return [];
@@ -128,7 +151,10 @@ function createDatabaseAutomationsRepository({ knex, fakeWaitHoursMultiplier })
128
151
  newOpensPerRevision.set(automationActionRevisionId, (newOpensPerRevision.get(automationActionRevisionId) ?? 0) + 1);
129
152
  }
130
153
  }
131
- for (const [id, opens] of newOpensPerRevision) {
154
+ // Keep lock acquisition order consistent across concurrent transactions to avoid deadlocks.
155
+ const revisions = [...newOpensPerRevision.entries()]
156
+ .sort(([left], [right]) => left.localeCompare(right));
157
+ for (const [id, opens] of revisions) {
132
158
  await trx('automation_action_revisions')
133
159
  .where({ id })
134
160
  .update({
@@ -329,6 +355,7 @@ async function fetchAndLockSteps(trx, limit) {
329
355
  .innerJoin('automations as automation', 'automation.id', 'run.automation_id')
330
356
  .innerJoin('automation_action_revisions as revision', 'revision.id', 'step.automation_action_revision_id')
331
357
  .innerJoin('automation_actions as action', 'action.id', 'revision.action_id')
358
+ .whereIn('step.id', candidateIds)
332
359
  .where('step.locked_by', lockId)
333
360
  .orderBy([
334
361
  'step.ready_at',
@@ -342,13 +369,14 @@ async function fetchAndLockSteps(trx, limit) {
342
369
  }
343
370
  async function findNextPendingReadyAt(trx, staleLockCutoff) {
344
371
  const row = await trx('automation_run_steps')
345
- .min({ next_ready_at: 'ready_at' })
372
+ .select({ next_ready_at: 'ready_at' })
346
373
  .where('status', 'pending')
347
374
  .where((builder) => {
348
375
  builder
349
376
  .whereNull('locked_by')
350
377
  .orWhere('locked_at', '<', toDatabaseDate(staleLockCutoff));
351
378
  })
379
+ .orderBy('ready_at')
352
380
  .first();
353
381
  return row?.next_ready_at ? new Date(row.next_ready_at) : null;
354
382
  }
@@ -874,6 +902,7 @@ async function loadActionStats(trx, actionIds) {
874
902
  const rows = await trx('automation_action_revisions')
875
903
  .select('action_id')
876
904
  .sum({
905
+ email_clicked_count: 'email_clicked_count',
877
906
  email_sent_count: 'email_sent_count',
878
907
  email_opened_count: 'email_opened_count'
879
908
  })
@@ -925,22 +954,26 @@ function buildActionPayload(row, stats) {
925
954
  }
926
955
  }
927
956
  const EMPTY_EMAIL_STATS = {
957
+ email_clicked_count: 0,
928
958
  email_sent_count: 0,
929
959
  email_opened_count: 0,
930
960
  opened_rate: null,
931
961
  clicked_rate: null
932
962
  };
933
963
  function buildEmailStats(row) {
964
+ const emailClickedCount = row.email_clicked_count ?? 0;
934
965
  const emailSentCount = row.email_sent_count ?? 0;
935
966
  const emailOpenedCount = row.email_opened_count ?? 0;
936
967
  return {
968
+ email_clicked_count: emailClickedCount,
937
969
  email_sent_count: emailSentCount,
938
970
  email_opened_count: emailOpenedCount,
939
971
  opened_rate: emailSentCount
940
972
  ? Math.round(emailOpenedCount / emailSentCount * 100)
941
973
  : null,
942
- // TODO(NY-1387) Populate clicked_rate once click tracking is implemented.
943
- clicked_rate: null
974
+ clicked_rate: emailSentCount
975
+ ? Math.round(emailClickedCount / emailSentCount * 100)
976
+ : null
944
977
  };
945
978
  }
946
979
  function requireValue(row, field) {
@@ -65,6 +65,7 @@ interface ActionRow {
65
65
 
66
66
  type ActionStatsRow = {
67
67
  action_id: string;
68
+ email_clicked_count: number | null;
68
69
  email_sent_count: number | null;
69
70
  email_opened_count: number | null;
70
71
  };
@@ -224,6 +225,31 @@ export function createDatabaseAutomationsRepository({
224
225
  return await knex.transaction(trx => retryStep(trx, step, retryAt));
225
226
  },
226
227
 
228
+ async recordEmailSent(options): Promise<void> {
229
+ await knex.transaction(async (trx) => {
230
+ await trx('automation_action_revisions')
231
+ .where('id', options.automationActionRevisionId)
232
+ .update({
233
+ email_sent_count: trx.raw('COALESCE(??, 0) + ?', ['email_sent_count', 1])
234
+ });
235
+
236
+ const now = toDatabaseDate(new Date());
237
+ await trx('automated_email_recipients').insert({
238
+ id: ObjectId().toHexString(),
239
+ member_id: options.memberId,
240
+ member_uuid: options.memberUuid,
241
+ member_email: options.memberEmail,
242
+ member_name: options.memberName,
243
+ automation_action_revision_id: options.automationActionRevisionId,
244
+ ...(options.mailgunMessageId ? {mailgun_message_id: options.mailgunMessageId} : {}),
245
+ track_clicks: options.trackClicks,
246
+ track_opens: options.trackOpens,
247
+ created_at: now,
248
+ updated_at: now
249
+ });
250
+ });
251
+ },
252
+
227
253
  async getAutomatedEmailRecipientsByMailgunIds(mailgunMessageIds) {
228
254
  if (mailgunMessageIds.length === 0) {
229
255
  return [];
@@ -266,7 +292,11 @@ export function createDatabaseAutomationsRepository({
266
292
  }
267
293
  }
268
294
 
269
- for (const [id, opens] of newOpensPerRevision) {
295
+ // Keep lock acquisition order consistent across concurrent transactions to avoid deadlocks.
296
+ const revisions = [...newOpensPerRevision.entries()]
297
+ .sort(([left], [right]) => left.localeCompare(right));
298
+
299
+ for (const [id, opens] of revisions) {
270
300
  await trx('automation_action_revisions')
271
301
  .where({id})
272
302
  .update({
@@ -542,6 +572,7 @@ async function fetchAndLockSteps(trx: Knex.Transaction, limit: number): Promise<
542
572
  .innerJoin('automations as automation', 'automation.id', 'run.automation_id')
543
573
  .innerJoin('automation_action_revisions as revision', 'revision.id', 'step.automation_action_revision_id')
544
574
  .innerJoin('automation_actions as action', 'action.id', 'revision.action_id')
575
+ .whereIn('step.id', candidateIds)
545
576
  .where('step.locked_by', lockId)
546
577
  .orderBy([
547
578
  'step.ready_at',
@@ -557,13 +588,14 @@ async function fetchAndLockSteps(trx: Knex.Transaction, limit: number): Promise<
557
588
 
558
589
  async function findNextPendingReadyAt(trx: Knex.Transaction, staleLockCutoff: Readonly<Date>): Promise<Date | null> {
559
590
  const row = await trx('automation_run_steps')
560
- .min({next_ready_at: 'ready_at'})
591
+ .select({next_ready_at: 'ready_at'})
561
592
  .where('status', 'pending')
562
593
  .where((builder) => {
563
594
  builder
564
595
  .whereNull('locked_by')
565
596
  .orWhere('locked_at', '<', toDatabaseDate(staleLockCutoff));
566
597
  })
598
+ .orderBy('ready_at')
567
599
  .first();
568
600
  return row?.next_ready_at ? new Date(row.next_ready_at) : null;
569
601
  }
@@ -1233,6 +1265,7 @@ async function loadActionStats(
1233
1265
  const rows: ActionStatsRow[] = await trx('automation_action_revisions')
1234
1266
  .select('action_id')
1235
1267
  .sum({
1268
+ email_clicked_count: 'email_clicked_count',
1236
1269
  email_sent_count: 'email_sent_count',
1237
1270
  email_opened_count: 'email_opened_count'
1238
1271
  })
@@ -1288,6 +1321,7 @@ function buildActionPayload(row: ActionRow, stats: AutomationEmailStats | null):
1288
1321
  }
1289
1322
 
1290
1323
  const EMPTY_EMAIL_STATS: AutomationEmailStats = {
1324
+ email_clicked_count: 0,
1291
1325
  email_sent_count: 0,
1292
1326
  email_opened_count: 0,
1293
1327
  opened_rate: null,
@@ -1295,16 +1329,19 @@ const EMPTY_EMAIL_STATS: AutomationEmailStats = {
1295
1329
  };
1296
1330
 
1297
1331
  function buildEmailStats(row: ActionStatsRow): AutomationEmailStats {
1332
+ const emailClickedCount = row.email_clicked_count ?? 0;
1298
1333
  const emailSentCount = row.email_sent_count ?? 0;
1299
1334
  const emailOpenedCount = row.email_opened_count ?? 0;
1300
1335
  return {
1336
+ email_clicked_count: emailClickedCount,
1301
1337
  email_sent_count: emailSentCount,
1302
1338
  email_opened_count: emailOpenedCount,
1303
1339
  opened_rate: emailSentCount
1304
1340
  ? Math.round(emailOpenedCount / emailSentCount * 100)
1305
1341
  : null,
1306
- // TODO(NY-1387) Populate clicked_rate once click tracking is implemented.
1307
- clicked_rate: null
1342
+ clicked_rate: emailSentCount
1343
+ ? Math.round(emailClickedCount / emailSentCount * 100)
1344
+ : null
1308
1345
  };
1309
1346
  }
1310
1347
 
@@ -112,6 +112,7 @@ const processStep = async ({ automationsApi, memberWelcomeEmailService, schedule
112
112
  break;
113
113
  }
114
114
  memberWelcomeEmailService.init();
115
+ const trackClicks = Boolean(settingsCache.get('email_track_clicks'));
115
116
  const trackOpens = Boolean(settingsCache.get('email_track_opens'));
116
117
  const sendResult = await memberWelcomeEmailService.api.sendAutomationEmail({
117
118
  email: {
@@ -138,6 +139,7 @@ const processStep = async ({ automationsApi, memberWelcomeEmailService, schedule
138
139
  memberId: step.member_id,
139
140
  memberName: member.get('name'),
140
141
  memberUuid: member.get('uuid'),
142
+ trackClicks,
141
143
  trackOpens: trackOpensForRecipient
142
144
  });
143
145
  }
@@ -151,18 +153,20 @@ const processStep = async ({ automationsApi, memberWelcomeEmailService, schedule
151
153
  }
152
154
  }, `[AUTOMATIONS] Failed to record automated email recipient for step ${step.id}`);
153
155
  }
154
- try {
155
- await scheduleAutomationEmailAnalyticsJob();
156
- }
157
- catch (err) {
158
- logging_1.default.error({
159
- err,
160
- system: {
161
- event: 'automations.poll.analytics_scheduling_failed',
162
- member_id: step.member_id,
163
- step_id: step.id
164
- }
165
- }, `[AUTOMATIONS] Failed to schedule email analytics job for step ${step.id}`);
156
+ if (mailgunMessageId) {
157
+ try {
158
+ await scheduleAutomationEmailAnalyticsJob();
159
+ }
160
+ catch (err) {
161
+ logging_1.default.error({
162
+ err,
163
+ system: {
164
+ event: 'automations.poll.analytics_scheduling_failed',
165
+ member_id: step.member_id,
166
+ step_id: step.id
167
+ }
168
+ }, `[AUTOMATIONS] Failed to schedule email analytics job for step ${step.id}`);
169
+ }
166
170
  }
167
171
  break;
168
172
  }
@@ -1,5 +1,4 @@
1
1
  import type {AutomationStepToRun, AutomationsRepository} from './automations-repository';
2
- import type {RecordEmailSentOptions} from './automations-api';
3
2
  import {getMailgunMessageId} from './mailgun-message-id';
4
3
  import logging from '@tryghost/logging';
5
4
  import errors from '@tryghost/errors';
@@ -44,10 +43,9 @@ type PollOptions = {
44
43
  'fetchAndLockSteps' |
45
44
  'finishStepAndEnqueueNext' |
46
45
  'markStepTerminal' |
46
+ 'recordEmailSent' |
47
47
  'retryStep'
48
- > & {
49
- recordEmailSent(options: RecordEmailSentOptions): Promise<void>;
50
- };
48
+ >;
51
49
  enqueueAnotherPollAt: (date: Readonly<Date>) => unknown;
52
50
  scheduleAutomationEmailAnalyticsJob: () => Promise<void>;
53
51
  memberWelcomeEmailService: MemberWelcomeEmailService;
@@ -185,6 +183,7 @@ const processStep = async ({
185
183
  break;
186
184
  }
187
185
  memberWelcomeEmailService.init();
186
+ const trackClicks = Boolean(settingsCache.get('email_track_clicks'));
188
187
  const trackOpens = Boolean(settingsCache.get('email_track_opens'));
189
188
  const sendResult = await memberWelcomeEmailService.api.sendAutomationEmail({
190
189
  email: {
@@ -211,6 +210,7 @@ const processStep = async ({
211
210
  memberId: step.member_id,
212
211
  memberName: member.get('name'),
213
212
  memberUuid: member.get('uuid'),
213
+ trackClicks,
214
214
  trackOpens: trackOpensForRecipient
215
215
  });
216
216
  } catch (err) {
@@ -223,17 +223,19 @@ const processStep = async ({
223
223
  }
224
224
  }, `[AUTOMATIONS] Failed to record automated email recipient for step ${step.id}`);
225
225
  }
226
- try {
227
- await scheduleAutomationEmailAnalyticsJob();
228
- } catch (err) {
229
- logging.error({
230
- err,
231
- system: {
232
- event: 'automations.poll.analytics_scheduling_failed',
233
- member_id: step.member_id,
234
- step_id: step.id
235
- }
236
- }, `[AUTOMATIONS] Failed to schedule email analytics job for step ${step.id}`);
226
+ if (mailgunMessageId) {
227
+ try {
228
+ await scheduleAutomationEmailAnalyticsJob();
229
+ } catch (err) {
230
+ logging.error({
231
+ err,
232
+ system: {
233
+ event: 'automations.poll.analytics_scheduling_failed',
234
+ member_id: step.member_id,
235
+ step_id: step.id
236
+ }
237
+ }, `[AUTOMATIONS] Failed to schedule email analytics job for step ${step.id}`);
238
+ }
237
239
  }
238
240
  break;
239
241
  }
@@ -45,7 +45,7 @@ const promises_1 = require("node:timers/promises");
45
45
  const soonest_timer_1 = require("../../lib/soonest-timer");
46
46
  // @ts-expect-error This module currently lacks type definitions.
47
47
  const jobs_1 = __importDefault(require("../email-analytics/jobs"));
48
- const urlUtils = require('../../../shared/url-utils');
48
+ const urlUtils = require('../../../shared/url-utils').default;
49
49
  const logging = require('@tryghost/logging');
50
50
  const { getSignedAdminToken } = require('../../adapters/scheduling/utils');
51
51
  const StartAutomationsPollEvent = require('./events/start-automations-poll-event');
@@ -1,4 +1,5 @@
1
1
  import assert from 'node:assert/strict';
2
+ import type {SchedulerAdapter} from '@tryghost/adapter-base-scheduling';
2
3
  import type {InternalKeys} from '../internal-keys';
3
4
  // @ts-expect-error @tryghost/domain-events currently lacks type declarations.
4
5
  import type DomainEvents from '@tryghost/domain-events';
@@ -10,29 +11,18 @@ import {SoonestTimer} from '../../lib/soonest-timer';
10
11
  // @ts-expect-error This module currently lacks type definitions.
11
12
  import emailAnalyticsJobs from '../email-analytics/jobs';
12
13
 
13
- const urlUtils = require('../../../shared/url-utils');
14
+ const urlUtils = require('../../../shared/url-utils').default;
14
15
  const logging = require('@tryghost/logging');
15
16
  const {getSignedAdminToken} = require('../../adapters/scheduling/utils');
16
17
  const StartAutomationsPollEvent = require('./events/start-automations-poll-event');
17
18
  const {welcomeEmailAutomationPoll} = require('./welcome-email-automation-poll');
18
19
  const memberWelcomeEmailService = require('../member-welcome-emails/service');
19
20
 
20
- type SchedulerAdapter = {
21
- schedule(job: {
22
- extra: {
23
- httpMethod: string;
24
- };
25
- time: number;
26
- url: string;
27
- }): void;
28
- register(rescheduler: {rescheduleAll: () => unknown}): void;
29
- };
30
-
31
21
  type AutomationsServiceOptions = {
32
22
  apiUrl: string;
33
23
  domainEvents: Pick<DomainEvents, 'dispatch' | 'subscribe'>;
34
24
  internalKeys: InternalKeys;
35
- schedulerAdapter: SchedulerAdapter;
25
+ schedulerAdapter: Pick<SchedulerAdapter, 'schedule' | 'register'>;
36
26
  };
37
27
 
38
28
  const scheduleAutomationEmailAnalyticsJob = () => (
@@ -235,7 +235,8 @@ async function processRun({
235
235
  member_uuid: member.get('uuid'),
236
236
  member_email: member.get('email'),
237
237
  member_name: member.get('name'),
238
- track_opens: false
238
+ track_opens: false,
239
+ track_clicks: false
239
240
  }, {transacting});
240
241
 
241
242
  await markExited(run.id, 'finished', transacting);
@@ -26,7 +26,10 @@ class CommentsServiceEmails {
26
26
  */
27
27
  getPostUrl(post, commentId) {
28
28
  const postData = toPlain(post);
29
- const baseUrl = this.urlService.facade.getUrlForResource({...postData, type: 'posts'}, {absolute: true});
29
+ // Comments live on pages as well as posts; the URL service routes by
30
+ // the passed type, so a page typed 'posts' resolves to /404/.
31
+ const routerType = postData.type === 'page' ? 'pages' : 'posts';
32
+ const baseUrl = this.urlService.facade.getUrlForResource({...postData, type: routerType}, {absolute: true});
30
33
  return `${baseUrl}#ghost-comments-${commentId}`;
31
34
  }
32
35
 
@@ -11,7 +11,7 @@ class CommentsServiceWrapper {
11
11
  const mailer = new GhostMailer();
12
12
  const settingsCache = require('../../../shared/settings-cache');
13
13
  const urlService = require('../url');
14
- const urlUtils = require('../../../shared/url-utils');
14
+ const urlUtils = require('../../../shared/url-utils').default;
15
15
  const membersService = require('../members');
16
16
  const db = require('../../data/db');
17
17
  const settingsHelpers = require('../settings-helpers');
@@ -1,6 +1,6 @@
1
1
  const config = require('../../../shared/config');
2
- const urlUtils = require('../../../shared/url-utils');
3
- const adapterManager = require('../adapter-manager');
2
+ const urlUtils = require('../../../shared/url-utils').default;
3
+ const adapterManager = require('../adapter-manager').default;
4
4
 
5
5
  const DynamicRedirectManager = require('../lib/dynamic-redirect-manager');
6
6
  const {RedirectsService} = require('./redirects-service');
@@ -8,6 +8,7 @@ const domainEvents = require('@tryghost/domain-events');
8
8
 
9
9
  class EmailAnalyticsServiceWrapper {
10
10
  /** @type {string} */ #logName;
11
+ #fetching = false;
11
12
  #restoredSchedule = false;
12
13
 
13
14
  get #logPrefix() {
@@ -128,9 +129,9 @@ class EmailAnalyticsServiceWrapper {
128
129
  logging.warn(`${this.#logPrefix} Opened events processing is ${lagMinutes.toFixed(1)} minutes behind (threshold: ${lagThreshold})`);
129
130
  }
130
131
 
131
- const fetchStartDate = new Date();
132
+ const fetchStartedAt = Date.now();
132
133
  const fetchResult = await this.service.fetchLatestOpenedEvents({maxEvents});
133
- const totalDuration = Date.now() - fetchStartDate.getTime();
134
+ const totalDuration = Date.now() - fetchStartedAt;
134
135
 
135
136
  this._logJobCompletion('latest-opened', fetchResult, totalDuration);
136
137
 
@@ -138,9 +139,9 @@ class EmailAnalyticsServiceWrapper {
138
139
  }
139
140
 
140
141
  async fetchLatestNonOpenedEvents({maxEvents} = {maxEvents: Infinity}) {
141
- const fetchStartDate = new Date();
142
+ const fetchStartedAt = Date.now();
142
143
  const fetchResult = await this.service.fetchLatestNonOpenedEvents({maxEvents});
143
- const totalDuration = Date.now() - fetchStartDate.getTime();
144
+ const totalDuration = Date.now() - fetchStartedAt;
144
145
 
145
146
  this._logJobCompletion('latest', fetchResult, totalDuration);
146
147
 
@@ -148,9 +149,9 @@ class EmailAnalyticsServiceWrapper {
148
149
  }
149
150
 
150
151
  async fetchMissing({maxEvents} = {maxEvents: Infinity}) {
151
- const fetchStartDate = new Date();
152
+ const fetchStartedAt = Date.now();
152
153
  const fetchResult = await this.service.fetchMissing({maxEvents});
153
- const totalDuration = Date.now() - fetchStartDate.getTime();
154
+ const totalDuration = Date.now() - fetchStartedAt;
154
155
 
155
156
  this._logJobCompletion('missing', fetchResult, totalDuration);
156
157
 
@@ -162,9 +163,9 @@ class EmailAnalyticsServiceWrapper {
162
163
  return 0;
163
164
  }
164
165
 
165
- const fetchStartDate = new Date();
166
+ const fetchStartedAt = Date.now();
166
167
  const fetchResult = await this.service.fetchScheduled({maxEvents});
167
- const totalDuration = Date.now() - fetchStartDate.getTime();
168
+ const totalDuration = Date.now() - fetchStartedAt;
168
169
 
169
170
  this._logJobCompletion('scheduled', fetchResult, totalDuration);
170
171
 
@@ -177,11 +178,11 @@ class EmailAnalyticsServiceWrapper {
177
178
  await this.service.restoreScheduled();
178
179
  }
179
180
 
180
- if (this.fetching) {
181
+ if (this.#fetching) {
181
182
  logging.info(`Email analytics fetch for ${this.#logName} already running, skipping`);
182
183
  return;
183
184
  }
184
- this.fetching = true;
185
+ this.#fetching = true;
185
186
 
186
187
  // NOTE: Data shows we can process ~2500 events per minute on Pro for a large-ish db (150k members).
187
188
  // This can vary locally, but we should be conservative with the number of events we fetch.
@@ -216,18 +217,18 @@ class EmailAnalyticsServiceWrapper {
216
217
  logging.info(`${this.#logPrefix} Job complete - No events`);
217
218
  }
218
219
 
219
- this.fetching = false;
220
+ this.#fetching = false;
220
221
  } catch (e) {
221
222
  logging.error(e, `Error while fetching email analytics for ${this.#logName}`);
222
223
 
223
224
  // Log again only the error, otherwise we lose the stack trace
224
225
  logging.error(e);
225
226
  }
226
- this.fetching = false;
227
+ this.#fetching = false;
227
228
  }
228
229
 
229
230
  _restartFetch(reason) {
230
- this.fetching = false;
231
+ this.#fetching = false;
231
232
  logging.info(`${this.#logPrefix} Restarting fetch due to ${reason}`);
232
233
  this.startFetch();
233
234
  }
@@ -105,7 +105,7 @@ module.exports = class EmailAnalyticsService {
105
105
  * @param {object} dependencies
106
106
  * @param {object} dependencies.queries
107
107
  * @param {object} dependencies.provider
108
- * @param {PrometheusClient} dependencies.prometheusClient
108
+ * @param {PrometheusClient} [dependencies.prometheusClient]
109
109
  * @param {() => BatchEventProcessor} dependencies.createEventProcessor
110
110
  * @param {JobNames} dependencies.jobNames
111
111
  * @param {CursorSeed} dependencies.cursorSeed
@@ -1,22 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StartEmailAnalyticsJobEvent = void 0;
1
4
  /**
2
5
  * This is an event that is used to circumvent the job manager that currently isn't able to run scheduled jobs on the main thread (not offloaded).
3
6
  * We simply emit this event in the job manager and listen for it on the main thread.
4
7
  */
5
- module.exports = class StartEmailAnalyticsJobEvent {
6
- /**
7
- * @param {any} data
8
- * @param {Date} timestamp
9
- */
10
- constructor(data, timestamp) {
11
- this.data = data;
8
+ class StartEmailAnalyticsJobEvent {
9
+ timestamp;
10
+ constructor(timestamp) {
12
11
  this.timestamp = timestamp;
13
12
  }
14
-
15
- /**
16
- * @param {any} [data]
17
- * @param {Date} [timestamp]
18
- */
19
- static create(data, timestamp) {
20
- return new StartEmailAnalyticsJobEvent(data, timestamp ?? new Date);
13
+ static create(timestamp = new Date()) {
14
+ return new StartEmailAnalyticsJobEvent(timestamp);
21
15
  }
22
- };
16
+ }
17
+ exports.StartEmailAnalyticsJobEvent = StartEmailAnalyticsJobEvent;
18
+ ;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * This is an event that is used to circumvent the job manager that currently isn't able to run scheduled jobs on the main thread (not offloaded).
3
+ * We simply emit this event in the job manager and listen for it on the main thread.
4
+ */
5
+ export class StartEmailAnalyticsJobEvent {
6
+ readonly timestamp: Date;
7
+
8
+ constructor(timestamp: Date) {
9
+ this.timestamp = timestamp;
10
+ }
11
+
12
+ static create(timestamp = new Date()) {
13
+ return new StartEmailAnalyticsJobEvent(timestamp);
14
+ }
15
+ };
@@ -59,8 +59,7 @@ const domain_events_1 = __importDefault(require("@tryghost/domain-events"));
59
59
  const prometheus_client_1 = __importDefault(require("../../../shared/prometheus-client"));
60
60
  // @ts-expect-error This module lacks type definitions.
61
61
  const queries_1 = __importDefault(require("./lib/queries"));
62
- // @ts-expect-error This module lacks type definitions.
63
- const start_email_analytics_job_event_1 = __importDefault(require("./events/start-email-analytics-job-event"));
62
+ const start_email_analytics_job_event_1 = require("./events/start-email-analytics-job-event");
64
63
  const start_automation_email_analytics_job_event_1 = require("./events/start-automation-email-analytics-job-event");
65
64
  const constants_1 = require("../member-welcome-emails/constants");
66
65
  const automationsApi = __importStar(require("../automations/automations-api"));
@@ -93,7 +92,7 @@ const init = () => {
93
92
  newsletterMailgunTags.push(config_1.default.get('bulkEmail:mailgun:tag'));
94
93
  }
95
94
  exports.newsletters.init({
96
- event: start_email_analytics_job_event_1.default,
95
+ event: start_email_analytics_job_event_1.StartEmailAnalyticsJobEvent,
97
96
  mailgunTags: newsletterMailgunTags,
98
97
  jobNames: {
99
98
  latestNonOpened: 'email-analytics-latest-others',
@@ -20,8 +20,7 @@ import domainEvents from '@tryghost/domain-events';
20
20
  import prometheusClient from '../../../shared/prometheus-client';
21
21
  // @ts-expect-error This module lacks type definitions.
22
22
  import queries from './lib/queries';
23
- // @ts-expect-error This module lacks type definitions.
24
- import StartEmailAnalyticsJobEvent from './events/start-email-analytics-job-event';
23
+ import {StartEmailAnalyticsJobEvent} from './events/start-email-analytics-job-event';
25
24
  import {StartAutomationEmailAnalyticsJobEvent} from './events/start-automation-email-analytics-job-event';
26
25
  import {AUTOMATION_EMAIL_TAG} from '../member-welcome-emails/constants';
27
26
  import * as automationsApi from '../automations/automations-api';