ghost 6.53.0 → 6.54.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (639) hide show
  1. package/components/ghost-storage-base-3.0.0.tgz +0 -0
  2. package/components/tryghost-adapter-base-cache-0.2.0.tgz +0 -0
  3. package/components/tryghost-adapter-base-scheduling-0.2.0.tgz +0 -0
  4. package/components/tryghost-adapter-base-sso-0.1.1.tgz +0 -0
  5. package/components/tryghost-admin-api-schema-0.0.0.tgz +0 -0
  6. package/components/tryghost-custom-field-types-0.0.0.tgz +0 -0
  7. package/components/tryghost-i18n-0.0.0.tgz +0 -0
  8. package/components/tryghost-kg-converters-1.2.3.tgz +0 -0
  9. package/components/tryghost-kg-default-nodes-2.1.3.tgz +0 -0
  10. package/components/tryghost-kg-lexical-html-renderer-1.4.3.tgz +0 -0
  11. package/core/boot.js +9 -6
  12. package/core/built/admin/assets/Combination-CJG7Flp-.js +41 -0
  13. package/core/built/admin/assets/Growth-BTP1LthE.js +3 -0
  14. package/core/built/admin/assets/Newsletters-CSEX0myc.js +1 -0
  15. package/core/built/admin/assets/Overview-BjACEsJF.js +1 -0
  16. package/core/built/admin/assets/{PolarAngleAxis-pciQ0MOy.js → PolarAngleAxis-BGjf7sBu.js} +1 -1
  17. package/core/built/admin/assets/{RadialBarChart-DWmw2PcX.js → RadialBarChart-zeFf9mBz.js} +1 -1
  18. package/core/built/admin/assets/Web-CxxxjCcv.js +2 -0
  19. package/core/built/admin/assets/account-migration-BklF2I_I.js +1 -0
  20. package/core/built/admin/assets/activitypub/{account-migration-BPZG37DJ.js → account-migration-CNovr6W-.js} +13 -13
  21. package/core/built/admin/assets/activitypub/activitypub.js +8 -8
  22. package/core/built/admin/assets/activitypub/{avatar-ZYco0ITb.js → avatar-B3DEDB1l.js} +10 -10
  23. package/core/built/admin/assets/activitypub/{avatar-flipboard-D541lc4F.js → avatar-flipboard-Cqrg0XMx.js} +3 -3
  24. package/core/built/admin/assets/activitypub/{bluesky-sharing-NOHUtHjl.js → bluesky-sharing-Ceslb1_M.js} +38 -37
  25. package/core/built/admin/assets/activitypub/{chunk-KS7C4IRE-B-GOFDPZ.js → chunk-KS7C4IRE-D4HEcEwi.js} +716 -710
  26. package/core/built/admin/assets/activitypub/{content-formatters-bwrp4iEO.js → content-formatters-BpQARh28.js} +229 -181
  27. package/core/built/admin/assets/activitypub/{copy-C7m7ovHw.js → copy-D9UWIAan.js} +2 -2
  28. package/core/built/admin/assets/activitypub/{dist-BqkDUQxJ2.js → dist-ByFmDSNP2.js} +64 -63
  29. package/core/built/admin/assets/activitypub/{dist-B5ira32t.js → dist-DHAjBcV3.js} +5 -5
  30. package/core/built/admin/assets/activitypub/{domain-iqE4YXwD.js → domain-C1qQvJ8C.js} +33 -33
  31. package/core/built/admin/assets/activitypub/{edit-profile-B8MFYh28.js → edit-profile-BcH-jEfM.js} +46 -45
  32. package/core/built/admin/assets/activitypub/{explore-BbdKodp3.js → explore-AxwBh9dI.js} +20 -20
  33. package/core/built/admin/assets/activitypub/{feed-Cl3A5owG.js → feed-BaOlbh7a.js} +15 -15
  34. package/core/built/admin/assets/activitypub/{field-DL6WyR-c.js → field-B7mYYQpN.js} +13 -13
  35. package/core/built/admin/assets/activitypub/{hash-6G3DzwL9.js → hash-BC9Q0N4c.js} +2 -2
  36. package/core/built/admin/assets/activitypub/{inbox-YmhuBice.js → inbox-DQ4ZnC1m.js} +2 -2
  37. package/core/built/admin/assets/activitypub/inbox-vXez-5uJ.js +1221 -0
  38. package/core/built/admin/assets/activitypub/{label-DGbLjDvE.js → label-Chv5T8bw.js} +6 -6
  39. package/core/built/admin/assets/activitypub/layout-CziktJXo.js +1 -0
  40. package/core/built/admin/assets/activitypub/{moderation-qnBtk1zS.js → moderation-DtSM2i1I.js} +32 -31
  41. package/core/built/admin/assets/activitypub/{note-C7ZRoSJv.js → note-Dckp4S-2.js} +21 -21
  42. package/core/built/admin/assets/activitypub/{notifications-DiEA4b1o.js → notifications-CG5T22vg.js} +17 -17
  43. package/core/built/admin/assets/activitypub/{onboarding-_JVgEwgV.js → onboarding-BFDkzeR2.js} +2 -2
  44. package/core/built/admin/assets/activitypub/{onboarding-DG4zu3qM.js → onboarding-D6rcBdPe.js} +5 -5
  45. package/core/built/admin/assets/activitypub/{preferences-B3FtocnP.js → preferences-D_799jdl.js} +1607 -1606
  46. package/core/built/admin/assets/activitypub/{profile-D8ZJfYXB.js → profile-D2JfXBQl.js} +264 -263
  47. package/core/built/admin/assets/activitypub/{reply-C1vggenw.js → reply-CpdMeAO5.js} +2 -2
  48. package/core/built/admin/assets/activitypub/{routes-BOii-V9n.js → routes-CCHe2dQp.js} +1317 -1298
  49. package/core/built/admin/assets/activitypub/{separator-1gNokN5S.js → separator-BI1FLsYM.js} +4 -4
  50. package/core/built/admin/assets/activitypub/{settings--9Sb0nbl.js → settings-kx-9Enkz.js} +14 -14
  51. package/core/built/admin/assets/activitypub/{site-fkMmqv0V.js → site-x4_IjVJ0.js} +10 -10
  52. package/core/built/admin/assets/activitypub/{step-1-QhivSMw2.js → step-1-DIDg4aHb.js} +15 -15
  53. package/core/built/admin/assets/activitypub/{step-2-pMk9YwqD.js → step-2-BfGe8BYt.js} +7 -7
  54. package/core/built/admin/assets/activitypub/{step-3-DvmVC1fo.js → step-3-mE9spAqw.js} +12 -12
  55. package/core/built/admin/assets/activitypub/{tabs-Dc0FEEYD.js → tabs-CyPRQQ1N.js} +241 -237
  56. package/core/built/admin/assets/activitypub/{topic-filter-CuDyM5bD.js → topic-filter-DLHBZT93.js} +4 -4
  57. package/core/built/admin/assets/activitypub/use-activity-pub-queries-VzbN99u_.js +1957 -0
  58. package/core/built/admin/assets/activitypub/{use-navigate-with-base-path-Drx1kdAK.js → use-navigate-with-base-path-CAwXTmqH.js} +165 -175
  59. package/core/built/admin/assets/activitypub/{use-reply-chain-data-BHkCHcW5.js → use-reply-chain-data-BAB6fNGt.js} +8 -8
  60. package/core/built/admin/assets/activitypub/users-BLeiOTHc.js +1464 -0
  61. package/core/built/admin/assets/activitypub/{x-BHCEe-c2.js → x-C8tAnXly.js} +2 -2
  62. package/core/built/admin/assets/{audience-adiFehTD.js → audience-X_XsZivI.js} +1 -1
  63. package/core/built/admin/assets/{automated-emails-UWM02CMr.js → automated-emails-of1MvVsv.js} +1 -1
  64. package/core/built/admin/assets/automations-B7-y3dXt.js +1 -0
  65. package/core/built/admin/assets/automations-DRFjW5fw.js +1 -0
  66. package/core/built/admin/assets/{avatar-flipboard-Lz3F9fNT.js → avatar-flipboard-C6Kj3Awu.js} +1 -1
  67. package/core/built/admin/assets/bluesky-sharing-BbbjWdzs.js +1 -0
  68. package/core/built/admin/assets/box-BWbhXh21.js +1 -0
  69. package/core/built/admin/assets/breadcrumb-B-M9Ip_2.js +1 -0
  70. package/core/built/admin/assets/card-DGoDJzrn.js +1 -0
  71. package/core/built/admin/assets/{chart-ChpW-NzQ.js → chart-BuRT2Y6p.js} +14 -14
  72. package/core/built/admin/assets/chart-helpers-xiSsW8r0.js +1 -0
  73. package/core/built/admin/assets/checkbox-EhJKHFdZ.js +1 -0
  74. package/core/built/admin/assets/{chunk.432.c2caa0b20f03e71d1a35.js → chunk.211.6f7328d63c41536451b3.js} +2025 -2819
  75. package/core/built/admin/assets/{chunk.432.c2caa0b20f03e71d1a35.js.LICENSE.txt → chunk.211.6f7328d63c41536451b3.js.LICENSE.txt} +1 -62
  76. package/core/built/admin/assets/{chunk.831.0703a12e49f51cec3f3a.js → chunk.361.3cdb584b973959e52ccc.js} +78 -85
  77. package/core/built/admin/assets/chunk.524.8365cd9280405c0f6216.js +25 -0
  78. package/core/built/admin/assets/chunk.582.61d078937e6102769f2c.js +27 -0
  79. package/core/built/admin/assets/code-editor-view-CZtJFGhR.js +1 -0
  80. package/core/built/admin/assets/comments-CvyXxOyN.js +1 -0
  81. package/core/built/admin/assets/container-BYz2Ed39.js +1 -0
  82. package/core/built/admin/assets/data-list-16rkJYYi.js +1 -0
  83. package/core/built/admin/assets/date-range-select-CTlyo8zW.js +1 -0
  84. package/core/built/admin/assets/disabled-sources-indicator-qs2GfLvl.js +1 -0
  85. package/core/built/admin/assets/{dist-DJ6c4_De.js → dist-2Tnz2Yfq.js} +1 -1
  86. package/core/built/admin/assets/{dist-CsekE4FL.js → dist-CQJY6SVY.js} +1 -1
  87. package/core/built/admin/assets/dist-CjY-f5Z1.js +1 -0
  88. package/core/built/admin/assets/dist-DGzPJ_bO.js +4 -0
  89. package/core/built/admin/assets/dist-DIC8yz5C.js +1 -0
  90. package/core/built/admin/assets/{dist-BbGrW05X.js → dist-DyViJwIy.js} +1 -1
  91. package/core/built/admin/assets/dist-Ndy-PuGN.js +1 -0
  92. package/core/built/admin/assets/dist-P_ohUlTi.js +1 -0
  93. package/core/built/admin/assets/domain-CPNXKVOV.js +1 -0
  94. package/core/built/admin/assets/dropzone-BmCXnw6J.js +5 -0
  95. package/core/built/admin/assets/edit-profile-SGrJve5M.js +1 -0
  96. package/core/built/admin/assets/editor-BOG2YPUm.js +8 -0
  97. package/core/built/admin/assets/empty-indicator-oX1u1Pkn.js +1 -0
  98. package/core/built/admin/assets/esm-CFX93H5M.js +2 -0
  99. package/core/built/admin/assets/explore-CUYLv9G9.js +1 -0
  100. package/core/built/admin/assets/feed-CPdJMttL.js +1 -0
  101. package/core/built/admin/assets/field-D0XISCK2.js +1 -0
  102. package/core/built/admin/assets/{filter-sources-v39ihhhV.js → filter-sources-Bieps75g.js} +1 -1
  103. package/core/built/admin/assets/filters-CuB-A7ma.js +1 -0
  104. package/core/built/admin/assets/filters-bXkkWro8.js +1 -0
  105. package/core/built/admin/assets/framework-provider-CmtnPXIT.js +4 -0
  106. package/core/built/admin/assets/{ghost-b57f077997b739a8ae9a70772dc016cb.js → ghost-05f9a7182ed56903dba05878a5b8422b.js} +46 -41
  107. package/core/built/admin/assets/ghost-dark-c8d0ab7f515b2010c173e23e9b32ea8a.css +1 -0
  108. package/core/built/admin/assets/gift-link-modal-su8MsRdg.js +1 -0
  109. package/core/built/admin/assets/{gift-links-CY3GwiVi.js → gift-links-nBxJjZiQ.js} +1 -1
  110. package/core/built/admin/assets/growth-Ba6S5FQX.js +1 -0
  111. package/core/built/admin/assets/hooks-BApwwBE0.js +2 -0
  112. package/core/built/admin/assets/{inbox-TEISAmth.js → inbox-Xx1CdnfO.js} +38 -38
  113. package/core/built/admin/assets/index-D8PbzuT9.css +1 -0
  114. package/core/built/admin/assets/index-ukW_0Uie.js +67 -0
  115. package/core/built/admin/assets/inline-EMAm3okk.js +1 -0
  116. package/core/built/admin/assets/input-group-CGOXcy4l.js +1 -0
  117. package/core/built/admin/assets/input-surface-BpAjZXY5.js +1 -0
  118. package/core/built/admin/assets/{react-dom-C6aoWSfl.js → jsx-runtime-DX3WBWVO.js} +1 -1
  119. package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +5 -2
  120. package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +2 -2
  121. package/core/built/admin/assets/{koenig-lexical-Di7b48ED.js → koenig-lexical-B61IALf5.js} +2 -2
  122. package/core/built/admin/assets/kpi-card-BlZaG1Lo.js +1 -0
  123. package/core/built/admin/assets/kpi-card-DCdlyaSS.js +1 -0
  124. package/core/built/admin/assets/kpi-helpers-DpAuS1Nb.js +1 -0
  125. package/core/built/admin/assets/kpi-tabs-Dme44bQS.js +1 -0
  126. package/core/built/admin/assets/label-dSs5aepE.js +1 -0
  127. package/core/built/admin/assets/label-picker-Uq91atex.js +1 -0
  128. package/core/built/admin/assets/{labels-GbxlXWtf.js → labels-Cyayfd-e.js} +1 -1
  129. package/core/built/admin/assets/layout-WUcz6tu1.js +1 -0
  130. package/core/built/admin/assets/limit-service-9fwD33lU.js +20 -0
  131. package/core/built/admin/assets/link-helpers-tOlxmuH5.js +1 -0
  132. package/core/built/admin/assets/list-page-B6ANtzkd.js +1 -0
  133. package/core/built/admin/assets/mailchimp-Ds_NQ04w.svg +9 -0
  134. package/core/built/admin/assets/member-custom-fields-NCzrMuba.js +1 -0
  135. package/core/built/admin/assets/member-detail-DPWDtYnN.js +1 -0
  136. package/core/built/admin/assets/members-B9rO7qr4.js +10 -0
  137. package/core/built/admin/assets/modals-CxRaan1J.js +31 -0
  138. package/core/built/admin/assets/moderation-D8zon60E.js +1 -0
  139. package/core/built/admin/assets/multi-select-combobox-1wYm3nle.js +1 -0
  140. package/core/built/admin/assets/newsletter-DbYMRxRS.js +1 -0
  141. package/core/built/admin/assets/{newsletters-DZm3yLj8.js → newsletters-D1jbtV-h.js} +1 -1
  142. package/core/built/admin/assets/note-PiWPnnrh.js +1 -0
  143. package/core/built/admin/assets/notifications-DEgqqB9G.js +1 -0
  144. package/core/built/admin/assets/nql-lang-B7faUf8D.js +19 -0
  145. package/core/built/admin/assets/{offers-D11QtPXX.js → offers-CrY6nSRR.js} +1 -1
  146. package/core/built/admin/assets/onboarding-route-BzF6HeVn.js +1 -0
  147. package/core/built/admin/assets/overview-DixLeIqY.js +1 -0
  148. package/core/built/admin/assets/page-header-op0eN36I.js +1 -0
  149. package/core/built/admin/assets/{pages-BnObVRrf.js → pages-BbNWFcGj.js} +1 -1
  150. package/core/built/admin/assets/pintura-CXOmq-5H.svg +15 -0
  151. package/core/built/admin/assets/post-analytics-WwRDEnrV.js +1 -0
  152. package/core/built/admin/assets/post-analytics-header-DsMoLx0R.js +1 -0
  153. package/core/built/admin/assets/{post-analytics-provider-DSfBCtnj.js → post-analytics-provider-BJCPLMIb.js} +1 -1
  154. package/core/built/admin/assets/post-share-modal-Dx-MEjhI.js +1 -0
  155. package/core/built/admin/assets/{posts-CwH8VJvB.js → posts-EWpZIjkr.js} +1 -1
  156. package/core/built/admin/assets/preferences-D7-j6A4C.js +5 -0
  157. package/core/built/admin/assets/profile-Dl69QPp0.js +1 -0
  158. package/core/built/admin/assets/{referrers-nxR52jPI.js → referrers-BCfFYSHc.js} +1 -1
  159. package/core/built/admin/assets/router-provider-C1R4AZ2o.js +1 -0
  160. package/core/built/admin/assets/select-C1qDZnW4.js +1 -0
  161. package/core/built/admin/assets/settings-BbmC_Iqq.js +4 -0
  162. package/core/built/admin/assets/settings-H6HxFgfI.js +1 -0
  163. package/core/built/admin/assets/shade-app-B3heOAfz-CGXQwWeO.js +3 -0
  164. package/core/built/admin/assets/share-modal-BJCadJyp.js +1 -0
  165. package/core/built/admin/assets/social-urls-BPL1nADp.js +8 -0
  166. package/core/built/admin/assets/sort-button-DyYlfYp7.js +1 -0
  167. package/core/built/admin/assets/source-icon-_ubRDbg_.js +1 -0
  168. package/core/built/admin/assets/stack-xiN0eQ6Z.js +1 -0
  169. package/core/built/admin/assets/stats-BQZMGMvn.js +1 -0
  170. package/core/built/admin/assets/stats-view-Doei-qCX.js +1 -0
  171. package/core/built/admin/assets/step-1-IKiLBPoC.js +1 -0
  172. package/core/built/admin/assets/step-2-jJ41PsDN.js +1 -0
  173. package/core/built/admin/assets/step-3-CaqFAEqf.js +2 -0
  174. package/core/built/admin/assets/switch-t-WyENU2.js +1 -0
  175. package/core/built/admin/assets/table-DxUL78jU.js +1 -0
  176. package/core/built/admin/assets/tabs-BQcJQ1ke.js +1 -0
  177. package/core/built/admin/assets/tags-CNujGwkT.js +1 -0
  178. package/core/built/admin/assets/text-DwtjwGkh.js +1 -0
  179. package/core/built/admin/assets/textarea-Bjccvh_E.js +1 -0
  180. package/core/built/admin/assets/{tiers-EghDzCKc.js → tiers-BgYLWRJv.js} +1 -1
  181. package/core/built/admin/assets/toggle-group-BeEpQ69p.js +1 -0
  182. package/core/built/admin/assets/topic-filter-Bb5MOD-1.js +1 -0
  183. package/core/built/admin/assets/{use-analytics-data-0l_OHtnR.js → use-analytics-data-Cds6XDjg.js} +1 -1
  184. package/core/built/admin/assets/use-filter-params-DjXkhO54.js +1 -0
  185. package/core/built/admin/assets/use-growth-stats-D8uf98-G.js +1 -0
  186. package/core/built/admin/assets/{use-post-referrers-DwI31Ril.js → use-post-referrers-CRtgyuXB.js} +1 -1
  187. package/core/built/admin/assets/use-reply-chain-data-DbKYX50v.js +1 -0
  188. package/core/built/admin/assets/use-simple-pagination-DC01kpo0.js +1 -0
  189. package/core/built/admin/assets/{use-tinybird-query-DvZBBMG7.js → use-tinybird-query-C7bQRJWw.js} +1 -1
  190. package/core/built/admin/assets/{use-tinybird-token-CQtebkvU.js → use-tinybird-token-Az4tam7_.js} +1 -1
  191. package/core/built/admin/assets/{users-Pc8IRjk9.js → users-CcSCQFcQ.js} +1 -1
  192. package/core/built/admin/assets/virtual-list-Dhuh9fGx.js +1 -0
  193. package/core/built/admin/assets/web-LtHNiNBV.js +1 -0
  194. package/core/built/admin/index.html +22 -22
  195. package/core/frontend/apps/private-blogging/index.js +1 -1
  196. package/core/frontend/apps/private-blogging/lib/middleware.js +1 -1
  197. package/core/frontend/helpers/split.js +2 -1
  198. package/core/frontend/meta/asset-url.js +1 -1
  199. package/core/frontend/meta/author-image.js +1 -1
  200. package/core/frontend/meta/blog-logo.js +1 -1
  201. package/core/frontend/meta/canonical-url.js +1 -1
  202. package/core/frontend/meta/cover-image.js +1 -1
  203. package/core/frontend/meta/get-meta.js +1 -1
  204. package/core/frontend/meta/og-image.js +1 -1
  205. package/core/frontend/meta/paginated-url.js +1 -1
  206. package/core/frontend/meta/twitter-image.js +1 -1
  207. package/core/frontend/meta/url.js +1 -1
  208. package/core/frontend/services/assets-minification/admin-auth-assets.js +1 -1
  209. package/core/frontend/services/llms/handler.js +1 -1
  210. package/core/frontend/services/proxy.js +42 -3
  211. package/core/frontend/services/routing/collection-router.js +1 -1
  212. package/core/frontend/services/routing/controllers/email-post.js +1 -1
  213. package/core/frontend/services/routing/controllers/entry/markdown.js +1 -1
  214. package/core/frontend/services/routing/controllers/entry/markdown.ts +1 -1
  215. package/core/frontend/services/routing/controllers/entry.js +1 -1
  216. package/core/frontend/services/routing/controllers/entry.ts +1 -1
  217. package/core/frontend/services/routing/controllers/previews.js +6 -7
  218. package/core/frontend/services/routing/controllers/unsubscribe.js +7 -3
  219. package/core/frontend/services/routing/email-router.js +1 -1
  220. package/core/frontend/services/routing/events.js +12 -0
  221. package/core/frontend/services/routing/middleware/page-param.js +1 -1
  222. package/core/frontend/services/routing/parent-router.js +1 -1
  223. package/core/frontend/services/routing/preview-router.js +1 -1
  224. package/core/frontend/services/routing/router-manager.js +4 -8
  225. package/core/frontend/services/routing/rss-router.js +1 -1
  226. package/core/frontend/services/routing/static-pages-router.js +1 -1
  227. package/core/frontend/services/routing/static-routes-router.js +1 -1
  228. package/core/frontend/services/routing/taxonomy-router.js +1 -1
  229. package/core/frontend/services/rss/generate-feed.js +1 -1
  230. package/core/frontend/services/sitemap/base-site-map-generator.js +23 -4
  231. package/core/frontend/services/sitemap/site-map-index-generator.js +1 -1
  232. package/core/frontend/services/sitemap/site-map-manager.js +14 -8
  233. package/core/frontend/services/sitemap/utils.js +1 -1
  234. package/core/frontend/services/theme-engine/middleware/update-global-template-options.js +1 -1
  235. package/core/frontend/services/theme-engine/middleware/update-local-template-options.js +1 -1
  236. package/core/frontend/utils/images.js +1 -1
  237. package/core/frontend/web/middleware/admin-toolbar.js +1 -1
  238. package/core/frontend/web/middleware/handle-image-sizes.js +2 -2
  239. package/core/frontend/web/middleware/redirect-ghost-to-admin.js +1 -1
  240. package/core/frontend/web/routers/serve-favicon.js +1 -1
  241. package/core/frontend/web/routers/serve-public-file.js +1 -1
  242. package/core/frontend/web/site.js +5 -5
  243. package/core/server/adapters/cache/AdapterCacheMemoryTTL.js +2 -2
  244. package/core/server/adapters/cache/MemoryCache.js +2 -2
  245. package/core/server/adapters/cache/Redis.js +1 -1
  246. package/core/server/adapters/cache/index.js +1 -1
  247. package/core/server/adapters/lib/redis/AdapterCacheRedis.js +2 -2
  248. package/core/server/adapters/route-settings/FileStore.js +2 -8
  249. package/core/server/adapters/route-settings/FileStore.ts +1 -6
  250. package/core/server/adapters/route-settings/S3RouteSettingsStore.js +206 -0
  251. package/core/server/adapters/route-settings/S3RouteSettingsStore.ts +199 -0
  252. package/core/server/adapters/route-settings/utils.js +13 -0
  253. package/core/server/adapters/route-settings/utils.ts +7 -0
  254. package/core/server/adapters/scheduling/deps.d.ts +0 -2
  255. package/core/server/adapters/scheduling/error-capture.js +76 -0
  256. package/core/server/adapters/scheduling/error-capture.ts +91 -0
  257. package/core/server/adapters/scheduling/utils.js +18 -34
  258. package/core/server/adapters/scheduling/utils.ts +36 -0
  259. package/core/server/adapters/storage/LocalFilesStorage.js +13 -11
  260. package/core/server/adapters/storage/LocalFilesStorage.ts +24 -0
  261. package/core/server/adapters/storage/LocalImagesStorage.js +14 -12
  262. package/core/server/adapters/storage/LocalImagesStorage.ts +24 -0
  263. package/core/server/adapters/storage/LocalMediaStorage.js +13 -11
  264. package/core/server/adapters/storage/LocalMediaStorage.ts +24 -0
  265. package/core/server/adapters/storage/LocalStorageBase.js +107 -167
  266. package/core/server/adapters/storage/LocalStorageBase.ts +342 -0
  267. package/core/server/adapters/storage/S3Storage.js +2 -2
  268. package/core/server/adapters/storage/S3Storage.ts +1 -1
  269. package/core/server/adapters/storage/utils.js +36 -50
  270. package/core/server/adapters/storage/utils.ts +60 -0
  271. package/core/server/api/endpoints/authentication.js +1 -1
  272. package/core/server/api/endpoints/db.js +6 -0
  273. package/core/server/api/endpoints/featurebase.js +1 -1
  274. package/core/server/api/endpoints/files.js +2 -2
  275. package/core/server/api/endpoints/images.js +2 -2
  276. package/core/server/api/endpoints/libraries.d.ts +0 -1
  277. package/core/server/api/endpoints/media.js +8 -5
  278. package/core/server/api/endpoints/member-custom-fields.js +4 -1
  279. package/core/server/api/endpoints/member-custom-fields.ts +4 -1
  280. package/core/server/api/endpoints/members.js +25 -28
  281. package/core/server/api/endpoints/pages.js +6 -1
  282. package/core/server/api/endpoints/posts.js +28 -3
  283. package/core/server/api/endpoints/search-index-public.js +4 -3
  284. package/core/server/api/endpoints/search-index.js +5 -4
  285. package/core/server/api/endpoints/settings-public.js +1 -1
  286. package/core/server/api/endpoints/settings.js +3 -1
  287. package/core/server/api/endpoints/utils/serializers/input/utils/url.js +9 -1
  288. package/core/server/api/endpoints/utils/serializers/output/default.js +7 -0
  289. package/core/server/api/endpoints/utils/serializers/output/files.js +1 -1
  290. package/core/server/api/endpoints/utils/serializers/output/mappers/comments.js +4 -1
  291. package/core/server/api/endpoints/utils/serializers/output/media.js +1 -1
  292. package/core/server/api/endpoints/utils/serializers/output/member-custom-fields.js +7 -4
  293. package/core/server/api/endpoints/utils/serializers/output/member-custom-fields.ts +8 -4
  294. package/core/server/api/endpoints/utils/serializers/output/members.js +27 -106
  295. package/core/server/api/endpoints/utils/serializers/output/pages.js +7 -0
  296. package/core/server/api/endpoints/utils/serializers/output/posts.js +13 -0
  297. package/core/server/api/endpoints/utils/serializers/output/utils/url.js +1 -1
  298. package/core/server/api/endpoints/utils/validators/input/members.js +2 -52
  299. package/core/server/data/db/backup.js +1 -1
  300. package/core/server/data/exporter/export-filename.js +2 -1
  301. package/core/server/data/importer/handlers/image.js +3 -3
  302. package/core/server/data/importer/import-manager.js +6 -4
  303. package/core/server/data/importer/importers/content-file-importer.js +2 -2
  304. package/core/server/data/importer/importers/data/revue-subscriber-importer.js +6 -10
  305. package/core/server/data/importer/importers/json-to-html.js +24 -4
  306. package/core/server/data/migrations/utils/schema.js +4 -2
  307. package/core/server/data/migrations/versions/6.54/2026-07-19-16-59-00-add-content-import-permission.js +10 -0
  308. package/core/server/data/migrations/versions/6.54/2026-07-20-13-59-21-drop-email-tracked-sent-count-from-automation-action-revisions.js +7 -0
  309. package/core/server/data/migrations/versions/6.54/2026-07-21-01-58-20-add-automation-run-steps-poller-index.js +3 -0
  310. package/core/server/data/migrations/versions/6.54/2026-07-21-21-08-15-add-automated-email-recipients-mailgun-message-id-index.js +3 -0
  311. package/core/server/data/migrations/versions/6.54/2026-07-22-10-41-08-add-click-tracking-to-automated-email-recipients.js +13 -0
  312. package/core/server/data/migrations/versions/6.54/2026-07-22-15-10-30-add-email-clicked-count-to-automation-action-revisions.js +7 -0
  313. package/core/server/data/migrations/versions/6.54/2026-07-23-10-24-18-add-automation-action-revision-to-redirects.js +9 -0
  314. package/core/server/data/schema/commands.js +37 -3
  315. package/core/server/data/schema/fixtures/fixtures.json +7 -0
  316. package/core/server/data/schema/lib/default-index-name.js +20 -0
  317. package/core/server/data/schema/schema.js +40 -17
  318. package/core/server/data/seeders/data-generator.js +4 -2
  319. package/core/server/lib/image/image-size.js +7 -23
  320. package/core/server/lib/image/image-utils.js +16 -2
  321. package/core/server/lib/image/index.js +4 -4
  322. package/core/server/lib/lexical.js +3 -3
  323. package/core/server/lib/mobiledoc.js +2 -2
  324. package/core/server/lib/request-external.js +1 -1
  325. package/core/server/lib/validate-password.js +1 -1
  326. package/core/server/models/action.js +9 -0
  327. package/core/server/models/base/plugins/generate-slug.js +1 -1
  328. package/core/server/models/collection.js +1 -1
  329. package/core/server/models/custom-theme-setting.js +1 -1
  330. package/core/server/models/member.js +73 -0
  331. package/core/server/models/newsletter.js +1 -1
  332. package/core/server/models/post.js +19 -5
  333. package/core/server/models/posts-meta.js +1 -1
  334. package/core/server/models/redirect.js +1 -1
  335. package/core/server/models/settings.js +1 -1
  336. package/core/server/models/snippet.js +1 -1
  337. package/core/server/models/tag.js +1 -1
  338. package/core/server/models/user.js +47 -71
  339. package/core/server/models/welcome-email-automated-email.js +1 -1
  340. package/core/server/services/activitypub/activity-pub-service-wrapper.js +1 -1
  341. package/core/server/services/adapter-manager/adapter-manager.js +5 -1
  342. package/core/server/services/adapter-manager/adapter-manager.ts +7 -2
  343. package/core/server/services/adapter-manager/index.js +18 -15
  344. package/core/server/services/adapter-manager/index.ts +23 -17
  345. package/core/server/services/adapter-manager/utils.js +124 -14
  346. package/core/server/services/adapter-manager/utils.ts +130 -14
  347. package/core/server/services/api-version-compatibility/mw-version-rewrites.js +1 -1
  348. package/core/server/services/audience-feedback/index.js +1 -1
  349. package/core/server/services/auth/passwordreset.js +1 -1
  350. package/core/server/services/auth/session/express-session.js +1 -1
  351. package/core/server/services/auth/session/index.js +2 -2
  352. package/core/server/services/auth/session/session-service.js +29 -2
  353. package/core/server/services/automations/automations-api.js +8 -25
  354. package/core/server/services/automations/automations-api.ts +8 -37
  355. package/core/server/services/automations/automations-repository.ts +16 -0
  356. package/core/server/services/automations/database-automations-repository.js +37 -4
  357. package/core/server/services/automations/database-automations-repository.ts +41 -4
  358. package/core/server/services/automations/poll.js +16 -12
  359. package/core/server/services/automations/poll.ts +17 -15
  360. package/core/server/services/automations/service.js +1 -1
  361. package/core/server/services/automations/service.ts +3 -13
  362. package/core/server/services/automations/welcome-email-automation-poll.js +2 -1
  363. package/core/server/services/comments/comments-service-emails.js +4 -1
  364. package/core/server/services/comments/index.js +1 -1
  365. package/core/server/services/custom-redirects/index.js +2 -2
  366. package/core/server/services/email-analytics/email-analytics-service-wrapper.js +14 -13
  367. package/core/server/services/email-analytics/email-analytics-service.js +1 -1
  368. package/core/server/services/email-analytics/events/start-email-analytics-job-event.js +11 -15
  369. package/core/server/services/email-analytics/events/start-email-analytics-job-event.ts +15 -0
  370. package/core/server/services/email-analytics/index.js +2 -3
  371. package/core/server/services/email-analytics/index.ts +1 -2
  372. package/core/server/services/email-analytics/jobs/email-analytics-job-scheduler.js +1 -6
  373. package/core/server/services/email-analytics/jobs/email-analytics-job-scheduler.ts +0 -9
  374. package/core/server/services/email-analytics/jobs/fetch-latest/index.js +1 -1
  375. package/core/server/services/email-analytics/jobs/index.js +0 -2
  376. package/core/server/services/email-service/email-service-wrapper.js +1 -1
  377. package/core/server/services/email-service/email-service.js +20 -4
  378. package/core/server/services/explore-ping/explore-ping-service.js +24 -39
  379. package/core/server/services/explore-ping/explore-ping-service.ts +198 -0
  380. package/core/server/services/explore-ping/index.js +11 -11
  381. package/core/server/services/explore-ping/index.ts +42 -0
  382. package/core/server/services/gifts/gift-reminder-scheduler.js +1 -1
  383. package/core/server/services/gifts/gift-reminder-scheduler.ts +1 -1
  384. package/core/server/services/gifts/gift-service-wrapper.js +1 -1
  385. package/core/server/services/identity-tokens/identity-token-service-wrapper.js +1 -1
  386. package/core/server/services/indexnow-ping/constants.js +30 -0
  387. package/core/server/services/indexnow-ping/constants.ts +32 -0
  388. package/core/server/services/indexnow-ping/index.js +29 -253
  389. package/core/server/services/indexnow-ping/index.ts +37 -0
  390. package/core/server/services/indexnow-ping/indexnow-ping-service.js +229 -0
  391. package/core/server/services/indexnow-ping/indexnow-ping-service.ts +319 -0
  392. package/core/server/services/invites/index.js +1 -1
  393. package/core/server/services/lib/mailgun-client.js +3 -3
  394. package/core/server/services/link-redirection/index.js +2 -2
  395. package/core/server/services/link-redirection/link-redirect-repository.js +1 -1
  396. package/core/server/services/link-redirection/link-redirect.js +12 -13
  397. package/core/server/services/link-redirection/link-redirect.ts +22 -0
  398. package/core/server/services/link-redirection/link-redirects-service.js +1 -1
  399. package/core/server/services/link-tracking/full-post-link.js +2 -2
  400. package/core/server/services/link-tracking/index.js +1 -1
  401. package/core/server/services/mail/ghost-mailer.js +1 -1
  402. package/core/server/services/mail/index.js +1 -1
  403. package/core/server/services/media-inliner/external-media-inliner.js +2 -2
  404. package/core/server/services/media-inliner/service.js +4 -3
  405. package/core/server/services/member-attribution/index.js +1 -1
  406. package/core/server/services/member-welcome-emails/service.js +1 -1
  407. package/core/server/services/members/api.js +8 -2
  408. package/core/server/services/members/import-export/config.js +30 -0
  409. package/core/server/services/members/import-export/config.ts +34 -0
  410. package/core/server/services/members/import-export/csv/index.js +10 -0
  411. package/core/server/services/members/import-export/csv/index.ts +2 -0
  412. package/core/server/services/members/import-export/csv/parse.js +64 -0
  413. package/core/server/services/members/import-export/csv/parse.ts +69 -0
  414. package/core/server/services/members/import-export/csv/serialize.js +13 -0
  415. package/core/server/services/members/import-export/csv/serialize.ts +18 -0
  416. package/core/server/services/members/import-export/export/exporter.js +202 -0
  417. package/core/server/services/members/import-export/export/exporter.ts +325 -0
  418. package/core/server/services/members/import-export/import/completion-email.js +65 -0
  419. package/core/server/services/members/import-export/import/completion-email.ts +119 -0
  420. package/core/server/services/members/import-export/import/importer.js +276 -0
  421. package/core/server/services/members/import-export/import/importer.ts +430 -0
  422. package/core/server/services/members/import-export/import/reader.js +32 -0
  423. package/core/server/services/members/import-export/import/reader.ts +33 -0
  424. package/core/server/services/members/import-export/import/row.js +33 -0
  425. package/core/server/services/members/import-export/import/row.ts +52 -0
  426. package/core/server/services/members/import-export/import/spool.js +30 -0
  427. package/core/server/services/members/import-export/import/spool.ts +38 -0
  428. package/core/server/services/members/import-export/index.js +90 -0
  429. package/core/server/services/members/import-export/index.ts +118 -0
  430. package/core/server/services/members/members-api/controllers/router-controller.js +7 -0
  431. package/core/server/services/members/members-api/members-api.js +4 -2
  432. package/core/server/services/members/members-api/repositories/event-repository.js +13 -2
  433. package/core/server/services/members/members-api/services/member-bread-service.js +42 -19
  434. package/core/server/services/members/middleware.js +1 -1
  435. package/core/server/services/members/service.js +28 -17
  436. package/core/server/services/members/stripe-connect.js +1 -1
  437. package/core/server/services/members-custom-fields/actions.js +3 -0
  438. package/core/server/services/members-custom-fields/actions.ts +6 -2
  439. package/core/server/services/members-custom-fields/config.js +34 -0
  440. package/core/server/services/members-custom-fields/config.ts +38 -0
  441. package/core/server/services/members-custom-fields/definitions-service.js +156 -21
  442. package/core/server/services/members-custom-fields/definitions-service.ts +170 -25
  443. package/core/server/services/members-custom-fields/index.js +16 -3
  444. package/core/server/services/members-custom-fields/index.ts +17 -3
  445. package/core/server/services/members-custom-fields/values-service.js +56 -10
  446. package/core/server/services/members-custom-fields/values-service.ts +62 -10
  447. package/core/server/services/mentions/mention-sending-service.js +22 -2
  448. package/core/server/services/mentions/service.js +21 -5
  449. package/core/server/services/newsletters/index.js +1 -1
  450. package/core/server/services/oembed/oembed-service.js +122 -33
  451. package/core/server/services/oembed/service.js +4 -2
  452. package/core/server/services/offers/service.js +1 -1
  453. package/core/server/services/post-scheduling/index.js +4 -3
  454. package/core/server/services/post-scheduling/index.ts +4 -3
  455. package/core/server/services/post-scheduling/post-scheduling.js +1 -1
  456. package/core/server/services/post-scheduling/post-scheduling.ts +1 -1
  457. package/core/server/services/posts/post-email-handler.js +13 -6
  458. package/core/server/services/posts/post-scheduling.js +1 -1
  459. package/core/server/services/posts/posts-exporter.js +6 -4
  460. package/core/server/services/posts/posts-service-instance.js +1 -1
  461. package/core/server/services/posts/posts-service.js +4 -4
  462. package/core/server/services/posts-public/service.js +1 -1
  463. package/core/server/services/public-config/site.js +1 -1
  464. package/core/server/services/recommendations/recommendation-service-wrapper.js +1 -1
  465. package/core/server/services/recommendations/service/libraries.d.ts +0 -2
  466. package/core/server/services/route-settings/dynamic-routing-service.js +2 -3
  467. package/core/server/services/route-settings/index.js +1 -1
  468. package/core/server/services/route-settings/route-settings-parser.js +134 -124
  469. package/core/server/services/route-settings/route-settings-parser.ts +160 -125
  470. package/core/server/services/route-settings/validation-errors.js +178 -0
  471. package/core/server/services/route-settings/validation-errors.ts +196 -0
  472. package/core/server/services/settings/settings-service.js +2 -2
  473. package/core/server/services/settings-helpers/index.js +1 -1
  474. package/core/server/services/slack-notifications/service.js +1 -1
  475. package/core/server/services/slack-ping/constants.js +16 -0
  476. package/core/server/services/slack-ping/constants.ts +15 -0
  477. package/core/server/services/slack-ping/index.js +26 -204
  478. package/core/server/services/slack-ping/index.ts +35 -0
  479. package/core/server/services/slack-ping/slack-ping-service.js +214 -0
  480. package/core/server/services/slack-ping/slack-ping-service.ts +296 -0
  481. package/core/server/services/staff/index.js +1 -1
  482. package/core/server/services/stats/posts-stats-service.js +1 -1
  483. package/core/server/services/stats/service.js +1 -1
  484. package/core/server/services/stripe/service.js +1 -1
  485. package/core/server/services/tags-public/service.js +1 -1
  486. package/core/server/services/themes/storage.js +9 -0
  487. package/core/server/services/themes/theme-storage.js +1 -1
  488. package/core/server/services/themes/validate.js +1 -1
  489. package/core/server/services/update-check/index.js +1 -1
  490. package/core/server/services/url/lazy-url-service.js +66 -6
  491. package/core/server/services/url/lazy-url-service.ts +73 -6
  492. package/core/server/services/url/url-generator.js +1 -1
  493. package/core/server/services/url/url-service-facade.js +68 -3
  494. package/core/server/services/url/url-service-facade.ts +79 -4
  495. package/core/server/services/url/url-service.js +1 -1
  496. package/core/server/services/url/urls.js +1 -1
  497. package/core/server/services/webhooks/index.js +19 -2
  498. package/core/server/services/webhooks/listen.js +6 -11
  499. package/core/server/services/webhooks/payload.js +1 -3
  500. package/core/server/services/webhooks/serialize.js +16 -1
  501. package/core/server/web/admin/app.js +1 -1
  502. package/core/server/web/admin/middleware/redirect-admin-urls.js +1 -1
  503. package/core/server/web/api/endpoints/admin/routes.js +1 -0
  504. package/core/server/web/api/middleware/cors.js +1 -1
  505. package/core/server/web/api/middleware/upload.js +4 -0
  506. package/core/server/web/gift-preview/controller.js +1 -1
  507. package/core/server/web/shared/middleware/redirect-amp-urls.js +1 -1
  508. package/core/server/web/shared/middleware/uncapitalise.js +2 -2
  509. package/core/server/web/shared/middleware/url-redirects.js +1 -1
  510. package/core/shared/config/defaults.json +10 -2
  511. package/core/shared/config/overrides.json +4 -0
  512. package/core/shared/express.js +6 -1
  513. package/core/shared/labs.js +2 -1
  514. package/core/shared/url-utils.js +19 -15
  515. package/core/shared/url-utils.ts +20 -0
  516. package/ghost.js +0 -1
  517. package/package.json +30 -35
  518. package/pnpm-lock.yaml +681 -2789
  519. package/pnpm-workspace.yaml +31 -17
  520. package/components/tryghost-adapter-base-scheduling-0.0.0.tgz +0 -0
  521. package/components/tryghost-adapter-base-sso-0.0.0.tgz +0 -0
  522. package/core/built/admin/assets/Combination--5EZGaDs.js +0 -43
  523. package/core/built/admin/assets/Growth-C0NoKcHQ.js +0 -3
  524. package/core/built/admin/assets/Newsletters-Ed8kDjdy.js +0 -1
  525. package/core/built/admin/assets/Overview-CArPgRZt.js +0 -1
  526. package/core/built/admin/assets/Web-CjjYoVM3.js +0 -2
  527. package/core/built/admin/assets/account-migration-mfa5mNI9.js +0 -1
  528. package/core/built/admin/assets/activitypub/inbox-B3rjKMTv.js +0 -1221
  529. package/core/built/admin/assets/activitypub/layout-jcurg3rU.js +0 -1
  530. package/core/built/admin/assets/activitypub/use-activity-pub-queries-yqGRcnLn.js +0 -2569
  531. package/core/built/admin/assets/activitypub/users-CfyHIsTG.js +0 -1316
  532. package/core/built/admin/assets/automations-DkUnxNdv.js +0 -1
  533. package/core/built/admin/assets/automations-vjXofmV_.js +0 -1
  534. package/core/built/admin/assets/bluesky-sharing-T-pO3RcP.js +0 -1
  535. package/core/built/admin/assets/breadcrumb-CekPYTCn.js +0 -1
  536. package/core/built/admin/assets/button--i2uMDDn.js +0 -4
  537. package/core/built/admin/assets/card-CSWz_BXq.js +0 -1
  538. package/core/built/admin/assets/chart-helpers-C_4Ka_vT.js +0 -1
  539. package/core/built/admin/assets/chunk.524.8ce2c741473e2f0929dc.js +0 -25
  540. package/core/built/admin/assets/chunk.582.453459d6228d2955408b.js +0 -27
  541. package/core/built/admin/assets/code-editor-view-BfkwQto2.js +0 -1
  542. package/core/built/admin/assets/command-K75Jzs0G.js +0 -1
  543. package/core/built/admin/assets/comments-BEIi1DH-.js +0 -1
  544. package/core/built/admin/assets/container-BNXvlcjA.js +0 -1
  545. package/core/built/admin/assets/data-list-BmK5QMab.js +0 -1
  546. package/core/built/admin/assets/date-range-select-5sKzwbt7.js +0 -1
  547. package/core/built/admin/assets/disabled-sources-indicator-L_ssJTNr.js +0 -1
  548. package/core/built/admin/assets/dist-BBIJuyPg.js +0 -1
  549. package/core/built/admin/assets/dist-BHE0dp6o.js +0 -1
  550. package/core/built/admin/assets/dist-CT46_f_J.js +0 -1
  551. package/core/built/admin/assets/dist-DW0QXQO3.js +0 -1
  552. package/core/built/admin/assets/dist-DxFLceO5.js +0 -1
  553. package/core/built/admin/assets/dist-QcACAOAD.js +0 -1
  554. package/core/built/admin/assets/dist-duxRDcQu.js +0 -177
  555. package/core/built/admin/assets/domain-CLaPZ9Rc.js +0 -1
  556. package/core/built/admin/assets/dropzone-E0bSX4_a.js +0 -5
  557. package/core/built/admin/assets/edit-profile-DqNPKaA4.js +0 -1
  558. package/core/built/admin/assets/editor-CkLXQDRp.js +0 -8
  559. package/core/built/admin/assets/empty-indicator-BTtOlgIo.js +0 -1
  560. package/core/built/admin/assets/esm-TSfGW7nz.js +0 -2
  561. package/core/built/admin/assets/explore-BEstLxKr.js +0 -1
  562. package/core/built/admin/assets/feed-C58p2voG.js +0 -1
  563. package/core/built/admin/assets/field-BSbDUHPv.js +0 -1
  564. package/core/built/admin/assets/filters-BgYv8Gt7.js +0 -1
  565. package/core/built/admin/assets/filters-DvenFkmK.js +0 -1
  566. package/core/built/admin/assets/framework-provider-jQktxm9P.js +0 -4
  567. package/core/built/admin/assets/ghost-dark-8590dea6cd695ff90f27d262c4464538.css +0 -1
  568. package/core/built/admin/assets/gift-link-modal-BPjXkEFt.js +0 -1
  569. package/core/built/admin/assets/growth-D4JNiVTe.js +0 -1
  570. package/core/built/admin/assets/hooks-Cjxexi_I.js +0 -2
  571. package/core/built/admin/assets/index-BacwlcOy.js +0 -67
  572. package/core/built/admin/assets/index-DxRNHH0o.css +0 -1
  573. package/core/built/admin/assets/inline-C22rnPro.js +0 -1
  574. package/core/built/admin/assets/input-group-CKfrILLP.js +0 -1
  575. package/core/built/admin/assets/jsx-runtime-CtMZ-PAS.js +0 -1
  576. package/core/built/admin/assets/kpi-card-DZxQKAIb.js +0 -1
  577. package/core/built/admin/assets/kpi-card-FidQ5zg3.js +0 -1
  578. package/core/built/admin/assets/kpi-helpers-C5T8Vaf1.js +0 -1
  579. package/core/built/admin/assets/kpi-tabs-_VRK6hGV.js +0 -1
  580. package/core/built/admin/assets/label-Cza7hPgn.js +0 -1
  581. package/core/built/admin/assets/label-picker-DgC_zLaw.js +0 -1
  582. package/core/built/admin/assets/layout-BxsXnKFX.js +0 -1
  583. package/core/built/admin/assets/limit-service-CTurluJQ.js +0 -20
  584. package/core/built/admin/assets/link-helpers-C3Gqy2cz.js +0 -1
  585. package/core/built/admin/assets/list-page-BtqCnow_.js +0 -1
  586. package/core/built/admin/assets/member-custom-fields-9uXFBqSt.js +0 -1
  587. package/core/built/admin/assets/member-detail-Dq6ZDIxo.js +0 -1
  588. package/core/built/admin/assets/members-CUWD9jal.js +0 -10
  589. package/core/built/admin/assets/modals-CIdwHVga.js +0 -31
  590. package/core/built/admin/assets/moderation-DTt04UDA.js +0 -1
  591. package/core/built/admin/assets/newsletter-cC8vcc9h.js +0 -1
  592. package/core/built/admin/assets/note-DZU0IY9e.js +0 -1
  593. package/core/built/admin/assets/notifications-NoHpBHJ4.js +0 -1
  594. package/core/built/admin/assets/nql-lang-CvCSOQG3.js +0 -19
  595. package/core/built/admin/assets/onboarding-route-Deg2hNm8.js +0 -1
  596. package/core/built/admin/assets/overview-BQPt_9w3.js +0 -1
  597. package/core/built/admin/assets/page-header-D6bEqPo2.js +0 -1
  598. package/core/built/admin/assets/post-analytics-header-BPw_B2_D.js +0 -1
  599. package/core/built/admin/assets/post-analytics-kp2_--XO.js +0 -1
  600. package/core/built/admin/assets/post-share-modal-Cave3Z4W.js +0 -1
  601. package/core/built/admin/assets/preferences-C7h3j_uy.js +0 -5
  602. package/core/built/admin/assets/profile-B2x4q2oB.js +0 -1
  603. package/core/built/admin/assets/router-provider-5fsX1CYn.js +0 -1
  604. package/core/built/admin/assets/select-PhPjIBBT.js +0 -1
  605. package/core/built/admin/assets/settings-D5P9Gwgo.js +0 -6
  606. package/core/built/admin/assets/settings-zUOzQV5I.js +0 -1
  607. package/core/built/admin/assets/share-modal-EfpfbuWF.js +0 -1
  608. package/core/built/admin/assets/social-urls-DgAF08Xc.js +0 -18
  609. package/core/built/admin/assets/sort-button-WOQYJm2H.js +0 -1
  610. package/core/built/admin/assets/source-icon-hm8Cj-Gx.js +0 -1
  611. package/core/built/admin/assets/stats-CnQDb62m.js +0 -1
  612. package/core/built/admin/assets/stats-view-CCfTJgSe.js +0 -1
  613. package/core/built/admin/assets/step-1-BGlhY4DS.js +0 -1
  614. package/core/built/admin/assets/step-2-D3sDEyFH.js +0 -1
  615. package/core/built/admin/assets/step-3-CvZoUdsc.js +0 -2
  616. package/core/built/admin/assets/switch-CNjkOmwz.js +0 -1
  617. package/core/built/admin/assets/table-C5nZYPnW.js +0 -1
  618. package/core/built/admin/assets/tabs-dtOcExye.js +0 -1
  619. package/core/built/admin/assets/tags-Dhm0FB_g.js +0 -1
  620. package/core/built/admin/assets/textarea-CeKw3wmV.js +0 -1
  621. package/core/built/admin/assets/toggle-group-DfhZIMTW.js +0 -1
  622. package/core/built/admin/assets/topic-filter-Cxe1Il41.js +0 -1
  623. package/core/built/admin/assets/typeof-Ca-duI-z.js +0 -1
  624. package/core/built/admin/assets/use-filter-params-Bub6BqNy.js +0 -1
  625. package/core/built/admin/assets/use-growth-stats-BJORomv0.js +0 -1
  626. package/core/built/admin/assets/use-reply-chain-data-B89YjVoo.js +0 -1
  627. package/core/built/admin/assets/use-simple-pagination-BL2SYXKi.js +0 -1
  628. package/core/built/admin/assets/virtual-list-DNJOSK9I.js +0 -1
  629. package/core/built/admin/assets/web-BHUE3YQc.js +0 -1
  630. package/core/server/adapters/scheduling/scheduling-base.js +0 -5
  631. package/core/server/adapters/sso/SSOBase.js +0 -5
  632. package/core/server/adapters/storage/index.js +0 -17
  633. package/core/server/services/mail/templates/newsletter.html +0 -876
  634. package/core/server/services/members/exporter/query.js +0 -206
  635. package/core/server/services/members/importer/index.js +0 -30
  636. package/core/server/services/members/importer/labels.js +0 -125
  637. package/core/server/services/members/importer/members-csv-importer.js +0 -502
  638. /package/core/server/services/members/{importer → import-export/import}/email-template.js +0 -0
  639. /package/core/server/services/members/{importer/members-csv-importer-stripe-utils.js → import-export/import/stripe-utils.js} +0 -0
