ghost 6.60.0 → 6.62.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 (613) 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-jobs-0.0.0.tgz +0 -0
  4. package/components/tryghost-adapter-base-redirects-0.0.0.tgz +0 -0
  5. package/components/tryghost-adapter-base-route-settings-0.0.0.tgz +0 -0
  6. package/components/tryghost-adapter-base-scheduling-0.2.3.tgz +0 -0
  7. package/components/tryghost-adapter-base-sso-0.1.3.tgz +0 -0
  8. package/components/tryghost-admin-api-schema-0.0.0.tgz +0 -0
  9. package/components/tryghost-checkout-0.0.0.tgz +0 -0
  10. package/components/tryghost-custom-field-types-0.0.0.tgz +0 -0
  11. package/components/tryghost-i18n-0.0.0.tgz +0 -0
  12. package/components/tryghost-kg-card-factory-5.2.4.tgz +0 -0
  13. package/components/tryghost-kg-clean-basic-html-4.3.4.tgz +0 -0
  14. package/components/tryghost-kg-converters-1.2.5.tgz +0 -0
  15. package/components/tryghost-kg-default-cards-10.3.5.tgz +0 -0
  16. package/components/tryghost-kg-default-nodes-2.2.1.tgz +0 -0
  17. package/components/tryghost-kg-default-transforms-1.3.4.tgz +0 -0
  18. package/components/tryghost-kg-html-to-lexical-1.4.0.tgz +0 -0
  19. package/components/tryghost-kg-lexical-html-renderer-1.5.0.tgz +0 -0
  20. package/components/tryghost-kg-markdown-html-renderer-7.2.4.tgz +0 -0
  21. package/components/tryghost-kg-utils-1.1.4.tgz +0 -0
  22. package/components/tryghost-nql-string-0.0.0.tgz +0 -0
  23. package/components/tryghost-parse-email-address-0.0.0.tgz +0 -0
  24. package/content/settings/README.md +1 -1
  25. package/content/themes/casper/.gitignore +28 -0
  26. package/content/themes/casper/assets/built/casper.js +1 -1
  27. package/content/themes/casper/assets/built/screen.css +1 -1
  28. package/content/themes/casper/assets/css/screen.css +2 -1
  29. package/content/themes/casper/assets/js/lightbox.js +63 -46
  30. package/content/themes/casper/package.json +6 -6
  31. package/content/themes/casper/page.hbs +1 -0
  32. package/content/themes/casper/post.hbs +1 -0
  33. package/content/themes/source/.gitignore +28 -0
  34. package/content/themes/source/assets/built/screen.css +1 -1
  35. package/content/themes/source/assets/built/source.js +1 -1
  36. package/content/themes/source/assets/css/screen.css +2 -1
  37. package/content/themes/source/assets/js/lightbox.js +62 -45
  38. package/content/themes/source/assets/js/main.js +2 -2
  39. package/content/themes/source/package.json +4 -4
  40. package/content/themes/source/partials/feature-image.hbs +1 -0
  41. package/core/boot.js +62 -21
  42. package/core/built/admin/assets/Combination-B0l4MKVh.js +41 -0
  43. package/core/built/admin/assets/InterVariable-DiVDrmQJ.woff2 +0 -0
  44. package/core/built/admin/assets/InterVariable-Italic-FCBEiFp6.woff2 +0 -0
  45. package/core/built/admin/assets/{PolarAngleAxis-C4qtHy1B.js → PolarAngleAxis-pkMyqz8g.js} +1 -1
  46. package/core/built/admin/assets/{RadialBarChart-Bh09Stsj.js → RadialBarChart-JAKoS4KT.js} +1 -1
  47. package/core/built/admin/assets/{about-BgpmhCuM.js → about-Dyae_UT6.js} +1 -1
  48. package/core/built/admin/assets/account-migration-CESa0mnX.js +1 -0
  49. package/core/built/admin/assets/{action-list-lGzZLHc8.js → action-list-C4v0-du8.js} +1 -1
  50. package/core/built/admin/assets/activitypub/{account-migration-DMHuPnJn.js → account-migration-By69CgCp.js} +16 -16
  51. package/core/built/admin/assets/activitypub/activitypub.js +9 -10
  52. package/core/built/admin/assets/activitypub/{avatar-DhTo5D1B.js → avatar-DLPL3Abs.js} +59 -68
  53. package/core/built/admin/assets/activitypub/{avatar-flipboard-DnVgbEfa.js → avatar-flipboard-C9iDY-QV.js} +2 -2
  54. package/core/built/admin/assets/activitypub/{bluesky-sharing-BT4zAlW7.js → bluesky-sharing-BJcPMrDd.js} +37 -37
  55. package/core/built/admin/assets/activitypub/{content-formatters-BeDZ-DIa.js → content-formatters-3rTHg3mp.js} +18 -18
  56. package/core/built/admin/assets/activitypub/{copy-8sqxUuNd.js → copy-DIAOQoCZ.js} +2 -2
  57. package/core/built/admin/assets/activitypub/{domain-xQDDu1CS.js → domain-DUR4xSkV.js} +121 -121
  58. package/core/built/admin/assets/activitypub/{edit-profile-BXdF_r2G.js → edit-profile-BqtfzxCp.js} +40 -40
  59. package/core/built/admin/assets/activitypub/{explore-CMt7gKlL.js → explore-BxuJd-J4.js} +27 -27
  60. package/core/built/admin/assets/activitypub/{feed-Bwqdddp_.js → feed-BM1TcksA.js} +51 -51
  61. package/core/built/admin/assets/activitypub/{field-4co_8FVg.js → field-Dn7HHx2-.js} +3 -3
  62. package/core/built/admin/assets/activitypub/{hash-DwakMs4X.js → hash-Bm3WxYN4.js} +2 -2
  63. package/core/built/admin/assets/activitypub/inbox-CCjkuow2.js +1284 -0
  64. package/core/built/admin/assets/activitypub/{inbox-ckD4wo_r.js → inbox-d8oJRTf4.js} +2 -2
  65. package/core/built/admin/assets/activitypub/label-1AA_s9Fa.js +16 -0
  66. package/core/built/admin/assets/activitypub/layout-2-0bw6HN.js +1 -0
  67. package/core/built/admin/assets/activitypub/{moderation-KCCO7L2J.js → moderation-CnmxEB8w.js} +91 -91
  68. package/core/built/admin/assets/activitypub/{note-BX_Bz5A0.js → note-ZKc_Bnba.js} +24 -24
  69. package/core/built/admin/assets/activitypub/{notifications-BQOYGvRv.js → notifications-CB2tJZau.js} +51 -51
  70. package/core/built/admin/assets/activitypub/{onboarding-CNelD_uF.js → onboarding-BsJ9E5qf.js} +2 -2
  71. package/core/built/admin/assets/activitypub/{onboarding-mat5Hrl0.js → onboarding-CSUJJIlh.js} +2 -2
  72. package/core/built/admin/assets/activitypub/{preferences-6h43G9_q.js → preferences-0-JZnUkI.js} +1519 -1519
  73. package/core/built/admin/assets/activitypub/{profile-BMN9VVZ2.js → profile-C35cFIhM.js} +256 -256
  74. package/core/built/admin/assets/activitypub/{reply-ZNo04xsO.js → reply-DYK5vVqb.js} +2 -2
  75. package/core/built/admin/assets/activitypub/{routes-3B9mUQ7i.js → routes-BD4vscyc.js} +796 -790
  76. package/core/built/admin/assets/activitypub/{separator-D9taVCCa.js → separator-BbQqTm-p.js} +3 -3
  77. package/core/built/admin/assets/activitypub/settings-BsMROdqh.js +315 -0
  78. package/core/built/admin/assets/activitypub/{site-DHoMupSB.js → site-O0RL9YCN.js} +2 -2
  79. package/core/built/admin/assets/activitypub/{step-1-BsGGnBuT.js → step-1-BMSx7c_X.js} +6 -6
  80. package/core/built/admin/assets/activitypub/{step-2-teosIS0k.js → step-2-DtPQzlTH.js} +6 -6
  81. package/core/built/admin/assets/activitypub/{step-3-BjD5TokC.js → step-3-CLlOZTyt.js} +11 -11
  82. package/core/built/admin/assets/activitypub/{tabs-Cvwl1wXU.js → tabs-Dxk-b9M-.js} +306 -306
  83. package/core/built/admin/assets/activitypub/{topic-filter-C3LZJc2X.js → topic-filter-5yZH6tId.js} +3 -3
  84. package/core/built/admin/assets/activitypub/{use-activity-pub-queries-Dp9f0gov.js → use-activity-pub-queries-CV50qe03.js} +3 -3
  85. package/core/built/admin/assets/activitypub/{use-navigate-with-base-path-C4RI0sa9.js → use-navigate-with-base-path-Bmk5h4lW.js} +220 -220
  86. package/core/built/admin/assets/activitypub/{use-reply-chain-data-C2oNDMUH.js → use-reply-chain-data-Cbvzgjzd.js} +30 -30
  87. package/core/built/admin/assets/activitypub/{users-CoX6FT_K.js → users-BjcoP_HC.js} +7 -5
  88. package/core/built/admin/assets/activitypub/{x-Dxm6pV9X.js → x-DbQZOLiI.js} +2 -2
  89. package/core/built/admin/assets/add-integration-modal-BlF6rs_f.js +1 -0
  90. package/core/built/admin/assets/add-newsletter-modal-CglVQqah.js +1 -0
  91. package/core/built/admin/assets/add-recommendation-modal-wz7BsuaG.js +1 -0
  92. package/core/built/admin/assets/analytics-C4HE1gBg.js +1 -0
  93. package/core/built/admin/assets/{announcement-bar-modal-BTHiy1ZO.js → announcement-bar-modal-Ci4zz8jO.js} +1 -1
  94. package/core/built/admin/assets/{api-keys-Boy5pLbD.js → api-keys-Ck-Yteiv.js} +1 -1
  95. package/core/built/admin/assets/audience-CtbA54Sn.js +1 -0
  96. package/core/built/admin/assets/{automated-emails-te1D5kq-.js → automated-emails-D5VVMND9.js} +1 -1
  97. package/core/built/admin/assets/automations-CzKt5fb8.js +1 -0
  98. package/core/built/admin/assets/bluesky-sharing-BEtJ_gL_.js +1 -0
  99. package/core/built/admin/assets/{box-By_EgGtm.js → box-CdfQAP_F.js} +1 -1
  100. package/core/built/admin/assets/{brand-icon-09YqFZjV.js → brand-icon-CrIGOA3Z.js} +1 -1
  101. package/core/built/admin/assets/{breadcrumb-CcFr_ltt.js → breadcrumb-zUrZrBtW.js} +1 -1
  102. package/core/built/admin/assets/{button-BshWPHvn.js → button-eNMKQWXr.js} +1 -1
  103. package/core/built/admin/assets/{card-CiiE7QfM.js → card--VNbfgo3.js} +1 -1
  104. package/core/built/admin/assets/{chart-BnXyfH11.js → chart-BrhA41Zi.js} +1 -1
  105. package/core/built/admin/assets/chart-helpers-CfBKt0vT.js +1 -0
  106. package/core/built/admin/assets/{checkbox-Dwwr_3Py.js → checkbox-CgOn_tKW.js} +1 -1
  107. package/core/built/admin/assets/{chunk.524.91ecb33e6afc3bd8949b.js → chunk.524.a697dee88db67fdf6021.js} +4 -4
  108. package/core/built/admin/assets/{chunk.582.512549909741883f960c.js → chunk.582.5ed5d124cfca9c259b9c.js} +6 -6
  109. package/core/built/admin/assets/{chunk.16.f76a6314082d813d67e0.js → chunk.598.7e056fabb47ce7dbd73f.js} +14 -14
  110. package/core/built/admin/assets/{code-editor-view-BwIdPy_k.js → code-editor-view-BYNoAoNV.js} +1 -1
  111. package/core/built/admin/assets/{code-editor-view-CtkF82Fv.js → code-editor-view-K2wI-I5f.js} +1 -1
  112. package/core/built/admin/assets/color-picker-Ddw80xX6.js +3 -0
  113. package/core/built/admin/assets/color-picker-field-D9nUhvA7.js +1 -0
  114. package/core/built/admin/assets/combobox-w9j8PPQT.js +1 -0
  115. package/core/built/admin/assets/command-BfpHORBv.js +1 -0
  116. package/core/built/admin/assets/comments-BLmCmyCs.js +1 -0
  117. package/core/built/admin/assets/confirmation-context-CBM8G0Vj.js +1 -0
  118. package/core/built/admin/assets/{container-LiZf3XdY.js → container-BuQG1wuP.js} +1 -1
  119. package/core/built/admin/assets/{content-api-modal-BtpNI92-.js → content-api-modal-TXRz3U7S.js} +1 -1
  120. package/core/built/admin/assets/context-menu-_QMdd3kp.js +1 -0
  121. package/core/built/admin/assets/{copy-field-CglgRZyG.js → copy-field-6N01S07E.js} +1 -1
  122. package/core/built/admin/assets/create-ghost-browse-value-source-qIBymvvf.js +1 -0
  123. package/core/built/admin/assets/custom-field-type-option-BddFlJFa.js +1 -0
  124. package/core/built/admin/assets/custom-integration-modal-DmNquxUV.js +1 -0
  125. package/core/built/admin/assets/{data-list-CupF7bjM.js → data-list-CA2jYGPq.js} +1 -1
  126. package/core/built/admin/assets/{date-range-select-JPwM0yUj.js → date-range-select-uvz_DtPh.js} +1 -1
  127. package/core/built/admin/assets/design-and-theme-modal-BSmo12Op.js +2 -0
  128. package/core/built/admin/assets/{detail-page-D8lx2SdP.js → detail-page-Dnv-CdR1.js} +1 -1
  129. package/core/built/admin/assets/dirty-confirm-dialog-BZ1iytEd.js +1 -0
  130. package/core/built/admin/assets/{disabled-sources-indicator-BTJ2ClQu.js → disabled-sources-indicator-DMRrxsiJ.js} +1 -1
  131. package/core/built/admin/assets/{dist-DzcfoDJ3.js → dist-8YJUlf3B.js} +1 -1
  132. package/core/built/admin/assets/{dist-Cb5RSHSg.js → dist-B3keLvjj.js} +1 -1
  133. package/core/built/admin/assets/dist-Dcsslyo72.js +1 -0
  134. package/core/built/admin/assets/{dist-BT_Z-eCn.js → dist-Dgt2cr6a.js} +1 -1
  135. package/core/built/admin/assets/domain-BNYrt0aD.js +1 -0
  136. package/core/built/admin/assets/dropzone-D7nFdAe5.js +5 -0
  137. package/core/built/admin/assets/edit-profile-C5Asm4LA.js +1 -0
  138. package/core/built/admin/assets/editor-REokrzci.js +8 -0
  139. package/core/built/admin/assets/{embed-signup-form-modal-BFTPf04i.js → embed-signup-form-modal-Ds6mPEi5.js} +1 -1
  140. package/core/built/admin/assets/{empty-indicator-WB1WgT9h.js → empty-indicator-D9QdpuNX.js} +1 -1
  141. package/core/built/admin/assets/en-B1jX3WMs.js +1 -0
  142. package/core/built/admin/assets/explore-UY10Egsp.js +1 -0
  143. package/core/built/admin/assets/feature-image-placeholder-D1iF_8bc.js +1 -0
  144. package/core/built/admin/assets/feed-81C8mJWR.js +1 -0
  145. package/core/built/admin/assets/{field-LmNk7wZh.js → field-Dihp5p18.js} +1 -1
  146. package/core/built/admin/assets/filter-bar-Da1qxybu.js +1 -0
  147. package/core/built/admin/assets/filter-sources-BO9xUPj7.js +1 -0
  148. package/core/built/admin/assets/filters-CRUWecfY.js +1 -0
  149. package/core/built/admin/assets/filters-DirqNXjH.js +1 -0
  150. package/core/built/admin/assets/first-promoter-modal-CT6MxYZb.js +1 -0
  151. package/core/built/admin/assets/{ghost-c8807202a07c20030acb719ee0114815.css → ghost-8eabfc1ece81b03cf7b90780d31487e8.css} +1 -1
  152. package/core/built/admin/assets/{ghost-403cb39badad3df411fc0ba27d220047.js → ghost-c2848508292937415f20f5a830eea59e.js} +31 -28
  153. package/core/built/admin/assets/{ghost-dark-fbf1e384aaef3ae315e540f0eb7373a7.css → ghost-dark-a7bebe2c561f55369dcf29f4c820f7ff.css} +1 -1
  154. package/core/built/admin/assets/gift-link-modal-CQVAye17.js +1 -0
  155. package/core/built/admin/assets/{grid-CUciBfjf.js → grid-Dj29PY05.js} +1 -1
  156. package/core/built/admin/assets/growth-BWIu-6xj.js +3 -0
  157. package/core/built/admin/assets/growth-DU29oxeA.js +1 -0
  158. package/core/built/admin/assets/{heading-CRZZ2FUe.js → heading-Dh5SFVjL.js} +1 -1
  159. package/core/built/admin/assets/history-modal-CFd1Hvx6.js +1 -0
  160. package/core/built/admin/assets/html-field-CJBCLTvv.js +1 -0
  161. package/core/built/admin/assets/{images-C0XvUYMb.js → images-scfkWZiK.js} +1 -1
  162. package/core/built/admin/assets/{inbox-DZXDUt4s.js → inbox-Mcp4DXZN.js} +14 -14
  163. package/core/built/admin/assets/index-6MkPdCtr.js +4 -0
  164. package/core/built/admin/assets/index-Bn7QhcZu.css +2 -0
  165. package/core/built/admin/assets/index.es-CNnuNH0d.js +1 -0
  166. package/core/built/admin/assets/{inline-Cw-gigDW.js → inline-BWSs_VzR.js} +1 -1
  167. package/core/built/admin/assets/{input-group-BPAxETpQ.js → input-group-CMhe2DvY.js} +1 -1
  168. package/core/built/admin/assets/{input-surface-BdOe4KzO.js → input-surface-BsrIZeSF.js} +1 -1
  169. package/core/built/admin/assets/{integration-header-B4DyXV06.js → integration-header-Bm6IDb1A.js} +1 -1
  170. package/core/built/admin/assets/invite-user-modal-DfheMXs0.js +1 -0
  171. package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +14 -14
  172. package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +3 -3
  173. package/core/built/admin/assets/koenig-lexical/style.css +1 -1
  174. package/core/built/admin/assets/{koenig-lexical-60O_8aiO.js → koenig-lexical-DBSqAuiI.js} +3 -3
  175. package/core/built/admin/assets/koenig-loader-aFQNlJlD.js +2 -0
  176. package/core/built/admin/assets/kpi-card-DBRMfGOW.js +1 -0
  177. package/core/built/admin/assets/{kpi-card-fUHZlzBX.js → kpi-card-DFafD1qq.js} +1 -1
  178. package/core/built/admin/assets/kpi-helpers-Cv8i8hns.js +1 -0
  179. package/core/built/admin/assets/kpi-tabs-BJItvLYm.js +1 -0
  180. package/core/built/admin/assets/{label-VIG969IC.js → label-BnSCvffu.js} +1 -1
  181. package/core/built/admin/assets/label-picker-KVoo91sh.js +1 -0
  182. package/core/built/admin/assets/layout-Bjv2Ll-5.js +1 -0
  183. package/core/built/admin/assets/{link-helpers-Dtq9fxQg.js → link-helpers-MVDdnFCY.js} +1 -1
  184. package/core/built/admin/assets/{list-page-CdsnQR9N.js → list-page-BucXJ0hi.js} +1 -1
  185. package/core/built/admin/assets/member-custom-fields-DDQV6QeG.js +1 -0
  186. package/core/built/admin/assets/member-detail-CdJF6Agw.js +1 -0
  187. package/core/built/admin/assets/members-DjQbq9Z2.js +4 -0
  188. package/core/built/admin/assets/{modal-page-BMTzFHVO.js → modal-page-xCivTMvI.js} +1 -1
  189. package/core/built/admin/assets/moderation-AgCIEso4.js +1 -0
  190. package/core/built/admin/assets/{multi-select-combobox-CGohnsxJ.js → multi-select-combobox-BcITkUVr.js} +1 -1
  191. package/core/built/admin/assets/navigation-modal-BkT7b1M2.js +1 -0
  192. package/core/built/admin/assets/newsletter-BMMAuvgq.js +1 -0
  193. package/core/built/admin/assets/newsletter-detail-modal-0SCJ7Zpm.js +1 -0
  194. package/core/built/admin/assets/{newsletter-emails-D5ql1rud.js → newsletter-emails-DKzwafuh.js} +1 -1
  195. package/core/built/admin/assets/newsletters-BRBb_uQC.js +1 -0
  196. package/core/built/admin/assets/note-DyGHtS9a.js +1 -0
  197. package/core/built/admin/assets/notifications-ZgWniKna.js +1 -0
  198. package/core/built/admin/assets/nql-BLpCn7qX.js +21 -0
  199. package/core/built/admin/assets/offers-container-modal-B-E8TIWr.js +1 -0
  200. package/core/built/admin/assets/{onboarding-B4YhlZ0i.js → onboarding-CzIsre-d.js} +1 -1
  201. package/core/built/admin/assets/onboarding-qg8Akovm.js +1 -0
  202. package/core/built/admin/assets/{onboarding-route-Cu_ROWPn.js → onboarding-route-CaavZulg.js} +1 -1
  203. package/core/built/admin/assets/overview-BW8GLeYi.js +1 -0
  204. package/core/built/admin/assets/overview-BkXZNzaZ.js +1 -0
  205. package/core/built/admin/assets/{page-header-Cfds8pCg.js → page-header-De0VzKBi.js} +1 -1
  206. package/core/built/admin/assets/pagemenu-B5KKCpbA.js +1 -0
  207. package/core/built/admin/assets/pages-jgaFm69d.js +1 -0
  208. package/core/built/admin/assets/pages-route-CIUAQxtY.js +1 -0
  209. package/core/built/admin/assets/papaparse.min-cQwnxGCG.js +10 -0
  210. package/core/built/admin/assets/{pintura-modal-TDTrJ89x.js → pintura-modal-BZ2J9w3n.js} +1 -1
  211. package/core/built/admin/assets/portal-frame-B6Hr9wHc.js +1 -0
  212. package/core/built/admin/assets/portal-modal-D4ceei3t.js +1 -0
  213. package/core/built/admin/assets/post-analytics-header-BYCsT0GP.js +1 -0
  214. package/core/built/admin/assets/post-analytics-ot7f6pih.js +1 -0
  215. package/core/built/admin/assets/{post-analytics-provider-Cu3jNeFh.js → post-analytics-provider-Bo1gmYaP.js} +1 -1
  216. package/core/built/admin/assets/{post-share-modal-P1_M6o-H.js → post-share-modal-C-PaYZ_e.js} +1 -1
  217. package/core/built/admin/assets/posts-DuGazgTb.js +1 -0
  218. package/core/built/admin/assets/posts-list-screen-CBGGgjjj.js +2 -0
  219. package/core/built/admin/assets/posts-route-D6xmS7Vf.js +1 -0
  220. package/core/built/admin/assets/preferences-C5YJLp74.js +5 -0
  221. package/core/built/admin/assets/{preview-chrome-BOVO6_PE.js → preview-chrome-BljUBlOk.js} +1 -1
  222. package/core/built/admin/assets/{preview-modal-MlTjP8UU.js → preview-modal-BfeFqi5y.js} +1 -1
  223. package/core/built/admin/assets/profile-B8mx2yAu.js +1 -0
  224. package/core/built/admin/assets/{radio-group-CjtmsCPl.js → radio-group-DczlLKOn.js} +1 -1
  225. package/core/built/admin/assets/{router-provider-CJC58zTy.js → router-provider-B0gZyiGJ.js} +1 -1
  226. package/core/built/admin/assets/{schemas-CRsC53ls.js → schemas-DppqmpeJ.js} +2 -2
  227. package/core/built/admin/assets/select-cb0t_TAJ.js +1 -0
  228. package/core/built/admin/assets/settings-DZqxR0Da.js +1 -0
  229. package/core/built/admin/assets/settings-DvfTNdHQ.js +4 -0
  230. package/core/built/admin/assets/{settings-breadcrumbs-sLDNedBW.js → settings-breadcrumbs-DLzbRRSt.js} +1 -1
  231. package/core/built/admin/assets/{shade-app-F7WxOyfk-nufqw1hd.js → shade-app-CcS3f8MZ-vwURazk8.js} +2 -2
  232. package/core/built/admin/assets/share-modal-D2-Bz1_I.js +1 -0
  233. package/core/built/admin/assets/{skeleton-D7hwjdry.js → skeleton-Ce9GgUpf.js} +1 -1
  234. package/core/built/admin/assets/slack-modal-DYDTUria.js +1 -0
  235. package/core/built/admin/assets/sort-button-VVeQjjbu.js +1 -0
  236. package/core/built/admin/assets/{source-icon-BPsD5ees.js → source-icon-Ck5_5Kgq.js} +1 -1
  237. package/core/built/admin/assets/{stack-CIfOAAVf.js → stack-B2eszIiq.js} +1 -1
  238. package/core/built/admin/assets/stats-Rjmk5owg.js +1 -0
  239. package/core/built/admin/assets/stats-view-BGGmkmgv.js +1 -0
  240. package/core/built/admin/assets/{step-1-CMta6YFO.js → step-1-CsaBjeN4.js} +1 -1
  241. package/core/built/admin/assets/{step-2-BG04nh5q.js → step-2-D2vnxOOM.js} +1 -1
  242. package/core/built/admin/assets/{step-3-ZnMaVIPj.js → step-3-wBoLdGEb.js} +2 -2
  243. package/core/built/admin/assets/{stripe-button-DDoUKN5a.js → stripe-button-CDgLz0S0.js} +1 -1
  244. package/core/built/admin/assets/stripe-connect-modal-CSjMJetP.js +1 -0
  245. package/core/built/admin/assets/{switch-C9djUIMO.js → switch-CI4gLWqb.js} +1 -1
  246. package/core/built/admin/assets/{table-CrqQtkR2.js → table-Do6iQ83Q.js} +1 -1
  247. package/core/built/admin/assets/{tabs-CGisSbWq.js → tabs-D2yWLMp_.js} +1 -1
  248. package/core/built/admin/assets/tag-detail-BhXlOsCa.js +2 -0
  249. package/core/built/admin/assets/tags-ldukRApe.js +1 -0
  250. package/core/built/admin/assets/testimonials-modal-CtnZBJKl.js +1 -0
  251. package/core/built/admin/assets/{text-DU9Hv33_.js → text-BQDSDsKs.js} +1 -1
  252. package/core/built/admin/assets/{textarea-d9qEkMOP.js → textarea-DJ1Q5V39.js} +1 -1
  253. package/core/built/admin/assets/tier-detail-modal-BOs8e_G8.js +1 -0
  254. package/core/built/admin/assets/{toggle-group-CtKZURJd.js → toggle-group-ByUJsxwD.js} +1 -1
  255. package/core/built/admin/assets/{topic-filter-D8JT8Tq1.js → topic-filter-BgC3g5_v.js} +1 -1
  256. package/core/built/admin/assets/{transistor-modal-6PUf0idx.js → transistor-modal-Drr0SNfo.js} +1 -1
  257. package/core/built/admin/assets/trend-badge-6ye93YAW.js +1 -0
  258. package/core/built/admin/assets/{unsplash-modal-BPuDBPja.js → unsplash-modal-p6AoQoWp.js} +1 -1
  259. package/core/built/admin/assets/{use-analytics-data--opuzwcz.js → use-analytics-data-CWCMAESo.js} +1 -1
  260. package/core/built/admin/assets/use-check-theme-limit-error-B8bjF-gO.css +1 -0
  261. package/core/built/admin/assets/use-check-theme-limit-error-Cw3WQHy8.js +2 -0
  262. package/core/built/admin/assets/use-filter-params-BIni9taJ.js +1 -0
  263. package/core/built/admin/assets/use-growth-stats-DCVG3s9w.js +1 -0
  264. package/core/built/admin/assets/{use-limiter-TDSNiHPB.js → use-limiter-D2WRRx0H.js} +1 -1
  265. package/core/built/admin/assets/{use-navigate-with-base-path-CK989MlC.js → use-navigate-with-base-path-BHPA228f.js} +1 -1
  266. package/core/built/admin/assets/{use-pintura-config-CnCGrDFk.js → use-pintura-config-h-J0Lvta.js} +1 -1
  267. package/core/built/admin/assets/{use-pintura-editor-ntphvtUd.js → use-pintura-editor-BfN1UwzH.js} +1 -1
  268. package/core/built/admin/assets/use-post-referrers-Czg47m8s.js +1 -0
  269. package/core/built/admin/assets/use-reply-chain-data-ns0caK8k.js +1 -0
  270. package/core/built/admin/assets/{use-router-history-entry-BwfQS2mq.js → use-router-history-entry-uldn7zJO.js} +1 -1
  271. package/core/built/admin/assets/{use-setting-group-DQxV42-O.js → use-setting-group-DpcuCUDg.js} +1 -1
  272. package/core/built/admin/assets/use-settings-navigation-CZjGrhsp.js +1 -0
  273. package/core/built/admin/assets/{use-simple-pagination-B2TdNX67.js → use-simple-pagination-DzJWobPR.js} +1 -1
  274. package/core/built/admin/assets/{use-staff-users-QrR9voeC.js → use-staff-users-Csipb-O0.js} +1 -1
  275. package/core/built/admin/assets/use-tinybird-query-CSnGXzZh.js +1 -0
  276. package/core/built/admin/assets/use-tinybird-token-DTOKRR7e.js +1 -0
  277. package/core/built/admin/assets/{use-unsaved-changes-guard-DpYJcj1d.js → use-unsaved-changes-guard-CBzs-KPi.js} +1 -1
  278. package/core/built/admin/assets/{use-url-input-WnIqckzS.js → use-url-input-DFr8lCbS.js} +1 -1
  279. package/core/built/admin/assets/user-detail-modal-B_iUClI6.js +1 -0
  280. package/core/built/admin/assets/users-Cg-OeGzC.js +1 -0
  281. package/core/built/admin/assets/{virtual-list-D3MfPNOh.js → virtual-list-BW-padMe.js} +1 -1
  282. package/core/built/admin/assets/web-C1v33ehA.js +2 -0
  283. package/core/built/admin/assets/web-C4BKzn2T.js +1 -0
  284. package/core/built/admin/assets/{zapier-modal-BO6PS_Vd.js → zapier-modal-BBFfI6Ml.js} +1 -1
  285. package/core/built/admin/index.html +24 -30
  286. package/core/frontend/apps/private-blogging/lib/views/private.hbs +44 -43
  287. package/core/frontend/helpers/cancel_link.js +2 -2
  288. package/core/frontend/helpers/pagination.js +2 -2
  289. package/core/frontend/helpers/social_accounts.js +2 -2
  290. package/core/frontend/public/ghost.css +1 -1
  291. package/core/frontend/public/ghost.min.css +1 -1
  292. package/core/frontend/services/rendering/renderer.js +15 -0
  293. package/core/frontend/services/sitemap/user-map-generator.js +9 -2
  294. package/core/server/adapters/storage/LocalStorageBase.js +8 -5
  295. package/core/server/api/endpoints/db.js +19 -5
  296. package/core/server/api/endpoints/index.js +6 -2
  297. package/core/server/api/endpoints/mail.js +1 -1
  298. package/core/server/api/endpoints/member-metafields.js +89 -0
  299. package/core/server/api/endpoints/members.js +4 -4
  300. package/core/server/api/endpoints/posts.js +4 -3
  301. package/core/server/api/endpoints/tiers-checkout-config.js +59 -0
  302. package/core/server/api/endpoints/utils/serializers/input/members.js +4 -7
  303. package/core/server/api/endpoints/utils/serializers/output/config.js +1 -0
  304. package/core/server/api/endpoints/utils/serializers/output/index.js +6 -2
  305. package/core/server/api/endpoints/utils/serializers/output/{member-custom-fields.js → member-metafields.js} +2 -4
  306. package/core/server/api/endpoints/utils/serializers/output/members.js +2 -4
  307. package/core/server/api/endpoints/utils/serializers/output/tiers-checkout-config.js +12 -0
  308. package/core/server/api/endpoints/utils/validators/input/invitations.js +0 -5
  309. package/core/server/api/endpoints/utils/validators/input/pages.js +1 -1
  310. package/core/server/api/endpoints/utils/validators/input/posts.js +1 -1
  311. package/core/server/data/exporter/table-lists.js +3 -0
  312. package/core/server/data/importer/content-files.js +57 -0
  313. package/core/server/data/importer/handlers/image.js +2 -2
  314. package/core/server/data/importer/import-archive.js +131 -0
  315. package/core/server/data/importer/import-manager.js +18 -180
  316. package/core/server/data/importer/importers/content-file-importer.js +66 -4
  317. package/core/server/data/importer/importers/data/data-importer.js +3 -3
  318. package/core/server/data/migrations/utils/migrations.js +1 -1
  319. package/core/server/data/migrations/versions/6.61/2026-08-19-14-30-20-add-written-by-to-members-custom-field-values.js +42 -0
  320. package/core/server/data/migrations/versions/6.61/2026-08-19-14-38-53-add-members-custom-field-bindings-table.js +26 -0
  321. package/core/server/data/migrations/versions/6.61/2026-08-19-14-48-06-add-tier-checkout-field-tables.js +35 -0
  322. package/core/server/data/schema/schema.js +90 -0
  323. package/core/server/data/seeders/importers/automation-action-revisions-importer.js +3 -3
  324. package/core/server/data/seeders/importers/automation-actions-importer.js +3 -3
  325. package/core/server/data/seeders/importers/automation-run-steps-importer.js +3 -3
  326. package/core/server/data/seeders/importers/automation-runs-importer.js +5 -5
  327. package/core/server/data/seeders/importers/automations-importer.js +3 -3
  328. package/core/server/data/seeders/importers/comment-reports-importer.js +1 -1
  329. package/core/server/data/seeders/importers/comments-importer.js +1 -1
  330. package/core/server/data/seeders/importers/email-batches-importer.js +1 -1
  331. package/core/server/data/seeders/importers/email-recipients-importer.js +1 -1
  332. package/core/server/data/seeders/importers/emails-importer.js +1 -1
  333. package/core/server/data/seeders/importers/labels-importer.js +1 -1
  334. package/core/server/data/seeders/importers/members-click-events-importer.js +1 -1
  335. package/core/server/data/seeders/importers/members-created-events-importer.js +1 -1
  336. package/core/server/data/seeders/importers/members-feedback-importer.js +1 -1
  337. package/core/server/data/seeders/importers/members-importer.js +1 -1
  338. package/core/server/data/seeders/importers/members-login-events-importer.js +1 -1
  339. package/core/server/data/seeders/importers/members-products-importer.js +1 -1
  340. package/core/server/data/seeders/importers/members-status-events-importer.js +1 -1
  341. package/core/server/data/seeders/importers/members-stripe-customers-importer.js +1 -1
  342. package/core/server/data/seeders/importers/members-stripe-customers-subscriptions-importer.js +1 -1
  343. package/core/server/data/seeders/importers/members-subscribe-events-importer.js +1 -1
  344. package/core/server/data/seeders/importers/members-subscription-created-events-importer.js +1 -1
  345. package/core/server/data/seeders/importers/offer-redemptions-importer.js +1 -1
  346. package/core/server/data/seeders/importers/offers-importer.js +1 -1
  347. package/core/server/data/seeders/importers/posts-importer.js +1 -1
  348. package/core/server/data/seeders/importers/table-importer.js +2 -2
  349. package/core/server/data/seeders/importers/tags-importer.js +1 -1
  350. package/core/server/data/seeders/importers/users-importer.js +1 -1
  351. package/core/server/data/seeders/importers/web-mentions-importer.js +1 -1
  352. package/core/server/data/seeders/utils/random.js +3 -3
  353. package/core/server/ghost-server.js +3 -2
  354. package/core/server/lib/db-types/boolean.js +18 -0
  355. package/core/server/lib/image/image-size.js +24 -0
  356. package/core/server/lib/package-json/parse.js +2 -2
  357. package/core/server/lib/promise-pool.js +31 -0
  358. package/core/server/models/member.js +6 -17
  359. package/core/server/models/post.js +2 -2
  360. package/core/server/models/relations/authors.js +2 -16
  361. package/core/server/models/user.js +9 -2
  362. package/core/server/services/auth/passwordreset.js +13 -0
  363. package/core/server/services/automations/database-automations-repository.js +26 -26
  364. package/core/server/services/automations/poll.js +1 -0
  365. package/core/server/services/comments/comments-controller.js +30 -9
  366. package/core/server/services/comments/comments-service.js +55 -5
  367. package/core/server/services/content-import/csv/formula.js +12 -0
  368. package/core/server/services/content-import/csv/index.js +6 -1
  369. package/core/server/services/content-import/csv/parse.js +27 -6
  370. package/core/server/services/content-import/csv/serialize.js +13 -0
  371. package/core/server/services/content-import/import/assets.js +74 -0
  372. package/core/server/services/content-import/import/completion-email.js +164 -0
  373. package/core/server/services/content-import/import/errors-file.js +36 -0
  374. package/core/server/services/content-import/import/importer.js +204 -54
  375. package/core/server/services/content-import/import/local-media-url.js +63 -0
  376. package/core/server/services/content-import/import/media.js +254 -0
  377. package/core/server/services/content-import/import/post-data.js +1 -1
  378. package/core/server/services/content-import/import/post-link.js +11 -0
  379. package/core/server/services/content-import/import/post-repository.js +100 -0
  380. package/core/server/services/content-import/import/reader.js +9 -2
  381. package/core/server/services/content-import/import/relations.js +149 -0
  382. package/core/server/services/content-import/import/report.js +34 -0
  383. package/core/server/services/content-import/import/row.js +11 -2
  384. package/core/server/services/content-import/import/schema.js +30 -0
  385. package/core/server/services/content-import/import/source.js +125 -0
  386. package/core/server/services/content-import/import/staged-file.js +29 -0
  387. package/core/server/services/content-import/import/store.js +25 -2
  388. package/core/server/services/content-import/index.js +58 -34
  389. package/core/server/services/content-import/jobs/content-csv-import-job.js +20 -0
  390. package/core/server/services/custom-redirects/redirect-config-parser.js +2 -2
  391. package/core/server/services/custom-redirects/redirects-service.js +1 -1
  392. package/core/server/services/custom-redirects/validation.js +1 -1
  393. package/core/server/services/email-address/email-address-parser.js +30 -38
  394. package/core/server/services/email-address/email-address-service.js +37 -4
  395. package/core/server/services/email-analytics/email-analytics-service.js +8 -1
  396. package/core/server/services/email-analytics/index.js +2 -7
  397. package/core/server/services/email-analytics/lib/queries.js +7 -1
  398. package/core/server/services/email-service/batch-sending-service.js +0 -4
  399. package/core/server/services/email-service/email-renderer.js +14 -4
  400. package/core/server/services/email-service/email-service-wrapper.js +0 -9
  401. package/core/server/services/email-service/mailgun-email-provider.js +20 -9
  402. package/core/server/services/gift-links/schema.js +3 -3
  403. package/core/server/services/gifts/CONTEXT.md +1 -1
  404. package/core/server/services/gifts/constants.js +1 -1
  405. package/core/server/services/gifts/email-templates/gift-delivery.hbs +3 -3
  406. package/core/server/services/gifts/gift-bookshelf-repository.js +2 -2
  407. package/core/server/services/gifts/gift-delivery-bookshelf-repository.js +18 -9
  408. package/core/server/services/gifts/gift-delivery-schema.js +5 -5
  409. package/core/server/services/gifts/gift-delivery-service.js +4 -0
  410. package/core/server/services/gifts/gift-email-service.js +0 -1
  411. package/core/server/services/gifts/gift-schema.js +10 -10
  412. package/core/server/services/gifts/gift-service.js +4 -2
  413. package/core/server/services/gifts/index.js +3 -3
  414. package/core/server/services/gifts/jobs/index.js +4 -4
  415. package/core/server/services/indexnow-ping/indexnow-ping-service.js +2 -2
  416. package/core/server/services/invitations/accept.js +4 -2
  417. package/core/server/services/jobs/job-service.js +0 -9
  418. package/core/server/services/jobs-service/register-job-handlers.js +25 -15
  419. package/core/server/services/lib/mailgun-client.js +44 -8
  420. package/core/server/services/mail/ghost-mailer.js +4 -4
  421. package/core/server/services/media-inliner/external-media-inliner-job.js +12 -0
  422. package/core/server/services/media-inliner/external-media-inliner.js +103 -29
  423. package/core/server/services/media-inliner/service.js +13 -41
  424. package/core/server/services/media-inliner/types.js +2 -0
  425. package/core/server/services/member-welcome-emails/service.js +7 -7
  426. package/core/server/services/members/api.js +1 -0
  427. package/core/server/services/members/import-export/csv/parse.js +0 -7
  428. package/core/server/services/members/import-export/export/exporter.js +4 -6
  429. package/core/server/services/members/import-export/import/completion-email.js +2 -5
  430. package/core/server/services/members/import-export/import/importer.js +21 -5
  431. package/core/server/services/members/import-export/import/row.js +0 -3
  432. package/core/server/services/members/import-export/import/stripe-utils.js +6 -1
  433. package/core/server/services/members/import-export/index.js +10 -12
  434. package/core/server/services/members/jobs/clean-expired-comped-job.js +7 -0
  435. package/core/server/services/members/jobs/clean-expired-comped-task.js +145 -0
  436. package/core/server/services/members/jobs/index.js +48 -24
  437. package/core/server/services/members/members-api/controllers/member-controller.js +11 -0
  438. package/core/server/services/members/members-api/controllers/router-controller.js +3 -6
  439. package/core/server/services/members/members-api/members-api.js +9 -6
  440. package/core/server/services/members/members-api/repositories/event-repository.js +0 -4
  441. package/core/server/services/members/members-api/services/member-bread-service.js +53 -63
  442. package/core/server/services/members/members-api/services/payments-service.js +47 -1
  443. package/core/server/services/members/service.js +1 -5
  444. package/core/server/services/members-custom-fields/actions.js +27 -1
  445. package/core/server/services/members-custom-fields/bindings-service.js +120 -0
  446. package/core/server/services/members-custom-fields/codec.js +3 -4
  447. package/core/server/services/members-custom-fields/definitions-service.js +165 -22
  448. package/core/server/services/members-custom-fields/filter.js +75 -93
  449. package/core/server/services/members-custom-fields/index.js +11 -4
  450. package/core/server/services/members-custom-fields/key.js +2 -1
  451. package/core/server/services/members-custom-fields/models.js +1 -1
  452. package/core/server/services/members-custom-fields/queries.js +5 -0
  453. package/core/server/services/members-custom-fields/schema.js +37 -6
  454. package/core/server/services/members-custom-fields/serializers.js +3 -5
  455. package/core/server/services/members-custom-fields/values-service.js +65 -31
  456. package/core/server/services/mentions/mention-controller.js +23 -21
  457. package/core/server/services/mentions/process-webmention-job.js +16 -0
  458. package/core/server/services/mentions/service.js +8 -4
  459. package/core/server/services/public-config/config.js +7 -0
  460. package/core/server/services/route-settings/validation-errors.js +1 -1
  461. package/core/server/services/route-settings/yaml-parser.js +1 -1
  462. package/core/server/services/settings/settings-service.js +1 -8
  463. package/core/server/services/settings-helpers/settings-helpers.js +4 -6
  464. package/core/server/services/slack-ping/slack-ping-service.js +1 -1
  465. package/core/server/services/staff/staff-service-emails.js +2 -2
  466. package/core/server/services/stripe/config.js +14 -8
  467. package/core/server/services/stripe/service.js +10 -1
  468. package/core/server/services/stripe/services/checkout/completed-session.js +68 -0
  469. package/core/server/services/stripe/services/checkout/session-options.js +100 -0
  470. package/core/server/services/stripe/services/webhook/checkout-session-event-service.js +71 -1
  471. package/core/server/services/stripe/stripe-api.js +31 -0
  472. package/core/server/services/stripe/stripe-service.js +26 -9
  473. package/core/server/services/stripe/webhook-controller.js +10 -0
  474. package/core/server/services/tier-checkout-config/codec.js +99 -0
  475. package/core/server/services/tier-checkout-config/index.js +26 -0
  476. package/core/server/services/tier-checkout-config/models.js +63 -0
  477. package/core/server/services/tier-checkout-config/queries.js +80 -0
  478. package/core/server/services/tier-checkout-config/schema.js +33 -0
  479. package/core/server/services/tier-checkout-config/serializers.js +128 -0
  480. package/core/server/services/tier-checkout-config/service.js +304 -0
  481. package/core/server/services/tiers/service.js +21 -0
  482. package/core/server/services/update-check/index.js +13 -13
  483. package/core/server/services/update-check/jobs/update-check-job.js +7 -0
  484. package/core/server/services/update-check/update-check-service.js +2 -2
  485. package/core/server/web/admin/controller.js +1 -1
  486. package/core/server/web/api/endpoints/admin/routes.js +34 -20
  487. package/core/server/web/api/middleware/upload.js +2 -2
  488. package/core/server/web/parent/app.js +5 -0
  489. package/core/server/web/parent/middleware/filter-query-parameters.js +94 -0
  490. package/core/server/web/parent/middleware/index.js +1 -0
  491. package/core/server/web/query-parameter-policy/index.js +9 -0
  492. package/core/server/web/query-parameter-policy/policy.json +58 -0
  493. package/core/server/web/query-parameter-policy/schema.js +38 -0
  494. package/core/shared/config/defaults.json +3 -0
  495. package/core/shared/config/env/config.testing-mysql.json +4 -1
  496. package/core/shared/config/env/config.testing.json +3 -0
  497. package/core/shared/config/overrides.json +4 -2
  498. package/core/shared/labs.js +9 -15
  499. package/package.json +25 -25
  500. package/pnpm-lock.yaml +741 -108
  501. package/pnpm-workspace.yaml +12 -9
  502. package/tsconfig.json +2 -3
  503. package/components/tryghost-kg-default-nodes-2.2.0.tgz +0 -0
  504. package/core/built/admin/assets/Combination-gnJO3vIw.js +0 -41
  505. package/core/built/admin/assets/account-migration-8qTEI1i1.js +0 -1
  506. package/core/built/admin/assets/activitypub/inbox-DQ5CwLma.js +0 -1284
  507. package/core/built/admin/assets/activitypub/label-B72sfvEU.js +0 -16
  508. package/core/built/admin/assets/activitypub/layout-CXajhRsL.js +0 -1
  509. package/core/built/admin/assets/activitypub/settings-71gCm3SO.js +0 -315
  510. package/core/built/admin/assets/add-integration-modal--YpTq3c0.js +0 -1
  511. package/core/built/admin/assets/add-newsletter-modal-C8Ix2hol.js +0 -1
  512. package/core/built/admin/assets/add-recommendation-modal-CScuNFz4.js +0 -1
  513. package/core/built/admin/assets/alert-dialog-wEbVxANM.js +0 -1
  514. package/core/built/admin/assets/analytics-Cnji45H5.js +0 -1
  515. package/core/built/admin/assets/app-utils-D2Wp7ZSS.js +0 -1
  516. package/core/built/admin/assets/audience-DTLMXAFH.js +0 -1
  517. package/core/built/admin/assets/automations-BWpRCZ_f.js +0 -1
  518. package/core/built/admin/assets/bluesky-sharing-DHOpQxff.js +0 -1
  519. package/core/built/admin/assets/chart-helpers-B3OqQ6Ez.js +0 -1
  520. package/core/built/admin/assets/color-picker-Bmo1r9Fc.js +0 -3
  521. package/core/built/admin/assets/color-picker-field-DywowPhF.js +0 -1
  522. package/core/built/admin/assets/combobox-C4QCh6Yw.js +0 -1
  523. package/core/built/admin/assets/command-DcLbSifC.js +0 -1
  524. package/core/built/admin/assets/comments-Bxy_3WyE.js +0 -1
  525. package/core/built/admin/assets/confirmation-context-CLFHhyyH.js +0 -1
  526. package/core/built/admin/assets/custom-field-type-option-D0PXoSnP.js +0 -10
  527. package/core/built/admin/assets/custom-integration-modal-DCIHKN33.js +0 -1
  528. package/core/built/admin/assets/design-and-theme-modal-CZ-PkW7o.js +0 -23
  529. package/core/built/admin/assets/dialog-Db7c164G.js +0 -1
  530. package/core/built/admin/assets/dirty-confirm-dialog-CmARpZQS.js +0 -1
  531. package/core/built/admin/assets/dist-QLZuGq7o2.js +0 -1
  532. package/core/built/admin/assets/domain-D0SAtc-T.js +0 -1
  533. package/core/built/admin/assets/dropzone-CaPOeDRZ.js +0 -5
  534. package/core/built/admin/assets/edit-profile-By7v5XW5.js +0 -1
  535. package/core/built/admin/assets/editor-COXn4Atu.js +0 -8
  536. package/core/built/admin/assets/explore-BsNYrubV.js +0 -1
  537. package/core/built/admin/assets/feed-8RR1O1bK.js +0 -1
  538. package/core/built/admin/assets/filter-sources-4C0kF1NU.js +0 -1
  539. package/core/built/admin/assets/filters-CV5jCb9n.js +0 -1
  540. package/core/built/admin/assets/filters-Dmr0PoqU.js +0 -1
  541. package/core/built/admin/assets/first-promoter-modal-OCzSaL3B.js +0 -1
  542. package/core/built/admin/assets/gift-link-modal-0mzjn5oF.js +0 -1
  543. package/core/built/admin/assets/growth-55vWlGT_.js +0 -1
  544. package/core/built/admin/assets/growth-DA5AluYw.js +0 -3
  545. package/core/built/admin/assets/history-modal-G1s5hHz7.js +0 -1
  546. package/core/built/admin/assets/html-field-BegxsWpw.js +0 -1
  547. package/core/built/admin/assets/index-CDP9tIOk.js +0 -4
  548. package/core/built/admin/assets/index-Dqf2x-ry.css +0 -1
  549. package/core/built/admin/assets/index.es-BMUCj9TR.js +0 -1
  550. package/core/built/admin/assets/input-UHrKuvBT.js +0 -1
  551. package/core/built/admin/assets/invite-user-modal-BrAkxEO3.js +0 -1
  552. package/core/built/admin/assets/koenig-loader-DwVY_V-H.js +0 -1
  553. package/core/built/admin/assets/kpi-card-LERqWBoY.js +0 -1
  554. package/core/built/admin/assets/kpi-helpers-DB3ouhYF.js +0 -1
  555. package/core/built/admin/assets/kpi-tabs-BGvtMD8S.js +0 -1
  556. package/core/built/admin/assets/label-picker-BBWykUeA.js +0 -1
  557. package/core/built/admin/assets/layout-Di5K7doM.js +0 -1
  558. package/core/built/admin/assets/loading-indicator-SFTqyYVE.js +0 -1
  559. package/core/built/admin/assets/member-custom-fields-gOv6Hoh3.js +0 -1
  560. package/core/built/admin/assets/member-detail-D7mZDDp3.js +0 -1
  561. package/core/built/admin/assets/member-route-0Aa52Ntz.js +0 -1
  562. package/core/built/admin/assets/members-DvZG9t69.js +0 -2
  563. package/core/built/admin/assets/moderation-DzzPLDyl.js +0 -1
  564. package/core/built/admin/assets/navigation-modal-CI8Bx5vn.js +0 -1
  565. package/core/built/admin/assets/newsletter-Bg3cq5U-.js +0 -1
  566. package/core/built/admin/assets/newsletter-detail-modal-DQU3r4g2.js +0 -1
  567. package/core/built/admin/assets/newsletters-DMDfZbMS.js +0 -1
  568. package/core/built/admin/assets/note-i8k6pjaw.js +0 -1
  569. package/core/built/admin/assets/notifications-psA_2Ph4.js +0 -1
  570. package/core/built/admin/assets/offers-container-modal-BWfjSdyg.js +0 -1
  571. package/core/built/admin/assets/onboarding-DGQuV7Ew.js +0 -1
  572. package/core/built/admin/assets/overview-C-6xOLaf.js +0 -1
  573. package/core/built/admin/assets/overview-DaLhpRrC.js +0 -1
  574. package/core/built/admin/assets/pages-B6vr9F_D.js +0 -1
  575. package/core/built/admin/assets/popover-CFgqFDvC.js +0 -1
  576. package/core/built/admin/assets/portal-frame-DjBF-uy2.js +0 -1
  577. package/core/built/admin/assets/portal-modal-Cf0pBAk8.js +0 -1
  578. package/core/built/admin/assets/post-analytics-Buz1COoY.js +0 -1
  579. package/core/built/admin/assets/post-analytics-header-B-P0eFnT.js +0 -1
  580. package/core/built/admin/assets/posts-KY3aUhVV.js +0 -1
  581. package/core/built/admin/assets/preferences-Cq1aOiLy.js +0 -5
  582. package/core/built/admin/assets/profile-D6dHYf2o.js +0 -1
  583. package/core/built/admin/assets/select-D_RQaXgt.js +0 -1
  584. package/core/built/admin/assets/settings-B5hJKZ5C.js +0 -1
  585. package/core/built/admin/assets/settings-DIo_F-MF.js +0 -4
  586. package/core/built/admin/assets/share-modal-CLBfj377.js +0 -1
  587. package/core/built/admin/assets/shim-ClF_m5ux.js +0 -1
  588. package/core/built/admin/assets/slack-modal-Bt9I_tEo.js +0 -1
  589. package/core/built/admin/assets/sort-button-DMBXF7tP.js +0 -1
  590. package/core/built/admin/assets/stats-B_YkF7bp.js +0 -1
  591. package/core/built/admin/assets/stats-view-BOCp9RG8.js +0 -1
  592. package/core/built/admin/assets/stripe-connect-modal-BeSukI8q.js +0 -1
  593. package/core/built/admin/assets/tag-detail-2a3BfzTW.js +0 -2
  594. package/core/built/admin/assets/tags-Dp2_8UzL.js +0 -1
  595. package/core/built/admin/assets/testimonials-modal-C9nrypNo.js +0 -1
  596. package/core/built/admin/assets/tier-detail-modal-CxRwgTPR.js +0 -1
  597. package/core/built/admin/assets/use-check-theme-limit-error-C9-QhGdV.js +0 -1
  598. package/core/built/admin/assets/use-filter-params-CSpAvgD2.js +0 -1
  599. package/core/built/admin/assets/use-growth-stats-BOmoPDHJ.js +0 -1
  600. package/core/built/admin/assets/use-post-referrers-CbXLFIex.js +0 -1
  601. package/core/built/admin/assets/use-reply-chain-data-JYFKSO83.js +0 -1
  602. package/core/built/admin/assets/use-settings-navigation-BBzro2-V.js +0 -1
  603. package/core/built/admin/assets/use-tinybird-query-D2Aeoty5.js +0 -39
  604. package/core/built/admin/assets/use-tinybird-token-DBuwMmln.js +0 -1
  605. package/core/built/admin/assets/user-detail-modal-59mBJqxN.js +0 -1
  606. package/core/built/admin/assets/users-5msE1WMs.js +0 -1
  607. package/core/built/admin/assets/web-DUuX7nE2.js +0 -2
  608. package/core/built/admin/assets/web-N8ucs2aG.js +0 -1
  609. package/core/server/api/endpoints/member-custom-fields.js +0 -100
  610. package/core/server/services/jobs/worker-model-event-bridge.js +0 -149
  611. package/core/server/services/members/jobs/clean-expired-comped.js +0 -132
  612. package/core/server/services/update-check/run-update-check.js +0 -63
  613. /package/core/server/lib/{db-date.js → db-types/date.js} +0 -0
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DbCustomFieldLeaf = exports.DbCustomFieldValue = exports.DbCustomField = exports.FieldStatusSchema = exports.FIELD_STATUS = void 0;
3
+ exports.DbBoundField = exports.DbCustomFieldBinding = exports.DbCustomFieldLeaf = exports.DbCustomFieldValue = exports.WrittenBy = exports.DbCustomField = exports.FieldStatusSchema = exports.FIELD_STATUS = void 0;
4
4
  const zod_1 = require("zod");
