ghost 6.47.0 → 6.48.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 (372) hide show
  1. package/MigratorConfig.js +0 -1
  2. package/bin/create-migration.js +1 -1
  3. package/bin/generate-golden-email.js +0 -1
  4. package/components/tryghost-i18n-0.0.0.tgz +0 -0
  5. package/core/boot.js +13 -7
  6. package/core/built/admin/assets/{PolarAngleAxis-CLluELUg.js → PolarAngleAxis-DufzOBEz.js} +1 -1
  7. package/core/built/admin/assets/{_baseAssignValue-Dz1iqdwD.js → _baseAssignValue-BjUm4QeA.js} +1 -1
  8. package/core/built/admin/assets/{a-large-small-BA74vHPp.js → a-large-small-D0RF_WS9.js} +1 -1
  9. package/core/built/admin/assets/{account-migration-B-NqdKuN.js → account-migration-B7n6ezrZ.js} +1 -1
  10. package/core/built/admin/assets/activitypub/{account-migration-ClmVrAXr.js → account-migration-BJeRnMCl.js} +3 -3
  11. package/core/built/admin/assets/activitypub/activitypub.js +1 -1
  12. package/core/built/admin/assets/activitypub/{at-sign-9F3qd4Nn.js → at-sign-BygVOKdj.js} +2 -2
  13. package/core/built/admin/assets/activitypub/{avatar-flipboard-jBHA13Ej.js → avatar-flipboard-CNcjI8lK.js} +2 -2
  14. package/core/built/admin/assets/activitypub/{bluesky-sharing-1irhvVtF.js → bluesky-sharing-mgBNeRfA.js} +4 -4
  15. package/core/built/admin/assets/activitypub/{copy-DXRvsGiK.js → copy-BMChXIQc.js} +2 -2
  16. package/core/built/admin/assets/activitypub/{deleted-feed-item-67VQJde4.js → deleted-feed-item-D-spb6V1.js} +2 -2
  17. package/core/built/admin/assets/activitypub/{edit-profile-BfpbEj98.js → edit-profile-CDQ3V8-c.js} +4 -4
  18. package/core/built/admin/assets/activitypub/{feed-DUrI7SPC.js → feed-Vqr3WU-V.js} +4 -4
  19. package/core/built/admin/assets/activitypub/{hash-CMtB10PN.js → hash-D7SSXVOg.js} +2 -2
  20. package/core/built/admin/assets/activitypub/{inbox-2xq8SJ7A.js → inbox-BHk5Dw27.js} +2 -2
  21. package/core/built/admin/assets/activitypub/{index-BT97xLpd.js → index-BejkeH-m.js} +2 -2
  22. package/core/built/admin/assets/activitypub/{index-DssHQAjK.js → index-BqL23J-m.js} +32 -32
  23. package/core/built/admin/assets/activitypub/{index-Ba6FXt8y.js → index-CHhvjNuG.js} +6 -6
  24. package/core/built/admin/assets/activitypub/{index-ERtz4Bvy.js → index-CZsNO9hA.js} +5 -5
  25. package/core/built/admin/assets/activitypub/{index-sgY7lLrg.js → index-CaIhRYzz.js} +3 -3
  26. package/core/built/admin/assets/activitypub/{index-D1EWoXrK.js → index-DA2MkQVu.js} +2 -2
  27. package/core/built/admin/assets/activitypub/{index-sudOvKcY.js → index-DHhFcmfu.js} +21 -21
  28. package/core/built/admin/assets/activitypub/{index-Ccighz1t.js → index-sh2bDSls.js} +4 -4
  29. package/core/built/admin/assets/activitypub/{label-KQSsSjmN.js → label-D80yhOIm.js} +2 -2
  30. package/core/built/admin/assets/activitypub/{moderation-B78if-r0.js → moderation-LJNmKBCi.js} +3 -3
  31. package/core/built/admin/assets/activitypub/{note-Bfr7ovn7.js → note-CyjKLcQ-.js} +4 -4
  32. package/core/built/admin/assets/activitypub/{reply-CehesW8Z.js → reply-BiiCFx7G.js} +2 -2
  33. package/core/built/admin/assets/activitypub/{separator-B_Ly_Qq8.js → separator-CY3PMmtI.js} +2 -2
  34. package/core/built/admin/assets/activitypub/{settings-D6R97p7v.js → settings-BQy6Gr7R.js} +3 -3
  35. package/core/built/admin/assets/activitypub/{step-1-Cl1YxgZ1.js → step-1-DCqRwgf3.js} +3 -3
  36. package/core/built/admin/assets/activitypub/{step-2-DDyR--Qe.js → step-2-DQlhehTO.js} +5 -5
  37. package/core/built/admin/assets/activitypub/{step-3-Don8gv0n.js → step-3-DAUCAcxW.js} +7 -7
  38. package/core/built/admin/assets/activitypub/{tabs-DTpfm-wu.js → tabs-B_6UuI7r.js} +3 -3
  39. package/core/built/admin/assets/activitypub/{topic-filter-Oee10885.js → topic-filter--FT1A_dc.js} +2 -2
  40. package/core/built/admin/assets/admin-x-settings/admin-x-settings.js +1 -1
  41. package/core/built/admin/assets/admin-x-settings/{code-editor-view-CGZuiDGx.js → code-editor-view-Bp_sCJR0.js} +2 -2
  42. package/core/built/admin/assets/admin-x-settings/{index-CwEblQZC.js → index-BPXA3pTW.js} +5 -5
  43. package/core/built/admin/assets/admin-x-settings/{index-rr_UntGE.js → index-BS375mg1.js} +3 -3
  44. package/core/built/admin/assets/admin-x-settings/{index-BpM6W2br.js → index-B_PlQoEG.js} +3 -3
  45. package/core/built/admin/assets/admin-x-settings/{index-BGdS5xw4.js → index-BflhAbu2.js} +3 -3
  46. package/core/built/admin/assets/admin-x-settings/{index-DtWUeJhp.js → index-CftMe8fe.js} +3 -3
  47. package/core/built/admin/assets/admin-x-settings/{index-B65inCwj.js → index-DRB7FH6y.js} +2 -2
  48. package/core/built/admin/assets/admin-x-settings/{index-DSX261S9.js → index-DijZ3oAM.js} +2 -2
  49. package/core/built/admin/assets/admin-x-settings/{index-DF6YEs01.js → index-cV0Lof9H.js} +1526 -1500
  50. package/core/built/admin/assets/admin-x-settings/{index-CluZYkUC.js → index-qc4x3vZj.js} +3 -3
  51. package/core/built/admin/assets/admin-x-settings/{modals-Bf4KOU31.js → modals-CkjuEByw.js} +55 -67
  52. package/core/built/admin/assets/{arrow-right-BxP3aeA5.js → arrow-right-BF77Yx73.js} +1 -1
  53. package/core/built/admin/assets/{at-sign-Bf0y-jim.js → at-sign-DhJF3n_V.js} +1 -1
  54. package/core/built/admin/assets/{audience-DHR1WgFK.js → audience-DHPKKayV.js} +1 -1
  55. package/core/built/admin/assets/{automated-emails-DbJbDLib.js → automated-emails-DInKYTEC.js} +1 -1
  56. package/core/built/admin/assets/{automations-aLgTzSsZ.js → automations-DJpeZw9T.js} +1 -1
  57. package/core/built/admin/assets/automations-DpQKN9j0.js +1 -0
  58. package/core/built/admin/assets/{avatar-flipboard-B0F2LMW5.js → avatar-flipboard-yRdmFC6R.js} +1 -1
  59. package/core/built/admin/assets/{bluesky-sharing-DjhtIuyr.js → bluesky-sharing-qSiCERoR.js} +1 -1
  60. package/core/built/admin/assets/{chart-BGwxlD0z.js → chart-CP2N9ZC-.js} +1 -1
  61. package/core/built/admin/assets/{chevron-up-C2FeVzre.js → chevron-up-BQ6fOpFR.js} +1 -1
  62. package/core/built/admin/assets/{chunk.524.31b31f7958dfae110016.js → chunk.524.ad4560630d4d62fbceb5.js} +4 -4
  63. package/core/built/admin/assets/{chunk.582.a855020953886af6e83b.js → chunk.582.fd4878e4e0af31ef86c0.js} +6 -6
  64. package/core/built/admin/assets/{chunk.972.258e6b1dab79b2189f1c.js → chunk.98.69968e0f393d82c2949c.js} +4 -4
  65. package/core/built/admin/assets/{code-editor-view-DzPkm_nJ.js → code-editor-view-CVODiRVJ.js} +1 -1
  66. package/core/built/admin/assets/{comments-DgItXUWN.js → comments-CP-NxopD.js} +1 -1
  67. package/core/built/admin/assets/{content-helpers-BNefU_PE.js → content-helpers-Crzkusiq.js} +1 -1
  68. package/core/built/admin/assets/{copy-DoNNUZlb.js → copy-r1LFsU75.js} +1 -1
  69. package/core/built/admin/assets/{data-list-CO1cZQRU.js → data-list-CzSc7z-2.js} +1 -1
  70. package/core/built/admin/assets/{deleted-feed-item-DC2wSAhv.js → deleted-feed-item-PyEM8FiX.js} +1 -1
  71. package/core/built/admin/assets/{dropzone-BTODLafn.js → dropzone-DI8A9qO6.js} +1 -1
  72. package/core/built/admin/assets/{edit-profile-BMMpmWIZ.js → edit-profile-DlJ64lV7.js} +1 -1
  73. package/core/built/admin/assets/editor-CevNZicQ.js +8 -0
  74. package/core/built/admin/assets/{empty-indicator-Dza0FQlj.js → empty-indicator-Dxg05yWg.js} +1 -1
  75. package/core/built/admin/assets/{en-yf9qAqTu.js → en-D93GVp3o.js} +1 -1
  76. package/core/built/admin/assets/{eye-CAqnnfQF.js → eye-6POPPpTw.js} +1 -1
  77. package/core/built/admin/assets/{feed-BkNsbWiF.js → feed-P_RMYb5x.js} +1 -1
  78. package/core/built/admin/assets/{field-Ddb1ZOqM.js → field-DeNjwWrL.js} +1 -1
  79. package/core/built/admin/assets/{filter-query-core-5Mac92kh.js → filter-query-core-DFs5WSmA.js} +1 -1
  80. package/core/built/admin/assets/{filters-BCb4bgtg.js → filters-C_BSQgb7.js} +1 -1
  81. package/core/built/admin/assets/{gh-chart-C6zkIg8k.js → gh-chart-pNHAbeQn.js} +1 -1
  82. package/core/built/admin/assets/{ghost-5313258fd425ced5db6516acde01ba36.js → ghost-3f5b3569e0beec61266cb74077677fbc.js} +3 -3
  83. package/core/built/admin/assets/{growth-ezUlN8OE.js → growth-B83tVOYO.js} +1 -1
  84. package/core/built/admin/assets/{hash-DE2OmChI.js → hash-BCTATV5W.js} +1 -1
  85. package/core/built/admin/assets/{inbox-OthiHvlV.js → inbox-rE3c5suT.js} +1 -1
  86. package/core/built/admin/assets/{index-BLyzLfyx.js → index-7EiRc5Ay.js} +1 -1
  87. package/core/built/admin/assets/{index-CV5v0eFE.js → index-B5bpZGTI.js} +1 -1
  88. package/core/built/admin/assets/index-BNtzAd7H.css +1 -0
  89. package/core/built/admin/assets/{index-BC1yWeaJ.js → index-BT33w2Io.js} +1 -1
  90. package/core/built/admin/assets/{index-DjffQ3VJ.js → index-BbkXWdhb.js} +1 -1
  91. package/core/built/admin/assets/{index-DH6PA3W6.js → index-BfhSrnrJ.js} +1 -1
  92. package/core/built/admin/assets/{index-CRvK0Iac.js → index-BmR_OUpb.js} +1 -1
  93. package/core/built/admin/assets/{index-CNV7fxKZ.js → index-BuhMgn5c.js} +1 -1
  94. package/core/built/admin/assets/{index-pkixJbdq.js → index-C-075SzJ.js} +34 -34
  95. package/core/built/admin/assets/{index-DJoByVS8.js → index-CB3hJd9E.js} +1 -1
  96. package/core/built/admin/assets/{index-D3bb-MEJ.js → index-CCISLIQd.js} +1 -1
  97. package/core/built/admin/assets/{index-BIEhcKiV.js → index-Cnptpx11.js} +1 -1
  98. package/core/built/admin/assets/{index-DK1cu59e.js → index-CrBRU81r.js} +1 -1
  99. package/core/built/admin/assets/{index-B0_p1-R0.js → index-CscUHFJp.js} +1 -1
  100. package/core/built/admin/assets/{index-Bi5qzf86.js → index-D3ZzfuJt.js} +1 -1
  101. package/core/built/admin/assets/{index-CKPny_6u.js → index-D4wn-U0V.js} +1 -1
  102. package/core/built/admin/assets/{index-YzcsD17L.js → index-DNRlkUeu.js} +1 -1
  103. package/core/built/admin/assets/{index-BoMsDCxD.js → index-D_G6negZ.js} +1 -1
  104. package/core/built/admin/assets/{index-CwsmINtV.js → index-DfxHSK1s.js} +1 -1
  105. package/core/built/admin/assets/{index-X91I8PcS.js → index-Dpc3COTl.js} +1 -1
  106. package/core/built/admin/assets/{index-c1h-EQpd.js → index-UsbnU2jy.js} +1 -1
  107. package/core/built/admin/assets/{index-oKgNVmwC.js → index-VfrJzh5m.js} +1 -1
  108. package/core/built/admin/assets/{index-D5MrQBSe.js → index-fbxc8Dpt.js} +1 -1
  109. package/core/built/admin/assets/{input-group-BOLMrDfJ.js → input-group-BLygwiDK.js} +1 -1
  110. package/core/built/admin/assets/{koenig-lexical-DlzcWUPw.js → koenig-lexical-B9U3sBS5.js} +1 -1
  111. package/core/built/admin/assets/{kpi-card-BlF7JKRC.js → kpi-card-Bmnvvp4X.js} +1 -1
  112. package/core/built/admin/assets/{kpi-card-HDshm3lO.js → kpi-card-CGVtzdgJ.js} +1 -1
  113. package/core/built/admin/assets/{kpi-tabs-Dty6zMSP.js → kpi-tabs-DxbvMkIU.js} +1 -1
  114. package/core/built/admin/assets/{kpis-CFz4r5wW.js → kpis-CQBAGVjP.js} +1 -1
  115. package/core/built/admin/assets/{label-CVzNcbjb.js → label-DpTwHQi_.js} +1 -1
  116. package/core/built/admin/assets/{links-D9dHwDlP.js → links-Bdw25FJF.js} +1 -1
  117. package/core/built/admin/assets/{list-page-shoQED7N.js → list-page-BvTQwP5F.js} +1 -1
  118. package/core/built/admin/assets/{loader-circle-cad701gH.js → loader-circle-3HJkQKWf.js} +1 -1
  119. package/core/built/admin/assets/{mail-DG4PKpZy.js → mail-DvrqP73n.js} +1 -1
  120. package/core/built/admin/assets/{main-layout-BmFla3Se.js → main-layout-BAPpm0bz.js} +1 -1
  121. package/core/built/admin/assets/{members-d19Z6k1C.js → members-CF4CzJSf.js} +1 -1
  122. package/core/built/admin/assets/minus-DJIePlnU.js +1 -0
  123. package/core/built/admin/assets/modals-CVsVi0zu.js +35 -0
  124. package/core/built/admin/assets/{moderation-BWBLnh4h.js → moderation-BX1KH5QL.js} +1 -1
  125. package/core/built/admin/assets/{newsletter-DNY4MroI.js → newsletter-BlKeb58e.js} +1 -1
  126. package/core/built/admin/assets/{newsletters-B10iBPP-.js → newsletters-3In8H0Z5.js} +1 -1
  127. package/core/built/admin/assets/{note-S0b6wjRR.js → note-ybwJCAxm.js} +1 -1
  128. package/core/built/admin/assets/{offers-B-9mZqKd.js → offers-Cl0ZNEMr.js} +1 -1
  129. package/core/built/admin/assets/{onboarding-route-AMFn0X5G.js → onboarding-route-A3ECeMAi.js} +1 -1
  130. package/core/built/admin/assets/{overview-WKadyZRW.js → overview-DrMrfsk-.js} +1 -1
  131. package/core/built/admin/assets/{pagemenu-BofQcFaF.js → pagemenu-O7HbsehH.js} +1 -1
  132. package/core/built/admin/assets/{pencil-LfMcD0vS.js → pencil-CknTbJeE.js} +1 -1
  133. package/core/built/admin/assets/{pin-CayUjL8e.js → pin-BNs-JdQ3.js} +1 -1
  134. package/core/built/admin/assets/{post-analytics-DMHvt3Jl.js → post-analytics-Dk1VloZp.js} +1 -1
  135. package/core/built/admin/assets/{post-analytics-context-10cqioP1.js → post-analytics-context-kPL94Ivz.js} +1 -1
  136. package/core/built/admin/assets/{post-analytics-header-DlICE18K.js → post-analytics-header-CpMOozq-.js} +1 -1
  137. package/core/built/admin/assets/{post-share-modal-Cfwy2UwD.js → post-share-modal-F0dobdhF.js} +1 -1
  138. package/core/built/admin/assets/posts/{alert-dialog-cQK32v9G.js → alert-dialog-NoPLULhG.js} +5 -5
  139. package/core/built/admin/assets/posts/{app-utils-DQ2hixop.js → app-utils-BiM9QO4L.js} +3 -3
  140. package/core/built/admin/assets/posts/{automations-BqkU9-zY.js → automations-BgIAmq9f.js} +3 -3
  141. package/core/built/admin/assets/posts/{automations-CoilKpVH.js → automations-D_XwO405.js} +30 -30
  142. package/core/built/admin/assets/posts/{avatar-BejAO6Rj.js → avatar-BYsYOpmq.js} +5 -5
  143. package/core/built/admin/assets/posts/{badge-BYGRyd2f.js → badge-B54vLono.js} +2 -2
  144. package/core/built/admin/assets/posts/{button-CG2Dpjqy.js → button-DMLfwOQt.js} +3 -3
  145. package/core/built/admin/assets/posts/{check-fsC5BvGC.js → check-D6qDi62T.js} +2 -2
  146. package/core/built/admin/assets/posts/{comments-CsyF5C1S.js → comments-CyYCbvUG.js} +26 -26
  147. package/core/built/admin/assets/posts/{data-list-JslRF2F5.js → data-list-B0DrMm-x.js} +4 -4
  148. package/core/built/admin/assets/posts/{dialog-3KY3A8t5.js → dialog-DtEZpY1q.js} +3 -3
  149. package/core/built/admin/assets/posts/{editor-3HPW_xW4.js → editor-LJHLmUoW.js} +1943 -1943
  150. package/core/built/admin/assets/posts/{ellipsis-BhK5S70U.js → ellipsis-JeIF0Biz.js} +2 -2
  151. package/core/built/admin/assets/posts/{empty-indicator-C9DbE9wZ.js → empty-indicator-dktzN32y.js} +2 -2
  152. package/core/built/admin/assets/posts/{filters-BCBDCnQF.js → filters-D1L-LU_m.js} +10 -10
  153. package/core/built/admin/assets/posts/{get-site-timezone-83C41MGz.js → get-site-timezone-dsyl8nlB.js} +3 -3
  154. package/core/built/admin/assets/posts/{growth-COoL1kMe.js → growth-yX8UB_ce.js} +12 -12
  155. package/core/built/admin/assets/posts/{heading-D3VqNO3z.js → heading-CNte43wH.js} +2 -2
  156. package/core/built/admin/assets/posts/{hooks-5YpJYWOw.js → hooks-BIgv7QBp.js} +2 -2
  157. package/core/built/admin/assets/posts/{index-Dqn5WIFh.js → index-2FO6Vy0r.js} +11 -11
  158. package/core/built/admin/assets/posts/{input-C1qcZBGw.js → input-BycmlCp8.js} +3 -3
  159. package/core/built/admin/assets/posts/{input-surface-C4vUAdbV.js → input-surface-vY3ACaso.js} +2 -2
  160. package/core/built/admin/assets/posts/{koenig-lexical-NZjxFY0X.js → koenig-lexical-Cq8SUcZC.js} +2 -2
  161. package/core/built/admin/assets/posts/{kpis-C2FEXoUT.js → kpis-CAJcU1w0.js} +27 -27
  162. package/core/built/admin/assets/posts/{label-CmJzmJY7.js → label-BmLTflMF.js} +3 -3
  163. package/core/built/admin/assets/posts/{links-nzud7t_t.js → links-BVcmMZmF.js} +4 -4
  164. package/core/built/admin/assets/posts/{list-page-D_rv4TgN.js → list-page-DX2WRn5T.js} +4 -4
  165. package/core/built/admin/assets/posts/{loading-indicator-DAOD6O2b.js → loading-indicator-C6FD4nS6.js} +3 -3
  166. package/core/built/admin/assets/posts/{mail-CtH0gTpq.js → mail-BMyoNUVM.js} +2 -2
  167. package/core/built/admin/assets/posts/{main-layout-VqvCxOXQ.js → main-layout-ClnxdW1Y.js} +2 -2
  168. package/core/built/admin/assets/posts/{message-circle-D4bCjxKS.js → message-circle-DwfHX-p1.js} +2 -2
  169. package/core/built/admin/assets/posts/{newsletter-BfwFyv6d.js → newsletter-Bid5_Bim.js} +19 -19
  170. package/core/built/admin/assets/posts/{overview-DKGum6ro.js → overview-BXti6Wg_.js} +18 -18
  171. package/core/built/admin/assets/posts/{pencil-Cffx-vm3.js → pencil-ChTk8IpW.js} +2 -2
  172. package/core/built/admin/assets/posts/{plus-D2ekwsq0.js → plus-DIKls8C6.js} +2 -2
  173. package/core/built/admin/assets/posts/{popover-DdbdKflP.js → popover-DVZsAT5u.js} +4 -4
  174. package/core/built/admin/assets/posts/{post-analytics-BleJYoNZ.js → post-analytics-DBL_kS0g.js} +6 -6
  175. package/core/built/admin/assets/posts/{post-analytics-context-DT3Avn9Q.js → post-analytics-context-Dr5y5nxd.js} +6 -6
  176. package/core/built/admin/assets/posts/{post-analytics-header-BktlrM_v.js → post-analytics-header-LH2-Jzgp.js} +13 -13
  177. package/core/built/admin/assets/posts/{post-share-modal-G8v3ZuSg.js → post-share-modal-D4DrfNfJ.js} +6 -6
  178. package/core/built/admin/assets/posts/{posts-CdWV_nlm.js → posts-ByxhcCrn.js} +2 -2
  179. package/core/built/admin/assets/posts/posts.js +1 -1
  180. package/core/built/admin/assets/posts/{search-CXP00fG8.js → search-DZR23LP-.js} +2 -2
  181. package/core/built/admin/assets/posts/{settings-DEXxDYc2.js → settings-CWyOKKnK.js} +2 -2
  182. package/core/built/admin/assets/posts/{sheet-CXHmD_eT.js → sheet-CNe7II5c.js} +3 -3
  183. package/core/built/admin/assets/posts/{site-C6DajagV.js → site-H9RAiQVv.js} +2 -2
  184. package/core/built/admin/assets/posts/{skeleton-Bihnkn8q.js → skeleton-Cn6x1x_C.js} +3 -3
  185. package/core/built/admin/assets/posts/{source-icon-C3oQy3UI.js → source-icon-BZOYujd1.js} +4 -4
  186. package/core/built/admin/assets/posts/{stats-DFicPtCX.js → stats-ugHCg8Oe.js} +4 -4
  187. package/core/built/admin/assets/posts/{table-DSJmeU5t.js → table-dG3Q5X95.js} +2 -2
  188. package/core/built/admin/assets/posts/{tabs-oRdVpN8P.js → tabs--EW8uL5B.js} +4 -4
  189. package/core/built/admin/assets/posts/{tags-6v5Qt_05.js → tags-DVdOfiSf.js} +2 -2
  190. package/core/built/admin/assets/posts/{tags-Upnkm0CF.js → tags-i0HJqNYU.js} +16 -16
  191. package/core/built/admin/assets/posts/{tooltip-Ci7pesWi.js → tooltip-ZvsT1Fs9.js} +4 -4
  192. package/core/built/admin/assets/posts/{trash-2-NCYWjRlg.js → trash-2-BT9fEHUL.js} +2 -2
  193. package/core/built/admin/assets/posts/{value-CcwzOh2_.js → value-DoFcsWDk.js} +2 -2
  194. package/core/built/admin/assets/posts/{virtual-list-window-CNahQBXY.js → virtual-list-window-Bt47XODn.js} +3 -3
  195. package/core/built/admin/assets/posts/{web-C3KrPq0T.js → web-BMTRLT-h.js} +20 -20
  196. package/core/built/admin/assets/posts/{zap-k30mZEuO.js → zap-DcIfEzKX.js} +2 -2
  197. package/core/built/admin/assets/{posts-DAfLuxAA.js → posts-DODOCB1E.js} +1 -1
  198. package/core/built/admin/assets/{power-Drkzg1xX.js → power-BZ7BM82m.js} +1 -1
  199. package/core/built/admin/assets/{referrers-TYxTJ2On.js → referrers-xwNb6L-8.js} +1 -1
  200. package/core/built/admin/assets/{repeat-CTM1qAzl.js → repeat-DHMCQMCA.js} +1 -1
  201. package/core/built/admin/assets/{reply-DXN16g7W.js → reply-DoLURZi2.js} +1 -1
  202. package/core/built/admin/assets/{rocket-DLixlWs0.js → rocket-BDH89dZr.js} +1 -1
  203. package/core/built/admin/assets/{select-DbiLEqYb.js → select-oE39QRll.js} +1 -1
  204. package/core/built/admin/assets/{send-B71C_46D.js → send-QgRN_yRy.js} +1 -1
  205. package/core/built/admin/assets/{settings-BBMPA3MP.js → settings-CF4NLxuS.js} +4 -4
  206. package/core/built/admin/assets/{settings-lSFHFrsJ.js → settings-D7e6KLAi.js} +1 -1
  207. package/core/built/admin/assets/{share-modal-CXrYja6o.js → share-modal-BxIh7i7o.js} +1 -1
  208. package/core/built/admin/assets/{sort-button-WYo-9Kge.js → sort-button-CEe_40Pi.js} +1 -1
  209. package/core/built/admin/assets/{source-icon-D6BzjYPP.js → source-icon-CzTNLO6j.js} +1 -1
  210. package/core/built/admin/assets/{sprout-DVfG_qhy.js → sprout-B2fN41p-.js} +1 -1
  211. package/core/built/admin/assets/{square-BbUJwQJi.js → square-CJZsjE-3.js} +1 -1
  212. package/core/built/admin/assets/{stats-CnXALQ4j.js → stats-jTxCK1CB.js} +1 -1
  213. package/core/built/admin/assets/{stats-view-B-yeMUkl.js → stats-view-B4jz69N8.js} +1 -1
  214. package/core/built/admin/assets/{step-1-DUl_hlpV.js → step-1-BovjhDNc.js} +1 -1
  215. package/core/built/admin/assets/{step-2-DjX_A4Ke.js → step-2-ClG40BfX.js} +1 -1
  216. package/core/built/admin/assets/{step-3-CnDCCA8T.js → step-3-ZMSyEHZI.js} +1 -1
  217. package/core/built/admin/assets/{table-AagTvMa9.js → table-B8Pj96or.js} +1 -1
  218. package/core/built/admin/assets/{tabs-IDJWnQD-.js → tabs-BZosOk0o.js} +1 -1
  219. package/core/built/admin/assets/{tags-CXAcIDw-.js → tags-BpWoYBfB.js} +1 -1
  220. package/core/built/admin/assets/{tags-C3lykbgu.js → tags-DZukMyuU.js} +1 -1
  221. package/core/built/admin/assets/{textarea-Cc3nUXep.js → textarea-BtnzsOk7.js} +1 -1
  222. package/core/built/admin/assets/{thumbs-down-SsjC2lMD.js → thumbs-down-CZTzyz7D.js} +1 -1
  223. package/core/built/admin/assets/{tiers-J8AeZmRd.js → tiers-Do7zBqAk.js} +1 -1
  224. package/core/built/admin/assets/{toggle-group-BzD8yimX.js → toggle-group-abk9FYXi.js} +1 -1
  225. package/core/built/admin/assets/{topic-filter-CA_L6ehz.js → topic-filter-CdMvjkmc.js} +1 -1
  226. package/core/built/admin/assets/{trash-BKhRqxsX.js → trash-DNXRsBf0.js} +1 -1
  227. package/core/built/admin/assets/{underline-_HIgX6e1.js → underline-HXWuVCAi.js} +1 -1
  228. package/core/built/admin/assets/{undo-2-ClkkOS0O.js → undo-2-C2ntNJKC.js} +1 -1
  229. package/core/built/admin/assets/{upload-DEPHbyvo.js → upload-D52l7HIb.js} +1 -1
  230. package/core/built/admin/assets/{use-growth-stats-BM2qWt0C.js → use-growth-stats-Dgs0UxDT.js} +1 -1
  231. package/core/built/admin/assets/{use-simple-pagination-zyklfekn.js → use-simple-pagination-Cj2rVggA.js} +1 -1
  232. package/core/built/admin/assets/{user-round-check-DoaGU2hC.js → user-round-check-C0GdT99c.js} +1 -1
  233. package/core/built/admin/assets/{user-round-x-CwEKNuU6.js → user-round-x-CVCvxuUG.js} +1 -1
  234. package/core/built/admin/assets/{virtual-list-window-C0Cv0gUC.js → virtual-list-window-mdQS2bt_.js} +1 -1
  235. package/core/built/admin/assets/{wallet-cards-BjdG5glh.js → wallet-cards-CtLF01jQ.js} +1 -1
  236. package/core/built/admin/assets/{web-BZNnanCT.js → web-DTib8_n8.js} +1 -1
  237. package/core/built/admin/index.html +6 -6
  238. package/core/frontend/helpers/ghost_foot.js +12 -2
  239. package/core/frontend/helpers/prev_post.js +1 -1
  240. package/core/frontend/helpers/tpl/gift-toast.hbs +130 -0
  241. package/core/frontend/services/proxy.js +9 -0
  242. package/core/frontend/services/routing/controllers/entry/canonical-url.js +15 -0
  243. package/core/frontend/services/routing/controllers/entry/canonical-url.ts +14 -0
  244. package/core/frontend/services/routing/controllers/entry/gift-links.js +82 -0
  245. package/core/frontend/services/routing/controllers/entry/gift-links.ts +92 -0
  246. package/core/frontend/services/routing/controllers/entry/markdown.js +62 -0
  247. package/core/frontend/services/routing/controllers/entry/markdown.ts +66 -0
  248. package/core/frontend/services/routing/controllers/entry.js +96 -105
  249. package/core/frontend/services/routing/controllers/entry.ts +97 -0
  250. package/core/frontend/services/routing/controllers/index.js +1 -1
  251. package/core/frontend/web/middleware/frontend-caching.js +9 -0
  252. package/core/server/adapters/cache/Redis.js +0 -1
  253. package/core/server/adapters/redirects/RedirectsStoreBase.d.ts +0 -4
  254. package/core/server/adapters/scheduling/scheduling-default.js +8 -1
  255. package/core/server/api/endpoints/gift-links.js +23 -16
  256. package/core/server/api/endpoints/gift-links.ts +25 -17
  257. package/core/server/api/endpoints/index.js +0 -1
  258. package/core/server/api/endpoints/previews.js +3 -24
  259. package/core/server/api/endpoints/utils/serializers/output/gift-links.js +4 -4
  260. package/core/server/api/endpoints/utils/serializers/output/gift-links.ts +4 -4
  261. package/core/server/api/endpoints/utils/serializers/output/index.js +0 -1
  262. package/core/server/api/endpoints/utils/validators/input/automation_email_previews.js +8 -9
  263. package/core/server/api/endpoints/utils/validators/input/index.js +0 -1
  264. package/core/server/data/migrations/versions/6.48/2026-06-23-00-00-00-drop-gift-links-revoked-at.js +6 -0
  265. package/core/server/data/migrations/versions/6.48/2026-06-23-00-00-01-rename-gift-links-revoke-all-permission-to-remove-all.js +37 -0
  266. package/core/server/data/migrations/versions/6.48/2026-06-24-00-00-00-drop-gift-links-redemption-columns.js +10 -0
  267. package/core/server/data/schema/fixtures/fixtures.json +2 -2
  268. package/core/server/data/schema/schema.js +1 -4
  269. package/core/server/data/seeders/data-generator.js +4 -1
  270. package/core/server/data/seeders/importers/members-login-events-importer.js +0 -1
  271. package/core/server/data/seeders/importers/members-newsletters-importer.js +0 -1
  272. package/core/server/data/seeders/importers/members-paid-subscription-events-importer.js +0 -1
  273. package/core/server/data/seeders/importers/members-status-events-importer.js +0 -1
  274. package/core/server/data/seeders/importers/members-stripe-customers-importer.js +0 -1
  275. package/core/server/data/seeders/importers/members-stripe-customers-subscriptions-importer.js +0 -1
  276. package/core/server/data/seeders/importers/members-subscribe-events-importer.js +0 -1
  277. package/core/server/data/seeders/importers/members-subscription-created-events-importer.js +0 -1
  278. package/core/server/lib/lexical.js +62 -36
  279. package/core/server/lib/post-revisions.js +0 -2
  280. package/core/server/lib/post-revisions.ts +0 -3
  281. package/core/server/models/index.js +0 -3
  282. package/core/server/services/auth/reset-authentication.js +0 -2
  283. package/core/server/services/auth/reset-authentication.ts +0 -3
  284. package/core/server/services/auth/session/index.js +0 -1
  285. package/core/server/services/automations/automations-api.js +59 -17
  286. package/core/server/services/automations/automations-api.ts +69 -16
  287. package/core/server/services/automations/database-automations-repository.js +58 -3
  288. package/core/server/services/automations/database-automations-repository.ts +70 -3
  289. package/core/server/services/automations/stale-lock-cutoff.js +7 -0
  290. package/core/server/services/automations/stale-lock-cutoff.ts +5 -0
  291. package/core/server/services/email-address/email-address-parser.js.d.ts +0 -1
  292. package/core/server/services/email-service/batch-sending-service.js +99 -26
  293. package/core/server/services/email-service/email-service-wrapper.js +7 -2
  294. package/core/server/services/email-service/email-service.js +146 -4
  295. package/core/server/services/gift-links/database.js +0 -3
  296. package/core/server/services/gift-links/database.ts +1 -4
  297. package/core/server/services/gift-links/index.js +2 -2
  298. package/core/server/services/gift-links/index.ts +4 -2
  299. package/core/server/services/gift-links/models.js +0 -2
  300. package/core/server/services/gift-links/models.ts +0 -2
  301. package/core/server/services/gift-links/queries.js +2 -2
  302. package/core/server/services/gift-links/queries.ts +2 -2
  303. package/core/server/services/gift-links/serializers.js +0 -2
  304. package/core/server/services/gift-links/serializers.ts +0 -2
  305. package/core/server/services/gift-links/service.js +54 -35
  306. package/core/server/services/gift-links/service.ts +70 -35
  307. package/core/server/services/gifts/gift-reminder-scheduler.js +0 -2
  308. package/core/server/services/gifts/gift-reminder-scheduler.ts +0 -2
  309. package/core/server/services/indexnow.js +8 -1
  310. package/core/server/services/internal-keys/index.js +0 -1
  311. package/core/server/services/internal-keys/index.ts +0 -2
  312. package/core/server/services/lib/dynamic-redirect-manager.d.ts +0 -1
  313. package/core/server/services/lib/in-memory-repository.js +0 -1
  314. package/core/server/services/lib/in-memory-repository.ts +0 -2
  315. package/core/server/services/members/api.js +0 -3
  316. package/core/server/services/members/create-paid-member-shim.js +31 -0
  317. package/core/server/services/members/create-paid-member-shim.ts +31 -0
  318. package/core/server/services/members/emails/signin.js +0 -1
  319. package/core/server/services/members/members-api/members-api.js +0 -2
  320. package/core/server/services/members/members-api/repositories/member-repository.js +0 -3
  321. package/core/server/services/members/service.js +4 -0
  322. package/core/server/services/post-scheduling/index.js +0 -2
  323. package/core/server/services/post-scheduling/index.ts +0 -2
  324. package/core/server/services/post-scheduling/post-scheduling.js +0 -5
  325. package/core/server/services/post-scheduling/post-scheduling.ts +0 -5
  326. package/core/server/services/recommendations/service/bookshelf-repository.js +0 -1
  327. package/core/server/services/recommendations/service/bookshelf-repository.ts +0 -4
  328. package/core/server/services/recommendations/service/incoming-recommendation-service.js +0 -1
  329. package/core/server/services/recommendations/service/incoming-recommendation-service.ts +0 -1
  330. package/core/server/services/recommendations/service/recommendation-controller.js +0 -1
  331. package/core/server/services/recommendations/service/recommendation-controller.ts +0 -1
  332. package/core/server/services/recommendations/service/recommendation-metadata-service.js +0 -1
  333. package/core/server/services/recommendations/service/recommendation-metadata-service.ts +0 -1
  334. package/core/server/services/recommendations/service/recommendation.js +0 -1
  335. package/core/server/services/recommendations/service/recommendation.ts +0 -1
  336. package/core/server/services/remote-flags/index.js +0 -1
  337. package/core/server/services/remote-flags/index.ts +0 -1
  338. package/core/server/services/slack.js +5 -1
  339. package/core/server/services/update-check/index.js +0 -1
  340. package/core/server/services/url/lazy-find-resource.js +0 -1
  341. package/core/server/services/url/lazy-find-resource.ts +0 -2
  342. package/core/server/services/url/lazy-url-service.js +0 -1
  343. package/core/server/services/url/lazy-url-service.ts +0 -2
  344. package/core/server/services/url/permalink-matcher.js +0 -1
  345. package/core/server/services/url/permalink-matcher.ts +0 -2
  346. package/core/server/services/url/router-filter.js +0 -2
  347. package/core/server/services/url/router-filter.ts +0 -2
  348. package/core/server/services/url/url-service-facade.js +0 -1
  349. package/core/server/services/url/url-service-facade.ts +0 -2
  350. package/core/server/services/verification/verification-webhook-service.js +0 -1
  351. package/core/server/services/verification/verification-webhook-service.ts +0 -1
  352. package/core/server/web/api/endpoints/admin/routes.js +7 -7
  353. package/core/shared/events-ts/post-deleted-event.js +0 -2
  354. package/core/shared/events-ts/post-deleted-event.ts +0 -2
  355. package/core/shared/labs.js +0 -1
  356. package/package.json +8 -16
  357. package/pnpm-lock.yaml +162 -113
  358. package/core/built/admin/assets/automations-BthXBzzq.js +0 -1
  359. package/core/built/admin/assets/editor-91xrI2A3.js +0 -8
  360. package/core/built/admin/assets/index-BYb09f-7.css +0 -1
  361. package/core/built/admin/assets/minus-DmrVsJ-z.js +0 -1
  362. package/core/built/admin/assets/modals-dnqxCS3l.js +0 -35
  363. package/core/server/models/outbox.js +0 -24
  364. package/core/server/services/outbox/events/start-outbox-processing-event.js +0 -22
  365. package/core/server/services/outbox/handlers/member-created.js +0 -85
  366. package/core/server/services/outbox/index.js +0 -49
  367. package/core/server/services/outbox/jobs/index.js +0 -30
  368. package/core/server/services/outbox/jobs/lib/constants.js +0 -17
  369. package/core/server/services/outbox/jobs/lib/process-entries.js +0 -117
  370. package/core/server/services/outbox/jobs/lib/process-outbox.js +0 -96
  371. package/core/server/services/outbox/jobs/outbox-job.js +0 -36
  372. package/types/ghost-storage-base.d.ts +0 -22
