ghost 6.54.0 → 6.55.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 (327) 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-custom-field-types-0.0.0.tgz +0 -0
  6. package/components/tryghost-kg-default-cards-10.3.3.tgz +0 -0
  7. package/core/boot.js +3 -6
  8. package/core/built/admin/assets/{account-migration-DLvVA5yq.js → account-migration-sjHLx5dy.js} +1 -1
  9. package/core/built/admin/assets/activitypub/{account-migration-DHbZcxGM.js → account-migration-DoYXtnZ8.js} +4 -4
  10. package/core/built/admin/assets/activitypub/activitypub.js +2 -2
  11. package/core/built/admin/assets/activitypub/{bluesky-sharing-zfxUey_L.js → bluesky-sharing-Bxeh6MKW.js} +4 -4
  12. package/core/built/admin/assets/activitypub/{dist-BqkDUQxJ2.js → dist-ByFmDSNP2.js} +64 -63
  13. package/core/built/admin/assets/activitypub/{dist-Ba_QxHHl.js → dist-D8sFfdpC.js} +2 -2
  14. package/core/built/admin/assets/activitypub/{domain-CmwSZLHK.js → domain-CWueFW6q.js} +5 -5
  15. package/core/built/admin/assets/activitypub/{edit-profile-CXdwNmVG.js → edit-profile-BGxPU7N5.js} +3 -3
  16. package/core/built/admin/assets/activitypub/{explore-DfbjzGM1.js → explore-DBK-u0Ch.js} +3 -3
  17. package/core/built/admin/assets/activitypub/{feed-DSEBJOqf.js → feed-Bcir5RQZ.js} +3 -3
  18. package/core/built/admin/assets/activitypub/{field-CY7XVcx6.js → field-BV-CIT3d.js} +2 -2
  19. package/core/built/admin/assets/activitypub/{inbox-DtQ0kytT.js → inbox-yC0nfvzl.js} +4 -4
  20. package/core/built/admin/assets/activitypub/{label-Dw96GQ7u.js → label-DTRS9TDk.js} +2 -2
  21. package/core/built/admin/assets/activitypub/layout-qx-bUL1k.js +1 -0
  22. package/core/built/admin/assets/activitypub/{moderation-Dg_-I-8C.js → moderation-Dwl9t0pb.js} +4 -4
  23. package/core/built/admin/assets/activitypub/{note-Cy1-uKMY.js → note-B-zKsZ7r.js} +3 -3
  24. package/core/built/admin/assets/activitypub/{notifications-B_fvoLIM.js → notifications-DjJZD54t.js} +3 -3
  25. package/core/built/admin/assets/activitypub/{preferences-ByJseZp6.js → preferences-CoU8vs6d.js} +6 -6
  26. package/core/built/admin/assets/activitypub/{profile-BFtbnIjz.js → profile-BAsaJekx.js} +6 -6
  27. package/core/built/admin/assets/activitypub/{routes-Dh3xXfce.js → routes-CLH3OVTP.js} +28 -25
  28. package/core/built/admin/assets/activitypub/{settings-DTgqJPxM.js → settings-DA6pNJ-Q.js} +3 -3
  29. package/core/built/admin/assets/activitypub/{site-CdL9ZLqm.js → site-CQD42Pw5.js} +2 -2
  30. package/core/built/admin/assets/activitypub/{tabs-ogqwoBlb.js → tabs-Cg0saow1.js} +7 -7
  31. package/core/built/admin/assets/activitypub/{use-reply-chain-data-CxonteFD.js → use-reply-chain-data-Br4aOWOh.js} +2 -2
  32. package/core/built/admin/assets/audience-DjEWNhp3.js +1 -0
  33. package/core/built/admin/assets/{automated-emails-Cn87L5Md.js → automated-emails-DRy7qY-J.js} +2 -2
  34. package/core/built/admin/assets/{automations-BP_aHamJ.js → automations-Bx3VcFIL.js} +1 -1
  35. package/core/built/admin/assets/{automations-B7-y3dXt.js → automations-DhKeS_U5.js} +1 -1
  36. package/core/built/admin/assets/{bluesky-sharing-Bh36XPh4.js → bluesky-sharing-ClMd0-Ft.js} +1 -1
  37. package/core/built/admin/assets/{breadcrumb-D34YWnaw.js → breadcrumb-BD0U2ygg.js} +1 -1
  38. package/core/built/admin/assets/{chart-helpers-DbklaJw9.js → chart-helpers-fjQKRVyY.js} +1 -1
  39. package/core/built/admin/assets/checkbox-CWa28lgO.js +1 -0
  40. package/core/built/admin/assets/{chunk.962.b73442b07be930bb5d85.js → chunk.211.6f7328d63c41536451b3.js} +737 -559
  41. package/core/built/admin/assets/{chunk.962.b73442b07be930bb5d85.js.LICENSE.txt → chunk.211.6f7328d63c41536451b3.js.LICENSE.txt} +2 -0
  42. package/core/built/admin/assets/{chunk.589.096f4d0bb775e5229aa9.js → chunk.481.6c7395a49484bb4583aa.js} +41 -38
  43. package/core/built/admin/assets/chunk.524.cffd399783a519e404a9.js +25 -0
  44. package/core/built/admin/assets/chunk.582.eebf0d0b2d202bb746a5.js +27 -0
  45. package/core/built/admin/assets/code-editor-view-CCr0rBWS.js +1 -0
  46. package/core/built/admin/assets/comments-DyUSMUdj.js +1 -0
  47. package/core/built/admin/assets/{date-range-select-B5vSsrpx.js → date-range-select-BFp58EMk.js} +1 -1
  48. package/core/built/admin/assets/{disabled-sources-indicator-NkOIoMue.js → disabled-sources-indicator-CUxMfiPa.js} +1 -1
  49. package/core/built/admin/assets/dist-2Tnz2Yfq.js +1 -0
  50. package/core/built/admin/assets/dist-CjY-f5Z1.js +1 -0
  51. package/core/built/admin/assets/dist-DIC8yz5C.js +1 -0
  52. package/core/built/admin/assets/domain-C0bV2UV8.js +1 -0
  53. package/core/built/admin/assets/dropzone-DlK-K2DQ.js +5 -0
  54. package/core/built/admin/assets/{edit-profile-rvDGrS8J.js → edit-profile-BKT-REJw.js} +1 -1
  55. package/core/built/admin/assets/editor-Dp865O-4.js +8 -0
  56. package/core/built/admin/assets/{explore-BZAZOg5X.js → explore-ClUpJZOp.js} +1 -1
  57. package/core/built/admin/assets/{feed-CFV8xDw9.js → feed-DF92dUMP.js} +1 -1
  58. package/core/built/admin/assets/field-Do7lieBA.js +1 -0
  59. package/core/built/admin/assets/{filter-sources-Fx8wiYYw.js → filter-sources-BV2rnpfA.js} +1 -1
  60. package/core/built/admin/assets/filters-CUXJ2Nm9.js +1 -0
  61. package/core/built/admin/assets/{filters-CGX_pf2N.js → filters-DfbIWc_l.js} +1 -1
  62. package/core/built/admin/assets/{ghost-3063eae29e6c9cc6d6e7131928a27da0.css → ghost-a9c788f6f0b1ea6cf0f14ca4b13f4496.css} +1 -1
  63. package/core/built/admin/assets/{ghost-b1dce91ad3232cc259ee5fbbf9526243.js → ghost-c4057474943effc568c5659ccc4909d7.js} +407 -406
  64. package/core/built/admin/assets/{ghost-dark-c8d0ab7f515b2010c173e23e9b32ea8a.css → ghost-dark-db36d795d21c61426837df40af270966.css} +1 -1
  65. package/core/built/admin/assets/gift-link-modal-f9VIMNDv.js +1 -0
  66. package/core/built/admin/assets/{gift-links-nBxJjZiQ.js → gift-links-CsUhefWG.js} +1 -1
  67. package/core/built/admin/assets/growth-B3I6gNLm.js +1 -0
  68. package/core/built/admin/assets/{Growth-CSaHoSVD.js → growth-CVw1My4S.js} +2 -2
  69. package/core/built/admin/assets/{hooks-BApwwBE0.js → hooks-CixO01lL.js} +1 -1
  70. package/core/built/admin/assets/{inbox-BRp1_aaC.js → inbox-CFBSu4Ed.js} +12 -12
  71. package/core/built/admin/assets/index-9Cw8z3rA.css +1 -0
  72. package/core/built/admin/assets/index-BGG7NckO.js +67 -0
  73. package/core/built/admin/assets/input-group-BSgG_lVw.js +1 -0
  74. package/core/built/admin/assets/input-surface-BpAjZXY5.js +1 -0
  75. package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +974 -937
  76. package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +28 -28
  77. package/core/built/admin/assets/koenig-lexical/style.css +1 -1
  78. package/core/built/admin/assets/{koenig-lexical-CM7UFNdL.js → koenig-lexical-f8vHRYvz.js} +28 -28
  79. package/core/built/admin/assets/{kpi-card-BrGH6FsT.js → kpi-card-DSap9rAy.js} +1 -1
  80. package/core/built/admin/assets/{kpi-card-CIGyijjx.js → kpi-card-DU0rn9Cj.js} +1 -1
  81. package/core/built/admin/assets/{kpi-helpers-_HRRsklE.js → kpi-helpers-Dz33AV6h.js} +1 -1
  82. package/core/built/admin/assets/{kpi-tabs-BSvh9eoq.js → kpi-tabs-BtTTrKvJ.js} +1 -1
  83. package/core/built/admin/assets/{label-BOR9XdKl.js → label-DS8Mi6G5.js} +1 -1
  84. package/core/built/admin/assets/label-picker-1DvSuLA1.js +1 -0
  85. package/core/built/admin/assets/labels-CDSUt4J_.js +1 -0
  86. package/core/built/admin/assets/layout-yQEi2qDM.js +1 -0
  87. package/core/built/admin/assets/{link-helpers-tOlxmuH5.js → link-helpers-7EYqvvHs.js} +1 -1
  88. package/core/built/admin/assets/member-custom-fields-yOMHyAg9.js +1 -0
  89. package/core/built/admin/assets/member-detail-BAq7gDaa.js +1 -0
  90. package/core/built/admin/assets/members-CQpVFJu4.js +10 -0
  91. package/core/built/admin/assets/modals-ReORvWnu.js +31 -0
  92. package/core/built/admin/assets/moderation-DySbgyUS.js +1 -0
  93. package/core/built/admin/assets/newsletter-CJQvtHqN.js +1 -0
  94. package/core/built/admin/assets/{Newsletters-C5cs6FGo.js → newsletters-B3QQXfGT.js} +1 -1
  95. package/core/built/admin/assets/{newsletters-D1jbtV-h.js → newsletters-BXJbJgA-.js} +1 -1
  96. package/core/built/admin/assets/note-C8kxrz6w.js +1 -0
  97. package/core/built/admin/assets/notifications-CgtSfX7t.js +1 -0
  98. package/core/built/admin/assets/{offers-CrY6nSRR.js → offers-DEniVRD5.js} +1 -1
  99. package/core/built/admin/assets/onboarding-route-4qtziA9d.js +1 -0
  100. package/core/built/admin/assets/overview-Bf2sbznq.js +1 -0
  101. package/core/built/admin/assets/overview-CBfePxcr.js +1 -0
  102. package/core/built/admin/assets/{page-header-C0jVxtS8.js → page-header-B3Wb9Jqv.js} +1 -1
  103. package/core/built/admin/assets/{pages-BbNWFcGj.js → pages-B4goRPUn.js} +1 -1
  104. package/core/built/admin/assets/{post-analytics-Iw7dk1mT.js → post-analytics-We-ko5Cb.js} +1 -1
  105. package/core/built/admin/assets/post-analytics-header-Bmc9su6q.js +1 -0
  106. package/core/built/admin/assets/post-analytics-provider-B6UynTGb.js +1 -0
  107. package/core/built/admin/assets/{post-share-modal-DBfKl2GZ.js → post-share-modal-DFfO93_0.js} +1 -1
  108. package/core/built/admin/assets/{posts-EWpZIjkr.js → posts-DhXE7b6r.js} +1 -1
  109. package/core/built/admin/assets/{preferences-D4EANGoc.js → preferences-DJPfHEGu.js} +2 -2
  110. package/core/built/admin/assets/profile-DqBQp-gT.js +1 -0
  111. package/core/built/admin/assets/{referrers-BCfFYSHc.js → referrers-pmJT4k3-.js} +1 -1
  112. package/core/built/admin/assets/select-C5_xEt5b.js +1 -0
  113. package/core/built/admin/assets/settings-BwiVIXau.js +4 -0
  114. package/core/built/admin/assets/{settings-Bz3RZRmE.js → settings-WXNeWyU1.js} +1 -1
  115. package/core/built/admin/assets/shade-app-B3heOAfz-CGXQwWeO.js +3 -0
  116. package/core/built/admin/assets/{share-modal-CkdTTMJd.js → share-modal-DsgW3wbg.js} +1 -1
  117. package/core/built/admin/assets/social-urls-BQPFEk1_.js +8 -0
  118. package/core/built/admin/assets/{sort-button-DZp9Y2r1.js → sort-button-Bb_FCl7e.js} +1 -1
  119. package/core/built/admin/assets/{source-icon-CHr9qJ2Y.js → source-icon-BeaRxUn9.js} +1 -1
  120. package/core/built/admin/assets/{stats-DGoXZxWE.js → stats-Bjj_kmJ1.js} +1 -1
  121. package/core/built/admin/assets/{stats-view-D2-1L0ms.js → stats-view-BxPbW6K1.js} +1 -1
  122. package/core/built/admin/assets/{step-1-RdahbwyG.js → step-1-B1e3-1F8.js} +1 -1
  123. package/core/built/admin/assets/{step-2-D83PeRwd.js → step-2-C5WaeBJo.js} +1 -1
  124. package/core/built/admin/assets/{step-3-p_Op4wv4.js → step-3-B46iVPwu.js} +2 -2
  125. package/core/built/admin/assets/switch-z5Y6Uzt6.js +1 -0
  126. package/core/built/admin/assets/{table-B8LgTQJZ.js → table-CB-4_HBJ.js} +1 -1
  127. package/core/built/admin/assets/tabs-CCEgKYzq.js +1 -0
  128. package/core/built/admin/assets/{tags-B4l891z2.js → tags-Cg2VJGmG.js} +1 -1
  129. package/core/built/admin/assets/textarea-Bjccvh_E.js +1 -0
  130. package/core/built/admin/assets/{tiers-BgYLWRJv.js → tiers-DYsa4DCo.js} +1 -1
  131. package/core/built/admin/assets/{toggle-group-DNXDkAwf.js → toggle-group-b3IlxvhV.js} +1 -1
  132. package/core/built/admin/assets/{topic-filter-DZGjEcz3.js → topic-filter-DAFT87tQ.js} +1 -1
  133. package/core/built/admin/assets/{use-analytics-data-CaT8RirX.js → use-analytics-data-S0FTd43s.js} +1 -1
  134. package/core/built/admin/assets/use-filter-params-Gpoq2E1L.js +1 -0
  135. package/core/built/admin/assets/{use-growth-stats-9Db2CuJe.js → use-growth-stats-CIaiHOVb.js} +1 -1
  136. package/core/built/admin/assets/{use-post-referrers-BV54YcQS.js → use-post-referrers-Cq2vBPrA.js} +1 -1
  137. package/core/built/admin/assets/{use-reply-chain-data-DuYZGDan.js → use-reply-chain-data-DBDRtGu-.js} +1 -1
  138. package/core/built/admin/assets/{use-simple-pagination-8fTua9Nt.js → use-simple-pagination-CjYNxdwe.js} +1 -1
  139. package/core/built/admin/assets/{use-tinybird-query-Dz156HvZ.js → use-tinybird-query-falHAtuK.js} +1 -1
  140. package/core/built/admin/assets/{use-tinybird-token-C9RUdL_n.js → use-tinybird-token-D7-8ND1y.js} +1 -1
  141. package/core/built/admin/assets/{users-CcSCQFcQ.js → users-Dkv8NQZe.js} +1 -1
  142. package/core/built/admin/assets/{virtual-list-BCvP0YF-.js → virtual-list-CvnC9zF2.js} +1 -1
  143. package/core/built/admin/assets/web-B_5GZRvH.js +1 -0
  144. package/core/built/admin/assets/web-jFYWCKDn.js +2 -0
  145. package/core/built/admin/index.html +14 -10
  146. package/core/frontend/services/proxy.js +10 -1
  147. package/core/frontend/services/routing/router-manager.js +14 -14
  148. package/core/frontend/services/routing/static-routes-router.js +8 -10
  149. package/core/server/adapters/storage/LocalFilesStorage.js +13 -11
  150. package/core/server/adapters/storage/LocalFilesStorage.ts +24 -0
  151. package/core/server/adapters/storage/LocalImagesStorage.js +14 -12
  152. package/core/server/adapters/storage/LocalImagesStorage.ts +24 -0
  153. package/core/server/adapters/storage/LocalMediaStorage.js +13 -11
  154. package/core/server/adapters/storage/LocalMediaStorage.ts +24 -0
  155. package/core/server/adapters/storage/LocalStorageBase.js +107 -167
  156. package/core/server/adapters/storage/LocalStorageBase.ts +342 -0
  157. package/core/server/adapters/storage/utils.js +36 -50
  158. package/core/server/adapters/storage/utils.ts +60 -0
  159. package/core/server/api/endpoints/automation-action-links.js +68 -0
  160. package/core/server/api/endpoints/automation-action-links.ts +46 -0
  161. package/core/server/api/endpoints/db.js +6 -0
  162. package/core/server/api/endpoints/index.js +4 -0
  163. package/core/server/api/endpoints/members.js +25 -28
  164. package/core/server/api/endpoints/pages.js +6 -1
  165. package/core/server/api/endpoints/posts.js +11 -2
  166. package/core/server/api/endpoints/settings.js +0 -2
  167. package/core/server/api/endpoints/utils/serializers/output/mappers/comments.js +4 -1
  168. package/core/server/api/endpoints/utils/serializers/output/members.js +18 -87
  169. package/core/server/api/endpoints/utils/serializers/output/utils/url.js +11 -1
  170. package/core/server/data/exporter/export-filename.js +2 -1
  171. package/core/server/data/importer/importers/data/revue-subscriber-importer.js +6 -10
  172. package/core/server/data/importer/importers/json-to-html.js +24 -4
  173. package/core/server/data/migrations/versions/6.55/2026-07-27-11-25-44-add-to-hash-to-redirects.js +51 -0
  174. package/core/server/data/migrations/versions/6.55/2026-07-28-12-08-00-remove-routes-hash-from-settings.js +5 -0
  175. package/core/server/data/schema/commands.js +5 -0
  176. package/core/server/data/schema/default-settings/default-settings.json +0 -4
  177. package/core/server/data/schema/schema.js +5 -1
  178. package/core/server/lib/image/image-size.js +3 -17
  179. package/core/server/lib/image/image-utils.js +15 -1
  180. package/core/server/lib/request-external.js +1 -1
  181. package/core/server/models/user.js +46 -70
  182. package/core/server/services/auth/session/session-service.js +28 -1
  183. package/core/server/services/automations/automations-api.js +21 -6
  184. package/core/server/services/automations/automations-api.ts +25 -6
  185. package/core/server/services/automations/automations-repository.ts +19 -0
  186. package/core/server/services/automations/database-automations-repository.js +116 -28
  187. package/core/server/services/automations/database-automations-repository.ts +118 -9
  188. package/core/server/services/automations/database-date.js +10 -0
  189. package/core/server/services/automations/database-date.ts +5 -0
  190. package/core/server/services/automations/poll.js +5 -2
  191. package/core/server/services/automations/poll.ts +7 -2
  192. package/core/server/services/automations/scheduler-poll-time.js +40 -0
  193. package/core/server/services/automations/scheduler-poll-time.ts +38 -0
  194. package/core/server/services/automations/service.js +15 -3
  195. package/core/server/services/automations/service.ts +16 -3
  196. package/core/server/services/comments/comments-service-emails.js +14 -8
  197. package/core/server/services/comments/comments-service.js +9 -4
  198. package/core/server/services/email-rendering/partials/email-wrapper.hbs +3 -1
  199. package/core/server/services/email-service/email-service-wrapper.js +6 -1
  200. package/core/server/services/email-service/email-templates/partials/styles.hbs +8 -0
  201. package/core/server/services/email-service/newsletter-email-event-storage.js +41 -10
  202. package/core/server/services/lib/dynamic-redirect-manager.js +12 -3
  203. package/core/server/services/link-redirection/link-redirect-repository.js +41 -4
  204. package/core/server/services/link-redirection/link-redirect.js +2 -0
  205. package/core/server/services/link-redirection/link-redirect.ts +3 -1
  206. package/core/server/services/link-redirection/link-redirects-service.js +38 -2
  207. package/core/server/services/link-tracking/click-event.js +3 -0
  208. package/core/server/services/link-tracking/index.js +38 -6
  209. package/core/server/services/link-tracking/link-click-repository.js +30 -9
  210. package/core/server/services/link-tracking/link-click-tracking-service.js +44 -3
  211. package/core/server/services/member-attribution/outbound-link-tagger.js +3 -1
  212. package/core/server/services/member-welcome-emails/member-welcome-email-renderer.js +19 -4
  213. package/core/server/services/member-welcome-emails/service.js +11 -3
  214. package/core/server/services/members/{importer → import-export}/config.js +4 -9
  215. package/core/server/services/members/{importer → import-export}/config.ts +4 -9
  216. package/core/server/services/members/import-export/csv/formula.js +16 -0
  217. package/core/server/services/members/import-export/csv/formula.ts +14 -0
  218. package/core/server/services/members/import-export/csv/index.js +12 -0
  219. package/core/server/services/members/import-export/csv/index.ts +3 -0
  220. package/core/server/services/members/import-export/csv/parse.js +64 -0
  221. package/core/server/services/members/import-export/csv/parse.ts +69 -0
  222. package/core/server/services/members/import-export/csv/serialize.js +13 -0
  223. package/core/server/services/members/import-export/csv/serialize.ts +18 -0
  224. package/core/server/services/members/import-export/export/exporter.js +202 -0
  225. package/core/server/services/members/import-export/export/exporter.ts +325 -0
  226. package/core/server/services/members/import-export/import/completion-email.js +84 -0
  227. package/core/server/services/members/import-export/import/completion-email.ts +141 -0
  228. package/core/server/services/members/import-export/import/importer.js +297 -0
  229. package/core/server/services/members/import-export/import/importer.ts +468 -0
  230. package/core/server/services/members/import-export/import/reader.js +32 -0
  231. package/core/server/services/members/import-export/import/reader.ts +33 -0
  232. package/core/server/services/members/import-export/import/row.js +33 -0
  233. package/core/server/services/members/import-export/import/row.ts +52 -0
  234. package/core/server/services/members/import-export/import/spool.js +30 -0
  235. package/core/server/services/members/import-export/import/spool.ts +38 -0
  236. package/core/server/services/members/import-export/index.js +99 -0
  237. package/core/server/services/members/import-export/index.ts +137 -0
  238. package/core/server/services/members/members-api/controllers/router-controller.js +7 -0
  239. package/core/server/services/members/service.js +25 -20
  240. package/core/server/services/members-custom-fields/values-service.js +19 -7
  241. package/core/server/services/members-custom-fields/values-service.ts +19 -7
  242. package/core/server/services/mentions/service.js +5 -1
  243. package/core/server/services/posts/posts-exporter.js +6 -4
  244. package/core/server/services/posts/posts-service.js +2 -2
  245. package/core/server/services/route-settings/activation-bridge.js +59 -49
  246. package/core/server/services/route-settings/activation-bridge.ts +91 -51
  247. package/core/server/services/route-settings/dynamic-routing-service.js +22 -51
  248. package/core/server/services/route-settings/index.js +1 -16
  249. package/core/server/services/settings/settings-service.js +0 -18
  250. package/core/server/services/themes/storage.js +9 -0
  251. package/core/server/services/themes/theme-storage.js +1 -1
  252. package/core/server/services/url/url-service-facade.js +1 -1
  253. package/core/server/services/url/url-service-facade.ts +8 -1
  254. package/core/server/web/api/endpoints/admin/routes.js +1 -0
  255. package/core/shared/config/defaults.json +2 -1
  256. package/core/shared/express.js +6 -1
  257. package/core/shared/labs.js +2 -1
  258. package/package.json +11 -11
  259. package/pnpm-lock.yaml +18 -18
  260. package/pnpm-workspace.yaml +8 -7
  261. package/components/tryghost-adapter-base-scheduling-0.1.1.tgz +0 -0
  262. package/core/built/admin/assets/Overview-j4NaeUNm.js +0 -1
  263. package/core/built/admin/assets/Web-_fD935OX.js +0 -2
  264. package/core/built/admin/assets/activitypub/layout-IdVq3lRy.js +0 -1
  265. package/core/built/admin/assets/audience-BKRdsFmy.js +0 -1
  266. package/core/built/admin/assets/checkbox-DA4-1UiI.js +0 -1
  267. package/core/built/admin/assets/chunk.524.45e0875f41b71e46e849.js +0 -25
  268. package/core/built/admin/assets/chunk.582.51defd4b009f0de8d4d5.js +0 -27
  269. package/core/built/admin/assets/code-editor-view-BKBrkffZ.js +0 -1
  270. package/core/built/admin/assets/comments-CzVNIT8b.js +0 -1
  271. package/core/built/admin/assets/constants-c-JNF9c2.js +0 -1
  272. package/core/built/admin/assets/dist-CT46_f_J.js +0 -1
  273. package/core/built/admin/assets/domain-B7_n5nfx.js +0 -1
  274. package/core/built/admin/assets/dropzone-DcuJEEUf.js +0 -5
  275. package/core/built/admin/assets/editor-BCiIyFjm.js +0 -8
  276. package/core/built/admin/assets/field-BW-M2Zwp.js +0 -1
  277. package/core/built/admin/assets/filters-DtcXMZDU.js +0 -1
  278. package/core/built/admin/assets/gift-link-modal-Bk8qpnMw.js +0 -1
  279. package/core/built/admin/assets/growth-Ck2s3JjR.js +0 -1
  280. package/core/built/admin/assets/index-BBf502Wg.js +0 -69
  281. package/core/built/admin/assets/index-BCCZKxP2.css +0 -1
  282. package/core/built/admin/assets/input-group-DjuYnNCd.js +0 -1
  283. package/core/built/admin/assets/label-picker-BdNAWuUX.js +0 -1
  284. package/core/built/admin/assets/labels-Cyayfd-e.js +0 -1
  285. package/core/built/admin/assets/layout-Bw4GnxXp.js +0 -1
  286. package/core/built/admin/assets/member-custom-fields-DvFyamLu.js +0 -1
  287. package/core/built/admin/assets/member-detail-Cg2vTqvJ.js +0 -1
  288. package/core/built/admin/assets/members-DsPxYAVm.js +0 -10
  289. package/core/built/admin/assets/modals-Bf_fyvHZ.js +0 -31
  290. package/core/built/admin/assets/moderation-Dlp7M5sa.js +0 -1
  291. package/core/built/admin/assets/multi-select-combobox-CH1o8XXQ.js +0 -1
  292. package/core/built/admin/assets/newsletter-CQ5CAYUI.js +0 -1
  293. package/core/built/admin/assets/note-BrAZ7Z0o.js +0 -1
  294. package/core/built/admin/assets/notifications-BnbHLOPC.js +0 -1
  295. package/core/built/admin/assets/onboarding-route-eU146kuA.js +0 -1
  296. package/core/built/admin/assets/overview-BpbaK-xu.js +0 -1
  297. package/core/built/admin/assets/post-analytics-header-D9pJ4iNm.js +0 -1
  298. package/core/built/admin/assets/post-analytics-provider-BDqcfBor.js +0 -1
  299. package/core/built/admin/assets/profile-dJ44Bn_W.js +0 -1
  300. package/core/built/admin/assets/select--2uVN9_-.js +0 -1
  301. package/core/built/admin/assets/settings-SD9bxIpt.js +0 -4
  302. package/core/built/admin/assets/social-urls-BvFZwYcE.js +0 -8
  303. package/core/built/admin/assets/switch-qp518gFQ.js +0 -1
  304. package/core/built/admin/assets/tabs-D3ZOYkM7.js +0 -1
  305. package/core/built/admin/assets/textarea-CTlb3Uu6.js +0 -1
  306. package/core/built/admin/assets/use-filter-params-DeQ8sX4N.js +0 -1
  307. package/core/built/admin/assets/web-DTZnnUGr.js +0 -1
  308. package/core/server/services/mail/templates/newsletter.html +0 -876
  309. package/core/server/services/members/csv/index.js +0 -10
  310. package/core/server/services/members/csv/index.ts +0 -3
  311. package/core/server/services/members/csv/parse.js +0 -94
  312. package/core/server/services/members/csv/parse.ts +0 -111
  313. package/core/server/services/members/csv/types.js +0 -2
  314. package/core/server/services/members/csv/types.ts +0 -39
  315. package/core/server/services/members/csv/unparse.js +0 -69
  316. package/core/server/services/members/csv/unparse.ts +0 -79
  317. package/core/server/services/members/exporter/query.js +0 -233
  318. package/core/server/services/members/importer/index.js +0 -30
  319. package/core/server/services/members/importer/labels.js +0 -125
  320. package/core/server/services/members/importer/members-csv-importer.js +0 -520
  321. package/core/server/services/route-settings/default-settings-manager.js +0 -63
  322. package/core/server/services/route-settings/route-settings.js +0 -170
  323. package/core/server/services/route-settings/settings-loader.js +0 -60
  324. package/core/server/services/route-settings/settings-path-manager.js +0 -47
  325. package/core/server/services/route-settings/validate.js +0 -440
  326. /package/core/server/services/members/{importer → import-export/import}/email-template.js +0 -0
  327. /package/core/server/services/members/{importer/members-csv-importer-stripe-utils.js → import-export/import/stripe-utils.js} +0 -0