5
5
  const custom_field_types_1 = require("@tryghost/custom-field-types");
6
- const db_date_1 = require("../../lib/db-date");
6
+ const date_1 = require("../../lib/db-types/date");
7
7
  // `archived` is soft: the field drops out of the values path but stays in the definition
8
8
  // list so it can be renamed, restored or deleted. Mirrors schema.js's `isIn` on the
9
9
  // column, which is static config and cannot import this.
@@ -17,9 +17,21 @@ exports.DbCustomField = zod_1.z.object({
17
17
  name: zod_1.z.string(),
18
18
  type: custom_field_types_1.FieldTypeSchema,
19
19
  status: exports.FieldStatusSchema,
20
- created_at: db_date_1.DbDate,
21
- updated_at: db_date_1.DbDate.nullable(),
20
+ created_at: date_1.DbDate,
21
+ updated_at: date_1.DbDate.nullable(),
22
22
  });
23
+ /**
24
+ * How a value arrived, not who caused it: who edited a member's fields is already an
25
+ * action, and Stripe is not a person. `type` is the namespace that makes `id` resolvable —
26
+ * `users`, `integrations`, `members_custom_field_bindings` — so the one writer that
27
+ * resolves in no table is the one with no id to give.
28
+ */
29
+ exports.WrittenBy = zod_1.z.discriminatedUnion('type', [
30
+ zod_1.z.object({ type: zod_1.z.literal('user'), id: zod_1.z.string() }),
31
+ zod_1.z.object({ type: zod_1.z.literal('integration'), id: zod_1.z.string() }),
32
+ zod_1.z.object({ type: zod_1.z.literal('binding'), id: zod_1.z.string() }),
33
+ zod_1.z.object({ type: zod_1.z.literal('import'), id: zod_1.z.null() }),
34
+ ]);
23
35
  // One part of a member's value. What a `path` means is storage.ts's business, so the row
