ghost 6.55.0 → 6.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (483) hide show
  1. package/bin/validate-adapters.js +74 -0
  2. package/bin/validate-adapters.ts +87 -0
  3. package/bin/warm-compile-cache.sh +60 -0
  4. package/components/tryghost-custom-field-types-0.0.0.tgz +0 -0
  5. package/components/tryghost-kg-default-cards-10.3.3.tgz +0 -0
  6. package/components/tryghost-kg-default-nodes-2.1.4.tgz +0 -0
  7. package/components/tryghost-kg-default-transforms-1.3.3.tgz +0 -0
  8. package/components/tryghost-kg-html-to-lexical-1.3.3.tgz +0 -0
  9. package/components/tryghost-kg-lexical-html-renderer-1.4.3.tgz +0 -0
  10. package/components/tryghost-nql-string-0.0.0.tgz +0 -0
  11. package/components/tryghost-parse-email-address-0.0.0.tgz +0 -0
  12. package/core/app.js +1 -1
  13. package/core/boot.js +21 -25
  14. package/core/bridge.js +10 -12
  15. package/core/built/admin/assets/Combination-BDvCdg1t.js +41 -0
  16. package/core/built/admin/assets/{PolarAngleAxis-BGjf7sBu.js → PolarAngleAxis-C4qtHy1B.js} +1 -1
  17. package/core/built/admin/assets/{RadialBarChart-zeFf9mBz.js → RadialBarChart-Bh09Stsj.js} +1 -1
  18. package/core/built/admin/assets/about-C7O-AgRZ.js +1 -0
  19. package/core/built/admin/assets/{account-migration-sjHLx5dy.js → account-migration-Cv_ol1ko.js} +1 -1
  20. package/core/built/admin/assets/action-list-lGzZLHc8.js +1 -0
  21. package/core/built/admin/assets/activitypub/{account-migration-DoYXtnZ8.js → account-migration-DHFbePl6.js} +7 -7
  22. package/core/built/admin/assets/activitypub/activitypub.js +6 -6
  23. package/core/built/admin/assets/activitypub/{avatar-B3DEDB1l.js → avatar-CT4tS2_S.js} +2 -2
  24. package/core/built/admin/assets/activitypub/{avatar-flipboard-Cqrg0XMx.js → avatar-flipboard-ByYWKipo.js} +2 -2
  25. package/core/built/admin/assets/activitypub/{bluesky-sharing-Bxeh6MKW.js → bluesky-sharing-srVnSHDz.js} +16 -16
  26. package/core/built/admin/assets/activitypub/{content-formatters-BpQARh28.js → content-formatters-C2sos5Ht.js} +3 -3
  27. package/core/built/admin/assets/activitypub/{copy-D9UWIAan.js → copy-B1UBTOoZ.js} +2 -2
  28. package/core/built/admin/assets/activitypub/{dist-D8sFfdpC.js → dist-MPsb2WZ1.js} +12 -12
  29. package/core/built/admin/assets/activitypub/{domain-CWueFW6q.js → domain-DzcM9Dzo.js} +9 -9
  30. package/core/built/admin/assets/activitypub/{edit-profile-BGxPU7N5.js → edit-profile-CsQ_4xAk.js} +945 -945
  31. package/core/built/admin/assets/activitypub/{explore-DBK-u0Ch.js → explore-CJe0DZBK.js} +8 -8
  32. package/core/built/admin/assets/activitypub/{feed-Bcir5RQZ.js → feed-CKV3qWON.js} +33 -33
  33. package/core/built/admin/assets/activitypub/{field-BV-CIT3d.js → field-DckHfDJf.js} +3 -3
  34. package/core/built/admin/assets/activitypub/{hash-BC9Q0N4c.js → hash-Dlp8RM55.js} +2 -2
  35. package/core/built/admin/assets/activitypub/{inbox-DQ4ZnC1m.js → inbox-CsPy4R0M.js} +2 -2
  36. package/core/built/admin/assets/activitypub/{inbox-yC0nfvzl.js → inbox-DAsjzUUe.js} +85 -85
  37. package/core/built/admin/assets/activitypub/{label-DTRS9TDk.js → label-DWyo9E5T.js} +3 -3
  38. package/core/built/admin/assets/activitypub/layout-DM_3pqsU.js +1 -0
  39. package/core/built/admin/assets/activitypub/{moderation-Dwl9t0pb.js → moderation-B0Inc03M.js} +11 -11
  40. package/core/built/admin/assets/activitypub/{note-B-zKsZ7r.js → note-CSE54lER.js} +7 -7
  41. package/core/built/admin/assets/activitypub/{notifications-DjJZD54t.js → notifications-RSwbKqdh.js} +9 -9
  42. package/core/built/admin/assets/activitypub/{preferences-CoU8vs6d.js → preferences-CE231n2_.js} +20 -20
  43. package/core/built/admin/assets/activitypub/{profile-BAsaJekx.js → profile-aaQ1j1Eo.js} +237 -237
  44. package/core/built/admin/assets/activitypub/{reply-CpdMeAO5.js → reply-Cjb0Vs3m.js} +2 -2
  45. package/core/built/admin/assets/activitypub/{routes-CLH3OVTP.js → routes-Djb0mc9k.js} +1139 -1150
  46. package/core/built/admin/assets/activitypub/{separator-BI1FLsYM.js → separator-D8pROI5n.js} +3 -3
  47. package/core/built/admin/assets/activitypub/{settings-DA6pNJ-Q.js → settings-DMc32IQl.js} +13 -13
  48. package/core/built/admin/assets/activitypub/{site-CQD42Pw5.js → site-DVIcsohX.js} +81 -81
  49. package/core/built/admin/assets/activitypub/{step-1-DIDg4aHb.js → step-1-9Yey9usF.js} +5 -5
  50. package/core/built/admin/assets/activitypub/{step-2-BfGe8BYt.js → step-2-DdYmKRXV.js} +6 -6
  51. package/core/built/admin/assets/activitypub/{step-3-mE9spAqw.js → step-3-hdSkcjZU.js} +10 -10
  52. package/core/built/admin/assets/activitypub/{tabs-Cg0saow1.js → tabs-CUqseYzQ.js} +317 -315
  53. package/core/built/admin/assets/activitypub/{topic-filter-DLHBZT93.js → topic-filter-Coni6OXM.js} +3 -3
  54. package/core/built/admin/assets/activitypub/{use-activity-pub-queries-VzbN99u_.js → use-activity-pub-queries-MeHTPMQv.js} +2 -2
  55. package/core/built/admin/assets/activitypub/{use-navigate-with-base-path-CAwXTmqH.js → use-navigate-with-base-path-B046AM38.js} +115 -96
  56. package/core/built/admin/assets/activitypub/{use-reply-chain-data-Br4aOWOh.js → use-reply-chain-data-1AO-Xob6.js} +5 -5
  57. package/core/built/admin/assets/activitypub/{x-C8tAnXly.js → x-BRfRYd16.js} +2 -2
  58. package/core/built/admin/assets/add-integration-modal-m9Dv6f77.js +1 -0
  59. package/core/built/admin/assets/add-newsletter-modal-CPSVZL2H.js +1 -0
  60. package/core/built/admin/assets/add-recommendation-modal-Ci9Z5yat.js +1 -0
  61. package/core/built/admin/assets/analytics-DqSCVV8U.js +1 -0
  62. package/core/built/admin/assets/announcement-bar-modal-DU3avV7d.js +1 -0
  63. package/core/built/admin/assets/api-keys-BK0LylyK.js +1 -0
  64. package/core/built/admin/assets/api-keys-_iCT4dxr.js +1 -0
  65. package/core/built/admin/assets/{audience-DjEWNhp3.js → audience-DTJtXXWY.js} +1 -1
  66. package/core/built/admin/assets/automated-emails-PayPCT8L.js +1 -0
  67. package/core/built/admin/assets/{automations-DhKeS_U5.js → automations-162q5HjL.js} +1 -1
  68. package/core/built/admin/assets/{automations-Bx3VcFIL.js → automations-dtQ_MRZ7.js} +1 -1
  69. package/core/built/admin/assets/{bluesky-sharing-ClMd0-Ft.js → bluesky-sharing-B8Es3AuV.js} +1 -1
  70. package/core/built/admin/assets/{box-BWbhXh21.js → box-By_EgGtm.js} +1 -1
  71. package/core/built/admin/assets/brand-icon-09YqFZjV.js +1 -0
  72. package/core/built/admin/assets/{breadcrumb-BD0U2ygg.js → breadcrumb-tg5zL--z.js} +1 -1
  73. package/core/built/admin/assets/build-CsiH26uS.js +1 -0
  74. package/core/built/admin/assets/{card-DGoDJzrn.js → card-aUHX0hyR.js} +1 -1
  75. package/core/built/admin/assets/{chart-BuRT2Y6p.js → chart-BnXyfH11.js} +1 -1
  76. package/core/built/admin/assets/{chart-helpers-fjQKRVyY.js → chart-helpers-CZElTGYL.js} +1 -1
  77. package/core/built/admin/assets/checkbox-Cyo-x7mC.js +1 -0
  78. package/core/built/admin/assets/chunk.524.cd5498dd4e195f679266.js +25 -0
  79. package/core/built/admin/assets/chunk.582.6f92ec1f03734bf2ea3f.js +27 -0
  80. package/core/built/admin/assets/{chunk.481.6c7395a49484bb4583aa.js → chunk.873.b8fc05a8ab877fb819ed.js} +62 -60
  81. package/core/built/admin/assets/code-editor-view-Dq1rQ4tS.js +1 -0
  82. package/core/built/admin/assets/color-picker-field-BonBgxhU.js +1 -0
  83. package/core/built/admin/assets/color-utils-BsrwXuDz.js +1 -0
  84. package/core/built/admin/assets/combobox-uX5r_paI.js +1 -0
  85. package/core/built/admin/assets/command-DxwBO2pF.js +1 -0
  86. package/core/built/admin/assets/comments-Dn-RO-nU.js +1 -0
  87. package/core/built/admin/assets/components-CwL6a6As-B0E0-NBJ.js +1 -0
  88. package/core/built/admin/assets/confirmation-modal-B6D6mk6R.js +1 -0
  89. package/core/built/admin/assets/{container-BYz2Ed39.js → container-LiZf3XdY.js} +1 -1
  90. package/core/built/admin/assets/content-api-modal-BxQ-7T6u.js +1 -0
  91. package/core/built/admin/assets/copy-field-BAxL4Zqn.js +1 -0
  92. package/core/built/admin/assets/currency-Dy4Tc2R2.js +1 -0
  93. package/core/built/admin/assets/custom-integration-modal---d_l7lc.js +1 -0
  94. package/core/built/admin/assets/{data-list-16rkJYYi.js → data-list-CupF7bjM.js} +1 -1
  95. package/core/built/admin/assets/{date-range-select-BFp58EMk.js → date-range-select-PB2n1HZf.js} +1 -1
  96. package/core/built/admin/assets/debounce-Dg2fW5Rg.js +3 -0
  97. package/core/built/admin/assets/design-and-theme-modal-DYRT207a.js +23 -0
  98. package/core/built/admin/assets/dirty-confirm-dialog-BnDJ39ao.js +1 -0
  99. package/core/built/admin/assets/disabled-sources-indicator-iMHrkyV3.js +1 -0
  100. package/core/built/admin/assets/dist-B2PvRwLn.js +1 -0
  101. package/core/built/admin/assets/{dist-DGzPJ_bO.js → dist-Cb5RSHSg.js} +1 -1
  102. package/core/built/admin/assets/{dist-P_ohUlTi.js → dist-CqO2lWS02.js} +1 -1
  103. package/core/built/admin/assets/{dist-pHiOxyxa.js → dist-D5vhMdXf.js} +1 -1
  104. package/core/built/admin/assets/dist-DlCyLrOC.js +1 -0
  105. package/core/built/admin/assets/dist-WeOIvSYM.js +23 -0
  106. package/core/built/admin/assets/{dist-DyViJwIy.js → dist-cFzKLG7y.js} +3 -3
  107. package/core/built/admin/assets/dist-j1xxxnY8.js +1 -0
  108. package/core/built/admin/assets/dist-myQaY0ka.js +1 -0
  109. package/core/built/admin/assets/domain-BR8FIdjD.js +1 -0
  110. package/core/built/admin/assets/{dropzone-DlK-K2DQ.js → dropzone-hNxmUvwD.js} +1 -1
  111. package/core/built/admin/assets/{edit-profile-BKT-REJw.js → edit-profile-CENrkY0l.js} +1 -1
  112. package/core/built/admin/assets/editor-B18D0lm8.js +8 -0
  113. package/core/built/admin/assets/embed-signup-form-modal-BsCYUMvQ.js +9 -0
  114. package/core/built/admin/assets/{empty-indicator-oX1u1Pkn.js → empty-indicator-WB1WgT9h.js} +1 -1
  115. package/core/built/admin/assets/{explore-ClUpJZOp.js → explore-BmrnljWw.js} +1 -1
  116. package/core/built/admin/assets/{feed-DF92dUMP.js → feed-Dy4li6i8.js} +1 -1
  117. package/core/built/admin/assets/{field-Do7lieBA.js → field-Dh_lwk13.js} +1 -1
  118. package/core/built/admin/assets/filter-sources-D2zDuJH5.js +1 -0
  119. package/core/built/admin/assets/filters-3JBQcNtJ.js +1 -0
  120. package/core/built/admin/assets/filters-CFt_BDe4.js +1 -0
  121. package/core/built/admin/assets/first-promoter-modal-D6Rjxugw.js +1 -0
  122. package/core/built/admin/assets/format-url-C-t8G6Qd.js +1 -0
  123. package/core/built/admin/assets/{ghost-a9c788f6f0b1ea6cf0f14ca4b13f4496.css → ghost-d38c30b866e59f2e06a357b5eb844fe5.css} +1 -1
  124. package/core/built/admin/assets/{ghost-c4057474943effc568c5659ccc4909d7.js → ghost-d683fbeb945b13155ea669caa5d8db41.js} +420 -398
  125. package/core/built/admin/assets/{ghost-dark-db36d795d21c61426837df40af270966.css → ghost-dark-1bffd5099ba7a749303133efacf8480b.css} +1 -1
  126. package/core/built/admin/assets/{gift-link-modal-f9VIMNDv.js → gift-link-modal-zMtlJhLQ.js} +1 -1
  127. package/core/built/admin/assets/{gift-links-CsUhefWG.js → gift-links-CVuqLhsZ.js} +1 -1
  128. package/core/built/admin/assets/global-data-provider-B949LDXJ.js +1 -0
  129. package/core/built/admin/assets/grid-CUciBfjf.js +1 -0
  130. package/core/built/admin/assets/{growth-CVw1My4S.js → growth-C38Xtp8D.js} +2 -2
  131. package/core/built/admin/assets/{growth-B3I6gNLm.js → growth-CFws67_i.js} +1 -1
  132. package/core/built/admin/assets/history-modal-ILAOkbxH.js +1 -0
  133. package/core/built/admin/assets/{hooks-CixO01lL.js → hooks-D6EE7BIt.js} +2 -2
  134. package/core/built/admin/assets/html-field-9a9Id_2q.js +1 -0
  135. package/core/built/admin/assets/iframe-buffering-e8vH4-Qn.js +1 -0
  136. package/core/built/admin/assets/images-CrQKVc9Q.js +1 -0
  137. package/core/built/admin/assets/{inbox-CFBSu4Ed.js → inbox-BrSRzyvz.js} +6 -6
  138. package/core/built/admin/assets/index-BHy2DZX-.js +67 -0
  139. package/core/built/admin/assets/index-Ds2iUoF6.css +1 -0
  140. package/core/built/admin/assets/index.es-B9tvf-t4.js +1 -0
  141. package/core/built/admin/assets/{inline-EMAm3okk.js → inline-Cw-gigDW.js} +1 -1
  142. package/core/built/admin/assets/input-group-6vEPvX9S.js +1 -0
  143. package/core/built/admin/assets/{input-surface-BpAjZXY5.js → input-surface-BdOe4KzO.js} +1 -1
  144. package/core/built/admin/assets/integration-header-B4DyXV06.js +1 -0
  145. package/core/built/admin/assets/integrations-BT6_iJvu.js +1 -0
  146. package/core/built/admin/assets/invite-user-modal-5xDCEw90.js +1 -0
  147. package/core/built/admin/assets/isEmail-BOfC647y.js +1 -0
  148. package/core/built/admin/assets/koenig-editor-base-BWLEB9Vf.js +1 -0
  149. package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +9535 -9527
  150. package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +124 -124
  151. package/core/built/admin/assets/{koenig-lexical-f8vHRYvz.js → koenig-lexical-Cj62r_y9.js} +86 -86
  152. package/core/built/admin/assets/{kpi-card-DSap9rAy.js → kpi-card-DOUnkZcN.js} +1 -1
  153. package/core/built/admin/assets/{kpi-card-DU0rn9Cj.js → kpi-card-IHDo8Q56.js} +1 -1
  154. package/core/built/admin/assets/{kpi-helpers-Dz33AV6h.js → kpi-helpers-CjUdECAK.js} +1 -1
  155. package/core/built/admin/assets/{kpi-tabs-BtTTrKvJ.js → kpi-tabs-X3DkOYbI.js} +1 -1
  156. package/core/built/admin/assets/{label-DS8Mi6G5.js → label-Dq6QaOuS.js} +1 -1
  157. package/core/built/admin/assets/label-picker-8YlhS2U3.js +1 -0
  158. package/core/built/admin/assets/labels-DAPjKPy2.js +1 -0
  159. package/core/built/admin/assets/layout-TMj4P-vv.js +1 -0
  160. package/core/built/admin/assets/limit-modal-BRPsit_B.js +1 -0
  161. package/core/built/admin/assets/link-helpers-Bzkk68GD.js +1 -0
  162. package/core/built/admin/assets/{list-page-B6ANtzkd.js → list-page-CdsnQR9N.js} +1 -1
  163. package/core/built/admin/assets/member-custom-fields-CmvsuuV_.js +1 -0
  164. package/core/built/admin/assets/member-detail-DCvRrkmJ.js +1 -0
  165. package/core/built/admin/assets/members-DxbSKngD.js +11 -0
  166. package/core/built/admin/assets/modal-page-BMTzFHVO.js +1 -0
  167. package/core/built/admin/assets/{moderation-DySbgyUS.js → moderation-Da5lhhWh.js} +1 -1
  168. package/core/built/admin/assets/multi-select-combobox-CYdkH7KQ.js +1 -0
  169. package/core/built/admin/assets/navigation-modal-BIoTwtMy.js +1 -0
  170. package/core/built/admin/assets/newsletter-BptlVoJm.js +1 -0
  171. package/core/built/admin/assets/newsletter-detail-modal-BIvxqE0N.js +1 -0
  172. package/core/built/admin/assets/newsletter-emails-Bf8IZLsP.js +1 -0
  173. package/core/built/admin/assets/newsletters-BgrIZk0V.js +1 -0
  174. package/core/built/admin/assets/{newsletters-BXJbJgA-.js → newsletters-Du0lzskS.js} +1 -1
  175. package/core/built/admin/assets/{note-C8kxrz6w.js → note-DYcLOmDb.js} +1 -1
  176. package/core/built/admin/assets/{notifications-CgtSfX7t.js → notifications-B2SPFIV9.js} +1 -1
  177. package/core/built/admin/assets/{offers-DEniVRD5.js → offers-Um6ab71O.js} +1 -1
  178. package/core/built/admin/assets/offers-container-modal-BZnZITMw.js +1 -0
  179. package/core/built/admin/assets/{onboarding-route-4qtziA9d.js → onboarding-route-DgdfxkQh.js} +1 -1
  180. package/core/built/admin/assets/overview-BYQJXSog.js +1 -0
  181. package/core/built/admin/assets/overview-Dt2_mR6U.js +1 -0
  182. package/core/built/admin/assets/{page-header-B3Wb9Jqv.js → page-header-CpmxJj5B.js} +1 -1
  183. package/core/built/admin/assets/{pages-B4goRPUn.js → pages-BVMnpI2O.js} +1 -1
  184. package/core/built/admin/assets/pintura-modal-B4MuBuuO.js +1 -0
  185. package/core/built/admin/assets/portal-frame-BF0NBIji.js +1 -0
  186. package/core/built/admin/assets/portal-modal-DMVbm0oy.js +1 -0
  187. package/core/built/admin/assets/{post-analytics-We-ko5Cb.js → post-analytics-CXWBOGyP.js} +1 -1
  188. package/core/built/admin/assets/post-analytics-header-ChzjXVPt.js +1 -0
  189. package/core/built/admin/assets/{post-analytics-provider-B6UynTGb.js → post-analytics-provider-Cgw4U_fw.js} +1 -1
  190. package/core/built/admin/assets/{post-share-modal-DFfO93_0.js → post-share-modal-B9Vmk_XM.js} +1 -1
  191. package/core/built/admin/assets/{posts-DhXE7b6r.js → posts-CxG7v0-M.js} +1 -1
  192. package/core/built/admin/assets/preferences-BfzJmnsd.js +5 -0
  193. package/core/built/admin/assets/preview-chrome-BOVO6_PE.js +1 -0
  194. package/core/built/admin/assets/preview-modal-Dw_HtD6S.js +1 -0
  195. package/core/built/admin/assets/profile-BT5vtv9b.js +1 -0
  196. package/core/built/admin/assets/radio-group-I7ou7PoJ.js +1 -0
  197. package/core/built/admin/assets/{referrers-pmJT4k3-.js → referrers-B9QDAfYm.js} +1 -1
  198. package/core/built/admin/assets/{router-provider-C1R4AZ2o.js → router-provider-DSQfprxH.js} +1 -1
  199. package/core/built/admin/assets/select-D9oU1IoM.js +1 -0
  200. package/core/built/admin/assets/settings-CfZFbyu_.js +4 -0
  201. package/core/built/admin/assets/{settings-WXNeWyU1.js → settings-CpvHWix7.js} +1 -1
  202. package/core/built/admin/assets/settings-breadcrumbs-K0USP2nw.js +1 -0
  203. package/core/built/admin/assets/{shade-app-B3heOAfz-CGXQwWeO.js → shade-app-B3heOAfz-BhQXxNkT.js} +1 -1
  204. package/core/built/admin/assets/{share-modal-DsgW3wbg.js → share-modal-ClIyPzc5.js} +1 -1
  205. package/core/built/admin/assets/slack-modal-1XXqOfiw.js +1 -0
  206. package/core/built/admin/assets/social-urls-CHQ9cTAK.js +1 -0
  207. package/core/built/admin/assets/{sort-button-Bb_FCl7e.js → sort-button-CdBsm40v.js} +1 -1
  208. package/core/built/admin/assets/{source-icon-BeaRxUn9.js → source-icon-CEYmVLXR.js} +1 -1
  209. package/core/built/admin/assets/{stack-xiN0eQ6Z.js → stack-CIfOAAVf.js} +1 -1
  210. package/core/built/admin/assets/{stats-Bjj_kmJ1.js → stats-D8nZCTy5.js} +1 -1
  211. package/core/built/admin/assets/{stats-view-BxPbW6K1.js → stats-view-CugFVf0g.js} +1 -1
  212. package/core/built/admin/assets/{step-1-B1e3-1F8.js → step-1-DOYjrORn.js} +1 -1
  213. package/core/built/admin/assets/{step-2-C5WaeBJo.js → step-2-vA6RsarH.js} +1 -1
  214. package/core/built/admin/assets/{step-3-B46iVPwu.js → step-3-BtIBxMId.js} +2 -2
  215. package/core/built/admin/assets/stripe-button-UFP4QRXd.js +1 -0
  216. package/core/built/admin/assets/stripe-connect-modal-C_L3uM6n.js +1 -0
  217. package/core/built/admin/assets/switch-CE2NuMn-.js +1 -0
  218. package/core/built/admin/assets/{table-CB-4_HBJ.js → table-TMCgCQK7.js} +1 -1
  219. package/core/built/admin/assets/tabs-Dd6oOKbv.js +1 -0
  220. package/core/built/admin/assets/tag-detail-D3l-UJPR.js +1 -0
  221. package/core/built/admin/assets/tags-BwCgmr5v.js +1 -0
  222. package/core/built/admin/assets/tags-WdKQGWR8.js +1 -0
  223. package/core/built/admin/assets/testimonials-modal-CqWp-xXJ.js +1 -0
  224. package/core/built/admin/assets/{text-DwtjwGkh.js → text-DU9Hv33_.js} +1 -1
  225. package/core/built/admin/assets/textarea-d9qEkMOP.js +1 -0
  226. package/core/built/admin/assets/tier-detail-modal-BkcR2u0A.js +1 -0
  227. package/core/built/admin/assets/{tiers-DYsa4DCo.js → tiers-Da6kxHQP.js} +1 -1
  228. package/core/built/admin/assets/toggle-group-Guorw93z.js +1 -0
  229. package/core/built/admin/assets/{topic-filter-DAFT87tQ.js → topic-filter-CbgoWIHn.js} +1 -1
  230. package/core/built/admin/assets/transistor-modal-DuNnnpal.js +1 -0
  231. package/core/built/admin/assets/unsplash-modal-y2bVwTHH.js +1 -0
  232. package/core/built/admin/assets/{use-analytics-data-S0FTd43s.js → use-analytics-data-B-b4wNSC.js} +1 -1
  233. package/core/built/admin/assets/use-check-theme-limit-error-m09J38Mq.js +2 -0
  234. package/core/built/admin/assets/use-feature-flag-ud0Qz8vt.js +1 -0
  235. package/core/built/admin/assets/{use-filter-params-Gpoq2E1L.js → use-filter-params-BnbBDc7T.js} +1 -1
  236. package/core/built/admin/assets/use-filterable-api-iMpDZBxD.js +1 -0
  237. package/core/built/admin/assets/use-form-vRjI0Kwk.js +1 -0
  238. package/core/built/admin/assets/{use-growth-stats-CIaiHOVb.js → use-growth-stats-DPU5rt3W.js} +1 -1
  239. package/core/built/admin/assets/use-hash-link-navigation-guard-B9j6HIrV.js +1 -0
  240. package/core/built/admin/assets/use-limiter-BkN3E4gw.js +2 -0
  241. package/core/built/admin/assets/use-pintura-config-C_z8HTG2.js +1 -0
  242. package/core/built/admin/assets/use-pintura-editor-DNgbkhGp.js +1 -0
  243. package/core/built/admin/assets/{use-post-referrers-Cq2vBPrA.js → use-post-referrers-C2mXyrp-.js} +1 -1
  244. package/core/built/admin/assets/use-query-params-DHhhu8wi.js +1 -0
  245. package/core/built/admin/assets/{use-reply-chain-data-DBDRtGu-.js → use-reply-chain-data-DaK8q2qQ.js} +1 -1
  246. package/core/built/admin/assets/use-setting-group-YlYcoNyP.js +1 -0
  247. package/core/built/admin/assets/use-settings-navigation-Bf1g1rEh.js +1 -0
  248. package/core/built/admin/assets/{use-simple-pagination-CjYNxdwe.js → use-simple-pagination-D9ckKo5-.js} +1 -1
  249. package/core/built/admin/assets/{use-tinybird-query-falHAtuK.js → use-tinybird-query-GSa32hVw.js} +1 -1
  250. package/core/built/admin/assets/{use-tinybird-token-D7-8ND1y.js → use-tinybird-token-CKLOZFsw.js} +1 -1
  251. package/core/built/admin/assets/use-url-input-z-p0Kewm.js +5 -0
  252. package/core/built/admin/assets/user-detail-modal-BMxOA4Sv.js +1 -0
  253. package/core/built/admin/assets/{users-Dkv8NQZe.js → users-B6hIds6n.js} +1 -1
  254. package/core/built/admin/assets/validator-Cr0sMKuW.js +7 -0
  255. package/core/built/admin/assets/{virtual-list-CvnC9zF2.js → virtual-list-RHeEL05L.js} +1 -1
  256. package/core/built/admin/assets/{web-jFYWCKDn.js → web-Bw2QMO5u.js} +2 -2
  257. package/core/built/admin/assets/web-xJtcwMy4.js +1 -0
  258. package/core/built/admin/assets/zapier-modal-BP2f4-vY.js +1 -0
  259. package/core/built/admin/index.html +20 -18
  260. package/core/frontend/helpers/authors.js +1 -1
  261. package/core/frontend/helpers/link.js +3 -8
  262. package/core/frontend/helpers/tags.js +1 -1
  263. package/core/frontend/meta/author-url.js +2 -2
  264. package/core/frontend/meta/url.js +4 -4
  265. package/core/frontend/services/data/fetch-data.js +10 -5
  266. package/core/frontend/services/proxy.js +1 -1
  267. package/core/frontend/services/routing/api-adapter.js +115 -0
  268. package/core/frontend/services/routing/api-adapter.ts +157 -0
  269. package/core/frontend/services/routing/collection-router.js +5 -3
  270. package/core/frontend/services/routing/controllers/index.js +1 -1
  271. package/core/frontend/services/routing/controllers/rss.js +26 -31
  272. package/core/frontend/services/routing/controllers/rss.ts +66 -0
  273. package/core/frontend/services/routing/controllers/static.js +8 -7
  274. package/core/frontend/services/routing/events.js +20 -6
  275. package/core/frontend/services/routing/parent-router.js +17 -4
  276. package/core/frontend/services/routing/permalink-adapter.js +13 -0
  277. package/core/frontend/services/routing/permalink-adapter.ts +10 -0
  278. package/core/frontend/services/routing/registry.js +59 -33
  279. package/core/frontend/services/routing/router-manager.js +24 -22
  280. package/core/frontend/services/routing/static-routes-router.js +4 -4
  281. package/core/frontend/services/routing/taxonomy-router.js +6 -2
  282. package/core/frontend/services/sitemap/base-site-map-generator.js +1 -28
  283. package/core/frontend/services/sitemap/site-map-manager.js +22 -57
  284. package/core/server/adapters/route-settings/utils.js +10 -2
  285. package/core/server/adapters/route-settings/utils.ts +12 -2
  286. package/core/server/api/endpoints/email-post.js +1 -1
  287. package/core/server/api/endpoints/previews.js +1 -1
  288. package/core/server/api/endpoints/search-index-public.js +3 -3
  289. package/core/server/api/endpoints/search-index.js +4 -4
  290. package/core/server/api/endpoints/utils/serializers/input/authors.js +2 -2
  291. package/core/server/api/endpoints/utils/serializers/input/comments.js +1 -1
  292. package/core/server/api/endpoints/utils/serializers/input/pages.js +3 -3
  293. package/core/server/api/endpoints/utils/serializers/input/posts.js +3 -3
  294. package/core/server/api/endpoints/utils/serializers/input/tags.js +1 -1
  295. package/core/server/api/endpoints/utils/serializers/input/users.js +2 -2
  296. package/core/server/api/endpoints/utils/serializers/input/utils/url.js +31 -13
  297. package/core/server/api/endpoints/utils/serializers/output/mappers/posts.js +2 -2
  298. package/core/server/api/endpoints/utils/serializers/output/mappers/tags.js +2 -2
  299. package/core/server/api/endpoints/utils/serializers/output/mappers/users.js +8 -0
  300. package/core/server/api/endpoints/utils/serializers/output/utils/url.js +18 -11
  301. package/core/server/data/migrations/versions/6.56/2026-08-03-19-27-51-add-automation-run-step-id-to-automated-email-recipients.js +8 -0
  302. package/core/server/data/migrations/versions/6.56/2026-08-04-14-42-39-restrict-notification-add-permission-to-administrators.js +12 -0
  303. package/core/server/data/migrations/versions/6.57/2026-08-04-18-00-00-store-custom-field-values-as-leaf-rows.js +74 -0
  304. package/core/server/data/migrations/versions/6.57/2026-08-04-18-54-14-reset-automation-email-analytics.js +25 -0
  305. package/core/server/data/schema/commands.js +21 -5
  306. package/core/server/data/schema/fixtures/fixtures.json +2 -2
  307. package/core/server/data/schema/schema.js +25 -5
  308. package/core/server/lib/common/to-plain.ts +1 -1
  309. package/core/server/models/post.js +12 -3
  310. package/core/server/services/adapter-manager/adapter-manager.js +1 -45
  311. package/core/server/services/adapter-manager/adapter-manager.ts +2 -48
  312. package/core/server/services/adapter-manager/adapter-paths.js +24 -0
  313. package/core/server/services/adapter-manager/adapter-paths.ts +21 -0
  314. package/core/server/services/adapter-manager/base-classes.js +22 -0
  315. package/core/server/services/adapter-manager/base-classes.ts +22 -0
  316. package/core/server/services/adapter-manager/index.js +4 -27
  317. package/core/server/services/adapter-manager/index.ts +4 -31
  318. package/core/server/services/adapter-manager/utils.js +50 -0
  319. package/core/server/services/adapter-manager/utils.ts +57 -0
  320. package/core/server/services/audience-feedback/audience-feedback-controller.js +1 -1
  321. package/core/server/services/audience-feedback/audience-feedback-service.js +2 -2
  322. package/core/server/services/automations/automations-repository.ts +3 -1
  323. package/core/server/services/automations/database-automations-repository.js +33 -14
  324. package/core/server/services/automations/database-automations-repository.ts +41 -15
  325. package/core/server/services/automations/get-scheduler-idempotency-key.js +13 -0
  326. package/core/server/services/automations/get-scheduler-idempotency-key.ts +8 -0
  327. package/core/server/services/automations/poll.js +3 -1
  328. package/core/server/services/automations/poll.ts +4 -1
  329. package/core/server/services/automations/service.js +7 -3
  330. package/core/server/services/automations/service.ts +7 -3
  331. package/core/server/services/comments/comments-service-emails.js +1 -1
  332. package/core/server/services/comments/comments-service.js +1 -1
  333. package/core/server/services/email-analytics/email-analytics-service-wrapper.js +11 -2
  334. package/core/server/services/email-analytics/email-analytics-service.js +1 -1
  335. package/core/server/services/email-service/email-service-wrapper.js +2 -1
  336. package/core/server/services/email-service/mailgun-email-provider.js +15 -0
  337. package/core/server/services/gift-links/CONTEXT.md +9 -0
  338. package/core/server/services/gifts/CONTEXT.md +55 -0
  339. package/core/server/services/gifts/README.md +28 -0
  340. package/core/server/services/gifts/gift-bookshelf-repository.js +65 -45
  341. package/core/server/services/gifts/gift-bookshelf-repository.ts +203 -74
  342. package/core/server/services/gifts/gift-checkout-adapter.js +59 -0
  343. package/core/server/services/gifts/gift-checkout-offer.js +74 -0
  344. package/core/server/services/gifts/gift-checkout-offer.ts +127 -0
  345. package/core/server/services/gifts/gift-codec.js +63 -0
  346. package/core/server/services/gifts/gift-codec.ts +62 -0
  347. package/core/server/services/gifts/gift-controller.js +6 -31
  348. package/core/server/services/gifts/gift-controller.ts +6 -69
  349. package/core/server/services/gifts/gift-email-service.ts +3 -2
  350. package/core/server/services/gifts/gift-schema.js +34 -0
  351. package/core/server/services/gifts/gift-schema.ts +39 -0
  352. package/core/server/services/gifts/gift-service-wrapper.js +13 -11
  353. package/core/server/services/gifts/gift-service.js +265 -52
  354. package/core/server/services/gifts/gift-service.ts +431 -97
  355. package/core/server/services/gifts/gift.ts +16 -39
  356. package/core/server/services/indexnow-ping/indexnow-ping-service.js +1 -1
  357. package/core/server/services/indexnow-ping/indexnow-ping-service.ts +2 -4
  358. package/core/server/services/lib/mailgun-client.js +3 -3
  359. package/core/server/services/link-tracking/link-click-repository.js +6 -1
  360. package/core/server/services/link-tracking/link-click-tracking-service.js +12 -3
  361. package/core/server/services/media-inliner/external-media-inliner.js +12 -8
  362. package/core/server/services/member-attribution/url-translator.js +5 -7
  363. package/core/server/services/member-welcome-emails/member-welcome-email-renderer.js +4 -3
  364. package/core/server/services/member-welcome-emails/service.js +79 -15
  365. package/core/server/services/members/api.js +2 -3
  366. package/core/server/services/members/import-export/import/completion-email.js +8 -4
  367. package/core/server/services/members/import-export/import/completion-email.ts +9 -4
  368. package/core/server/services/members/import-export/import/importer.js +25 -4
  369. package/core/server/services/members/import-export/import/importer.ts +27 -6
  370. package/core/server/services/members/import-export/import/row.ts +5 -1
  371. package/core/server/services/members/import-export/index.js +6 -2
  372. package/core/server/services/members/import-export/index.ts +10 -4
  373. package/core/server/services/members/members-api/controllers/router-controller.js +38 -36
  374. package/core/server/services/members/members-api/members-api.js +13 -7
  375. package/core/server/services/members/members-api/repositories/event-repository.js +4 -94
  376. package/core/server/services/members/members-api/services/member-bread-service.js +3 -3
  377. package/core/server/services/members/members-api/services/payments-service.js +6 -68
  378. package/core/server/services/members-custom-fields/queries.js +4 -13
  379. package/core/server/services/members-custom-fields/queries.ts +4 -13
  380. package/core/server/services/members-custom-fields/schema.js +19 -21
  381. package/core/server/services/members-custom-fields/schema.ts +18 -20
  382. package/core/server/services/members-custom-fields/storage.js +94 -27
  383. package/core/server/services/members-custom-fields/storage.ts +114 -39
  384. package/core/server/services/members-custom-fields/values-service.js +98 -103
  385. package/core/server/services/members-custom-fields/values-service.ts +116 -114
  386. package/core/server/services/mentions/resource-service.js +1 -1
  387. package/core/server/services/mentions/service.js +2 -2
  388. package/core/server/services/oembed/oembed-service.js +44 -3
  389. package/core/server/services/posts/posts-service.js +11 -0
  390. package/core/server/services/route-settings/dynamic-routing-service.js +10 -62
  391. package/core/server/services/route-settings/route-settings-parser.js +25 -25
  392. package/core/server/services/route-settings/route-settings-parser.ts +27 -27
  393. package/core/server/services/route-settings/validation-errors.js +68 -4
  394. package/core/server/services/route-settings/validation-errors.ts +79 -4
  395. package/core/server/services/slack-ping/slack-ping-service.js +2 -2
  396. package/core/server/services/slack-ping/slack-ping-service.ts +3 -5
  397. package/core/server/services/stats/content-stats-service.js +3 -3
  398. package/core/server/services/stats/posts-stats-service.js +29 -25
  399. package/core/server/services/stripe/services/webhook/charge-refunded-event-service.js +1 -1
  400. package/core/server/services/stripe/services/webhook/checkout-session-event-service.js +16 -4
  401. package/core/server/services/stripe/stripe-api.js +10 -0
  402. package/core/server/services/url/config.js +90 -135
  403. package/core/server/services/url/index.js +6 -49
  404. package/core/server/services/url/lazy-find-resource.js +14 -11
  405. package/core/server/services/url/lazy-find-resource.ts +14 -11
  406. package/core/server/services/url/lazy-url-service.js +174 -94
  407. package/core/server/services/url/lazy-url-service.ts +233 -97
  408. package/core/server/services/url/routable-resources.js +62 -71
  409. package/core/server/services/url/router-filter.js +12 -4
  410. package/core/server/services/url/router-filter.ts +12 -4
  411. package/core/server/services/webhooks/index.js +1 -1
  412. package/core/server/services/webhooks/serialize.js +2 -1
  413. package/core/server/web/gift-preview/controller.js +10 -25
  414. package/core/shared/config/env/config.testing-mysql.json +1 -2
  415. package/core/shared/config/env/config.testing.json +1 -2
  416. package/core/shared/events/index.js +1 -2
  417. package/core/shared/labs.js +4 -4
  418. package/package.json +10 -10
  419. package/pnpm-lock.yaml +27 -20
  420. package/pnpm-workspace.yaml +3 -2
  421. package/tsconfig.json +1 -0
  422. package/components/tryghost-kg-default-nodes-2.1.3.tgz +0 -0
  423. package/core/built/admin/assets/Combination-CJG7Flp-.js +0 -41
  424. package/core/built/admin/assets/activitypub/layout-qx-bUL1k.js +0 -1
  425. package/core/built/admin/assets/automated-emails-DRy7qY-J.js +0 -7
  426. package/core/built/admin/assets/checkbox-CWa28lgO.js +0 -1
  427. package/core/built/admin/assets/chunk.524.cffd399783a519e404a9.js +0 -25
  428. package/core/built/admin/assets/chunk.582.eebf0d0b2d202bb746a5.js +0 -27
  429. package/core/built/admin/assets/code-editor-view-CCr0rBWS.js +0 -1
  430. package/core/built/admin/assets/comments-DyUSMUdj.js +0 -1
  431. package/core/built/admin/assets/disabled-sources-indicator-CUxMfiPa.js +0 -1
  432. package/core/built/admin/assets/dist-2Tnz2Yfq.js +0 -1
  433. package/core/built/admin/assets/dist-CjY-f5Z1.js +0 -1
  434. package/core/built/admin/assets/dist-DDY6GRVz.js +0 -1
  435. package/core/built/admin/assets/dist-DG78yroX.js +0 -23
  436. package/core/built/admin/assets/domain-C0bV2UV8.js +0 -1
  437. package/core/built/admin/assets/editor-Dp865O-4.js +0 -8
  438. package/core/built/admin/assets/esm-CFX93H5M.js +0 -2
  439. package/core/built/admin/assets/filter-sources-BV2rnpfA.js +0 -1
  440. package/core/built/admin/assets/filters-CUXJ2Nm9.js +0 -1
  441. package/core/built/admin/assets/filters-DfbIWc_l.js +0 -1
  442. package/core/built/admin/assets/index-9Cw8z3rA.css +0 -1
  443. package/core/built/admin/assets/index-BGG7NckO.js +0 -67
  444. package/core/built/admin/assets/input-group-BSgG_lVw.js +0 -1
  445. package/core/built/admin/assets/label-picker-1DvSuLA1.js +0 -1
  446. package/core/built/admin/assets/labels-CDSUt4J_.js +0 -1
  447. package/core/built/admin/assets/layout-yQEi2qDM.js +0 -1
  448. package/core/built/admin/assets/link-helpers-7EYqvvHs.js +0 -1
  449. package/core/built/admin/assets/member-custom-fields-yOMHyAg9.js +0 -1
  450. package/core/built/admin/assets/member-detail-BAq7gDaa.js +0 -1
  451. package/core/built/admin/assets/members-CQpVFJu4.js +0 -10
  452. package/core/built/admin/assets/modals-ReORvWnu.js +0 -31
  453. package/core/built/admin/assets/newsletter-CJQvtHqN.js +0 -1
  454. package/core/built/admin/assets/newsletters-B3QQXfGT.js +0 -1
  455. package/core/built/admin/assets/nql-BsgFMd93.js +0 -1
  456. package/core/built/admin/assets/overview-Bf2sbznq.js +0 -1
  457. package/core/built/admin/assets/overview-CBfePxcr.js +0 -1
  458. package/core/built/admin/assets/post-analytics-header-Bmc9su6q.js +0 -1
  459. package/core/built/admin/assets/preferences-DJPfHEGu.js +0 -5
  460. package/core/built/admin/assets/profile-DqBQp-gT.js +0 -1
  461. package/core/built/admin/assets/select-C5_xEt5b.js +0 -1
  462. package/core/built/admin/assets/settings-BwiVIXau.js +0 -4
  463. package/core/built/admin/assets/social-urls-BQPFEk1_.js +0 -8
  464. package/core/built/admin/assets/switch-z5Y6Uzt6.js +0 -1
  465. package/core/built/admin/assets/tabs-CCEgKYzq.js +0 -1
  466. package/core/built/admin/assets/tags-Cg2VJGmG.js +0 -1
  467. package/core/built/admin/assets/textarea-Bjccvh_E.js +0 -1
  468. package/core/built/admin/assets/toggle-group-b3IlxvhV.js +0 -1
  469. package/core/built/admin/assets/web-B_5GZRvH.js +0 -1
  470. package/core/server/services/gifts/gift-repository.js +0 -2
  471. package/core/server/services/gifts/gift-repository.ts +0 -29
  472. package/core/server/services/route-settings/activation-bridge.js +0 -174
  473. package/core/server/services/route-settings/activation-bridge.ts +0 -250
  474. package/core/server/services/url/local-file-cache.js +0 -75
  475. package/core/server/services/url/queue.js +0 -260
  476. package/core/server/services/url/resource.js +0 -102
  477. package/core/server/services/url/resources.js +0 -480
  478. package/core/server/services/url/url-generator.js +0 -276
  479. package/core/server/services/url/url-service-facade.js +0 -366
  480. package/core/server/services/url/url-service-facade.ts +0 -519
  481. package/core/server/services/url/url-service.js +0 -387
  482. package/core/server/services/url/urls.js +0 -140
  483. package/core/shared/events/url-resource-updated-event.js +0 -33