@@ -1,14 +1,18 @@
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 });
1
6
  // # Local File Base Storage module
2
7
  // The (default) module for storing files using the local file system
8
+ const fs_extra_1 = __importDefault(require("fs-extra"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const tpl_1 = __importDefault(require("@tryghost/tpl"));
11
+ const errors_1 = __importDefault(require("@tryghost/errors"));
12
+ const ghost_storage_base_1 = require("ghost-storage-base");
13
+ const url_utils_1 = __importDefault(require("../../../shared/url-utils"));
14
+ const errify_1 = require("../../../shared/errify");
3
15
  const serveStatic = require('../../../shared/express').static;
4
-
5
- const fs = require('fs-extra');
6
- const path = require('path');
7
- const tpl = require('@tryghost/tpl');
8
- const errors = require('@tryghost/errors');
9
- const urlUtils = require('../../../shared/url-utils').default;
10
- const {StorageBase} = require('ghost-storage-base');
11
-
12
16
  const messages = {
13
17
  notFound: 'File not found',
14
18
  notFoundWithRef: 'File not found: {file}',
@@ -16,50 +20,34 @@ const messages = {
16
20
  invalidUrlParameter: `The URL "{url}" is not a valid URL for this site.`,
17
21
  invalidPathParameter: 'The path "{path}" is not valid for this storage.'
18
22
  };
19
-
20
- class LocalStorageBase extends StorageBase {
21
- /**
22
- *
23
- * @param {Object} options
24
- * @param {string} options.storagePath
25
- * @param {string} options.siteUrl
26
- * @param {string} [options.staticFileURLPrefix]
27
- * @param {Object} [options.errorMessages]
28
- * @param {string} [options.errorMessages.notFound]
29
- * @param {string} [options.errorMessages.notFoundWithRef]
30
- * @param {string} [options.errorMessages.cannotRead]
31
- */
32
- constructor({storagePath, staticFileURLPrefix, siteUrl, errorMessages}) {
23
+ class LocalStorageBase extends ghost_storage_base_1.StorageBase {
24
+ staticFileURLPrefix;
25
+ siteUrl;
26
+ staticFileUrl;
27
+ errorMessages;
28
+ constructor({ storagePath, staticFileURLPrefix, siteUrl, errorMessages }) {
33
29
  super();
34
-
35
30
  this.storagePath = storagePath;
36
31
  this.staticFileURLPrefix = staticFileURLPrefix;
37
32
  this.siteUrl = siteUrl;
38
33
  this.staticFileUrl = `${siteUrl}${staticFileURLPrefix}`;
39
34
  this.errorMessages = errorMessages || messages;
40
35
  }
41
-
42
36
  /**
43
37
  * Normalizes a relative storage path and rejects traversal outside the storage root.
44
- *
45
- * @param {string} filePath
46
- * @returns {string}
47
38
  */
48
39
  _normalizeStorageRelativePath(filePath) {
49
- const normalized = path.posix.normalize(String(filePath || '')
40
+ const normalized = path_1.default.posix.normalize(String(filePath || '')
50
41
  .replaceAll('\\', '/')
51
42
  .replace(/^\/+/, '')
52
43
  .replace(/\/+$/, ''));
53
-
54
44
  if (normalized === '.' || normalized === '..' || normalized.startsWith('../')) {
55
- throw new errors.IncorrectUsageError({
56
- message: tpl(messages.invalidPathParameter, {path: filePath})
45
+ throw new errors_1.default.IncorrectUsageError({
46
+ message: (0, tpl_1.default)(messages.invalidPathParameter, { path: filePath })
57
47
  });
58
48
  }
59
-
60
49
  return normalized;
61
50
  }
62
-
63
51
  /**
64
52
  * Resolves a target directory and optional file name into a full path,
65
53
  * validating the result is inside the storage root.
@@ -67,258 +55,210 @@ class LocalStorageBase extends StorageBase {
67
55
  * Supports relative paths (preferred) and absolute paths (legacy).
68
56
  * TODO: remove absolute path support once all callers pass relative paths
69
57
  *
70
- * @param {string} [targetDir] absolute or relative directory
71
- * @param {string} [fileName] file name to normalize and append
72
- * @returns {string} resolved absolute path inside storagePath
58
+ * @param targetDir absolute or relative directory
59
+ * @param fileName file name to normalize and append
60
+ * @returns resolved absolute path inside storagePath
73
61
  */
74
62
  _resolveAndValidateStoragePath(targetDir, fileName) {
75
- const resolvedRoot = path.resolve(this.storagePath);
76
-
63
+ const resolvedRoot = path_1.default.resolve(this.storagePath);
77
64
  // Resolve targetDir: if already inside storage root use as-is, otherwise treat as relative
78
65
  let resolvedBase;
79
66
  if (targetDir) {
80
- const resolvedTargetDir = path.resolve(targetDir);
81
- const relToRoot = path.relative(resolvedRoot, resolvedTargetDir);
82
- if (relToRoot === '' || (!relToRoot.startsWith('..') && !path.isAbsolute(relToRoot))) {
67
+ const resolvedTargetDir = path_1.default.resolve(targetDir);
68
+ const relToRoot = path_1.default.relative(resolvedRoot, resolvedTargetDir);
69
+ if (relToRoot === '' || (!relToRoot.startsWith('..') && !path_1.default.isAbsolute(relToRoot))) {
83
70
  resolvedBase = resolvedTargetDir;
84
- } else {
85
- resolvedBase = path.resolve(this.storagePath, targetDir);
86
71
  }
87
- } else {
72
+ else {
73
+ resolvedBase = path_1.default.resolve(this.storagePath, targetDir);
74
+ }
75
+ }
76
+ else {
88
77
  resolvedBase = resolvedRoot;
89
78
  }
90
-
91
79
  // If fileName provided, normalize and resolve
92
80
  let resolvedPath;
93
81
  if (fileName) {
94
82
  const normalizedFileName = this._normalizeStorageRelativePath(fileName);
95
- resolvedPath = path.resolve(resolvedBase, normalizedFileName);
96
- } else {
83
+ resolvedPath = path_1.default.resolve(resolvedBase, normalizedFileName);
84
+ }
85
+ else {
97
86
  resolvedPath = resolvedBase;
98
87
  }
99
-
100
88
  // Validate the resolved path is strictly inside the storage root (not equal to it)
101
- const relative = path.relative(resolvedRoot, resolvedPath);
102
- if (relative === '' || relative === '..' || relative.startsWith('..' + path.sep) || path.isAbsolute(relative)) {
103
- throw new errors.IncorrectUsageError({
104
- message: tpl(messages.invalidPathParameter, {path: fileName || targetDir || ''})
89
+ const relative = path_1.default.relative(resolvedRoot, resolvedPath);
90
+ if (relative === '' || relative === '..' || relative.startsWith('..' + path_1.default.sep) || path_1.default.isAbsolute(relative)) {
91
+ throw new errors_1.default.IncorrectUsageError({
92
+ message: (0, tpl_1.default)(messages.invalidPathParameter, { path: fileName || targetDir || '' })
105
93
  });
106
94
  }
107
-
108
95
  return resolvedPath;
109
96
  }
110
-
111
97
  /**
112
98
  * Saves the file to storage (the file system)
113
99
  * - returns a promise which ultimately returns the full url to the uploaded file
114
- *
115
- * @param {import('ghost-storage-base').StorageFile} file
116
- * @param {string} targetDir
117
- * @returns {Promise<String>}
118
100
  */
119
101
  async save(file, targetDir) {
120
102
  let targetFilename;
121
-
122
103
  targetDir = targetDir
123
104
  ? this._resolveAndValidateStoragePath(targetDir)
124
105
  : this.getTargetDir(this.storagePath);
125
-
126
106
  const filename = await this.getUniqueFileName(file, targetDir);
127
-
128
107
  targetFilename = filename;
129
- await fs.mkdirs(targetDir);
130
-
108
+ // Verify that we are saving directly under `targetDir` and not outside of it.
109
+ const expectedPrefix = path_1.default.join(path_1.default.resolve(targetDir), '/');
110
+ if (!path_1.default.resolve(targetFilename).startsWith(expectedPrefix)) {
111
+ throw new errors_1.default.BadRequestError({ message: 'Cannot save to the given filename' });
112
+ }
113
+ await fs_extra_1.default.mkdirs(targetDir);
131
114
  try {
132
- await fs.copy(file.path, targetFilename);
133
- } catch (err) {
115
+ await fs_extra_1.default.copy(file.path, targetFilename);
116
+ }
117
+ catch (err) {
134
118
  if (err.code === 'ENAMETOOLONG') {
135
- throw new errors.BadRequestError({err});
119
+ throw new errors_1.default.BadRequestError({ err: (0, errify_1.errify)(err) });
136
120
  }
137
-
138
121
  throw err;
139
122
  }
140
-
141
123
  // The src for the image must be in URI format, not a file system path, which in Windows uses \
142
124
  // For local file system storage can use relative path so add a slash
143
- const fullUrl = (
144
- urlUtils.urlJoin('/',
145
- urlUtils.getSubdir(),
146
- this.staticFileURLPrefix,
147
- path.relative(this.storagePath, targetFilename))
148
- ).replace(new RegExp(`\\${path.sep}`, 'g'), '/');
149
-
125
+ const fullUrl = (url_utils_1.default.urlJoin('/', url_utils_1.default.getSubdir(), this.staticFileURLPrefix, path_1.default.relative(this.storagePath, targetFilename))).replace(new RegExp(`\\${path_1.default.sep}`, 'g'), '/');
150
126
  return fullUrl;
151
127
  }
152
-
153
128
  /**
154
129
  * Saves a buffer in the targetPath
155
- * @param {Buffer} buffer is an instance of Buffer
156
- * @param {string} targetPath relative path NOT including storage path to which the buffer should be written
157
- * @returns {Promise<String>} a URL to retrieve the data
130
+ *
131
+ * @param buffer is an instance of Buffer
132
+ * @param targetPath relative path NOT including storage path to which the buffer should be written
133
+ * @returns a URL to retrieve the data
158
134
  */
159
135
  async saveRaw(buffer, targetPath) {
160
- const storagePath = path.join(this.storagePath, this._normalizeStorageRelativePath(targetPath));
161
- const targetDir = path.dirname(storagePath);
162
-
163
- await fs.mkdirs(targetDir);
164
- await fs.writeFile(storagePath, buffer);
165
-
136
+ const storagePath = path_1.default.join(this.storagePath, this._normalizeStorageRelativePath(targetPath));
137
+ const targetDir = path_1.default.dirname(storagePath);
138
+ await fs_extra_1.default.mkdirs(targetDir);
139
+ await fs_extra_1.default.writeFile(storagePath, buffer);
166
140
  // For local file system storage can use relative path so add a slash
167
- const fullUrl = (
168
- urlUtils.urlJoin('/', urlUtils.getSubdir(),
169
- this.staticFileURLPrefix,
170
- targetPath)
171
- ).replace(new RegExp(`\\${path.sep}`, 'g'), '/');
172
-
141
+ const fullUrl = (url_utils_1.default.urlJoin('/', url_utils_1.default.getSubdir(), this.staticFileURLPrefix, targetPath)).replace(new RegExp(`\\${path_1.default.sep}`, 'g'), '/');
173
142
  return fullUrl;
174
143
  }
175
-
176
144
  /**
177
- * @param {string} url full url under which the stored content is served, result of save method
178
- * @returns {string} relative path under which the content is stored
145
+ * @param url full url under which the stored content is served, result of save method
146
+ * @returns relative path under which the content is stored
179
147
  */
180
148
  urlToPath(url) {
181
149
  let relativePath;
182
-
183
- const prefix = urlUtils.urlJoin('/',
184
- urlUtils.getSubdir(),
185
- this.staticFileURLPrefix
186
- );
187
-
150
+ const prefix = url_utils_1.default.urlJoin('/', url_utils_1.default.getSubdir(), this.staticFileURLPrefix);
188
151
  if (url.startsWith(this.staticFileUrl)) {
189
152
  // CASE: full path that includes the site url
190
153
  relativePath = url.replace(this.staticFileUrl, '');
191
- } else if (url.startsWith(prefix)) {
154
+ }
155
+ else if (url.startsWith(prefix)) {
192
156
  // CASE: The result of the save method doesn't include the site url. So we need to handle this case.
193
157
  relativePath = url.replace(prefix, '');
194
- } else {
195
- throw new errors.IncorrectUsageError({
196
- message: tpl(messages.invalidUrlParameter, {url})
158
+ }
159
+ else {
160
+ throw new errors_1.default.IncorrectUsageError({
161
+ message: (0, tpl_1.default)(messages.invalidUrlParameter, { url })
197
162
  });
198
163
  }
199
-
200
164
  try {
201
165
  return this._normalizeStorageRelativePath(relativePath);
202
- } catch (err) {
203
- throw new errors.IncorrectUsageError({
204
- message: tpl(messages.invalidUrlParameter, {url})
166
+ }
167
+ catch (err) {
168
+ throw new errors_1.default.IncorrectUsageError({
169
+ message: (0, tpl_1.default)(messages.invalidUrlParameter, { url })
205
170
  });
206
171
  }
207
172
  }
208
-
209
173
  async exists(fileName, targetDir) {
210
174
  let filePath;
211
-
212
175
  try {
213
176
  filePath = this._resolveAndValidateStoragePath(targetDir, fileName);
214
- } catch (err) {
215
- if (err instanceof errors.IncorrectUsageError) {
177
+ }
178
+ catch (err) {
179
+ if (err instanceof errors_1.default.IncorrectUsageError) {
216
180
  return false;
217
181
  }
218
-
219
182
  throw err;
220
183
  }
221
-
222
184
  try {
223
- await fs.stat(filePath);
185
+ await fs_extra_1.default.stat(filePath);
224
186
  return true;
225
- } catch {
187
+ }
188
+ catch {
226
189
  return false;
227
190
  }
228
191
  }
229
-
230
192
  /**
231
193
  * For some reason send divides the max age number by 1000
232
194
  * Fallthrough: false ensures that if an image isn't found, it automatically 404s
233
195
  * Wrap server static errors
234
- *
235
- * @returns {serveStaticContent}
236
196
  */
237
197
  serve() {
238
- const {storagePath, errorMessages} = this;
239
-
198
+ const { storagePath, errorMessages } = this;
240
199
  return function serveStaticContent(req, res, next) {
241
- return serveStatic(
242
- storagePath,
243
- {
244
- maxAge: (365 * 24 * 60 * 60 * 1000), // 1 year in ms
245
- fallthrough: false
246
- }
247
- )(req, res, (err) => {
200
+ return serveStatic(storagePath, {
201
+ maxAge: (365 * 24 * 60 * 60 * 1000), // 1 year in ms
202
+ fallthrough: false
203
+ })(req, res, (err) => {
248
204
  if (err) {
249
205
  if (err.statusCode === 404) {
250
- return next(new errors.NotFoundError({
251
- message: tpl(errorMessages.notFound),
206
+ return next(new errors_1.default.NotFoundError({
207
+ message: (0, tpl_1.default)(errorMessages.notFound),
252
208
  code: 'STATIC_FILE_NOT_FOUND',
253
209
  property: err.path
254
210
  }));
255
211
  }
256
-
257
212
  if (err.statusCode === 400) {
258
- return next(new errors.BadRequestError({err: err}));
213
+ return next(new errors_1.default.BadRequestError({ err: err }));
259
214
  }
260
-
261
215
  if (err.statusCode === 403) {
262
- return next(new errors.NoPermissionError({err: err}));
216
+ return next(new errors_1.default.NoPermissionError({ err: err }));
263
217
  }
264
-
265
218
  if (err.name === 'RangeNotSatisfiableError') {
266
- return next(new errors.RangeNotSatisfiableError({err}));
219
+ return next(new errors_1.default.RangeNotSatisfiableError({ err }));
267
220
  }
268
-
269
- return next(new errors.InternalServerError({err: err}));
221
+ return next(new errors_1.default.InternalServerError({ err: err }));
270
222
  }
271
-
272
223
  next();
273
224
  });
274
225
  };
275
226
  }
276
-
277
- /**
278
- * @param {string} filePath
279
- * @returns {Promise.<*>}
280
- */
281
227
  async delete(fileName, targetDir) {
282
228
  const filePath = this._resolveAndValidateStoragePath(targetDir, fileName);
283
- return await fs.remove(filePath);
229
+ return await fs_extra_1.default.remove(filePath);
284
230
  }
285
-
286
231
  /**
287
232
  * Reads bytes from disk for a target file
288
233
  * - path of target file (without content path!)
289
- *
290
- * @param options
291
234
  */
292
235
  async read(options) {
293
236
  options = options || {};
294
-
295
237
  const normalizedPath = this._normalizeStorageRelativePath(options.path);
296
- const targetPath = path.join(this.storagePath, normalizedPath);
297
-
238
+ const targetPath = path_1.default.join(this.storagePath, normalizedPath);
298
239
  try {
299
- return await fs.readFile(targetPath);
300
- } catch (err) {
301
- if (err.code === 'ENOENT' || err.code === 'ENOTDIR') {
302
- throw new errors.NotFoundError({
240
+ return await fs_extra_1.default.readFile(targetPath);
241
+ }
242
+ catch (rawError) {
243
+ const err = (0, errify_1.errify)(rawError);
244
+ const code = rawError.code;
245
+ if (code === 'ENOENT' || code === 'ENOTDIR') {
246
+ throw new errors_1.default.NotFoundError({
303
247
  err: err,
304
- message: tpl(this.errorMessages.notFoundWithRef, {file: options.path})
248
+ message: (0, tpl_1.default)(this.errorMessages.notFoundWithRef, { file: options.path })
305
249
  });
306
250
  }
307
-
308
- if (err.code === 'ENAMETOOLONG') {
309
- throw new errors.BadRequestError({err: err});
251
+ if (code === 'ENAMETOOLONG') {
252
+ throw new errors_1.default.BadRequestError({ err: err });
310
253
  }
311
-
312
- if (err.code === 'EACCES') {
313
- throw new errors.NoPermissionError({err: err});
254
+ if (code === 'EACCES') {
255
+ throw new errors_1.default.NoPermissionError({ err: err });
314
256
  }
315
-
316
- throw new errors.InternalServerError({
257
+ throw new errors_1.default.InternalServerError({
317
258
  err: err,
318
- message: tpl(this.errorMessages.cannotRead, {file: options.path})
259
+ message: (0, tpl_1.default)(this.errorMessages.cannotRead, { file: options.path })
319
260
  });
320
261
  }
321
262
  }
322
263
  }
323
-
324
- module.exports = LocalStorageBase;
264
+ exports.default = LocalStorageBase;