24
36
  // carries it as a plain string.
25
37
  exports.DbCustomFieldValue = zod_1.z.object({
@@ -30,8 +42,13 @@ exports.DbCustomFieldValue = zod_1.z.object({
30
42
  // Nullable like the column, though nothing here writes a null: a part with no value
31
43
  // has no row.
32
44
  value_text: zod_1.z.string().nullable(),
33
- created_at: db_date_1.DbDate,
34
- updated_at: db_date_1.DbDate.nullable(),
45
+ // Plain columns rather than the `WrittenBy` union: the rule holds at the write
46
+ // boundary, so one malformed row cannot throw away a member's whole profile on read.
47
+ written_by_type: zod_1.z.string(),
48
+ // Null for the one writer that resolves nowhere: an import, until runs are tracked.
49
+ written_by_id: zod_1.z.string().nullable(),
50
+ created_at: date_1.DbDate,
51
+ updated_at: date_1.DbDate.nullable(),
35
52
  });
36
53
  // The field's key travels with the row so a value assembles without a second lookup.
37
54
  //
@@ -45,3 +62,17 @@ exports.DbCustomFieldLeaf = zod_1.z.object({
45
62
  path: zod_1.z.string(),
46
63
  value_text: zod_1.z.string(),
47
64
  });
65
+ exports.DbCustomFieldBinding = zod_1.z.object({
66
+ id: zod_1.z.string(),
67
+ product_id: zod_1.z.string(),
68
+ port: zod_1.z.string(),
69
+ custom_field_key: zod_1.z.string(),
70
+ created_at: date_1.DbDate,
71
+ updated_at: date_1.DbDate.nullable(),
72
+ });
73
+ /** A binding joined to the field it points at, which is how a collected value is routed. */
74
+ exports.DbBoundField = zod_1.z.object({
75
+ binding_id: zod_1.z.string(),
76
+ key: zod_1.z.string(),
77
+ type: custom_field_types_1.FieldTypeSchema,
78
+ });
@@ -4,10 +4,8 @@ exports.toCustomFieldsResponse = void 0;
4
4
  const zod_1 = require("zod");
5
5
  const case_keys_1 = require("../../lib/case-keys");
6
6
  const models_1 = require("./models");
7
- // Response schema — the field-definition shape the admin endpoints emit. `id` is
8
- // the DB primary key and deliberately never leaves the API; a field is addressed
9
- // by its immutable `key`. The `.pipe` below strips id from the mapped output.
10
7
  const CustomFieldResource = zod_1.z.object({
8
+ namespace: zod_1.z.string(),
11
9
  key: zod_1.z.string(),
12
10
  name: zod_1.z.string(),
13
11
  type: zod_1.z.string(),
@@ -15,10 +13,10 @@ const CustomFieldResource = zod_1.z.object({
15
13
  created_at: zod_1.z.date(),
16
14
  updated_at: zod_1.z.date().nullable(),
17
15
  });
18
- const CustomFieldsResponse = zod_1.z.object({ members_custom_fields: zod_1.z.array(CustomFieldResource) });
16
+ const CustomFieldsResponse = zod_1.z.object({ members_metafields: zod_1.z.array(CustomFieldResource) });
19
17
  exports.toCustomFieldsResponse = zod_1.z
20
18
  .array(models_1.CustomField)
21
19
  .transform((fields) => ({
22
- members_custom_fields: fields.map((field) => (0, case_keys_1.snakeKeys)(field)),
20
+ members_metafields: fields.map((field) => (0, case_keys_1.snakeKeys)(field)),
23
21
  }))
24
22
  .pipe(CustomFieldsResponse);
@@ -9,6 +9,7 @@ const errors_1 = __importDefault(require("@tryghost/errors"));
9
9
  const logging_1 = __importDefault(require("@tryghost/logging"));
10
10
  const zod_1 = require("zod");
11
11
  const custom_field_types_1 = require("@tryghost/custom-field-types");
12
+ const identity_1 = require("@tryghost/custom-field-types/identity");
12
13
  const schema_1 = require("./schema");
13
14
  const queries_1 = require("./queries");
14
15
  const storage_1 = require("./storage");
@@ -29,9 +30,9 @@ const MAX_KEY_LENGTH = require('../../data/schema').tables[FIELDS_TABLE].key.max
29
30
  * go when that lands; until then the alternative is hand-written upsert SQL per engine.
30
31
  */
31
32
  const UPSERT_CHUNK = 400;
32
- // Values stay `unknown`: each is validated by its own field type, which is not known
33
- // until the key is resolved to a definition.
34
- const ValuesInput = zod_1.z.record(zod_1.z.string().max(MAX_KEY_LENGTH), zod_1.z.unknown());
33
+ const MAX_IDENTITY_LENGTH = MAX_KEY_LENGTH * 2 + 1;
34
+ const ValuesInput = zod_1.z.record(zod_1.z.string().max(MAX_IDENTITY_LENGTH), zod_1.z.unknown());
35
+ const wireProperty = (identity) => [identity_1.QUALIFIER, identity].join('.');
35
36
  /**
36
37
  * What a member holds for each defined field. Separate from the definitions service
37
38
  * because a value belongs to the member and a definition belongs to the site's settings,
@@ -45,22 +46,22 @@ class CustomFieldValuesService {
45
46
  this.knex = knex;
46
47
  this.getMaxDefinitions = getMaxDefinitions;
47
48
  }
48
- async activeFieldsByKey(keys) {
49
+ async activeFieldsByIdentity(identities) {
50
+ const keys = identities
51
+ .map((identity) => (0, identity_1.parseIdentity)(identity))
52
+ .filter((parsed) => parsed !== null && parsed.namespace === identity_1.CUSTOM_NAMESPACE)
53
+ .map((parsed) => parsed.key);
49
54
  if (keys.length === 0) {
50
55
  return new Map();
51
56
  }
52
57
  const fields = await (0, queries_1.activeFields)(this.knex)
53
58
  .whereIn('key', keys)
54
59
  .select('id', 'key', 'name', 'type');
55
- return new Map(fields.map((field) => [field.key, field]));
60
+ return new Map(fields.map((field) => [
61
+ (0, identity_1.formatIdentity)({ namespace: identity_1.CUSTOM_NAMESPACE, key: field.key, partPath: null }),
62
+ { ...field, namespace: identity_1.CUSTOM_NAMESPACE },
63
+ ]));
56
64
  }
57
- /**
58
- * Members' values, keyed by member id then field key; anything absent is unset.
59
- *
60
- * Archived fields are excluded to match the definitions browse: their values stay in
61
- * the database and stop being addressable. A row that will not parse is dropped and
62
- * logged rather than failing the read, so one stale row cannot take down a member.
63
- */
64
65
  async getValuesForMembers(memberIds) {
65
66
  if (memberIds.length === 0) {
66
67
  return new Map();
@@ -80,22 +81,51 @@ class CustomFieldValuesService {
80
81
  leaves.push(schema_1.DbCustomFieldLeaf.parse(row));
81
82
  }
82
83
  catch (err) {
83
- logging_1.default.warn(`Skipping unreadable custom field value (field '${row.key}', path '${row.path}'): ${err instanceof Error ? err.message : String(err)}`);
84
+ logging_1.default.warn({
85
+ event: { name: 'members.custom_fields.value_unreadable' },
86
+ err,
87
+ customFieldKey: row.key,
88
+ path: row.path,
89
+ }, 'Skipping an unreadable custom field value');
84
90
  }
85
91
  }
86
- return (0, storage_1.valuesFromLeaves)(leaves);
92
+ const flat = (0, storage_1.valuesFromLeaves)(leaves);
93
+ return new Map(memberIds.map((memberId) => [memberId, { [identity_1.CUSTOM_NAMESPACE]: flat.get(memberId) ?? {} }]));
87
94
  }
88
- /** Shared by every caller so they cannot disagree on what a values object is. */
89
95
  parseValues(input) {
90
96
  const parsed = ValuesInput.safeParse(input);
91
97
  if (!parsed.success) {
92
98
  throw new errors_1.default.ValidationError({
93
- message: 'Custom field values must be an object keyed by field key.',
94
- property: 'custom_fields',
99
+ message: 'Custom field values must be an object keyed by field identity.',
100
+ property: identity_1.QUALIFIER,
95
101
  });
96
102
  }
97
103
  return parsed.data;
98
104
  }
105
+ unwrapWire(input) {
106
+ if (input === undefined) {
107
+ return undefined;
108
+ }
109
+ if (typeof input !== 'object' || input === null || Array.isArray(input)) {
110
+ throw new errors_1.default.ValidationError({
111
+ message: 'Metafields must be an object keyed by namespace.',
112
+ property: identity_1.QUALIFIER,
113
+ });
114
+ }
115
+ const identified = {};
116
+ for (const [namespace, values] of Object.entries(input)) {
117
+ if (typeof values !== 'object' || values === null || Array.isArray(values)) {
118
+ throw new errors_1.default.ValidationError({
119
+ message: 'Metafield values must be an object keyed by field key.',
120
+ property: [identity_1.QUALIFIER, namespace].join('.'),
121
+ });
122
+ }
123
+ for (const [key, raw] of Object.entries(values)) {
124
+ identified[`${namespace}.${key}`] = raw;
125
+ }
126
+ }
127
+ return identified;
128
+ }
99
129
  /**
100
130
  * Whether input names any values. Asks the shape question alone, with no catalog
101
131
  * lookup, so it can be asked before a write is known to be permitted.
@@ -113,27 +143,24 @@ class CustomFieldValuesService {
113
143
  */
114
144
  async planWrite(input) {
115
145
  const values = this.parseValues(input);
116
- const keys = Object.keys(values);
146
+ const identities = Object.keys(values);
117
147
  // Bounded by the definitions ceiling, which also holds the lookup below inside
118
148
  // the driver's bound-parameter limit.
119
149
  const maxKeys = this.getMaxDefinitions();
120
- if (keys.length > maxKeys) {
150
+ if (identities.length > maxKeys) {
121
151
  throw new errors_1.default.ValidationError({
122
152
  message: `Custom field values are limited to ${maxKeys} fields per request.`,
123
- property: 'custom_fields',
153
+ property: identity_1.QUALIFIER,
124
154
  });
125
155
  }
126
- const byKey = await this.activeFieldsByKey(keys);
156
+ const byIdentity = await this.activeFieldsByIdentity(identities);
127
157
  const writes = [];
128
- for (const [key, raw] of Object.entries(values)) {
129
- const field = byKey.get(key);
158
+ for (const [identity, raw] of Object.entries(values)) {
159
+ const field = byIdentity.get(identity);
130
160
  if (!field) {
131
- // Unknown or archived. Refused rather than ignored: a typo that silently
132
- // drops what somebody typed is worse than a save that fails. The catalog
133
- // applies the same rule to the parts of a composite value.
134
161
  throw new errors_1.default.ValidationError({
135
- message: `Unknown custom field: ${key}`,
136
- property: `custom_fields.${key}`,
162
+ message: `Unknown custom field: ${identity}`,
163
+ property: wireProperty(identity),
137
164
  });
138
165
  }
139
166
  // `null` clears any field, and `''` clears one with no parts. For a value
@@ -152,7 +179,7 @@ class CustomFieldValuesService {
152
179
  const issue = value.error.issues[0];
153
180
  throw new errors_1.default.ValidationError({
154
181
  message: issue.message,
155
- property: [`custom_fields.${key}`, ...issue.path].join('.'),
182
+ property: [wireProperty(identity), ...issue.path].join('.'),
156
183
  });
157
184
  }
158
185
  writes.push({ field, value: value.data });
@@ -167,10 +194,13 @@ class CustomFieldValuesService {
167
194
  * them, and saying nothing about a path leaves it alone. There is no whole-value
168
195
  * replace, so a caller that does not know about a field cannot erase it.
169
196
  *
197
+ * `writtenBy` is required and has no default: every writer has to name itself, so a new
198
+ * one cannot quietly inherit the identity of whichever was written first.
199
+ *
170
200
  * Always transactional. Given an executor it joins that transaction, so the importer's
171
201
  * failed value write takes its member with it; given none it opens its own.
172
202
  */
173
- async applyWrite(memberId, writes, { executor = this.knex } = {}) {
203
+ async applyWrite(memberId, writes, { writtenBy, executor = this.knex }) {
174
204
  if (writes.length === 0) {
175
205
  return;
176
206
  }
@@ -197,6 +227,8 @@ class CustomFieldValuesService {
197
227
  custom_field_key: field.key,
198
228
  path: leaf.path,
199
229
  value_text: leaf.value_text,
230
+ written_by_type: writtenBy.type,
231
+ written_by_id: writtenBy.id,
200
232
  created_at: now,
201
233
  updated_at: now,
202
234
  })));
@@ -227,7 +259,9 @@ class CustomFieldValuesService {
227
259
  // Naming the columns rather than giving values takes each from the row
228
260
  // that lost the conflict, so every part updates to its own value.
229
261
  .onConflict(['member_id', 'custom_field_key', 'path'])
230
- .merge(['value_text', 'updated_at']);
262
+ // The writer is merged with the value, so a leaf names who wrote what
263
+ // it currently holds rather than who wrote its first value.
264
+ .merge(['value_text', 'written_by_type', 'written_by_id', 'updated_at']);
231
265
  }
232
266
  };
233
267
  // knex's marker for a transactor: join it rather than nesting a savepoint under it.
@@ -1,4 +1,5 @@
1
1
  const logging = require('@tryghost/logging');
2
+ const ProcessWebmentionJob = require('./process-webmention-job').default;
2
3
 
3
4
  /**
4
5
  * @typedef {import('./mentions-api')} MentionsAPI
@@ -22,11 +23,6 @@ const logging = require('@tryghost/logging');
22
23
  * @prop {Resource} resource
23
24
  */
24
25
 
25
- /**
26
- * @typedef {object} IJobService
27
- * @prop {(name: string, fn: Function) => void} addJob
28
- */
29
-
30
26
  /**
31
27
  * @typedef {object} IMentionResourceService
32
28
  * @prop {(id: import('bson-objectid').default) => Promise<MentionResource>} getByID
@@ -36,8 +32,8 @@ module.exports = class MentionController {
36
32
  /** @type {import('./mentions-api')} */
37
33
  #api;
38
34
 
39
- /** @type {IJobService} */
40
- #jobService;
35
+ /** @type {import('../jobs-service/jobs-service').JobsService} */
36
+ #jobsService;
41
37
 
42
38
  /** @type {IMentionResourceService} */
43
39
  #mentionResourceService;
@@ -45,12 +41,12 @@ module.exports = class MentionController {
45
41
  /**
46
42
  * @param {object} deps
47
43
  * @param {import('./mentions-api')} deps.api
48
- * @param {IJobService} deps.jobService
44
+ * @param {import('../jobs-service/jobs-service').JobsService} deps.jobsService
49
45
  * @param {IMentionResourceService} deps.mentionResourceService
50
46
  */
51
47
  async init(deps) {
52
48
  this.#api = deps.api;
53
- this.#jobService = deps.jobService;
49
+ this.#jobsService = deps.jobsService;
54
50
  this.#mentionResourceService = deps.mentionResourceService;
55
51
  }
56
52
 
@@ -127,17 +123,23 @@ module.exports = class MentionController {
127
123
  */
128
124
  async receive(frame) {
129
125
  logging.info('[Webmention] ' + JSON.stringify(frame.data));
130
- this.#jobService.addJob('processWebmention', async () => {
131
- const { source, target, ...payload } = frame.data;
132
- try {
133
- await this.#api.processWebmention({
134
- source: new URL(source),
135
- target: new URL(target),
136
- payload,
137
- });
138
- } catch (err) {
139
- logging.error(err, '[Webmention] Failed processing webmention');
140
- }
141
- });
126
+ const { source, target, ...payload } = frame.data;
127
+ await this.#jobsService.dispatch(new ProcessWebmentionJob({ source, target, payload }));
128
+ }
129
+
130
+ /**
131
+ * @param {import('./process-webmention-job').default} job
132
+ * @returns {Promise<void>}
133
+ */
134
+ async processWebmention({ source, target, payload }) {
135
+ try {
136
+ await this.#api.processWebmention({
137
+ source: new URL(source),
138
+ target: new URL(target),
139
+ payload,
140
+ });
141
+ } catch (err) {
142
+ logging.error(err, '[Webmention] Failed processing webmention');
143
+ }
142
144
  }
143
145
  };
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const job_1 = require("../jobs-service/job");
4
+ class ProcessWebmentionJob extends job_1.Job {
5
+ static type = 'process-webmention';
6
+ source;
7
+ target;
8
+ payload;
9
+ constructor({ source, target, payload, }) {
10
+ super();
11
+ this.source = source;
12
+ this.target = target;
13
+ this.payload = payload;
14
+ }
15
+ }
16
+ exports.default = ProcessWebmentionJob;
@@ -15,7 +15,7 @@ const urlService = require('../url');
15
15
  const settingsCache = require('../../../shared/settings-cache');
16
16
  const DomainEvents = require('@tryghost/domain-events');
17
17
  const logging = require('@tryghost/logging');
18
- const jobsService = require('../mentions-jobs');
18
+ const mentionsJobService = require('../mentions-jobs');
19
19
 
20
20
  // Serializes a post model to the data the URL service needs, loading the
21
21
  // relations it reads for filtered collections (event-emitted models don't
@@ -45,7 +45,7 @@ function makeLoggingJobService() {
45
45
  return {
46
46
  async addJob(name, fn) {
47
47
  logging.info(`[Background Job] ${name} queued`);
48
- jobsService.addJob({
48
+ mentionsJobService.addJob({
49
49
  name,
50
50
  job: async () => {
51
51
  const startedAt = Date.now();
@@ -75,7 +75,11 @@ module.exports = {
75
75
  /** @type {import('./mention-sending-service')} */
76
76
  sendingService: null,
77
77
  didInit: false,
78
- async init() {
78
+ /**
79
+ * @param {object} deps
80
+ * @param {import('../jobs-service/jobs-service').JobsService} deps.jobsService
81
+ */
82
+ async init({ jobsService }) {
79
83
  if (this.didInit) {
80
84
  return;
81
85
  }
@@ -110,7 +114,7 @@ module.exports = {
110
114
 
111
115
  this.controller.init({
112
116
  api,
113
- jobService: makeLoggingJobService(),
117
+ jobsService,
114
118
  mentionResourceService: {
115
119
  async getByID(id) {
116
120
  if (!id) {
@@ -86,5 +86,12 @@ module.exports = function getConfigProperties() {
86
86
  };
87
87
  }
88
88
 
89
+ if (config.get('docsbot')) {
90
+ configProperties.docsbot = {
91
+ enabled: config.get('docsbot:enabled'),
92
+ id: config.get('docsbot:id'),
93
+ };
94
+ }
95
+
89
96
  return configProperties;
90
97
  };
@@ -14,7 +14,7 @@ const tpl_1 = __importDefault(require("@tryghost/tpl"));
14
14
  const messages = {
15
15
  validationError: 'The following definition "{at}" is invalid: {reason}',
16
16
  };
17
- const DOCS_URL = 'https://ghost.org/docs/themes/routing/';
17
+ const DOCS_URL = 'https://docs.ghost.org/themes/routing/';
18
18
  const MAX_SHOWN_LENGTH = 40;
19
19
  /**
20
20
  * Stable, machine-readable codes describing the class of a routes.yaml failure.
@@ -9,7 +9,7 @@ const messages = {
9
9
  },
10
10
  invalidYamlFormat: {
11
11
  message: 'YAML input cannot be a plain string. Check the format of your YAML file.',
12
- help: 'https://ghost.org/docs/themes/routing/',
12
+ help: 'https://docs.ghost.org/themes/routing/',
13
13
  },
14
14
  };
15
15
 
@@ -200,14 +200,7 @@ module.exports = {
200
200
  type: 'boolean',
201
201
  group: 'members',
202
202
  fn: settingsHelpers.allowSelfSignup.bind(settingsHelpers),
203
- dependents: [
204
- 'members_signup_access',
205
- 'portal_plans',
206
- 'stripe_secret_key',
207
- 'stripe_publishable_key',
208
- 'stripe_connect_secret_key',
209
- 'stripe_connect_publishable_key',
210
- ],
203
+ dependents: ['members_signup_access'],
211
204
  }),
212
205
  );
213
206
  fields.push(
@@ -1,7 +1,7 @@
1
1
  const net = require('net');
2
2
  const tpl = require('@tryghost/tpl');
3
3
  const errors = require('@tryghost/errors');
4
- const EmailAddressParser = require('../email-address/email-address-parser');
4
+ const emailAddressParser = require('../email-address/email-address-parser');
5
5
  const logging = require('@tryghost/logging');
6
6
  const crypto = require('crypto');
7
7
  const debug = require('@tryghost/debug')('services:settings-helpers');
@@ -130,11 +130,9 @@ class SettingsHelpers {
130
130
  if (!supportAddress) {
131
131
  // In the new flow, we make a difference between an empty setting (= use default) and a 'noreply' setting (=use noreply @ domain)
132
132
  // Also keep the name of the default email!
133
- return EmailAddressParser.stringify(this.getDefaultEmail());
133
+ return emailAddressParser.stringify(this.getDefaultEmail());
134
134
  }
135
135
 
136
- supportAddress = supportAddress || 'noreply';
137
-
138
136
  // Any fromAddress without domain uses site domain, like default setting `noreply`
139
137
  if (supportAddress.indexOf('@') < 0) {
140
138
  return `${supportAddress}@${this.getDefaultEmailDomain()}`;
@@ -143,7 +141,7 @@ class SettingsHelpers {
143
141
  }
144
142
 
145
143
  /**
146
- * @deprecated Use getDefaultEmail().address (without name) or EmailAddressParser.stringify(this.getDefaultEmail()) (with name) instead
144
+ * @deprecated Use getDefaultEmail().address (without name) or emailAddressParser.stringify(this.getDefaultEmail()) (with name) instead
147
145
  */
148
146
  getNoReplyAddress() {
149
147
  return this.getDefaultEmailAddress();
@@ -157,7 +155,7 @@ class SettingsHelpers {
157
155
  // parse the email here and remove the sender name
158
156
  // E.g. when set to "bar" <from@default.com>
159
157
  const configAddress = this.config.get('mail:from');
160
- const parsed = EmailAddressParser.parse(configAddress);
158
+ const parsed = emailAddressParser.parse(configAddress);
161
159
  if (parsed) {
162
160
  return parsed;
163
161
  }
@@ -173,7 +173,7 @@ class SlackPingService {
173
173
  this.logging.error(new errors_1.default.InternalServerError({
174
174
  err: err,
175
175
  context: (0, tpl_1.default)(constants_1.messages.requestFailedError, { service: 'slack' }),
176
- help: (0, tpl_1.default)(constants_1.messages.requestFailedHelp, { url: 'https://ghost.org/docs/' }),
176
+ help: (0, tpl_1.default)(constants_1.messages.requestFailedHelp, { url: 'https://docs.ghost.org/' }),
177
177
  }));
178
178
  });
179
179
  }
@@ -2,7 +2,7 @@ const { promises: fs, readFileSync } = require('fs');
2
2
  const path = require('path');
3
3
  const moment = require('moment');
4
4
  const { globSync } = require('glob');
5
- const EmailAddressParser = require('../email-address/email-address-parser');
5
+ const emailAddressParser = require('../email-address/email-address-parser');
6
6
 
7
7
  class StaffServiceEmails {
8
8
  constructor({
@@ -593,7 +593,7 @@ class StaffServiceEmails {
593
593
  }
594
594
 
595
595
  get fromEmailAddress() {
596
- return EmailAddressParser.stringify(this.settingsHelpers.getDefaultEmail());
596
+ return emailAddressParser.stringify(this.settingsHelpers.getDefaultEmail());
597
597
  }
598
598
 
599
599
  extractInitials(name = '') {
@@ -4,7 +4,7 @@ const labs = require('../../../shared/labs');
4
4
 
5
5
  const messages = {
6
6
  remoteWebhooksInDevelopment:
7
- 'Cannot use remote webhooks in development. See https://ghost.org/docs/webhooks/#stripe-webhooks for developing with Stripe.',
7
+ 'Cannot use remote webhooks in development. See https://docs.ghost.org/webhooks/#stripe-webhooks for developing with Stripe.',
8
8
  };
9
9
 
10
10
  // @TODO Refactor to a class w/ constructor
@@ -62,16 +62,19 @@ module.exports = {
62
62
  }
63
63
 
64
64
  const env = config.get('env');
65
- let webhookSecret = process.env.WEBHOOK_SECRET;
65
+ const remoteWebhooks = env !== 'production' && config.get('stripeRemoteWebhooks') === true;
66
+ let webhookSecret = remoteWebhooks ? undefined : process.env.WEBHOOK_SECRET;
66
67
 
67
- if (env !== 'production') {
68
- if (!webhookSecret) {
69
- webhookSecret = 'DEFAULT_WEBHOOK_SECRET';
70
- logging.warn(tpl(messages.remoteWebhooksInDevelopment));
71
- }
68
+ if (env !== 'production' && !remoteWebhooks && !webhookSecret) {
69
+ webhookSecret = 'DEFAULT_WEBHOOK_SECRET';
70
+ logging.warn(tpl(messages.remoteWebhooksInDevelopment));
72
71
  }
73
72
 
74
- const webhookHandlerUrl = new URL('members/webhooks/stripe/', urlUtils.getSiteUrl());
73
+ // Development can tunnel the webhook URL alone while the site stays on localhost.
74
+ const webhookHandlerUrl = new URL(
75
+ config.get('stripeWebhookUrl') || 'members/webhooks/stripe/',
76
+ urlUtils.getSiteUrl(),
77
+ );
75
78
  const webhookCustomerIgnoreList = parseIgnoreCustomerList(
76
79
  config.get('stripeWebhookCustomerIgnoreList'),
77
80
  );
@@ -88,6 +91,9 @@ module.exports = {
88
91
  },
89
92
  webhookSecret: webhookSecret,
90
93
  webhookHandlerUrl: webhookHandlerUrl.href,
94
+ // A development registration points at a tunnel that closes with the process,
95
+ // so it is removed on shutdown rather than kept for the next boot.
96
+ ephemeralWebhook: remoteWebhooks,
91
97
  webhookCustomerIgnoreList,
92
98
  siteUrl,
93
99
  };
@@ -14,6 +14,12 @@ const giftService = require('../gifts');
14
14
  const staffService = require('../staff');
15
15
  const labs = require('../../../shared/labs');
16
16
  const settingsCache = require('../../../shared/settings-cache');
17
+ const tpl = require('@tryghost/tpl');
18
+
19
+ const messages = {
20
+ remoteWebhooksWithoutStripe:
21
+ 'stripeRemoteWebhooks is set but Stripe is not connected, so no webhook endpoint was registered. Connect Stripe in Ghost Admin under Settings, then restart.',
22
+ };
17
23
 
18
24
  async function configureApi() {
19
25
  const cfg = getConfig({ settingsHelpers, config, urlUtils });
@@ -84,7 +90,10 @@ function stripeSettingsChanged(model) {
84
90
 
85
91
  module.exports.init = async function init() {
86
92
  try {
87
- await configureApi();
93
+ const configured = await configureApi();
94
+ if (!configured && config.get('stripeRemoteWebhooks') === true) {
95
+ logging.warn(tpl(messages.remoteWebhooksWithoutStripe));
96
+ }
88
97
  } catch (err) {
89
98
  logging.error(err);
90
99
  }