@@ -222,8 +222,8 @@ class PostsStatsService {
222
222
  if (this.urlService && row.attribution_url) {
223
223
  try {
224
224
  // Check if URL service is ready
225
- if (this.urlService.facade.hasFinished && this.urlService.facade.hasFinished()) {
226
- const resource = await this.urlService.facade.resolveUrl(row.attribution_url);
225
+ if (this.urlService.hasFinished && this.urlService.hasFinished()) {
226
+ const resource = await this.urlService.resolveUrl(row.attribution_url);
227
227
  urlExists = !!resource; // Convert to boolean
228
228
  }
229
229
  // If URL service isn't ready, we default to true (clickable)
@@ -399,29 +399,33 @@ class PostsStatsService {
399
399
 
400
400
  async getGrowthStatsForPost(postId) {
401
401
  try {
402
- const freeMembers = await this.knex('members_created_events as mce')
403
- .countDistinct('mce.member_id as free_members')
404
- .leftJoin('members_subscription_created_events as msce', function () {
405
- this.on('mce.member_id', '=', 'msce.member_id')
406
- .andOn('mce.attribution_id', '=', 'msce.attribution_id');
407
- })
408
- .where('mce.attribution_id', postId)
409
- .whereIn('mce.attribution_type', ['post', 'page'])
410
- .where('msce.id', null);
411
-
412
- const paidMembers = await this.knex('members_subscription_created_events as msce')
413
- .countDistinct('msce.member_id as paid_members')
414
- .where('msce.attribution_id', postId)
415
- .whereIn('msce.attribution_type', ['post', 'page']);
416
-
417
- const mrr = await this.knex('members_subscription_created_events as msce')
418
- .sum('mpse.mrr_delta as mrr')
419
- .join('members_paid_subscription_events as mpse', function () {
420
- this.on('mpse.subscription_id', '=', 'msce.subscription_id');
421
- this.andOn('mpse.member_id', '=', 'msce.member_id');
422
- })
423
- .where('msce.attribution_id', postId)
424
- .whereIn('msce.attribution_type', ['post', 'page']);
402
+ // The three aggregates only depend on postId, so run them together:
403
+ // the wait becomes the slowest query instead of the sum of all three.
404
+ const [freeMembers, paidMembers, mrr] = await Promise.all([
405
+ this.knex('members_created_events as mce')
406
+ .countDistinct('mce.member_id as free_members')
407
+ .leftJoin('members_subscription_created_events as msce', function () {
408
+ this.on('mce.member_id', '=', 'msce.member_id')
409
+ .andOn('mce.attribution_id', '=', 'msce.attribution_id');
410
+ })
411
+ .where('mce.attribution_id', postId)
412
+ .whereIn('mce.attribution_type', ['post', 'page'])
413
+ .where('msce.id', null),
414
+
415
+ this.knex('members_subscription_created_events as msce')
416
+ .countDistinct('msce.member_id as paid_members')
417
+ .where('msce.attribution_id', postId)
418
+ .whereIn('msce.attribution_type', ['post', 'page']),
419
+
420
+ this.knex('members_subscription_created_events as msce')
421
+ .sum('mpse.mrr_delta as mrr')
422
+ .join('members_paid_subscription_events as mpse', function () {
423
+ this.on('mpse.subscription_id', '=', 'msce.subscription_id');
424
+ this.andOn('mpse.member_id', '=', 'msce.member_id');
425
+ })
426
+ .where('msce.attribution_id', postId)
427
+ .whereIn('msce.attribution_type', ['post', 'page'])
428
+ ]);
425
429
 
426
430
  return {
427
431
  data: [
@@ -50,7 +50,7 @@ module.exports = class ChargeRefundedEventService {
50
50
  * @private
51
51
  */
52
52
  async handleGiftRefundEvent(paymentIntentId) {
53
- const refunded = await this.deps.giftService.refund(paymentIntentId);
53
+ const refunded = await this.deps.giftService.handlePaymentRefund({paymentIntentId});
54
54
 
55
55
  if (!refunded) {
56
56
  logging.info(`charge.refunded: no gift found for payment_intent ${paymentIntentId}, skipping`);
@@ -18,6 +18,18 @@ function hasConflictingCheckoutFlowMetadata(metadata) {
18
18
  return hasStripeMetadataKey(metadata, 'ghost_donation') && hasStripeMetadataKey(metadata, 'ghost_gift');
19
19
  }
20
20
 
21
+ function getStripeResourceId(resource) {
22
+ if (typeof resource === 'string') {
23
+ return resource;
24
+ }
25
+
26
+ if (resource && typeof resource === 'object' && typeof resource.id === 'string') {
27
+ return resource.id;
28
+ }
29
+
30
+ return null;
31
+ }
32
+
21
33
  /**
22
34
  * Handles `checkout.session.completed` webhook events
23
35
  *
@@ -83,17 +95,17 @@ module.exports = class CheckoutSessionEventService {
83
95
  * @param {import('stripe').Stripe.Checkout.Session} session
84
96
  */
85
97
  async handleGiftEvent(session) {
86
- await this.deps.giftService.recordPurchase({
98
+ await this.deps.giftService.completePurchase({
87
99
  token: session.metadata?.gift_token,
88
100
  buyerEmail: session.customer_details?.email,
89
- stripeCustomerId: session.customer ?? null,
101
+ stripeCustomerId: getStripeResourceId(session.customer),
90
102
  tierId: session.metadata?.tier_id,
91
103
  cadence: session.metadata?.cadence,
92
- duration: session.metadata?.duration,
104
+ duration: Number(session.metadata?.duration),
93
105
  currency: session.currency,
94
106
  amount: session.amount_total,
95
107
  stripeCheckoutSessionId: session.id,
96
- stripePaymentIntentId: session.payment_intent
108
+ stripePaymentIntentId: getStripeResourceId(session.payment_intent)
97
109
  });
98
110
  }
99
111
 
@@ -23,6 +23,12 @@ const SEARCH_MODE_RATE_LIMIT = isTesting ? 10_000 : 100;
23
23
 
24
24
  const STRIPE_API_VERSION = '2020-08-27';
25
25
 
26
+ // Stripe's Managed Payments does not support Connect, and some Stripe
27
+ // accounts have it enabled by default for all Checkout Sessions.
28
+ // On those accounts, session creation fails with "Managed Payments cannot be
29
+ // used with Connect" unless it is explicitly disabled per session.
30
+ const MANAGED_PAYMENTS_DISABLED = {enabled: false};
31
+
26
32
  /**
27
33
  * @typedef {import('stripe').Stripe.Customer} ICustomer
28
34
  * @typedef {import('stripe').Stripe.DeletedCustomer} IDeletedCustomer
@@ -584,6 +590,7 @@ module.exports = class StripeAPI {
584
590
 
585
591
  let stripeSessionOptions = {
586
592
  payment_method_types: this.PAYMENT_METHOD_TYPES,
593
+ managed_payments: MANAGED_PAYMENTS_DISABLED,
587
594
  success_url: options.successUrl || this._config.checkoutSessionSuccessUrl,
588
595
  cancel_url: options.cancelUrl || this._config.checkoutSessionCancelUrl,
589
596
  // @ts-ignore - we need to update to latest stripe library to correctly use newer features
@@ -649,6 +656,7 @@ module.exports = class StripeAPI {
649
656
 
650
657
  const stripeSessionOptions = {
651
658
  mode: 'payment',
659
+ managed_payments: MANAGED_PAYMENTS_DISABLED,
652
660
  success_url: successUrl || this._config.checkoutSessionSuccessUrl,
653
661
  cancel_url: cancelUrl || this._config.checkoutSessionCancelUrl,
654
662
  automatic_tax: {
@@ -715,6 +723,7 @@ module.exports = class StripeAPI {
715
723
 
716
724
  const stripeSessionOptions = {
717
725
  mode: 'payment',
726
+ managed_payments: MANAGED_PAYMENTS_DISABLED,
718
727
  success_url: successUrl,
719
728
  cancel_url: cancelUrl,
720
729
  automatic_tax: {
@@ -761,6 +770,7 @@ module.exports = class StripeAPI {
761
770
  await this._rateLimitBucket.throttle();
762
771
  const session = await this._stripe.checkout.sessions.create({
763
772
  mode: 'setup',
773
+ managed_payments: MANAGED_PAYMENTS_DISABLED,
764
774
  payment_method_types: this.PAYMENT_METHOD_TYPES,
765
775
  success_url: options.successUrl || this._config.checkoutSetupSessionSuccessUrl,
766
776
  cancel_url: options.cancelUrl || this._config.checkoutSetupSessionCancelUrl,
@@ -1,153 +1,108 @@
1
1
  /*
2
- * These are the default resources and filters.
3
- * They contain minimum filters for public accessibility of resources.
2
+ * Columns a routes.yaml filter must not be evaluated against.
3
+ *
4
+ * Ghost used to answer URLs from a map precomputed at boot, and kept that map
5
+ * lean by dropping these columns from every cached record. A collection filter
6
+ * referencing one therefore matched it as absent, which NQL reads as null. The
7
+ * URL service loads full records and would see the real value, so it strips
8
+ * these before evaluating a filter — otherwise routes.yaml files written
9
+ * against the old behaviour would start routing differently.
10
+ *
11
+ * `lazy-find-resource` strips the same columns so a resolved resource has the
12
+ * shape callers have always seen.
4
13
  */
5
14
 
6
15
  // TODO: switch exclude lists to include lists to make this more explicit
7
16
  module.exports = [
8
17
  {
9
18
  type: 'posts',
10
- modelOptions: {
11
- modelName: 'Post',
12
- filter: 'status:published+type:post',
13
- exclude: [
14
- 'title',
15
- 'mobiledoc',
16
- 'lexical',
17
- 'html',
18
- 'plaintext',
19
- // @TODO: https://github.com/TryGhost/Ghost/issues/10335
20
- // 'page',
21
- 'status',
22
- 'codeinjection_head',
23
- 'codeinjection_foot',
24
- 'meta_title',
25
- 'meta_description',
26
- 'custom_excerpt',
27
- 'og_image',
28
- 'og_title',
29
- 'og_description',
30
- 'twitter_image',
31
- 'twitter_title',
32
- 'twitter_description',
33
- 'custom_template',
34
- 'locale',
35
- 'newsletter_id',
36
- 'show_title_and_feature_image',
37
- 'email_recipient_filter',
38
- 'comment_id',
39
- 'tiers'
40
- ],
41
- withRelated: ['tags', 'authors'],
42
- withRelatedPrimary: {
43
- primary_tag: 'tags',
44
- primary_author: 'authors'
45
- },
46
- withRelatedFields: {
47
- tags: ['tags.id', 'tags.slug'],
48
- authors: ['users.id', 'users.slug']
49
- }
50
- },
51
- events: {
52
- add: 'post.published',
53
- update: 'post.published.edited',
54
- remove: 'post.unpublished'
55
- }
19
+ exclude: [
20
+ 'title',
21
+ 'mobiledoc',
22
+ 'lexical',
23
+ 'html',
24
+ 'plaintext',
25
+ // @TODO: https://github.com/TryGhost/Ghost/issues/10335
26
+ // 'page',
27
+ 'status',
28
+ 'codeinjection_head',
29
+ 'codeinjection_foot',
30
+ 'meta_title',
31
+ 'meta_description',
32
+ 'custom_excerpt',
33
+ 'og_image',
34
+ 'og_title',
35
+ 'og_description',
36
+ 'twitter_image',
37
+ 'twitter_title',
38
+ 'twitter_description',
39
+ 'custom_template',
40
+ 'locale',
41
+ 'newsletter_id',
42
+ 'show_title_and_feature_image',
43
+ 'email_recipient_filter',
44
+ 'comment_id',
45
+ 'tiers'
46
+ ]
56
47
  },
57
48
  {
58
49
  type: 'pages',
59
- modelOptions: {
60
- modelName: 'Post',
61
- exclude: [
62
- 'title',
63
- 'mobiledoc',
64
- 'lexical',
65
- 'html',
66
- 'plaintext',
67
- // @TODO: https://github.com/TryGhost/Ghost/issues/10335
68
- // 'page',
69
- // 'status',
70
- 'codeinjection_head',
71
- 'codeinjection_foot',
72
- 'meta_title',
73
- 'meta_description',
74
- 'custom_excerpt',
75
- 'og_image',
76
- 'og_title',
77
- 'og_description',
78
- 'twitter_image',
79
- 'twitter_title',
80
- 'twitter_description',
81
- 'custom_template',
82
- 'locale',
83
- 'tags',
84
- 'authors',
85
- 'primary_tag',
86
- 'primary_author',
87
- 'newsletter_id',
88
- 'show_title_and_feature_image',
89
- 'email_recipient_filter',
90
- 'comment_id',
91
- 'tiers'
92
- ],
93
- filter: 'status:published+type:page'
94
- },
95
- events: {
96
- add: 'page.published',
97
- update: 'page.published.edited',
98
- remove: 'page.unpublished'
99
- }
50
+ exclude: [
51
+ 'title',
52
+ 'mobiledoc',
53
+ 'lexical',
54
+ 'html',
55
+ 'plaintext',
56
+ // @TODO: https://github.com/TryGhost/Ghost/issues/10335
57
+ // 'page',
58
+ // 'status',
59
+ 'codeinjection_head',
60
+ 'codeinjection_foot',
61
+ 'meta_title',
62
+ 'meta_description',
63
+ 'custom_excerpt',
64
+ 'og_image',
65
+ 'og_title',
66
+ 'og_description',
67
+ 'twitter_image',
68
+ 'twitter_title',
69
+ 'twitter_description',
70
+ 'custom_template',
71
+ 'locale',
72
+ 'tags',
73
+ 'authors',
74
+ 'primary_tag',
75
+ 'primary_author',
76
+ 'newsletter_id',
77
+ 'show_title_and_feature_image',
78
+ 'email_recipient_filter',
79
+ 'comment_id',
80
+ 'tiers'
81
+ ]
100
82
  },
101
83
  {
102
84
  type: 'tags',
103
- keep: ['id', 'slug'],
104
- modelOptions: {
105
- modelName: 'Tag',
106
- exclude: [
107
- 'description',
108
- 'meta_title',
109
- 'meta_description',
110
- 'parent_id'
111
- ],
112
- filter: 'visibility:public',
113
- shouldHavePosts: {
114
- joinTo: 'tag_id',
115
- joinTable: 'posts_tags'
116
- }
117
- },
118
- events: {
119
- add: 'tag.added',
120
- update: ['tag.edited', 'tag.attached', 'tag.detached'],
121
- remove: 'tag.deleted'
122
- }
85
+ exclude: [
86
+ 'description',
87
+ 'meta_title',
88
+ 'meta_description',
89
+ 'parent_id'
90
+ ]
123
91
  },
124
92
  {
125
93
  type: 'authors',
126
- modelOptions: {
127
- modelName: 'User',
128
- exclude: [
129
- 'bio',
130
- 'website',
131
- 'location',
132
- 'facebook',
133
- 'twitter',
134
- 'locale',
135
- 'accessibility',
136
- 'meta_title',
137
- 'meta_description',
138
- 'tour',
139
- 'last_seen'
140
- ],
141
- filter: 'visibility:public',
142
- shouldHavePosts: {
143
- joinTo: 'author_id',
144
- joinTable: 'posts_authors'
145
- }
146
- },
147
- events: {
148
- add: 'user.activated',
149
- update: ['user.activated.edited', 'user.attached', 'user.detached'],
150
- remove: 'user.deleted'
151
- }
94
+ exclude: [
95
+ 'bio',
96
+ 'website',
97
+ 'location',
98
+ 'facebook',
99
+ 'twitter',
100
+ 'locale',
101
+ 'accessibility',
102
+ 'meta_title',
103
+ 'meta_description',
104
+ 'tour',
105
+ 'last_seen'
106
+ ]
152
107
  }
153
108
  ];
@@ -1,50 +1,7 @@
1
- const config = require('../../../shared/config');
2
- const LocalFileCache = require('./local-file-cache');
3
- const UrlService = require('./url-service');
4
- const UrlServiceFacade = require('./url-service-facade');
1
+ const LazyUrlService = require('./lazy-url-service');
2
+ const {createFindResource} = require('./lazy-find-resource');
3
+ const models = require('../../models');
5
4
 
6
- // NOTE: instead of a path we could give UrlService a "data-resolver" of some sort
7
- // so it doesn't have to contain the logic to read data at all. This would be
8
- // a possible improvement in the future
9
- let writeDisabled = false;
10
- let storagePath = config.getContentPath('data');
11
-
12
- // TODO: remove this hack in favor of loading from the content path when it's possible to do so
13
- // by mocking content folders in pre-boot phase
14
- if (process.env.NODE_ENV.startsWith('test')){
15
- storagePath = config.get('paths').urlCache;
16
-
17
- // NOTE: prevents test suites from overwriting cache fixtures.
18
- // A better solution would be injecting a different implementation of the
19
- // cache based on the environment, this approach should do the trick for now
20
- writeDisabled = true;
21
- }
22
-
23
- const cache = new LocalFileCache({storagePath, writeDisabled});
24
- const urlService = new UrlService({cache});
25
-
26
- // Build a lazy backend alongside eager for shadow comparison, gated by the
27
- // existing `lazyRouting` flag (unset by default = pure eager, unchanged).
28
- // models is already loaded via url-service -> resources, so this require is safe.
29
- let lazyUrlService = null;
30
- let fetchRoutableResources = null;
31
- if (config.get('lazyRouting')) {
32
- const LazyUrlService = require('./lazy-url-service');
33
- const {createFindResource} = require('./lazy-find-resource');
34
- const {createFetchRoutableResources} = require('./routable-resources');
35
- const models = require('../../models');
36
- lazyUrlService = new LazyUrlService({findResource: createFindResource(models)});
37
- fetchRoutableResources = createFetchRoutableResources({lazyUrlService});
38
- }
39
-
40
- const urlServiceFacade = lazyUrlService
41
- ? new UrlServiceFacade({urlService, lazyUrlService, compare: true, fetchRoutableResources})
42
- : new UrlServiceFacade({urlService});
43
-
44
- // Singleton: default export remains the eager UrlService for backwards
45
- // compatibility with existing imports. The new facade is exposed alongside
46
- // it via `urlService.facade` so RouterManager and migrating callers can
47
- // reach for it without forcing every consumer to update at once.
48
- urlService.facade = urlServiceFacade;
49
-
50
- module.exports = urlService;
5
+ // Singleton: every caller shares the router registrations made by
6
+ // RouterManager at boot and on every routes.yaml reload.
7
+ module.exports = new LazyUrlService({findResource: createFindResource(models)});
@@ -7,15 +7,17 @@ const POST_SCOPE = { type: 'post', status: 'published' };
7
7
  const PAGE_SCOPE = { type: 'page', status: 'published' };
8
8
  const POST_RELATIONS = ['tags', 'authors'];
9
9
  const RELATION_KEYS = ['tags', 'authors', 'primary_tag', 'primary_author'];
10
- // Drop the same fields the eager resourceConfig excludes so the resolved record
11
- // has the same shape the eager service exposes (no post body, no extra
12
- // author/tag fields). posts_meta is an auto-loaded relation eager never keeps.
10
+ // Drop the same columns the URL service excludes from filter evaluation, so a
11
+ // resolved record keeps the shape callers have always seen (no post body, no
12
+ // extra author/tag fields). posts_meta is an auto-loaded relation Ghost has
13
+ // never exposed here.
13
14
  function excludeFor(type) {
14
15
  const cfg = resourcesConfig.find((c) => c.type === type);
15
- const exclude = (cfg && cfg.modelOptions.exclude) || [];
16
+ const exclude = cfg?.exclude ?? [];
16
17
  return [...exclude, 'posts_meta'];
17
18
  }
18
- // Eager trims relations to {id, slug} via withRelatedFields; match that.
19
+ // Relations are trimmed to {id, slug}: permalinks and filters read nothing
20
+ // else off them, and callers have never seen more.
19
21
  function trimRelation(value) {
20
22
  if (Array.isArray(value)) {
21
23
  return value.map(item => _.pick(item, ['id', 'slug']));
@@ -25,11 +27,11 @@ function trimRelation(value) {
25
27
  }
26
28
  return value;
27
29
  }
28
- function pruneToEagerShape(record, type) {
30
+ function pruneToPublicShape(record, type) {
29
31
  const pruned = _.omit(record, excludeFor(type));
30
32
  if (type === 'pages') {
31
- // Eager always exposes primary_tag/primary_author as null on pages (they
32
- // are virtual Post fields) but never carries the tags/authors arrays.
33
+ // primary_tag/primary_author are always null on pages (they are virtual
34
+ // Post fields), and pages never carry the tags/authors arrays.
33
35
  pruned.primary_tag = null;
34
36
  pruned.primary_author = null;
35
37
  return pruned;
@@ -43,8 +45,9 @@ function pruneToEagerShape(record, type) {
43
45
  }
44
46
  /**
45
47
  * Builds the per-request DB lookup hook injected into LazyUrlService.resolveUrl.
46
- * Visibility rules mirror the eager service so a guessed slug can't surface
47
- * anything the eager path hid; unknown types resolve to null.
48
+ * Visibility rules match the forward lookup's base filters, so a guessed slug
49
+ * can't surface anything a generated URL would have hidden; unknown types
50
+ * resolve to null.
48
51
  */
49
52
  function createFindResource(models) {
50
53
  const loadOne = async (Model, query, type, options = {}) => {
@@ -57,7 +60,7 @@ function createFindResource(models) {
57
60
  if (Array.isArray(record.authors)) {
58
61
  record.primary_author = record.authors[0] ?? null;
59
62
  }
60
- return pruneToEagerShape(record, type);
63
+ return pruneToPublicShape(record, type);
61
64
  };
62
65
  return (type, params) => {
63
66
  switch (type) {
@@ -18,16 +18,18 @@ const PAGE_SCOPE = {type: 'page', status: 'published'};
18
18
  const POST_RELATIONS = ['tags', 'authors'];
19
19
  const RELATION_KEYS = ['tags', 'authors', 'primary_tag', 'primary_author'];
20
20
 
21
- // Drop the same fields the eager resourceConfig excludes so the resolved record
22
- // has the same shape the eager service exposes (no post body, no extra
23
- // author/tag fields). posts_meta is an auto-loaded relation eager never keeps.
21
+ // Drop the same columns the URL service excludes from filter evaluation, so a
22
+ // resolved record keeps the shape callers have always seen (no post body, no
23
+ // extra author/tag fields). posts_meta is an auto-loaded relation Ghost has
24
+ // never exposed here.
24
25
  function excludeFor(type: string): string[] {
25
26
  const cfg = resourcesConfig.find((c: {type: string}) => c.type === type);
26
- const exclude = (cfg && cfg.modelOptions.exclude) || [];
27
+ const exclude = cfg?.exclude ?? [];
27
28
  return [...exclude, 'posts_meta'];
28
29
  }
29
30
 
30
- // Eager trims relations to {id, slug} via withRelatedFields; match that.
31
+ // Relations are trimmed to {id, slug}: permalinks and filters read nothing
32
+ // else off them, and callers have never seen more.
31
33
  function trimRelation(value: unknown): unknown {
32
34
  if (Array.isArray(value)) {
33
35
  return value.map(item => _.pick(item, ['id', 'slug']));
@@ -38,12 +40,12 @@ function trimRelation(value: unknown): unknown {
38
40
  return value;
39
41
  }
40
42
 
41
- function pruneToEagerShape(record: Record<string, unknown>, type: string): Record<string, unknown> {
43
+ function pruneToPublicShape(record: Record<string, unknown>, type: string): Record<string, unknown> {
42
44
  const pruned = _.omit(record, excludeFor(type));
43
45
 
44
46
  if (type === 'pages') {
45
- // Eager always exposes primary_tag/primary_author as null on pages (they
46
- // are virtual Post fields) but never carries the tags/authors arrays.
47
+ // primary_tag/primary_author are always null on pages (they are virtual
48
+ // Post fields), and pages never carry the tags/authors arrays.
47
49
  pruned.primary_tag = null;
48
50
  pruned.primary_author = null;
49
51
  return pruned;
@@ -59,8 +61,9 @@ function pruneToEagerShape(record: Record<string, unknown>, type: string): Recor
59
61
 
60
62
  /**
61
63
  * Builds the per-request DB lookup hook injected into LazyUrlService.resolveUrl.
62
- * Visibility rules mirror the eager service so a guessed slug can't surface
63
- * anything the eager path hid; unknown types resolve to null.
64
+ * Visibility rules match the forward lookup's base filters, so a guessed slug
65
+ * can't surface anything a generated URL would have hidden; unknown types
66
+ * resolve to null.
64
67
  */
65
68
  export function createFindResource(models: Models): FindResource {
66
69
  const loadOne = async (
@@ -78,7 +81,7 @@ export function createFindResource(models: Models): FindResource {
78
81
  if (Array.isArray(record.authors)) {
79
82
  record.primary_author = record.authors[0] ?? null;
80
83
  }
81
- return pruneToEagerShape(record, type);
84
+ return pruneToPublicShape(record, type);
82
85
  };
83
86
 
84
87
  return (type: string, params: ResourceLookupParams): Promise<Record<string, unknown> | null> => {