@@ -0,0 +1,342 @@
1
+ // # Local File Base Storage module
2
+ // The (default) module for storing files using the local file system
3
+ import fs from 'fs-extra';
4
+ import path from 'path';
5
+ import type {NextFunction, Request, RequestHandler, Response} from 'express';
6
+ import type express from 'express';
7
+ import tpl from '@tryghost/tpl';
8
+ import errors from '@tryghost/errors';
9
+ import {StorageBase, type ReadOptions, type StorageFile} from 'ghost-storage-base';
10
+ import urlUtils from '../../../shared/url-utils';
11
+ import {errify} from '../../../shared/errify';
12
+
13
+ const serveStatic: typeof express.static = require('../../../shared/express').static;
14
+
15
+ const messages = {
16
+ notFound: 'File not found',
17
+ notFoundWithRef: 'File not found: {file}',
18
+ cannotRead: 'Could not read file: {file}',
19
+ invalidUrlParameter: `The URL "{url}" is not a valid URL for this site.`,
20
+ invalidPathParameter: 'The path "{path}" is not valid for this storage.'
21
+ };
22
+
23
+ export interface LocalStorageBaseErrorMessages {
24
+ notFound: string;
25
+ notFoundWithRef: string;
26
+ cannotRead: string;
27
+ }
28
+
29
+ export interface LocalStorageBaseOptions {
30
+ storagePath: string;
31
+ siteUrl?: string;
32
+ staticFileURLPrefix?: string;
33
+ errorMessages?: LocalStorageBaseErrorMessages;
34
+ }
35
+
36
+ /**
37
+ * Errors thrown by `serve-static` carry an HTTP status alongside the standard
38
+ * Error fields.
39
+ */
40
+ interface ServeStaticError extends Error {
41
+ statusCode?: number;
42
+ path?: string;
43
+ }
44
+
45
+ class LocalStorageBase extends StorageBase {
46
+ readonly staticFileURLPrefix: string | undefined;
47
+
48
+ readonly siteUrl: string | undefined;
49
+
50
+ readonly staticFileUrl: string;
51
+
52
+ readonly errorMessages: LocalStorageBaseErrorMessages;
53
+
54
+ constructor({storagePath, staticFileURLPrefix, siteUrl, errorMessages}: LocalStorageBaseOptions) {
55
+ super();
56
+
57
+ this.storagePath = storagePath;
58
+ this.staticFileURLPrefix = staticFileURLPrefix;
59
+ this.siteUrl = siteUrl;
60
+ this.staticFileUrl = `${siteUrl}${staticFileURLPrefix}`;
61
+ this.errorMessages = errorMessages || messages;
62
+ }
63
+
64
+ /**
65
+ * Normalizes a relative storage path and rejects traversal outside the storage root.
66
+ */
67
+ _normalizeStorageRelativePath(filePath?: string): string {
68
+ const normalized = path.posix.normalize(String(filePath || '')
69
+ .replaceAll('\\', '/')
70
+ .replace(/^\/+/, '')
71
+ .replace(/\/+$/, ''));
72
+
73
+ if (normalized === '.' || normalized === '..' || normalized.startsWith('../')) {
74
+ throw new errors.IncorrectUsageError({
75
+ message: tpl(messages.invalidPathParameter, {path: filePath})
76
+ });
77
+ }
78
+
79
+ return normalized;
80
+ }
81
+
82
+ /**
83
+ * Resolves a target directory and optional file name into a full path,
84
+ * validating the result is inside the storage root.
85
+ *
86
+ * Supports relative paths (preferred) and absolute paths (legacy).
87
+ * TODO: remove absolute path support once all callers pass relative paths
88
+ *
89
+ * @param targetDir absolute or relative directory
90
+ * @param fileName file name to normalize and append
91
+ * @returns resolved absolute path inside storagePath
92
+ */
93
+ _resolveAndValidateStoragePath(targetDir?: string, fileName?: string): string {
94
+ const resolvedRoot = path.resolve(this.storagePath);
95
+
96
+ // Resolve targetDir: if already inside storage root use as-is, otherwise treat as relative
97
+ let resolvedBase;
98
+ if (targetDir) {
99
+ const resolvedTargetDir = path.resolve(targetDir);
100
+ const relToRoot = path.relative(resolvedRoot, resolvedTargetDir);
101
+ if (relToRoot === '' || (!relToRoot.startsWith('..') && !path.isAbsolute(relToRoot))) {
102
+ resolvedBase = resolvedTargetDir;
103
+ } else {
104
+ resolvedBase = path.resolve(this.storagePath, targetDir);
105
+ }
106
+ } else {
107
+ resolvedBase = resolvedRoot;
108
+ }
109
+
110
+ // If fileName provided, normalize and resolve
111
+ let resolvedPath;
112
+ if (fileName) {
113
+ const normalizedFileName = this._normalizeStorageRelativePath(fileName);
114
+ resolvedPath = path.resolve(resolvedBase, normalizedFileName);
115
+ } else {
116
+ resolvedPath = resolvedBase;
117
+ }
118
+
119
+ // Validate the resolved path is strictly inside the storage root (not equal to it)
120
+ const relative = path.relative(resolvedRoot, resolvedPath);
121
+ if (relative === '' || relative === '..' || relative.startsWith('..' + path.sep) || path.isAbsolute(relative)) {
122
+ throw new errors.IncorrectUsageError({
123
+ message: tpl(messages.invalidPathParameter, {path: fileName || targetDir || ''})
124
+ });
125
+ }
126
+
127
+ return resolvedPath;
128
+ }
129
+
130
+ /**
131
+ * Saves the file to storage (the file system)
132
+ * - returns a promise which ultimately returns the full url to the uploaded file
133
+ */
134
+ async save(file: StorageFile, targetDir?: string): Promise<string> {
135
+ let targetFilename;
136
+
137
+ targetDir = targetDir
138
+ ? this._resolveAndValidateStoragePath(targetDir)
139
+ : this.getTargetDir(this.storagePath);
140
+
141
+ const filename = await this.getUniqueFileName(file, targetDir);
142
+
143
+ targetFilename = filename;
144
+
145
+ // Verify that we are saving directly under `targetDir` and not outside of it.
146
+ const expectedPrefix = path.join(path.resolve(targetDir), '/');
147
+ if (!path.resolve(targetFilename).startsWith(expectedPrefix)) {
148
+ throw new errors.BadRequestError({message: 'Cannot save to the given filename'});
149
+ }
150
+
151
+ await fs.mkdirs(targetDir);
152
+
153
+ try {
154
+ await fs.copy(file.path, targetFilename);
155
+ } catch (err) {
156
+ if ((err as NodeJS.ErrnoException).code === 'ENAMETOOLONG') {
157
+ throw new errors.BadRequestError({err: errify(err)});
158
+ }
159
+
160
+ throw err;
161
+ }
162
+
163
+ // The src for the image must be in URI format, not a file system path, which in Windows uses \
164
+ // For local file system storage can use relative path so add a slash
165
+ const fullUrl = (
166
+ urlUtils.urlJoin('/',
167
+ urlUtils.getSubdir(),
168
+ this.staticFileURLPrefix as string,
169
+ path.relative(this.storagePath, targetFilename))
170
+ ).replace(new RegExp(`\\${path.sep}`, 'g'), '/');
171
+
172
+ return fullUrl;
173
+ }
174
+
175
+ /**
176
+ * Saves a buffer in the targetPath
177
+ *
178
+ * @param buffer is an instance of Buffer
179
+ * @param targetPath relative path NOT including storage path to which the buffer should be written
180
+ * @returns a URL to retrieve the data
181
+ */
182
+ async saveRaw(buffer: Buffer, targetPath: string): Promise<string> {
183
+ const storagePath = path.join(this.storagePath, this._normalizeStorageRelativePath(targetPath));
184
+ const targetDir = path.dirname(storagePath);
185
+
186
+ await fs.mkdirs(targetDir);
187
+ await fs.writeFile(storagePath, buffer);
188
+
189
+ // For local file system storage can use relative path so add a slash
190
+ const fullUrl = (
191
+ urlUtils.urlJoin('/', urlUtils.getSubdir(),
192
+ this.staticFileURLPrefix as string,
193
+ targetPath)
194
+ ).replace(new RegExp(`\\${path.sep}`, 'g'), '/');
195
+
196
+ return fullUrl;
197
+ }
198
+
199
+ /**
200
+ * @param url full url under which the stored content is served, result of save method
201
+ * @returns relative path under which the content is stored
202
+ */
203
+ urlToPath(url: string): string {
204
+ let relativePath;
205
+
206
+ const prefix = urlUtils.urlJoin('/',
207
+ urlUtils.getSubdir(),
208
+ this.staticFileURLPrefix as string
209
+ );
210
+
211
+ if (url.startsWith(this.staticFileUrl)) {
212
+ // CASE: full path that includes the site url
213
+ relativePath = url.replace(this.staticFileUrl, '');
214
+ } else if (url.startsWith(prefix)) {
215
+ // CASE: The result of the save method doesn't include the site url. So we need to handle this case.
216
+ relativePath = url.replace(prefix, '');
217
+ } else {
218
+ throw new errors.IncorrectUsageError({
219
+ message: tpl(messages.invalidUrlParameter, {url})
220
+ });
221
+ }
222
+
223
+ try {
224
+ return this._normalizeStorageRelativePath(relativePath);
225
+ } catch (err) {
226
+ throw new errors.IncorrectUsageError({
227
+ message: tpl(messages.invalidUrlParameter, {url})
228
+ });
229
+ }
230
+ }
231
+
232
+ async exists(fileName: string, targetDir?: string): Promise<boolean> {
233
+ let filePath;
234
+
235
+ try {
236
+ filePath = this._resolveAndValidateStoragePath(targetDir, fileName);
237
+ } catch (err) {
238
+ if (err instanceof errors.IncorrectUsageError) {
239
+ return false;
240
+ }
241
+
242
+ throw err;
243
+ }
244
+
245
+ try {
246
+ await fs.stat(filePath);
247
+ return true;
248
+ } catch {
249
+ return false;
250
+ }
251
+ }
252
+
253
+ /**
254
+ * For some reason send divides the max age number by 1000
255
+ * Fallthrough: false ensures that if an image isn't found, it automatically 404s
256
+ * Wrap server static errors
257
+ */
258
+ serve(): RequestHandler {
259
+ const {storagePath, errorMessages} = this;
260
+
261
+ return function serveStaticContent(req: Request, res: Response, next: NextFunction) {
262
+ return serveStatic(
263
+ storagePath,
264
+ {
265
+ maxAge: (365 * 24 * 60 * 60 * 1000), // 1 year in ms
266
+ fallthrough: false
267
+ }
268
+ )(req, res, (err?: ServeStaticError) => {
269
+ if (err) {
270
+ if (err.statusCode === 404) {
271
+ return next(new errors.NotFoundError({
272
+ message: tpl(errorMessages.notFound),
273
+ code: 'STATIC_FILE_NOT_FOUND',
274
+ property: err.path
275
+ }));
276
+ }
277
+
278
+ if (err.statusCode === 400) {
279
+ return next(new errors.BadRequestError({err: err}));
280
+ }
281
+
282
+ if (err.statusCode === 403) {
283
+ return next(new errors.NoPermissionError({err: err}));
284
+ }
285
+
286
+ if (err.name === 'RangeNotSatisfiableError') {
287
+ return next(new errors.RangeNotSatisfiableError({err}));
288
+ }
289
+
290
+ return next(new errors.InternalServerError({err: err}));
291
+ }
292
+
293
+ next();
294
+ });
295
+ };
296
+ }
297
+
298
+ async delete(fileName: string, targetDir?: string): Promise<void> {
299
+ const filePath = this._resolveAndValidateStoragePath(targetDir, fileName);
300
+ return await fs.remove(filePath);
301
+ }
302
+
303
+ /**
304
+ * Reads bytes from disk for a target file
305
+ * - path of target file (without content path!)
306
+ */
307
+ async read(options?: Partial<ReadOptions>): Promise<Buffer> {
308
+ options = options || {};
309
+
310
+ const normalizedPath = this._normalizeStorageRelativePath(options.path);
311
+ const targetPath = path.join(this.storagePath, normalizedPath);
312
+
313
+ try {
314
+ return await fs.readFile(targetPath);
315
+ } catch (rawError) {
316
+ const err = errify(rawError);
317
+ const code = (rawError as NodeJS.ErrnoException).code;
318
+
319
+ if (code === 'ENOENT' || code === 'ENOTDIR') {
320
+ throw new errors.NotFoundError({
321
+ err: err,
322
+ message: tpl(this.errorMessages.notFoundWithRef, {file: options.path})
323
+ });
324
+ }
325
+
326
+ if (code === 'ENAMETOOLONG') {
327
+ throw new errors.BadRequestError({err: err});
328
+ }
329
+
330
+ if (code === 'EACCES') {
331
+ throw new errors.NoPermissionError({err: err});
332
+ }
333
+
334
+ throw new errors.InternalServerError({
335
+ err: err,
336
+ message: tpl(this.errorMessages.cannotRead, {file: options.path})
337
+ });
338
+ }
339
+ }
340
+ }
341
+
342
+ export default LocalStorageBase;
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const node_fs_1 = __importDefault(require("node:fs"));
7
7
  const node_path_1 = __importDefault(require("node:path"));