@@ -1,61 +1,68 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const gift_links_1 = require("../../services/gift-links");
4
- // permissions is untyped JS; require, don't import.
5
- // eslint-disable-next-line @typescript-eslint/no-require-imports
6
4
  const permissionsService = require('../../services/permissions');
7
- // Also requires edit access to the post — you can gift a post only if you can edit it.
8
- async function assertCanManageGiftLink(frame) {
5
+ async function assertCanEditAndGift(frame) {
9
6
  const { context, id } = frame.options;
10
7
  await permissionsService.canThis(context).manage.gift_link(id);
11
8
  await permissionsService.canThis(context).edit.post(id);
12
9
  }
10
+ function requestContextFromFrame(frame) {
11
+ const context = (frame.options.context ?? {});
12
+ if (context.integration) {
13
+ return { actor: { id: context.integration.id, type: 'integration' } };
14
+ }
15
+ if (context.user) {
16
+ return { actor: { id: context.user, type: 'user' } };
17
+ }
18
+ return { actor: null };
19
+ }
13
20
  const noCacheInvalidation = { cacheInvalidate: false };
14
21
  const controller = {
15
22
  docName: 'gift_links',
16
- read: {
23
+ browse: {
17
24
  headers: noCacheInvalidation,
18
25
  options: ['id'],
19
26
  validation: { options: { id: { required: true } } },
20
27
  permissions(frame) {
21
- return assertCanManageGiftLink(frame);
28
+ return assertCanEditAndGift(frame);
22
29
  },
23
30
  query(frame) {
24
31
  return gift_links_1.service.getPost(frame.options.id);
25
32
  }
26
33
  },
27
- issue: {
34
+ ensure: {
28
35
  headers: noCacheInvalidation,
29
36
  statusCode: 200,
30
37
  options: ['id'],
31
38
  validation: { options: { id: { required: true } } },
32
39
  permissions(frame) {
33
- return assertCanManageGiftLink(frame);
40
+ return assertCanEditAndGift(frame);
34
41
  },
35
42
  query(frame) {
36
- return gift_links_1.service.issue(frame.options.id);
43
+ return gift_links_1.service.ensure(requestContextFromFrame(frame), frame.options.id);
37
44
  }
38
45
  },
39
- reissue: {
46
+ create: {
40
47
  headers: noCacheInvalidation,
41
48
  statusCode: 200,
42
49
  options: ['id'],
43
50
  validation: { options: { id: { required: true } } },
44
51
  permissions(frame) {
45
- return assertCanManageGiftLink(frame);
52
+ return assertCanEditAndGift(frame);
46
53
  },
47
54
  query(frame) {
48
- return gift_links_1.service.reissue(frame.options.id);
55
+ return gift_links_1.service.create(requestContextFromFrame(frame), frame.options.id);
49
56
  }
50
57
  },
51
- revokeAll: {
58
+ removeAll: {
52
59
  headers: noCacheInvalidation,
53
60
  statusCode: 200,
54
61
  permissions(frame) {
55
- return permissionsService.canThis(frame.options.context).revokeAll.gift_link();
62
+ return permissionsService.canThis(frame.options.context).removeAll.gift_link();
56
63
  },
57
- async query() {
58
- const count = await gift_links_1.service.revokeAll();
64
+ async query(frame) {
65
+ const count = await gift_links_1.service.removeAll(requestContextFromFrame(frame));
59
66
  return { count };
60
67
  }
61
68
  }
@@ -1,7 +1,5 @@
1
- import {service} from '../../services/gift-links';
1
+ import {service, type RequestContext} from '../../services/gift-links';
2
2
 
3
- // permissions is untyped JS; require, don't import.
4
- // eslint-disable-next-line @typescript-eslint/no-require-imports
5
3
  const permissionsService = require('../../services/permissions');
6
4
 
7
5
  interface Frame {
@@ -12,64 +10,74 @@ interface Frame {
12
10
  };
13
11
  }
14
12
 
15
- // Also requires edit access to the post — you can gift a post only if you can edit it.
16
- async function assertCanManageGiftLink(frame: Frame): Promise<void> {
13
+ async function assertCanEditAndGift(frame: Frame): Promise<void> {
17
14
  const {context, id} = frame.options;
18
15
  await permissionsService.canThis(context).manage.gift_link(id);
19
16
  await permissionsService.canThis(context).edit.post(id);
20
17
  }
21
18
 
19
+ function requestContextFromFrame(frame: Frame): RequestContext {
20
+ const context = (frame.options.context ?? {}) as {user?: string; integration?: {id: string}};
21
+ if (context.integration) {
22
+ return {actor: {id: context.integration.id, type: 'integration'}};
23
+ }
24
+ if (context.user) {
25
+ return {actor: {id: context.user, type: 'user'}};
26
+ }
27
+ return {actor: null};
28
+ }
29
+
22
30
  const noCacheInvalidation = {cacheInvalidate: false};
23
31
 
24
32
  const controller = {
25
33
  docName: 'gift_links',
26
34
 
27
- read: {
35
+ browse: {
28
36
  headers: noCacheInvalidation,
29
37
  options: ['id'],
30
38
  validation: {options: {id: {required: true}}},
31
39
  permissions(frame: Frame) {
32
- return assertCanManageGiftLink(frame);
40
+ return assertCanEditAndGift(frame);
33
41
  },
34
42
  query(frame: Frame) {
35
43
  return service!.getPost(frame.options.id);
36
44
  }
37
45
  },
38
46
 
39
- issue: {
47
+ ensure: {
40
48
  headers: noCacheInvalidation,
41
49
  statusCode: 200,
42
50
  options: ['id'],
43
51
  validation: {options: {id: {required: true}}},
44
52
  permissions(frame: Frame) {
45
- return assertCanManageGiftLink(frame);
53
+ return assertCanEditAndGift(frame);
46
54
  },
47
55
  query(frame: Frame) {
48
- return service!.issue(frame.options.id);
56
+ return service!.ensure(requestContextFromFrame(frame), frame.options.id);
49
57
  }
50
58
  },
51
59
 
52
- reissue: {
60
+ create: {
53
61
  headers: noCacheInvalidation,
54
62
  statusCode: 200,
55
63
  options: ['id'],
56
64
  validation: {options: {id: {required: true}}},
57
65
  permissions(frame: Frame) {
58
- return assertCanManageGiftLink(frame);
66
+ return assertCanEditAndGift(frame);
59
67
  },
60
68
  query(frame: Frame) {
61
- return service!.reissue(frame.options.id);
69
+ return service!.create(requestContextFromFrame(frame), frame.options.id);
62
70
  }
63
71
  },
64
72
 
65
- revokeAll: {
73
+ removeAll: {
66
74
  headers: noCacheInvalidation,
67
75
  statusCode: 200,
68
76
  permissions(frame: Frame) {
69
- return permissionsService.canThis(frame.options.context).revokeAll.gift_link();
77
+ return permissionsService.canThis(frame.options.context).removeAll.gift_link();
70
78
  },
71
- async query() {
72
- const count = await service!.revokeAll();
79
+ async query(frame: Frame) {
80
+ const count = await service!.removeAll(requestContextFromFrame(frame));
73
81
  return {count};
74
82
  }
75
83
  }
@@ -5,7 +5,6 @@ const localUtils = require('./utils');
5
5
  // This is a valid index.js file - it just exports a lot of stuff!
6
6
  // Long term we would like to change the API architecture to reduce this file,
7
7
  // but that's not the problem the index.js max - line eslint "proxy" rule is there to solve.
8
- /* eslint-disable max-lines */
9
8
 
10
9
  module.exports = {
11
10
  get automations() {
@@ -1,7 +1,7 @@
1
1
  const tpl = require('@tryghost/tpl');
2
2
  const errors = require('@tryghost/errors');
3
3
  const models = require('../../models');
4
- const logging = require('@tryghost/logging');
4
+ const membersService = require('../../services/members');
5
5
  const ALLOWED_INCLUDES = ['authors', 'tags', 'tiers'];
6
6
  const ALLOWED_MEMBER_STATUSES = ['anonymous', 'free', 'paid'];
7
7
 
@@ -31,29 +31,8 @@ const _addMemberContextToFrame = async (frame) => {
31
31
  }
32
32
 
33
33
  if (frame.options?.member_status === 'paid') {
34
- // For member_status=paid, add all paid tiers to the member context
35
- let memberProducts = [];
36
- try {
37
- const paidProducts = await models.Product.findAll({
38
- status: 'active',
39
- type: 'paid'
40
- });
41
- if (paidProducts.length > 0) {
42
- memberProducts = paidProducts.map((product) => {
43
- return {
44
- slug: product.get('slug')
45
- };
46
- });
47
- }
48
- } catch (error) {
49
- // Log error but don't fail preview - fallback to empty products array
50
- logging.error('Failed to fetch paid products for preview:', error);
51
- }
52
-
53
- frame.original.context.member = {
54
- status: 'paid',
55
- products: memberProducts
56
- };
34
+ // For member_status=paid, render as a member with all active paid tiers
35
+ frame.original.context.member = await membersService.createPaidMemberShim();
57
36
  }
58
37
  };
59
38
 
@@ -7,10 +7,10 @@ const serializeGiftLinks = (post, _apiConfig, frame) => {
7
7
  // module.exports (not export): the API framework loads serializers via require(). The endpoint ->
8
8
  // serializer mapping lives here; the response shaping lives with the gift-links service module.
9
9
  module.exports = {
10
- read: serializeGiftLinks,
11
- issue: serializeGiftLinks,
12
- reissue: serializeGiftLinks,
13
- revokeAll(data, _apiConfig, frame) {
10
+ browse: serializeGiftLinks,
11
+ ensure: serializeGiftLinks,
12
+ create: serializeGiftLinks,
13
+ removeAll(data, _apiConfig, frame) {
14
14
  frame.response = serializers_1.toRevokeAllResponse.parse(data);
15
15
  }
16
16
  };
@@ -12,10 +12,10 @@ const serializeGiftLinks = (post: Post, _apiConfig: unknown, frame: Frame): void
12
12
  // module.exports (not export): the API framework loads serializers via require(). The endpoint ->
13
13
  // serializer mapping lives here; the response shaping lives with the gift-links service module.
14
14
  module.exports = {
15
- read: serializeGiftLinks,
16
- issue: serializeGiftLinks,
17
- reissue: serializeGiftLinks,
18
- revokeAll(data: {count: number}, _apiConfig: unknown, frame: Frame): void {
15
+ browse: serializeGiftLinks,
16
+ ensure: serializeGiftLinks,
17
+ create: serializeGiftLinks,
18
+ removeAll(data: {count: number}, _apiConfig: unknown, frame: Frame): void {
19
19
  frame.response = toRevokeAllResponse.parse(data);
20
20
  }
21
21
  };
@@ -2,7 +2,6 @@
2
2
  // This is a valid index.js file - it just exports a lot of stuff!
3
3
  // Long term we would like to change the API architecture to reduce this file,
4
4
  // but that's not the problem the index.js max - line eslint "proxy" rule is there to solve.
5
- /* eslint-disable max-lines */
6
5
 
7
6
  module.exports = {
8
7
  get all() {
@@ -4,15 +4,16 @@
4
4
  const validator = require('@tryghost/validator');
5
5
  const {ValidationError} = require('@tryghost/errors');
6
6
  const tpl = require('@tryghost/tpl');
7
+ const lexicalLib = require('../../../../../lib/lexical');
7
8
 
8
9
  const messages = {
9
10
  invalidEmailReceived: 'The server did not receive a valid email',
10
- invalidLexical: 'Lexical must be a valid JSON string',
11
+ invalidLexical: 'Lexical must be a well-formed Lexical document',
11
12
  subjectRequired: 'Subject is required',
12
13
  lexicalRequired: 'Email content is required'
13
14
  };
14
15
 
15
- const validatePreviewData = (frame) => {
16
+ const validatePreviewData = async (frame) => {
16
17
  const subject = frame.data.subject;
17
18
  const lexical = frame.data.lexical;
18
19
 
@@ -30,9 +31,7 @@ const validatePreviewData = (frame) => {
30
31
  });
31
32
  }
32
33
 
33
- try {
34
- JSON.parse(lexical);
35
- } catch (e) {
34
+ if (!await lexicalLib.validate(lexical)) {
36
35
  throw new ValidationError({
37
36
  message: tpl(messages.invalidLexical),
38
37
  property: 'lexical'
@@ -41,11 +40,11 @@ const validatePreviewData = (frame) => {
41
40
  };
42
41
 
43
42
  module.exports = {
44
- preview(apiConfig, frame) {
45
- validatePreviewData(frame);
43
+ async preview(apiConfig, frame) {
44
+ await validatePreviewData(frame);
46
45
  },
47
46
 
48
- sendTestEmail(apiConfig, frame) {
47
+ async sendTestEmail(apiConfig, frame) {
49
48
  const email = frame.data.email;
50
49
 
51
50
  if (typeof email !== 'string' || !validator.isEmail(email)) {
@@ -55,6 +54,6 @@ module.exports = {
55
54
  });
56
55
  }
57
56
 
58
- validatePreviewData(frame);
57
+ await validatePreviewData(frame);
59
58
  }
60
59
  };
@@ -2,7 +2,6 @@
2
2
  // This is a valid index.js file - it just exports a lot of stuff!
3
3
  // Long term we would like to change the API architecture to reduce this file,
4
4
  // but that's not the problem the index.js max - line eslint "proxy" rule is there to solve.
5
- /* eslint-disable max-lines */
6
5
 
7
6
  module.exports = {
8
7
  get automation_email_previews() {
@@ -0,0 +1,6 @@
1
+ const {createDropColumnMigration} = require('../../utils');
2
+
3
+ module.exports = createDropColumnMigration('gift_links', 'revoked_at', {
4
+ type: 'dateTime',
5
+ nullable: true
6
+ });
@@ -0,0 +1,37 @@
1
+ const logging = require('@tryghost/logging');
2
+ const {createTransactionalMigration} = require('../../utils');
3
+
4
+ module.exports = createTransactionalMigration(
5
+ async function up(knex) {
6
+ const revokeAll = await knex('permissions')
7
+ .where({object_type: 'gift_link', action_type: 'revokeAll'})
8
+ .first();
9
+ if (!revokeAll) {
10
+ return;
11
+ }
12
+
13
+ // A removeAll permission can already exist (fresh fixtures plus this migration both
14
+ // running): the unique name rules out a rename, so drop the legacy revokeAll and its
15
+ // grants. Otherwise rename in place, keeping the existing grants.
16
+ const removeAllExists = await knex('permissions')
17
+ .where({object_type: 'gift_link', action_type: 'removeAll'})
18
+ .first();
19
+ if (removeAllExists) {
20
+ await knex('permissions_roles').where({permission_id: revokeAll.id}).del();
21
+ await knex('permissions_users').where({permission_id: revokeAll.id}).del();
22
+ await knex('permissions').where({id: revokeAll.id}).del();
23
+ logging.info('Removed duplicate gift_link revokeAll permission (removeAll already present)');
24
+ return;
25
+ }
26
+
27
+ await knex('permissions')
28
+ .where({id: revokeAll.id})
29
+ .update({name: 'Remove all gift links', action_type: 'removeAll', updated_at: new Date()});
30
+ logging.info('Renamed gift_link revokeAll permission to removeAll');
31
+ },
32
+ async function down(knex) {
33
+ await knex('permissions')
34
+ .where({object_type: 'gift_link', action_type: 'removeAll'})
35
+ .update({name: 'Revoke all gift links', action_type: 'revokeAll', updated_at: new Date()});
36
+ }
37
+ );
@@ -0,0 +1,10 @@
1
+ const {combineNonTransactionalMigrations, createDropColumnMigration} = require('../../utils');
2
+
3
+ module.exports = combineNonTransactionalMigrations(
4
+ createDropColumnMigration('gift_links', 'redeemed_count', {
5
+ type: 'integer', nullable: false, unsigned: true, defaultTo: 0
6
+ }),
7
+ createDropColumnMigration('gift_links', 'last_redeemed_at', {
8
+ type: 'dateTime', nullable: true
9
+ })
10
+ );
@@ -805,8 +805,8 @@
805
805
  "object_type": "gift_link"
806
806
  },
807
807
  {
808
- "name": "Revoke all gift links",
809
- "action_type": "revokeAll",
808
+ "name": "Remove all gift links",
809
+ "action_type": "removeAll",
810
810
  "object_type": "gift_link"
811
811
  }
812
812
  ]
@@ -121,13 +121,10 @@ module.exports = {
121
121
  feature_image_caption: {type: 'text', maxlength: 65535, nullable: true},
122
122
  email_only: {type: 'boolean', nullable: false, defaultTo: false}
123
123
  },
124
- // Every gift link issued for a post; reissued tokens remain as history. Liveness lives in post_gift_links.
124
+ // Every gift link added to a post; replaced tokens remain as history. Liveness lives in post_gift_links.
125
125
  gift_links: {
126
126
  token: {type: 'string', maxlength: 32, nullable: false, primary: true},
127
127
  post_id: {type: 'string', maxlength: 24, nullable: false, references: 'posts.id', cascadeDelete: true},
128
- redeemed_count: {type: 'integer', nullable: false, unsigned: true, defaultTo: 0},
129
- last_redeemed_at: {type: 'dateTime', nullable: true},
130
- revoked_at: {type: 'dateTime', nullable: true},
131
128
  created_at: {type: 'dateTime', nullable: false},
132
129
  updated_at: {type: 'dateTime', nullable: true}
133
130
  },
@@ -210,13 +210,16 @@ class DataGenerator {
210
210
  }
211
211
 
212
212
  if (this.useTransaction) {
213
+ // SQLite only supports serializable transactions and warns if an
214
+ // isolation level is passed, so only set it for other databases.
215
+ const transactionConfig = DatabaseInfo.isSQLite(this.knex) ? {} : {isolationLevel: 'read committed'};
213
216
  await this.knex.transaction(async (transaction) => {
214
217
  if (!DatabaseInfo.isSQLite(this.knex)) {
215
218
  await transaction.raw('SET autocommit=0;');
216
219
  }
217
220
 
218
221
  await this.#run(transaction);
219
- }, {isolationLevel: 'read committed'});
222
+ }, transactionConfig);
220
223
  } else {
221
224
  await this.#run(this.knex);
222
225
  }
@@ -19,7 +19,6 @@ class MembersLoginEventsImporter extends TableImporter {
19
19
  let offset = 0;
20
20
  let limit = 100000;
21
21
 
22
- // eslint-disable-next-line no-constant-condition
23
22
  while (true) {
24
23
  const members = await this.transaction.select('id', 'created_at').from('members').limit(limit).offset(offset);
25
24
 
@@ -12,7 +12,6 @@ class MembersNewslettersImporter extends TableImporter {
12
12
  let offset = 0;
13
13
  let limit = 100000;
14
14
 
15
- // eslint-disable-next-line no-constant-condition
16
15
  while (true) {
17
16
  const membersSubscribeEvents = await this.transaction.select('member_id', 'newsletter_id').from('members_subscribe_events').limit(limit).offset(offset);
18
17
 
@@ -12,7 +12,6 @@ class MembersPaidSubscriptionEventsImporter extends TableImporter {
12
12
  let offset = 0;
13
13
  let limit = 1000;
14
14
 
15
- // eslint-disable-next-line no-constant-condition
16
15
  while (true) {
17
16
  const subscriptions = await this.transaction.select('id', 'customer_id', 'plan_currency', 'plan_amount', 'created_at', 'plan_id', 'status', 'cancel_at_period_end', 'current_period_end').from('members_stripe_customers_subscriptions').limit(limit).offset(offset);
18
17
 
@@ -13,7 +13,6 @@ class MembersStatusEventsImporter extends TableImporter {
13
13
  let offset = 0;
14
14
  let limit = 100000;
15
15
 
16
- // eslint-disable-next-line no-constant-condition
17
16
  while (true) {
18
17
  const members = await this.transaction.select('id', 'created_at', 'status').from('members').limit(limit).offset(offset);
19
18
 
@@ -18,7 +18,6 @@ class MembersStripeCustomersImporter extends TableImporter {
18
18
  let offset = 0;
19
19
  let limit = 100000;
20
20
 
21
- // eslint-disable-next-line no-constant-condition
22
21
  while (true) {
23
22
  const members = await this.transaction.select('id', 'name', 'email', 'created_at', 'status').from('members').limit(limit).offset(offset);
24
23
 
@@ -19,7 +19,6 @@ class MembersStripeCustomersSubscriptionsImporter extends TableImporter {
19
19
  this.stripeProducts = await this.transaction.select('id', 'product_id', 'stripe_product_id').from('stripe_products');
20
20
  this.stripePrices = await this.transaction.select('id', 'nickname', 'stripe_product_id', 'stripe_price_id', 'amount', 'interval', 'currency').from('stripe_prices');
21
21
 
22
- // eslint-disable-next-line no-constant-condition
23
22
  while (true) {
24
23
  const membersStripeCustomers = await this.transaction.select('id', 'member_id', 'customer_id').from('members_stripe_customers').limit(limit).offset(offset);
25
24
 
@@ -19,7 +19,6 @@ class MembersSubscribeEventsImporter extends TableImporter {
19
19
  let limit = 100000;
20
20
  this.newsletters = await this.transaction.select('id').from('newsletters').orderBy('sort_order');
21
21
 
22
- // eslint-disable-next-line no-constant-condition
23
22
  while (true) {
24
23
  const members = await this.transaction.select('id', 'created_at', 'status').from('members').limit(limit).offset(offset);
25
24
 
@@ -17,7 +17,6 @@ class MembersSubscriptionCreatedEventsImporter extends TableImporter {
17
17
  this.posts = await this.transaction.select('id', 'published_at', 'visibility', 'type', 'slug').from('posts').whereNotNull('published_at').where('visibility', 'public').orderBy('published_at', 'desc');
18
18
  this.incomingRecommendations = await this.transaction.select('id', 'source', 'created_at').from('mentions');
19
19
 
20
- // eslint-disable-next-line no-constant-condition
21
20
  while (true) {
22
21
  const membersStripeCustomersSubscriptions = await this.transaction.select('id', 'created_at', 'customer_id').from('members_stripe_customers_subscriptions').limit(limit).offset(offset);
23
22
 
@@ -18,6 +18,51 @@ function populateNodes() {
18
18
  nodes = DEFAULT_NODES;
19
19
  }
20
20
 
21
+ function createLexicalHtmlRenderer(onError) {
22
+ if (!nodes) {
23
+ populateNodes();
24
+ }
25
+
26
+ const {LexicalHTMLRenderer} = require('@tryghost/kg-lexical-html-renderer');
27
+ return new LexicalHTMLRenderer({
28
+ nodes,
29
+ onError
30
+ });
31
+ }
32
+
33
+ function buildRenderOptions(userOptions, nodeRenderers) {
34
+ if (!postsService) {
35
+ const getPostServiceInstance = require('../services/posts/posts-service-instance');
36
+ postsService = getPostServiceInstance();
37
+ }
38
+ if (!serializePosts) {
39
+ serializePosts = require('../api/endpoints/utils/serializers/output/posts').all;
40
+ }
41
+
42
+ return Object.assign({
43
+ siteUuid: settingsCache.get('site_uuid'),
44
+ siteUrl: config.get('url'),
45
+ imageBaseUrl: config.get('urls:image') || '',
46
+ imageOptimization: config.get('imageOptimization'),
47
+ canTransformImage(storagePath) {
48
+ const imageTransform = require('@tryghost/image-transform');
49
+ const {ext} = path.parse(storagePath);
50
+
51
+ // NOTE: the "saveRaw" check is smelly
52
+ return imageTransform.canTransformFiles()
53
+ && imageTransform.shouldResizeFileExtension(ext)
54
+ && typeof storage.getStorage('images').saveRaw === 'function';
55
+ },
56
+ feature: {
57
+ contentVisibility: true, // force on until Koenig has been bumped
58
+ emailCustomization: true, // force on until Koenig has been bumped
59
+ emailUniqueid: labs.isSet('emailUniqueid'),
60
+ pictureImageFormats: labs.isSet('pictureImageFormats')
61
+ },
62
+ nodeRenderers
63
+ }, userOptions);
64
+ }
65
+
21
66
  module.exports = {
22
67
  get blankDocument() {
23
68
  return {
@@ -43,12 +88,7 @@ module.exports = {
43
88
 
44
89
  get lexicalHtmlRenderer() {
45
90
  if (!lexicalHtmlRenderer) {
46
- if (!nodes) {
47
- populateNodes();
48
- }
49
-
50
- const {LexicalHTMLRenderer} = require('@tryghost/kg-lexical-html-renderer');
51
- lexicalHtmlRenderer = new LexicalHTMLRenderer({nodes});
91
+ lexicalHtmlRenderer = createLexicalHtmlRenderer();
52
92
  }
53
93
 
54
94
  return lexicalHtmlRenderer;
@@ -72,38 +112,24 @@ module.exports = {
72
112
  },
73
113
 
74
114
  async render(lexical, userOptions = {}) {
75
- if (!postsService) {
76
- const getPostServiceInstance = require('../services/posts/posts-service-instance');
77
- postsService = getPostServiceInstance();
78
- }
79
- if (!serializePosts) {
80
- serializePosts = require('../api/endpoints/utils/serializers/output/posts').all;
81
- }
115
+ const options = buildRenderOptions(userOptions, this.customNodeRenderers);
116
+ return await this.lexicalHtmlRenderer.render(lexical, options);
117
+ },
82
118
 
83
- const options = Object.assign({
84
- siteUuid: settingsCache.get('site_uuid'),
85
- siteUrl: config.get('url'),
86
- imageBaseUrl: config.get('urls:image') || '',
87
- imageOptimization: config.get('imageOptimization'),
88
- canTransformImage(storagePath) {
89
- const imageTransform = require('@tryghost/image-transform');
90
- const {ext} = path.parse(storagePath);
91
-
92
- // NOTE: the "saveRaw" check is smelly
93
- return imageTransform.canTransformFiles()
94
- && imageTransform.shouldResizeFileExtension(ext)
95
- && typeof storage.getStorage('images').saveRaw === 'function';
96
- },
97
- feature: {
98
- contentVisibility: true, // force on until Koenig has been bumped
99
- emailCustomization: true, // force on until Koenig has been bumped
100
- emailUniqueid: labs.isSet('emailUniqueid'),
101
- pictureImageFormats: labs.isSet('pictureImageFormats')
102
- },
103
- nodeRenderers: this.customNodeRenderers
104
- }, userOptions);
119
+ async validate(lexical, userOptions = {}) {
120
+ try {
121
+ const lexicalValidationRenderer = createLexicalHtmlRenderer((error) => {
122
+ throw error;
123
+ });
105
124
 
106
- return await this.lexicalHtmlRenderer.render(lexical, options);
125
+ // The validation renderer rethrows parser errors so this method can
126
+ // convert every malformed document into a boolean result.
127
+ const options = buildRenderOptions(userOptions, this.customNodeRenderers);
128
+ await lexicalValidationRenderer.render(lexical, options);
129
+ return true;
130
+ } catch {
131
+ return false;
132
+ }
107
133
  },
108
134
 
109
135
  get nodes() {
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PostRevisions = void 0;
4
4
  class PostRevisions {
5
5
  config;
6
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
6
  model;
8
7
  constructor(deps) {
9
8
  this.config = deps.config;
@@ -79,7 +78,6 @@ class PostRevisions {
79
78
  post_status: input.post_status
80
79
  };
81
80
  }
82
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
83
81
  async removeAuthorFromRevisions(authorId, options) {
84
82
  const revisions = await this.model.findAll({
85
83
  filter: `author_id:'${authorId}'`,