8
8
  const zod_1 = require("zod");
9
- const ghost_storage_base_1 = __importDefault(require("ghost-storage-base"));
9
+ const ghost_storage_base_1 = require("ghost-storage-base");
10
10
  const tpl_1 = __importDefault(require("@tryghost/tpl"));
11
11
  const errors_1 = __importDefault(require("@tryghost/errors"));
12
12
  const logging_1 = __importDefault(require("@tryghost/logging"));
@@ -81,7 +81,7 @@ const configSchema = zod_1.z.object({
81
81
  const hasCredentialPair = hasAccessKey && hasSecretKey;
82
82
  return !((hasAccessKey || hasSecretKey || hasSessionToken) && !hasCredentialPair);
83
83
  }, { error: (0, tpl_1.default)(messages.partialCredentials) });
84
- class S3Storage extends ghost_storage_base_1.default {
84
+ class S3Storage extends ghost_storage_base_1.StorageBase {
85
85
  client;
86
86
  bucket;
87
87
  tenantPrefix;
@@ -2,7 +2,7 @@ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import type {Request, Response, NextFunction, RequestHandler} from 'express';
4
4
  import {z} from 'zod';
5
- import StorageBase from 'ghost-storage-base';
5
+ import {StorageBase} from 'ghost-storage-base';
6
6
  import tpl from '@tryghost/tpl';
7
7
  import errors from '@tryghost/errors';
8
8
  import logging from '@tryghost/logging';
@@ -1,68 +1,54 @@
1
- const config = require('../../../shared/config');
2
- const urlUtils = require('../../../shared/url-utils');
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getLocalImagesStoragePath = getLocalImagesStoragePath;
7
+ exports.isLocalImage = isLocalImage;
8
+ exports.isInternalImage = isInternalImage;
9
+ const config_1 = __importDefault(require("../../../shared/config"));
10
+ const url_utils_1 = __importDefault(require("../../../shared/url-utils"));
3
11
  /**
4
12
  * @TODO: move `events.js` to here - e.g. storageUtils.getStorage
5
13
  */
6
-
7
14
  /**
8
- * Sanitizes a given URL or path for an image to be readable by the local file storage
9
- * as storage needs the path without `/content/images/` prefix
10
- * Always returns {string} url
11
- * @param {string} imagePath
12
- * @returns {string} imagePath
13
- * @description Takes a url or filepath and returns a filepath with is readable
14
- * for the local file storage.
15
+ * Sanitizes a given URL or path for an image to be readable by the local file
16
+ * storage, as storage needs the path without the `/content/images/` prefix.
17
+ *
18
+ * Takes a url or filepath and returns a filepath which is readable for the
19
+ * local file storage.
15
20
  */
16
- exports.getLocalImagesStoragePath = function getLocalImagesStoragePath(imagePath) {
21
+ function getLocalImagesStoragePath(imagePath) {
17
22
  // The '/' in urlJoin is necessary to add the '/' to `content/images`, if no subdirectory is setup
18
- const urlRegExp = new RegExp(`^${urlUtils.urlJoin(
19
- urlUtils.urlFor('home', true),
20
- urlUtils.getSubdir(),
21
- '/',
22
- urlUtils.STATIC_IMAGE_URL_PREFIX)}`
23
- );
24
-
25
- const filePathRegExp = new RegExp(`^${urlUtils.urlJoin(
26
- urlUtils.getSubdir(),
27
- '/',
28
- urlUtils.STATIC_IMAGE_URL_PREFIX)}`
29
- );
30
-
23
+ const urlRegExp = new RegExp(`^${url_utils_1.default.urlJoin(url_utils_1.default.urlFor('home', true), url_utils_1.default.getSubdir(), '/', url_utils_1.default.STATIC_IMAGE_URL_PREFIX)}`);
24
+ const filePathRegExp = new RegExp(`^${url_utils_1.default.urlJoin(url_utils_1.default.getSubdir(), '/', url_utils_1.default.STATIC_IMAGE_URL_PREFIX)}`);
31
25
  if (imagePath.match(urlRegExp)) {
32
26
  return imagePath.replace(urlRegExp, '');
33
- } else if (imagePath.match(filePathRegExp)) {
27
+ }
28
+ else if (imagePath.match(filePathRegExp)) {
34
29
  return imagePath.replace(filePathRegExp, '');
35
- } else {
30
+ }
31
+ else {
36
32
  return imagePath;
37
33
  }
38
- };
39
-
34
+ }
40
35
  /**
41
- * @description compares the imagePath with a regex that reflects our local file storage
42
- * @param {string} imagePath as URL or filepath
43
- * @returns {boolean}
36
+ * Compares the imagePath with a regex that reflects our local file storage
37
+ *
38
+ * @param imagePath as URL or filepath
44
39
  */
45
-
46
- exports.isLocalImage = function isLocalImage(imagePath) {
47
- const localImagePath = this.getLocalImagesStoragePath(imagePath);
48
-
49
- if (localImagePath !== imagePath) {
50
- return true;
51
- } else {
52
- return false;
53
- }
54
- };
55
-
40
+ function isLocalImage(imagePath) {
41
+ return getLocalImagesStoragePath(imagePath) !== imagePath;
42
+ }
56
43
  /**
57
- * @description Checks whether the image is managed by Ghost storage (local or CDN)
58
- * @param {string} imagePath as URL or filepath
59
- * @returns {boolean}
44
+ * Checks whether the image is managed by Ghost storage (local or CDN)
45
+ *
46
+ * @param imagePath as URL or filepath
60
47
  */
61
- exports.isInternalImage = function isInternalImage(imagePath) {
62
- if (this.isLocalImage(imagePath)) {
48
+ function isInternalImage(imagePath) {
49
+ if (isLocalImage(imagePath)) {
63
50
  return true;
64
51
  }
65
-
66
- const imageBaseUrl = (config.get('urls:image') || '').replace(/\/+$/, '');
52
+ const imageBaseUrl = (config_1.default.get('urls:image') || '').replace(/\/+$/, '');
67
53
  return !!(imageBaseUrl && imagePath.startsWith(imageBaseUrl + '/'));
68
- };
54
+ }
@@ -0,0 +1,60 @@
1
+ import config from '../../../shared/config';
2
+ import urlUtils from '../../../shared/url-utils';
3
+
4
+ /**
5
+ * @TODO: move `events.js` to here - e.g. storageUtils.getStorage
6
+ */
7
+
8
+ /**
9
+ * Sanitizes a given URL or path for an image to be readable by the local file
10
+ * storage, as storage needs the path without the `/content/images/` prefix.
11
+ *
12
+ * Takes a url or filepath and returns a filepath which is readable for the
13
+ * local file storage.
14
+ */
15
+ export function getLocalImagesStoragePath(imagePath: string): string {
16
+ // The '/' in urlJoin is necessary to add the '/' to `content/images`, if no subdirectory is setup
17
+ const urlRegExp = new RegExp(`^${urlUtils.urlJoin(
18
+ urlUtils.urlFor('home', true),
19
+ urlUtils.getSubdir(),
20
+ '/',
21
+ urlUtils.STATIC_IMAGE_URL_PREFIX)}`
22
+ );
23
+
24
+ const filePathRegExp = new RegExp(`^${urlUtils.urlJoin(
25
+ urlUtils.getSubdir(),
26
+ '/',
27
+ urlUtils.STATIC_IMAGE_URL_PREFIX)}`
28
+ );
29
+
30
+ if (imagePath.match(urlRegExp)) {
31
+ return imagePath.replace(urlRegExp, '');
32
+ } else if (imagePath.match(filePathRegExp)) {
33
+ return imagePath.replace(filePathRegExp, '');
34
+ } else {
35
+ return imagePath;
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Compares the imagePath with a regex that reflects our local file storage
41
+ *
42
+ * @param imagePath as URL or filepath
43
+ */
44
+ export function isLocalImage(imagePath: string): boolean {
45
+ return getLocalImagesStoragePath(imagePath) !== imagePath;
46
+ }
47
+
48
+ /**
49
+ * Checks whether the image is managed by Ghost storage (local or CDN)
50
+ *
51
+ * @param imagePath as URL or filepath
52
+ */
53
+ export function isInternalImage(imagePath: string): boolean {
54
+ if (isLocalImage(imagePath)) {
55
+ return true;
56
+ }
57
+
58
+ const imageBaseUrl = (config.get('urls:image') || '').replace(/\/+$/, '');
59
+ return !!(imageBaseUrl && imagePath.startsWith(imageBaseUrl + '/'));
60
+ }
@@ -12,7 +12,7 @@ const apiMail = require('./index').mail;
12
12
  const apiSettings = require('./index').settings;
13
13
  const UsersService = require('../../services/users');
14
14
  const userService = new UsersService({dbBackup, models, auth, apiMail, apiSettings});
15
- const adapterManager = require('../../services/adapter-manager');
15
+ const adapterManager = require('../../services/adapter-manager').default;
16
16
  const schedulerAdapter = adapterManager.getAdapter('scheduling');
17
17
 
18
18
  async function destroyRequestSession(req) {
@@ -1,4 +1,5 @@
1
1
  const moment = require('moment-timezone');
2
+ const path = require('path');
2
3
  const dbBackup = require('../../data/db/backup');
3
4
  const exporter = require('../../data/exporter');
4
5
  const importer = require('../../data/importer');
@@ -29,6 +30,11 @@ const controller = {
29
30
  }
30
31
  },
31
32
  query(frame) {
33
+ const filename = frame.options.filename;
34
+ if (filename && path.basename(filename) !== filename) {
35
+ throw new errors.ValidationError({message: 'Export filename must not contain path separators'});
36
+ }
37
+
32
38
  // NOTE: we need to have `include` property available as backupDatabase uses it internally
33
39
  Object.assign(frame.options, {include: frame.options.withRelated});
34
40
 
@@ -2,7 +2,7 @@ const jwt = require('jsonwebtoken');
2
2
  const errors = require('@tryghost/errors');
3
3
  const config = require('../../../shared/config');
4
4
  const settingsCache = require('../../../shared/settings-cache');
5
- const urlUtils = require('../../../shared/url-utils');
5
+ const urlUtils = require('../../../shared/url-utils').default;
6
6
 
7
7
  function generateJWTToken(frame) {
8
8
  const userData = {
@@ -1,5 +1,5 @@
1
- const storage = require('../../adapters/storage');
2
1
  const {getStorageContentType} = require('../../services/files/file-type-utils');
2
+ const adapterManager = require('../../services/adapter-manager').default;
3
3
 
4
4
  /** @type {import('@tryghost/api-framework').Controller} */
5
5
  const controller = {
@@ -11,7 +11,7 @@ const controller = {
11
11
  },
12
12
  permissions: false,
13
13
  async query(frame) {
14
- const filePath = await storage.getStorage('files').save({
14
+ const filePath = await adapterManager.getAdapter('storage:files').save({
15
15
  name: frame.file.originalname,
16
16
  path: frame.file.path,
17
17
  type: getStorageContentType(frame.file.originalname)
@@ -3,7 +3,7 @@ const path = require('path');
3
3
  const errors = require('@tryghost/errors');
4
4
  const imageTransform = require('@tryghost/image-transform');
5
5
 
6
- const storage = require('../../adapters/storage');
6
+ const adapterManager = require('../../services/adapter-manager').default;
7
7
  const config = require('../../../shared/config');
8
8
 
9
9
  /** @type {import('@tryghost/api-framework').Controller} */
@@ -16,7 +16,7 @@ const controller = {
16
16
  },
17
17
  permissions: false,
18
18
  async query(frame) {
19
- const store = storage.getStorage('images');
19
+ const store = adapterManager.getAdapter('storage:images');
20
20
 
21
21
  // Normalize
22
22
  const imageOptimizationOptions = config.get('imageOptimization');
@@ -1,3 +1,2 @@
1
1
  // Type declarations for untyped modules used by TypeScript endpoints
2
2
  declare module '@tryghost/api-framework';
3
- declare module '@tryghost/tpl';
@@ -1,5 +1,6 @@
1
1
  const path = require('path');
2
- const storage = require('../../adapters/storage');
2
+
3
+ const adapterManager = require('../../services/adapter-manager').default;
3
4
 
4
5
  /** @type {import('@tryghost/api-framework').Controller} */
5
6
  const controller = {
@@ -11,12 +12,14 @@ const controller = {
11
12
  },
12
13
  permissions: false,
13
14
  async query(frame) {
15
+ const storage = adapterManager.getAdapter('storage:media');
16
+
14
17
  let thumbnailPath = null;
15
18
  if (frame.files.thumbnail && frame.files.thumbnail[0]) {
16
- thumbnailPath = await storage.getStorage('media').save(frame.files.thumbnail[0]);
19
+ thumbnailPath = await storage.save(frame.files.thumbnail[0]);
17
20
  }
18
21
 
19
- const filePath = await storage.getStorage('media').save(frame.files.file[0]);
22
+ const filePath = await storage.save(frame.files.file[0]);
20
23
 
21
24
  return {
22
25
  filePath,
@@ -35,12 +38,12 @@ const controller = {
35
38
  'ref'
36
39
  ],
37
40
  async query(frame) {
38
- const mediaStorage = storage.getStorage('media');
41
+ const mediaStorage = adapterManager.getAdapter('storage:media');
39
42
  const targetDir = path.dirname(mediaStorage.urlToPath(frame.data.url));
40
43
 
41
44
  // NOTE: need to cleanup otherwise the parent media name won't match thumb name
42
45
  // due to "unique name" generation during save
43
- if (mediaStorage.exists(frame.file.name, targetDir)) {
46
+ if (await mediaStorage.exists(frame.file.name, targetDir)) {
44
47
  await mediaStorage.delete(frame.file.name, targetDir);
45
48
  }
46
49
 
@@ -53,8 +53,11 @@ const controller = {
53
53
  permissions(frame) {
54
54
  return canThis(frame).add.member_custom_field();
55
55
  },
56
+ // The whole array is passed through: create is a batch, applied
57
+ // all-or-nothing. A client sending a single definition (as Admin does)
58
+ // is just the one-item case and sees no change.
56
59
  query(frame) {
57
- return members_custom_fields_1.definitions.add(requestContextFromFrame(frame), frame.data.members_custom_fields[0]);
60
+ return members_custom_fields_1.definitions.add(requestContextFromFrame(frame), frame.data.members_custom_fields);
58
61
  }
59
62
  },
60
63
  edit: {