ghost 6.61.0 → 6.62.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (472) hide show
  1. package/components/ghost-storage-base-3.0.0.tgz +0 -0
  2. package/components/tryghost-adapter-base-cache-0.2.0.tgz +0 -0
  3. package/components/tryghost-adapter-base-jobs-0.0.0.tgz +0 -0
  4. package/components/tryghost-adapter-base-redirects-0.0.0.tgz +0 -0
  5. package/components/tryghost-adapter-base-route-settings-0.0.0.tgz +0 -0
  6. package/components/tryghost-adapter-base-scheduling-0.2.3.tgz +0 -0
  7. package/components/tryghost-adapter-base-sso-0.1.3.tgz +0 -0
  8. package/components/tryghost-admin-api-schema-0.0.0.tgz +0 -0
  9. package/components/tryghost-checkout-0.0.0.tgz +0 -0
  10. package/components/tryghost-custom-field-types-0.0.0.tgz +0 -0
  11. package/components/tryghost-i18n-0.0.0.tgz +0 -0
  12. package/components/tryghost-kg-card-factory-5.2.4.tgz +0 -0
  13. package/components/tryghost-kg-clean-basic-html-4.3.4.tgz +0 -0
  14. package/components/tryghost-kg-converters-1.2.5.tgz +0 -0
  15. package/components/tryghost-kg-default-cards-10.3.5.tgz +0 -0
  16. package/components/tryghost-kg-default-nodes-2.2.1.tgz +0 -0
  17. package/components/tryghost-kg-default-transforms-1.3.4.tgz +0 -0
  18. package/components/tryghost-kg-html-to-lexical-1.4.0.tgz +0 -0
  19. package/components/tryghost-kg-lexical-html-renderer-1.5.0.tgz +0 -0
  20. package/components/tryghost-kg-markdown-html-renderer-7.2.4.tgz +0 -0
  21. package/components/tryghost-kg-utils-1.1.4.tgz +0 -0
  22. package/components/tryghost-nql-string-0.0.0.tgz +0 -0
  23. package/components/tryghost-parse-email-address-0.0.0.tgz +0 -0
  24. package/content/settings/README.md +1 -1
  25. package/content/themes/casper/.gitignore +28 -0
  26. package/content/themes/casper/assets/built/casper.js +1 -1
  27. package/content/themes/casper/assets/built/screen.css +1 -1
  28. package/content/themes/casper/assets/css/screen.css +2 -1
  29. package/content/themes/casper/assets/js/lightbox.js +63 -46
  30. package/content/themes/casper/package.json +6 -6
  31. package/content/themes/casper/page.hbs +1 -0
  32. package/content/themes/casper/post.hbs +1 -0
  33. package/content/themes/source/.gitignore +28 -0
  34. package/content/themes/source/assets/built/screen.css +1 -1
  35. package/content/themes/source/assets/built/source.js +1 -1
  36. package/content/themes/source/assets/css/screen.css +2 -1
  37. package/content/themes/source/assets/js/lightbox.js +62 -45
  38. package/content/themes/source/assets/js/main.js +2 -2
  39. package/content/themes/source/package.json +4 -4
  40. package/content/themes/source/partials/feature-image.hbs +1 -0
  41. package/core/boot.js +54 -22
  42. package/core/built/admin/assets/Combination-B0l4MKVh.js +41 -0
  43. package/core/built/admin/assets/InterVariable-DiVDrmQJ.woff2 +0 -0
  44. package/core/built/admin/assets/InterVariable-Italic-FCBEiFp6.woff2 +0 -0
  45. package/core/built/admin/assets/{about-Bve7IJS2.js → about-Dyae_UT6.js} +1 -1
  46. package/core/built/admin/assets/account-migration-CESa0mnX.js +1 -0
  47. package/core/built/admin/assets/activitypub/{account-migration-C-aej4x_.js → account-migration-By69CgCp.js} +16 -16
  48. package/core/built/admin/assets/activitypub/activitypub.js +9 -9
  49. package/core/built/admin/assets/activitypub/{bluesky-sharing-BXkA5mqV.js → bluesky-sharing-BJcPMrDd.js} +36 -36
  50. package/core/built/admin/assets/activitypub/{content-formatters-CHcyMFk4.js → content-formatters-3rTHg3mp.js} +3 -3
  51. package/core/built/admin/assets/activitypub/{domain-B3ihkPde.js → domain-DUR4xSkV.js} +121 -121
  52. package/core/built/admin/assets/activitypub/{edit-profile-DsZM3rTX.js → edit-profile-BqtfzxCp.js} +40 -40
  53. package/core/built/admin/assets/activitypub/{explore-BodNrZgR.js → explore-BxuJd-J4.js} +26 -26
  54. package/core/built/admin/assets/activitypub/{feed-PwH1iJ84.js → feed-BM1TcksA.js} +48 -48
  55. package/core/built/admin/assets/activitypub/{field-D06-kmOJ.js → field-Dn7HHx2-.js} +2 -2
  56. package/core/built/admin/assets/activitypub/inbox-CCjkuow2.js +1284 -0
  57. package/core/built/admin/assets/activitypub/label-1AA_s9Fa.js +16 -0
  58. package/core/built/admin/assets/activitypub/layout-2-0bw6HN.js +1 -0
  59. package/core/built/admin/assets/activitypub/{moderation-D1Yapsod.js → moderation-CnmxEB8w.js} +91 -91
  60. package/core/built/admin/assets/activitypub/{note-C5zjqq5C.js → note-ZKc_Bnba.js} +23 -23
  61. package/core/built/admin/assets/activitypub/{notifications-B9p8eCHD.js → notifications-CB2tJZau.js} +48 -48
  62. package/core/built/admin/assets/activitypub/{onboarding-CNelD_uF.js → onboarding-BsJ9E5qf.js} +2 -2
  63. package/core/built/admin/assets/activitypub/{onboarding-mat5Hrl0.js → onboarding-CSUJJIlh.js} +2 -2
  64. package/core/built/admin/assets/activitypub/{preferences-BCqUdC3v.js → preferences-0-JZnUkI.js} +1519 -1519
  65. package/core/built/admin/assets/activitypub/{profile-BRCWoFem.js → profile-C35cFIhM.js} +183 -183
  66. package/core/built/admin/assets/activitypub/{routes-BSXT992i.js → routes-BD4vscyc.js} +740 -731
  67. package/core/built/admin/assets/activitypub/settings-BsMROdqh.js +315 -0
  68. package/core/built/admin/assets/activitypub/{site-DHoMupSB.js → site-O0RL9YCN.js} +2 -2
  69. package/core/built/admin/assets/activitypub/{step-1-B-YfsVeO.js → step-1-BMSx7c_X.js} +4 -4
  70. package/core/built/admin/assets/activitypub/{step-3-D6BFMXL_.js → step-3-CLlOZTyt.js} +3 -3
  71. package/core/built/admin/assets/activitypub/{tabs-GpNecvfB.js → tabs-Dxk-b9M-.js} +306 -306
  72. package/core/built/admin/assets/activitypub/{topic-filter-BPDeQQys.js → topic-filter-5yZH6tId.js} +2 -2
  73. package/core/built/admin/assets/activitypub/{use-activity-pub-queries-BoVOxXkV.js → use-activity-pub-queries-CV50qe03.js} +2 -2
  74. package/core/built/admin/assets/activitypub/{use-reply-chain-data-wVBX7swM.js → use-reply-chain-data-Cbvzgjzd.js} +30 -30
  75. package/core/built/admin/assets/activitypub/{users-CoX6FT_K.js → users-BjcoP_HC.js} +7 -5
  76. package/core/built/admin/assets/add-integration-modal-BlF6rs_f.js +1 -0
  77. package/core/built/admin/assets/add-newsletter-modal-CglVQqah.js +1 -0
  78. package/core/built/admin/assets/add-recommendation-modal-wz7BsuaG.js +1 -0
  79. package/core/built/admin/assets/analytics-C4HE1gBg.js +1 -0
  80. package/core/built/admin/assets/{announcement-bar-modal-DM3cYOpo.js → announcement-bar-modal-Ci4zz8jO.js} +1 -1
  81. package/core/built/admin/assets/{api-keys-BLm2NDBh.js → api-keys-Ck-Yteiv.js} +1 -1
  82. package/core/built/admin/assets/{audience-9mwU5TW6.js → audience-CtbA54Sn.js} +1 -1
  83. package/core/built/admin/assets/{automated-emails-te1D5kq-.js → automated-emails-D5VVMND9.js} +1 -1
  84. package/core/built/admin/assets/automations-CzKt5fb8.js +1 -0
  85. package/core/built/admin/assets/bluesky-sharing-BEtJ_gL_.js +1 -0
  86. package/core/built/admin/assets/{breadcrumb-DLiqCyFc.js → breadcrumb-zUrZrBtW.js} +1 -1
  87. package/core/built/admin/assets/{button-B2jcu6bk.js → button-eNMKQWXr.js} +1 -1
  88. package/core/built/admin/assets/{chart-helpers-Fo3bUL3K.js → chart-helpers-CfBKt0vT.js} +1 -1
  89. package/core/built/admin/assets/{checkbox-BfKktMph.js → checkbox-CgOn_tKW.js} +1 -1
  90. package/core/built/admin/assets/{chunk.524.60ca4692d91c6022042f.js → chunk.524.a697dee88db67fdf6021.js} +4 -4
  91. package/core/built/admin/assets/{chunk.582.525c7617c2d9e94c940a.js → chunk.582.5ed5d124cfca9c259b9c.js} +6 -6
  92. package/core/built/admin/assets/{chunk.896.435fe0637944d4a69810.js → chunk.598.7e056fabb47ce7dbd73f.js} +14 -14
  93. package/core/built/admin/assets/{code-editor-view-CYVu4EW6.js → code-editor-view-BYNoAoNV.js} +1 -1
  94. package/core/built/admin/assets/{code-editor-view-DCQJxsfU.js → code-editor-view-K2wI-I5f.js} +1 -1
  95. package/core/built/admin/assets/color-picker-Ddw80xX6.js +3 -0
  96. package/core/built/admin/assets/color-picker-field-D9nUhvA7.js +1 -0
  97. package/core/built/admin/assets/combobox-w9j8PPQT.js +1 -0
  98. package/core/built/admin/assets/command-BfpHORBv.js +1 -0
  99. package/core/built/admin/assets/comments-BLmCmyCs.js +1 -0
  100. package/core/built/admin/assets/confirmation-context-CBM8G0Vj.js +1 -0
  101. package/core/built/admin/assets/{content-api-modal-CyQEC3fr.js → content-api-modal-TXRz3U7S.js} +1 -1
  102. package/core/built/admin/assets/context-menu-_QMdd3kp.js +1 -0
  103. package/core/built/admin/assets/{copy-field-B3M1s78L.js → copy-field-6N01S07E.js} +1 -1
  104. package/core/built/admin/assets/create-ghost-browse-value-source-qIBymvvf.js +1 -0
  105. package/core/built/admin/assets/custom-field-type-option-BddFlJFa.js +1 -0
  106. package/core/built/admin/assets/custom-integration-modal-DmNquxUV.js +1 -0
  107. package/core/built/admin/assets/{date-range-select-DD2RKkgB.js → date-range-select-uvz_DtPh.js} +1 -1
  108. package/core/built/admin/assets/design-and-theme-modal-BSmo12Op.js +2 -0
  109. package/core/built/admin/assets/dirty-confirm-dialog-BZ1iytEd.js +1 -0
  110. package/core/built/admin/assets/{disabled-sources-indicator-Cvy47bE2.js → disabled-sources-indicator-DMRrxsiJ.js} +1 -1
  111. package/core/built/admin/assets/dist-Dcsslyo72.js +1 -0
  112. package/core/built/admin/assets/domain-BNYrt0aD.js +1 -0
  113. package/core/built/admin/assets/dropzone-D7nFdAe5.js +5 -0
  114. package/core/built/admin/assets/edit-profile-C5Asm4LA.js +1 -0
  115. package/core/built/admin/assets/editor-REokrzci.js +8 -0
  116. package/core/built/admin/assets/{embed-signup-form-modal-DeBMLxlL.js → embed-signup-form-modal-Ds6mPEi5.js} +1 -1
  117. package/core/built/admin/assets/en-B1jX3WMs.js +1 -0
  118. package/core/built/admin/assets/explore-UY10Egsp.js +1 -0
  119. package/core/built/admin/assets/feature-image-placeholder-D1iF_8bc.js +1 -0
  120. package/core/built/admin/assets/feed-81C8mJWR.js +1 -0
  121. package/core/built/admin/assets/{field-Cj8lmDOo.js → field-Dihp5p18.js} +1 -1
  122. package/core/built/admin/assets/filter-bar-Da1qxybu.js +1 -0
  123. package/core/built/admin/assets/filter-sources-BO9xUPj7.js +1 -0
  124. package/core/built/admin/assets/filters-CRUWecfY.js +1 -0
  125. package/core/built/admin/assets/filters-DirqNXjH.js +1 -0
  126. package/core/built/admin/assets/first-promoter-modal-CT6MxYZb.js +1 -0
  127. package/core/built/admin/assets/{ghost-c8807202a07c20030acb719ee0114815.css → ghost-8eabfc1ece81b03cf7b90780d31487e8.css} +1 -1
  128. package/core/built/admin/assets/{ghost-3894eedcc6968f658578c0abfe942aab.js → ghost-c2848508292937415f20f5a830eea59e.js} +31 -28
  129. package/core/built/admin/assets/{ghost-dark-fbf1e384aaef3ae315e540f0eb7373a7.css → ghost-dark-a7bebe2c561f55369dcf29f4c820f7ff.css} +1 -1
  130. package/core/built/admin/assets/gift-link-modal-CQVAye17.js +1 -0
  131. package/core/built/admin/assets/growth-BWIu-6xj.js +3 -0
  132. package/core/built/admin/assets/growth-DU29oxeA.js +1 -0
  133. package/core/built/admin/assets/history-modal-CFd1Hvx6.js +1 -0
  134. package/core/built/admin/assets/{html-field-C8qVGGC1.js → html-field-CJBCLTvv.js} +1 -1
  135. package/core/built/admin/assets/{images-h8VZEQ9k.js → images-scfkWZiK.js} +1 -1
  136. package/core/built/admin/assets/{inbox-BYd1M06Q.js → inbox-Mcp4DXZN.js} +14 -14
  137. package/core/built/admin/assets/index-6MkPdCtr.js +4 -0
  138. package/core/built/admin/assets/index-Bn7QhcZu.css +2 -0
  139. package/core/built/admin/assets/index.es-CNnuNH0d.js +1 -0
  140. package/core/built/admin/assets/{input-group-D8sCXRF5.js → input-group-CMhe2DvY.js} +1 -1
  141. package/core/built/admin/assets/invite-user-modal-DfheMXs0.js +1 -0
  142. package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +14 -14
  143. package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +3 -3
  144. package/core/built/admin/assets/koenig-lexical/style.css +1 -1
  145. package/core/built/admin/assets/{koenig-lexical-_-IsVI7E.js → koenig-lexical-DBSqAuiI.js} +3 -3
  146. package/core/built/admin/assets/koenig-loader-aFQNlJlD.js +2 -0
  147. package/core/built/admin/assets/{kpi-card-DZQk_0W8.js → kpi-card-DBRMfGOW.js} +1 -1
  148. package/core/built/admin/assets/{kpi-card-DW_2y3ug.js → kpi-card-DFafD1qq.js} +1 -1
  149. package/core/built/admin/assets/{kpi-helpers-PueTKuA6.js → kpi-helpers-Cv8i8hns.js} +1 -1
  150. package/core/built/admin/assets/{kpi-tabs-CojDs-Qz.js → kpi-tabs-BJItvLYm.js} +1 -1
  151. package/core/built/admin/assets/{label-DjbT91GM.js → label-BnSCvffu.js} +1 -1
  152. package/core/built/admin/assets/label-picker-KVoo91sh.js +1 -0
  153. package/core/built/admin/assets/layout-Bjv2Ll-5.js +1 -0
  154. package/core/built/admin/assets/member-custom-fields-DDQV6QeG.js +1 -0
  155. package/core/built/admin/assets/member-detail-CdJF6Agw.js +1 -0
  156. package/core/built/admin/assets/members-DjQbq9Z2.js +4 -0
  157. package/core/built/admin/assets/moderation-AgCIEso4.js +1 -0
  158. package/core/built/admin/assets/{multi-select-combobox-B6LiRzDO.js → multi-select-combobox-BcITkUVr.js} +1 -1
  159. package/core/built/admin/assets/navigation-modal-BkT7b1M2.js +1 -0
  160. package/core/built/admin/assets/newsletter-BMMAuvgq.js +1 -0
  161. package/core/built/admin/assets/newsletter-detail-modal-0SCJ7Zpm.js +1 -0
  162. package/core/built/admin/assets/{newsletter-emails-CFeLlt4z.js → newsletter-emails-DKzwafuh.js} +1 -1
  163. package/core/built/admin/assets/newsletters-BRBb_uQC.js +1 -0
  164. package/core/built/admin/assets/note-DyGHtS9a.js +1 -0
  165. package/core/built/admin/assets/notifications-ZgWniKna.js +1 -0
  166. package/core/built/admin/assets/nql-BLpCn7qX.js +21 -0
  167. package/core/built/admin/assets/offers-container-modal-B-E8TIWr.js +1 -0
  168. package/core/built/admin/assets/{onboarding-B4YhlZ0i.js → onboarding-CzIsre-d.js} +1 -1
  169. package/core/built/admin/assets/onboarding-qg8Akovm.js +1 -0
  170. package/core/built/admin/assets/{onboarding-route-Dmc4IPm3.js → onboarding-route-CaavZulg.js} +1 -1
  171. package/core/built/admin/assets/overview-BW8GLeYi.js +1 -0
  172. package/core/built/admin/assets/overview-BkXZNzaZ.js +1 -0
  173. package/core/built/admin/assets/{page-header-BR_nbIPp.js → page-header-De0VzKBi.js} +1 -1
  174. package/core/built/admin/assets/pagemenu-B5KKCpbA.js +1 -0
  175. package/core/built/admin/assets/pages-jgaFm69d.js +1 -0
  176. package/core/built/admin/assets/pages-route-CIUAQxtY.js +1 -0
  177. package/core/built/admin/assets/papaparse.min-cQwnxGCG.js +10 -0
  178. package/core/built/admin/assets/{pintura-modal-BR9hEvS8.js → pintura-modal-BZ2J9w3n.js} +1 -1
  179. package/core/built/admin/assets/portal-frame-B6Hr9wHc.js +1 -0
  180. package/core/built/admin/assets/portal-modal-D4ceei3t.js +1 -0
  181. package/core/built/admin/assets/post-analytics-header-BYCsT0GP.js +1 -0
  182. package/core/built/admin/assets/post-analytics-ot7f6pih.js +1 -0
  183. package/core/built/admin/assets/{post-analytics-provider-CLfKGWZy.js → post-analytics-provider-Bo1gmYaP.js} +1 -1
  184. package/core/built/admin/assets/{post-share-modal-Cl0NXRJr.js → post-share-modal-C-PaYZ_e.js} +1 -1
  185. package/core/built/admin/assets/posts-DuGazgTb.js +1 -0
  186. package/core/built/admin/assets/posts-list-screen-CBGGgjjj.js +2 -0
  187. package/core/built/admin/assets/posts-route-D6xmS7Vf.js +1 -0
  188. package/core/built/admin/assets/preferences-C5YJLp74.js +5 -0
  189. package/core/built/admin/assets/{preview-modal-C-BL-F9k.js → preview-modal-BfeFqi5y.js} +1 -1
  190. package/core/built/admin/assets/profile-B8mx2yAu.js +1 -0
  191. package/core/built/admin/assets/radio-group-DczlLKOn.js +1 -0
  192. package/core/built/admin/assets/{schemas-4UPic-oD.js → schemas-DppqmpeJ.js} +1 -1
  193. package/core/built/admin/assets/select-cb0t_TAJ.js +1 -0
  194. package/core/built/admin/assets/settings-DZqxR0Da.js +1 -0
  195. package/core/built/admin/assets/settings-DvfTNdHQ.js +4 -0
  196. package/core/built/admin/assets/{settings-breadcrumbs-CyP_9zTo.js → settings-breadcrumbs-DLzbRRSt.js} +1 -1
  197. package/core/built/admin/assets/share-modal-D2-Bz1_I.js +1 -0
  198. package/core/built/admin/assets/slack-modal-DYDTUria.js +1 -0
  199. package/core/built/admin/assets/{sort-button-Cc-Z96sA.js → sort-button-VVeQjjbu.js} +1 -1
  200. package/core/built/admin/assets/{source-icon-v6PUnmyM.js → source-icon-Ck5_5Kgq.js} +1 -1
  201. package/core/built/admin/assets/stats-Rjmk5owg.js +1 -0
  202. package/core/built/admin/assets/stats-view-BGGmkmgv.js +1 -0
  203. package/core/built/admin/assets/{step-1-DSRp2vBj.js → step-1-CsaBjeN4.js} +1 -1
  204. package/core/built/admin/assets/{step-2-COqv2g0u.js → step-2-D2vnxOOM.js} +1 -1
  205. package/core/built/admin/assets/{step-3-6W1NMVQc.js → step-3-wBoLdGEb.js} +2 -2
  206. package/core/built/admin/assets/{stripe-button-D2K42Uty.js → stripe-button-CDgLz0S0.js} +1 -1
  207. package/core/built/admin/assets/stripe-connect-modal-CSjMJetP.js +1 -0
  208. package/core/built/admin/assets/{table-B2pIKjVh.js → table-Do6iQ83Q.js} +1 -1
  209. package/core/built/admin/assets/{tabs-SaW_UT-Q.js → tabs-D2yWLMp_.js} +1 -1
  210. package/core/built/admin/assets/tag-detail-BhXlOsCa.js +2 -0
  211. package/core/built/admin/assets/tags-ldukRApe.js +1 -0
  212. package/core/built/admin/assets/testimonials-modal-CtnZBJKl.js +1 -0
  213. package/core/built/admin/assets/tier-detail-modal-BOs8e_G8.js +1 -0
  214. package/core/built/admin/assets/{toggle-group-EM9WpESu.js → toggle-group-ByUJsxwD.js} +1 -1
  215. package/core/built/admin/assets/{topic-filter-DY4gNHn2.js → topic-filter-BgC3g5_v.js} +1 -1
  216. package/core/built/admin/assets/{transistor-modal-CpyPG-MH.js → transistor-modal-Drr0SNfo.js} +1 -1
  217. package/core/built/admin/assets/{trend-badge-ByMkuAuH.js → trend-badge-6ye93YAW.js} +1 -1
  218. package/core/built/admin/assets/{unsplash-modal-Cv2Q6GtY.js → unsplash-modal-p6AoQoWp.js} +1 -1
  219. package/core/built/admin/assets/{use-analytics-data-CHvjMYuT.js → use-analytics-data-CWCMAESo.js} +1 -1
  220. package/core/built/admin/assets/use-check-theme-limit-error-B8bjF-gO.css +1 -0
  221. package/core/built/admin/assets/{use-check-theme-limit-error-Qv4SVXqw.js → use-check-theme-limit-error-Cw3WQHy8.js} +1 -1
  222. package/core/built/admin/assets/use-filter-params-BIni9taJ.js +1 -0
  223. package/core/built/admin/assets/use-growth-stats-DCVG3s9w.js +1 -0
  224. package/core/built/admin/assets/{use-limiter-cwJvsNBo.js → use-limiter-D2WRRx0H.js} +1 -1
  225. package/core/built/admin/assets/{use-pintura-config-CzTfnufz.js → use-pintura-config-h-J0Lvta.js} +1 -1
  226. package/core/built/admin/assets/{use-pintura-editor-BDBXWUYq.js → use-pintura-editor-BfN1UwzH.js} +1 -1
  227. package/core/built/admin/assets/use-post-referrers-Czg47m8s.js +1 -0
  228. package/core/built/admin/assets/use-reply-chain-data-ns0caK8k.js +1 -0
  229. package/core/built/admin/assets/{use-router-history-entry-Bg6BhBQQ.js → use-router-history-entry-uldn7zJO.js} +1 -1
  230. package/core/built/admin/assets/{use-setting-group-VM7FQwMY.js → use-setting-group-DpcuCUDg.js} +1 -1
  231. package/core/built/admin/assets/use-settings-navigation-CZjGrhsp.js +1 -0
  232. package/core/built/admin/assets/{use-simple-pagination-Dum6Irbs.js → use-simple-pagination-DzJWobPR.js} +1 -1
  233. package/core/built/admin/assets/{use-staff-users-cZg4ugOF.js → use-staff-users-Csipb-O0.js} +1 -1
  234. package/core/built/admin/assets/use-tinybird-query-CSnGXzZh.js +1 -0
  235. package/core/built/admin/assets/use-tinybird-token-DTOKRR7e.js +1 -0
  236. package/core/built/admin/assets/{use-unsaved-changes-guard-BAy0RANR.js → use-unsaved-changes-guard-CBzs-KPi.js} +1 -1
  237. package/core/built/admin/assets/{use-url-input-Df5QzNa7.js → use-url-input-DFr8lCbS.js} +1 -1
  238. package/core/built/admin/assets/user-detail-modal-B_iUClI6.js +1 -0
  239. package/core/built/admin/assets/users-Cg-OeGzC.js +1 -0
  240. package/core/built/admin/assets/{virtual-list-DEx8WgiO.js → virtual-list-BW-padMe.js} +1 -1
  241. package/core/built/admin/assets/web-C1v33ehA.js +2 -0
  242. package/core/built/admin/assets/web-C4BKzn2T.js +1 -0
  243. package/core/built/admin/assets/{zapier-modal-Cw3BTBUu.js → zapier-modal-BBFfI6Ml.js} +1 -1
  244. package/core/built/admin/index.html +17 -22
  245. package/core/frontend/apps/private-blogging/lib/views/private.hbs +44 -43
  246. package/core/frontend/helpers/cancel_link.js +2 -2
  247. package/core/frontend/helpers/pagination.js +2 -2
  248. package/core/frontend/helpers/social_accounts.js +2 -2
  249. package/core/frontend/public/ghost.css +1 -1
  250. package/core/frontend/public/ghost.min.css +1 -1
  251. package/core/frontend/services/sitemap/user-map-generator.js +9 -2
  252. package/core/server/api/endpoints/index.js +2 -2
  253. package/core/server/api/endpoints/mail.js +1 -1
  254. package/core/server/api/endpoints/{member-custom-fields.js → member-metafields.js} +27 -28
  255. package/core/server/api/endpoints/members.js +4 -4
  256. package/core/server/api/endpoints/posts.js +3 -3
  257. package/core/server/api/endpoints/utils/serializers/input/members.js +4 -7
  258. package/core/server/api/endpoints/utils/serializers/output/index.js +2 -2
  259. package/core/server/api/endpoints/utils/serializers/output/{member-custom-fields.js → member-metafields.js} +2 -4
  260. package/core/server/api/endpoints/utils/serializers/output/members.js +2 -4
  261. package/core/server/api/endpoints/utils/validators/input/invitations.js +0 -5
  262. package/core/server/api/endpoints/utils/validators/input/pages.js +1 -1
  263. package/core/server/api/endpoints/utils/validators/input/posts.js +1 -1
  264. package/core/server/data/importer/importers/data/data-importer.js +3 -3
  265. package/core/server/data/migrations/utils/migrations.js +1 -1
  266. package/core/server/lib/image/image-size.js +24 -0
  267. package/core/server/lib/package-json/parse.js +2 -2
  268. package/core/server/models/member.js +6 -17
  269. package/core/server/models/post.js +2 -2
  270. package/core/server/models/relations/authors.js +2 -16
  271. package/core/server/models/user.js +9 -2
  272. package/core/server/services/auth/passwordreset.js +13 -0
  273. package/core/server/services/comments/comments-controller.js +30 -9
  274. package/core/server/services/comments/comments-service.js +55 -5
  275. package/core/server/services/content-import/csv/formula.js +12 -0
  276. package/core/server/services/content-import/csv/index.js +6 -1
  277. package/core/server/services/content-import/csv/parse.js +27 -6
  278. package/core/server/services/content-import/csv/serialize.js +13 -0
  279. package/core/server/services/content-import/import/completion-email.js +164 -0
  280. package/core/server/services/content-import/import/errors-file.js +36 -0
  281. package/core/server/services/content-import/import/importer.js +160 -53
  282. package/core/server/services/content-import/import/local-media-url.js +63 -0
  283. package/core/server/services/content-import/import/media.js +254 -0
  284. package/core/server/services/content-import/import/post-data.js +0 -1
  285. package/core/server/services/content-import/import/post-link.js +11 -0
  286. package/core/server/services/content-import/import/post-repository.js +25 -3
  287. package/core/server/services/content-import/import/reader.js +9 -2
  288. package/core/server/services/content-import/import/report.js +34 -0
  289. package/core/server/services/content-import/import/row.js +0 -2
  290. package/core/server/services/content-import/import/schema.js +1 -0
  291. package/core/server/services/content-import/import/staged-file.js +29 -0
  292. package/core/server/services/content-import/import/store.js +25 -2
  293. package/core/server/services/content-import/index.js +52 -6
  294. package/core/server/services/content-import/jobs/content-csv-import-job.js +20 -0
  295. package/core/server/services/custom-redirects/redirect-config-parser.js +2 -2
  296. package/core/server/services/custom-redirects/redirects-service.js +1 -1
  297. package/core/server/services/custom-redirects/validation.js +1 -1
  298. package/core/server/services/email-address/email-address-parser.js +30 -38
  299. package/core/server/services/email-address/email-address-service.js +37 -4
  300. package/core/server/services/email-analytics/index.js +2 -7
  301. package/core/server/services/email-service/batch-sending-service.js +0 -4
  302. package/core/server/services/email-service/email-renderer.js +14 -4
  303. package/core/server/services/email-service/email-service-wrapper.js +0 -9
  304. package/core/server/services/email-service/mailgun-email-provider.js +20 -9
  305. package/core/server/services/gifts/email-templates/gift-delivery.hbs +3 -3
  306. package/core/server/services/gifts/gift-email-service.js +0 -1
  307. package/core/server/services/gifts/index.js +3 -3
  308. package/core/server/services/gifts/jobs/index.js +4 -4
  309. package/core/server/services/indexnow-ping/indexnow-ping-service.js +2 -2
  310. package/core/server/services/invitations/accept.js +4 -2
  311. package/core/server/services/jobs/job-service.js +0 -9
  312. package/core/server/services/jobs-service/register-job-handlers.js +21 -11
  313. package/core/server/services/mail/ghost-mailer.js +4 -4
  314. package/core/server/services/member-welcome-emails/service.js +7 -7
  315. package/core/server/services/members/api.js +1 -0
  316. package/core/server/services/members/import-export/csv/parse.js +0 -7
  317. package/core/server/services/members/import-export/import/completion-email.js +2 -5
  318. package/core/server/services/members/import-export/import/row.js +0 -3
  319. package/core/server/services/members/import-export/index.js +4 -11
  320. package/core/server/services/members/jobs/clean-expired-comped-job.js +7 -0
  321. package/core/server/services/members/jobs/clean-expired-comped-task.js +145 -0
  322. package/core/server/services/members/jobs/index.js +48 -24
  323. package/core/server/services/members/members-api/controllers/member-controller.js +11 -0
  324. package/core/server/services/members/members-api/controllers/router-controller.js +3 -6
  325. package/core/server/services/members/members-api/members-api.js +4 -6
  326. package/core/server/services/members/members-api/repositories/event-repository.js +0 -4
  327. package/core/server/services/members/members-api/services/member-bread-service.js +34 -62
  328. package/core/server/services/members/members-api/services/payments-service.js +1 -1
  329. package/core/server/services/members/service.js +1 -5
  330. package/core/server/services/members-custom-fields/bindings-service.js +2 -1
  331. package/core/server/services/members-custom-fields/codec.js +3 -4
  332. package/core/server/services/members-custom-fields/definitions-service.js +62 -10
  333. package/core/server/services/members-custom-fields/filter.js +75 -93
  334. package/core/server/services/members-custom-fields/key.js +2 -1
  335. package/core/server/services/members-custom-fields/models.js +1 -1
  336. package/core/server/services/members-custom-fields/serializers.js +3 -5
  337. package/core/server/services/members-custom-fields/values-service.js +50 -28
  338. package/core/server/services/mentions/mention-controller.js +23 -21
  339. package/core/server/services/mentions/process-webmention-job.js +16 -0
  340. package/core/server/services/mentions/service.js +8 -4
  341. package/core/server/services/route-settings/validation-errors.js +1 -1
  342. package/core/server/services/route-settings/yaml-parser.js +1 -1
  343. package/core/server/services/settings/settings-service.js +1 -8
  344. package/core/server/services/settings-helpers/settings-helpers.js +4 -6
  345. package/core/server/services/slack-ping/slack-ping-service.js +1 -1
  346. package/core/server/services/staff/staff-service-emails.js +2 -2
  347. package/core/server/services/stripe/config.js +14 -8
  348. package/core/server/services/stripe/service.js +10 -1
  349. package/core/server/services/stripe/services/checkout/completed-session.js +2 -2
  350. package/core/server/services/stripe/services/checkout/session-options.js +18 -15
  351. package/core/server/services/stripe/services/webhook/checkout-session-event-service.js +26 -5
  352. package/core/server/services/stripe/stripe-api.js +2 -0
  353. package/core/server/services/stripe/stripe-service.js +20 -10
  354. package/core/server/services/stripe/webhook-controller.js +10 -0
  355. package/core/server/services/tier-checkout-config/codec.js +9 -5
  356. package/core/server/services/tier-checkout-config/models.js +9 -3
  357. package/core/server/services/tier-checkout-config/queries.js +4 -4
  358. package/core/server/services/tier-checkout-config/serializers.js +16 -10
  359. package/core/server/services/tier-checkout-config/service.js +13 -12
  360. package/core/server/services/update-check/index.js +13 -13
  361. package/core/server/services/update-check/jobs/update-check-job.js +7 -0
  362. package/core/server/services/update-check/update-check-service.js +2 -2
  363. package/core/server/web/admin/controller.js +1 -1
  364. package/core/server/web/api/endpoints/admin/routes.js +19 -16
  365. package/core/shared/config/env/config.testing-mysql.json +1 -1
  366. package/core/shared/labs.js +5 -2
  367. package/package.json +24 -23
  368. package/pnpm-lock.yaml +704 -69
  369. package/pnpm-workspace.yaml +8 -5
  370. package/components/tryghost-kg-default-nodes-2.2.0.tgz +0 -0
  371. package/core/built/admin/assets/Combination-5fYEzgbs.js +0 -41
  372. package/core/built/admin/assets/account-migration-DRhAehfw.js +0 -1
  373. package/core/built/admin/assets/activitypub/inbox-BluD2ucT.js +0 -1284
  374. package/core/built/admin/assets/activitypub/label-FHSh6ZAw.js +0 -16
  375. package/core/built/admin/assets/activitypub/layout-Cq4NG0Xr.js +0 -1
  376. package/core/built/admin/assets/activitypub/settings-DQDkr06X.js +0 -315
  377. package/core/built/admin/assets/add-integration-modal-BC0jExDZ.js +0 -1
  378. package/core/built/admin/assets/add-newsletter-modal-DchTkA7l.js +0 -1
  379. package/core/built/admin/assets/add-recommendation-modal-DMvaJZKp.js +0 -1
  380. package/core/built/admin/assets/alert-dialog-QhXzdHfc.js +0 -1
  381. package/core/built/admin/assets/analytics-No1DDY3A.js +0 -1
  382. package/core/built/admin/assets/automations-DpUNUdcZ.js +0 -1
  383. package/core/built/admin/assets/bluesky-sharing-Cjrv_f62.js +0 -1
  384. package/core/built/admin/assets/color-picker-BTY_NdEm.js +0 -3
  385. package/core/built/admin/assets/color-picker-field-CPlkzOH0.js +0 -1
  386. package/core/built/admin/assets/combobox-DrMtv_4P.js +0 -1
  387. package/core/built/admin/assets/command-ZdgYJpoI.js +0 -1
  388. package/core/built/admin/assets/comments-kidj60-h.js +0 -1
  389. package/core/built/admin/assets/confirmation-context-BhbmQQEl.js +0 -1
  390. package/core/built/admin/assets/custom-field-type-option-CsGIZk1J.js +0 -10
  391. package/core/built/admin/assets/custom-integration-modal-BY37O_9X.js +0 -1
  392. package/core/built/admin/assets/design-and-theme-modal-DUSKM4uC.js +0 -22
  393. package/core/built/admin/assets/dialog-B44iRwlc.js +0 -1
  394. package/core/built/admin/assets/dirty-confirm-dialog-BxgQgQ6H.js +0 -1
  395. package/core/built/admin/assets/dist-Cy8tfrp_.js +0 -1
  396. package/core/built/admin/assets/domain-Ca6KhoQt.js +0 -1
  397. package/core/built/admin/assets/dropzone-Bb-5zQTk.js +0 -5
  398. package/core/built/admin/assets/edit-profile-BdupLlus.js +0 -1
  399. package/core/built/admin/assets/editor-BP883Lpn.js +0 -8
  400. package/core/built/admin/assets/explore-FB-CimXw.js +0 -1
  401. package/core/built/admin/assets/feed-C1GxsmI2.js +0 -1
  402. package/core/built/admin/assets/filter-sources-D5n5bFA2.js +0 -1
  403. package/core/built/admin/assets/filters-DJEzkMUK.js +0 -1
  404. package/core/built/admin/assets/filters-MZXvdH5D.js +0 -1
  405. package/core/built/admin/assets/first-promoter-modal-CGTGLCr5.js +0 -1
  406. package/core/built/admin/assets/gift-link-modal-B6v0tnRN.js +0 -1
  407. package/core/built/admin/assets/growth-BGAJD1rs.js +0 -3
  408. package/core/built/admin/assets/growth-D6mhcx3q.js +0 -1
  409. package/core/built/admin/assets/history-modal-iKwUY3XR.js +0 -1
  410. package/core/built/admin/assets/index-DjQe-e5s.js +0 -4
  411. package/core/built/admin/assets/index-Dqf2x-ry.css +0 -1
  412. package/core/built/admin/assets/index.es-VihPwfeH.js +0 -1
  413. package/core/built/admin/assets/input--W-rCTrX.js +0 -1
  414. package/core/built/admin/assets/invite-user-modal-MdImLCaJ.js +0 -1
  415. package/core/built/admin/assets/koenig-loader-DYZpm6El.js +0 -2
  416. package/core/built/admin/assets/label-picker-cB51xl1r.js +0 -1
  417. package/core/built/admin/assets/layout-c_B_1hax.js +0 -1
  418. package/core/built/admin/assets/loading-indicator-BpFWTVgh.js +0 -1
  419. package/core/built/admin/assets/member-custom-fields-qs0dIkxM.js +0 -1
  420. package/core/built/admin/assets/member-detail-B6uec2a6.js +0 -1
  421. package/core/built/admin/assets/members-BQF3CqhI.js +0 -2
  422. package/core/built/admin/assets/moderation-DY4wF1Q3.js +0 -1
  423. package/core/built/admin/assets/navigation-modal-DX-gNF3X.js +0 -1
  424. package/core/built/admin/assets/newsletter-CyQA7m3m.js +0 -1
  425. package/core/built/admin/assets/newsletter-detail-modal-BDrptuxn.js +0 -1
  426. package/core/built/admin/assets/newsletters-DXuNmC42.js +0 -1
  427. package/core/built/admin/assets/note-Cgo2LCJ6.js +0 -1
  428. package/core/built/admin/assets/notifications-BC50AMku.js +0 -1
  429. package/core/built/admin/assets/offers-container-modal-DWycIMzT.js +0 -1
  430. package/core/built/admin/assets/onboarding-DGQuV7Ew.js +0 -1
  431. package/core/built/admin/assets/overview-CVbFtn-k.js +0 -1
  432. package/core/built/admin/assets/overview-YKj7SZaK.js +0 -1
  433. package/core/built/admin/assets/pages-B6vr9F_D.js +0 -1
  434. package/core/built/admin/assets/popover-CCy0h5rq.js +0 -1
  435. package/core/built/admin/assets/portal-frame-dc4XKr0e.js +0 -1
  436. package/core/built/admin/assets/portal-modal-BvvdF_B9.js +0 -1
  437. package/core/built/admin/assets/post-analytics-DX470WRG.js +0 -1
  438. package/core/built/admin/assets/post-analytics-header-CXpJmdDv.js +0 -1
  439. package/core/built/admin/assets/posts-KY3aUhVV.js +0 -1
  440. package/core/built/admin/assets/preferences-DO0UUWFp.js +0 -5
  441. package/core/built/admin/assets/profile-CxT-0l4d.js +0 -1
  442. package/core/built/admin/assets/radio-group-Bgz60i81.js +0 -1
  443. package/core/built/admin/assets/select-DuDUFdPq.js +0 -1
  444. package/core/built/admin/assets/settings-BjCii7BM.js +0 -1
  445. package/core/built/admin/assets/settings-b8kNzZSQ.js +0 -4
  446. package/core/built/admin/assets/share-modal-BV70mr9k.js +0 -1
  447. package/core/built/admin/assets/shim-ClF_m5ux.js +0 -1
  448. package/core/built/admin/assets/slack-modal-Be2_KK-z.js +0 -1
  449. package/core/built/admin/assets/stats-C4reGh9O.js +0 -1
  450. package/core/built/admin/assets/stats-view-DP9pQ62k.js +0 -1
  451. package/core/built/admin/assets/stripe-connect-modal-Z-UT_BGc.js +0 -1
  452. package/core/built/admin/assets/tag-detail-Dc0nTOtU.js +0 -2
  453. package/core/built/admin/assets/tags-BLaXBwnb.js +0 -1
  454. package/core/built/admin/assets/testimonials-modal-sFwRnNLh.js +0 -1
  455. package/core/built/admin/assets/tier-detail-modal-BCFpWwUS.js +0 -1
  456. package/core/built/admin/assets/use-filter-params-CAvfDvf1.js +0 -1
  457. package/core/built/admin/assets/use-growth-stats-D6mZXGhK.js +0 -1
  458. package/core/built/admin/assets/use-post-referrers-DbY-mzci.js +0 -1
  459. package/core/built/admin/assets/use-reply-chain-data-BeQwz8oF.js +0 -1
  460. package/core/built/admin/assets/use-settings-navigation-BbrSUVcf.js +0 -1
  461. package/core/built/admin/assets/use-tinybird-query-B1IMyAcv.js +0 -39
  462. package/core/built/admin/assets/use-tinybird-token-Bow0Zwn8.js +0 -1
  463. package/core/built/admin/assets/user-detail-modal-yipSoQfv.js +0 -1
  464. package/core/built/admin/assets/users-5msE1WMs.js +0 -1
  465. package/core/built/admin/assets/web-CKcXAu86.js +0 -1
  466. package/core/built/admin/assets/web-DR4TqM3E.js +0 -2
  467. package/core/server/services/jobs/worker-model-event-bridge.js +0 -149
  468. package/core/server/services/members/jobs/clean-expired-comped.js +0 -132
  469. package/core/server/services/stripe/services/checkout/allowed-countries.js +0 -267
  470. package/core/server/services/stripe/services/checkout/field-ports.js +0 -34
  471. package/core/server/services/tier-checkout-config/destinations.js +0 -17
  472. package/core/server/services/update-check/run-update-check.js +0 -63
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.urlForImportedPost = urlForImportedPost;
4
+ function urlForImportedPost(post, options) {
5
+ const data = post.toJSON();
6
+ if (data.status === 'draft') {
7
+ const editorType = data.type === 'page' ? 'page' : 'post';
8
+ return new URL(`#/editor/${editorType}/${post.id}`, options.adminUrl).href;
9
+ }
10
+ return options.publishedUrl(post);
11
+ }
@@ -12,7 +12,11 @@ class BookshelfPostsRepository {
12
12
  write(data, options, metadata = {}) {
13
13
  return this._models.Base.transaction(async (transacting) => {
14
14
  const writeOptions = { ...options, transacting };
15
- const lookupOptions = { ...writeOptions, forUpdate: true };
15
+ const lookupOptions = {
16
+ ...writeOptions,
17
+ forUpdate: true,
18
+ ...(metadata.runTagName ? { withRelated: ['tags'] } : {}),
19
+ };
16
20
  let existingMatch;
17
21
  if (data.comment_id) {
18
22
  const existing = await this._models.Post.findOne({ comment_id: data.comment_id, status: 'all' }, lookupOptions);
@@ -20,6 +24,7 @@ class BookshelfPostsRepository {
20
24
  existingMatch = {
21
25
  post: existing,
22
26
  duplicateReason: `A post with the source ID "${data.comment_id}" already exists.`,
27
+ matchedBy: 'source_id',
23
28
  };
24
29
  }
25
30
  }
@@ -29,13 +34,18 @@ class BookshelfPostsRepository {
29
34
  existingMatch = {
30
35
  post: existing,
31
36
  duplicateReason: `A post with the slug "${data.slug}" already exists.`,
37
+ matchedBy: 'slug',
32
38
  };
33
39
  }
34
40
  }
35
41
  if (existingMatch) {
36
- const { post: existing, duplicateReason } = existingMatch;
42
+ const { post: existing, duplicateReason, matchedBy } = existingMatch;
43
+ const duplicate = {
44
+ origin: hasRunTag(existing, metadata.runTagName) ? 'this_import' : 'pre_existing',
45
+ matchedBy,
46
+ };
37
47
  if (!metadata.sourceUpdatedAt) {
38
- return { status: 'skipped', reason: duplicateReason };
48
+ return { status: 'skipped', reason: duplicateReason, duplicate };
39
49
  }
40
50
  const incomingInstant = new Date(metadata.sourceUpdatedAt).getTime();
41
51
  const storedUpdatedAt = existing.toJSON().updated_at;
@@ -47,6 +57,7 @@ class BookshelfPostsRepository {
47
57
  return {
48
58
  status: 'skipped',
49
59
  reason: 'The existing post is newer than or as recent as the imported row.',
60
+ duplicate,
50
61
  };
51
62
  }
52
63
  // Ghost's collision plugin treats updated_at as the client's version token.
@@ -76,3 +87,14 @@ class BookshelfPostsRepository {
76
87
  }
77
88
  }
78
89
  exports.BookshelfPostsRepository = BookshelfPostsRepository;
90
+ function hasRunTag(post, runTagName) {
91
+ if (!runTagName) {
92
+ return false;
93
+ }
94
+ const tags = post.toJSON().tags;
95
+ return (Array.isArray(tags) &&
96
+ tags.some((tag) => typeof tag === 'object' &&
97
+ tag !== null &&
98
+ 'name' in tag &&
99
+ tag.name === runTagName));
100
+ }
@@ -5,6 +5,13 @@ const csv_1 = require("../csv");
5
5
  const row_1 = require("./row");
6
6
  const FIELD_BY_HEADER = Object.fromEntries(row_1.EDITORIAL_POST_FIELDS.map((field) => [field, field]));
7
7
  async function readPostRows(path, mapping) {
8
- const rows = await (0, csv_1.parse)(path, mapping ?? FIELD_BY_HEADER);
9
- return rows.map((row) => row_1.postImportRowSchema.parse(row));
8
+ const parsed = await (0, csv_1.parseWithSource)(path, mapping ?? FIELD_BY_HEADER);
9
+ return {
10
+ columns: parsed.columns,
11
+ rows: parsed.rows.map(({ data, source, line }) => ({
12
+ data: row_1.postImportRowSchema.parse(data),
13
+ source,
14
+ line,
15
+ })),
16
+ };
10
17
  }
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = buildImportReport;
4
+ const csv_1 = require("../csv");
5
+ const REPORT_COLUMNS = [
6
+ 'line',
7
+ 'title',
8
+ 'outcome',
9
+ 'reason',
10
+ 'duplicate_origin',
11
+ 'matched_by',
12
+ 'warnings',
13
+ 'media_failures',
14
+ 'post_url',
15
+ ];
16
+ function formatMediaFailures(row) {
17
+ return (row.mediaFailures?.map(({ sourceUrl, reason }) => `${sourceUrl}: ${reason}`).join('\n') ?? '');
18
+ }
19
+ function buildImportReport(run) {
20
+ if (!run.rows.length) {
21
+ return undefined;
22
+ }
23
+ return (0, csv_1.serialize)(run.rows.map((row) => ({
24
+ line: row.line,
25
+ title: row.title ?? '',
26
+ outcome: row.duplicate ? 'duplicate' : row.status,
27
+ reason: row.reason ?? '',
28
+ duplicate_origin: row.duplicate?.origin ?? '',
29
+ matched_by: row.duplicate?.matchedBy ?? '',
30
+ warnings: row.warnings?.join('\n') ?? '',
31
+ media_failures: formatMediaFailures(row),
32
+ post_url: row.url ?? '',
33
+ })), { columns: REPORT_COLUMNS });
34
+ }
@@ -36,7 +36,6 @@ exports.EDITORIAL_POST_FIELDS = [
36
36
  'custom_template',
37
37
  'codeinjection_head',
38
38
  'codeinjection_foot',
39
- 'frontmatter',
40
39
  ];
41
40
  // An empty cell (or the literal 'undefined') reads as absent, not as a value.
42
41
  const optionalCell = zod_1.z
@@ -82,7 +81,6 @@ exports.postImportRowSchema = zod_1.z
82
81
  custom_template: optionalCell,
83
82
  codeinjection_head: optionalCell,
84
83
  codeinjection_foot: optionalCell,
85
- frontmatter: optionalCell,
86
84
  })
87
85
  .loose();
88
86
  const ENUM_FIELDS = {
@@ -26,4 +26,5 @@ exports.importRequestSchema = zod_1.z.object({
26
26
  filePath: zod_1.z.string().min(1),
27
27
  fileName: zod_1.z.string().min(1),
28
28
  mapping: exports.mappingSchema.optional(),
29
+ requestUserEmail: zod_1.z.string().email().nullable().optional(),
29
30
  });
@@ -0,0 +1,29 @@
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.createImportFileStager = createImportFileStager;
7
+ const node_crypto_1 = __importDefault(require("node:crypto"));
8
+ const node_os_1 = __importDefault(require("node:os"));
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const fs_extra_1 = __importDefault(require("fs-extra"));
11
+ function createImportFileStager() {
12
+ return {
13
+ async stage({ filePath, fileName }) {
14
+ const stagedPath = node_path_1.default.join(node_os_1.default.tmpdir(), `content-csv-import-${node_crypto_1.default.randomUUID()}`);
15
+ try {
16
+ await fs_extra_1.default.copyFile(filePath, stagedPath, fs_extra_1.default.constants.COPYFILE_EXCL);
17
+ await fs_extra_1.default.chmod(stagedPath, 0o600);
18
+ }
19
+ catch (error) {
20
+ await fs_extra_1.default.remove(stagedPath).catch(() => { });
21
+ throw error;
22
+ }
23
+ return { path: stagedPath, name: fileName };
24
+ },
25
+ async remove(file) {
26
+ await fs_extra_1.default.remove(file.path);
27
+ },
28
+ };
29
+ }
@@ -10,17 +10,19 @@ const MAX_RUN_AGE_MS = 60 * 60 * 1000;
10
10
  class ImportRunStore {
11
11
  // Insertion-ordered, so count-eviction drops the oldest run first.
12
12
  _runs = new Map();
13
+ _settledWaiters = new Set();
13
14
  _now;
14
15
  constructor({ now = () => new Date() } = {}) {
15
16
  this._now = now;
16
17
  }
17
- create(id, total) {
18
+ create(id, total, sourceColumns = []) {
18
19
  this.evict();
19
20
  const run = {
20
21
  id,
21
22
  status: 'running',
22
23
  startedAt: this._now(),
23
24
  total,
25
+ sourceColumns,
24
26
  rows: [],
25
27
  };
26
28
  this._runs.set(id, run);
@@ -47,10 +49,31 @@ class ImportRunStore {
47
49
  get(id) {
48
50
  return this._runs.get(id);
49
51
  }
52
+ release(id) {
53
+ this._runs.delete(id);
54
+ this.resolveSettledWaiters();
55
+ }
56
+ allSettled() {
57
+ if (this._runs.size === 0) {
58
+ return Promise.resolve();
59
+ }
60
+ return new Promise((resolve) => {
61
+ this._settledWaiters.add(resolve);
62
+ });
63
+ }
64
+ resolveSettledWaiters() {
65
+ if (this._runs.size > 0) {
66
+ return;
67
+ }
68
+ for (const resolve of this._settledWaiters) {
69
+ resolve();
70
+ }
71
+ this._settledWaiters.clear();
72
+ }
50
73
  // A running run is never evicted, whatever its age: the job holds only the runId,
51
74
  // so evicting mid-import would silently turn its record()/finish() calls into
52
75
  // no-ops and lose the report. The count cap can briefly overshoot while several
53
- // imports run at once; the inline job queue bounds how many that can be.
76
+ // imports run at once; the jobs backend bounds how many that can be.
54
77
  evict() {
55
78
  const cutoff = this._now().getTime() - MAX_RUN_AGE_MS;
56
79
  for (const [id, run] of this._runs) {
@@ -5,13 +5,21 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.init = init;
7
7
  exports.importCSV = importCSV;
8
+ exports.handleJob = handleJob;
9
+ exports.allSettled = allSettled;
8
10
  const zod_1 = require("zod");
9
11
  const importer_1 = __importDefault(require("./import/importer"));
12
+ const completion_email_1 = __importDefault(require("./import/completion-email"));
10
13
  const post_repository_1 = require("./import/post-repository");
11
14
  const reader_1 = __importDefault(require("./import/reader"));
12
15
  const schema_1 = require("./import/schema");
13
16
  const store_1 = require("./import/store");
14
17
  const source_1 = require("./import/source");
18
+ const media_1 = require("./import/media");
19
+ const local_media_url_1 = require("./import/local-media-url");
20
+ const post_link_1 = require("./import/post-link");
21
+ const staged_file_1 = require("./import/staged-file");
22
+ const jobs_service_1 = require("../jobs-service");
15
23
  // The request is built from HTTP upload metadata, so it is validated at the
16
24
  // service boundary rather than trusted.
17
25
  // A junk timezone setting falls back to UTC rather than mis-stamping the batch tag.
@@ -26,12 +34,16 @@ function makeImporter() {
26
34
  // are guaranteed loaded.
27
35
  const models = require('../../models');
28
36
  const lexicalLib = require('../../lib/lexical');
29
- const jobsService = require('../jobs');
30
37
  const settingsCache = require('../../../shared/settings-cache');
31
38
  const urlService = require('../url');
39
+ const urlUtils = require('../../../shared/url-utils').default;
40
+ const mediaInlinerService = require('../media-inliner');
41
+ const config = require('../../../shared/config');
32
42
  const ObjectID = require('bson-objectid').default;
33
- // Inline jobs never reach the job manager's Sentry handler, which is wired to the
34
- // offloaded worker path only, so a throw here would be seen by nobody.
43
+ const { GhostMailer } = require('../mail');
44
+ const ghostMailer = new GhostMailer();
45
+ // Row aggregates and best-effort cleanup are intentionally reported without
46
+ // failing a run. Fatal handler errors are reported by the class-based jobs service.
35
47
  const report = (error) => {
36
48
  try {
37
49
  logging.error({ event: { name: 'content.import.error' }, err: error }, '[Background Job] content-import error');
@@ -41,6 +53,10 @@ function makeImporter() {
41
53
  // Callers report from catch blocks, so this must not throw.
42
54
  }
43
55
  };
56
+ const email = {
57
+ send: (run, recipient) => ghostMailer.send((0, completion_email_1.default)(run, recipient, urlUtils.urlFor('admin', true))),
58
+ getDefaultRecipient: async () => (await models.User.getOwnerUser()).get('email'),
59
+ };
44
60
  return new importer_1.default({
45
61
  readRows: reader_1.default,
46
62
  prepareSource: source_1.prepareImportSource,
@@ -48,11 +64,27 @@ function makeImporter() {
48
64
  getHtmlToLexical: () => lexicalLib.htmlToLexicalConverter,
49
65
  getMarkdownToHtml: () => require('@tryghost/kg-markdown-html-renderer').render,
50
66
  getCleanHTML: () => require('@tryghost/mg-clean-html').cleanHTML,
51
- addJob: jobsService.addJob.bind(jobsService),
67
+ createMediaInliner: () => new media_1.PostMediaInliner({
68
+ media: mediaInlinerService.getInstance(),
69
+ isLocalMediaUrl: (sourceUrl) => (0, local_media_url_1.isLocalMediaUrl)(sourceUrl, {
70
+ siteUrl: config.getSiteUrl(),
71
+ subdir: config.getSubdir(),
72
+ assetBaseUrls: [
73
+ config.get('urls:image'),
74
+ config.get('urls:media'),
75
+ config.get('urls:files'),
76
+ ],
77
+ }),
78
+ }),
79
+ email,
80
+ dispatchJob: (job) => (0, jobs_service_1.getInstance)().dispatch(job),
81
+ fileStager: (0, staged_file_1.createImportFileStager)(),
52
82
  report,
53
83
  store: new store_1.ImportRunStore(),
54
- // Degrades to the 404 URL for a post the URL service cannot route yet (e.g. a draft).
55
- urlForPost: (post) => urlService.getUrlForResource({ ...post.toJSON(), type: 'posts' }, { absolute: true }),
84
+ urlForPost: (post) => (0, post_link_1.urlForImportedPost)(post, {
85
+ adminUrl: urlUtils.urlFor('admin', true),
86
+ publishedUrl: (publishedPost) => urlService.getUrlForResource({ ...publishedPost.toJSON(), type: 'posts' }, { absolute: true }),
87
+ }),
56
88
  newRunId: () => new ObjectID().toHexString(),
57
89
  getTimezone: () => timezoneSchema.parse(settingsCache.get('timezone')),
58
90
  });
@@ -75,3 +107,17 @@ function importCSV(request) {
75
107
  }
76
108
  return importer.importCSV(parsedRequest.data);
77
109
  }
110
+ function handleJob(job) {
111
+ if (!importer) {
112
+ throw new errors.InternalServerError({ message: 'Content import service used before init' });
113
+ }
114
+ return importer.handle(job);
115
+ }
116
+ // Test-facing parity with the legacy inline queue while the import run store
117
+ // remains in memory. M8 removes this together with that store.
118
+ function allSettled() {
119
+ if (!importer) {
120
+ return Promise.resolve();
121
+ }
122
+ return importer.allSettled();
123
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const job_1 = require("../../jobs-service/job");
4
+ class ContentCSVImportJob extends job_1.Job {
5
+ static type = 'content-csv-import';
6
+ importId;
7
+ file;
8
+ mapping;
9
+ importTagNames;
10
+ emailRecipient;
11
+ constructor(data) {
12
+ super();
13
+ this.importId = data.importId;
14
+ this.file = data.file;
15
+ this.mapping = data.mapping;
16
+ this.importTagNames = data.importTagNames;
17
+ this.emailRecipient = data.emailRecipient;
18
+ }
19
+ }
20
+ exports.default = ContentCSVImportJob;
@@ -45,7 +45,7 @@ const messages = {
45
45
  jsonInvalid: 'JSON input must be an array of redirect objects.',
46
46
  yamlParse: 'Could not parse YAML: {context}.',
47
47
  yamlInvalid: 'YAML input is invalid. Check the contents of your YAML file.',
48
- redirectsHelp: 'https://ghost.org/docs/themes/routing/#redirects',
48
+ redirectsHelp: 'https://docs.ghost.org/themes/routing/#redirects',
49
49
  };
50
50
  const parseJson = (content) => {
51
51
  let parsed;
@@ -124,7 +124,7 @@ const parseYaml = (content) => {
124
124
  exports.parseYaml = parseYaml;
125
125
  // Round-trips through parseYaml to []. Avoids a "download → save →
126
126
  // re-upload throws on empty body" footgun on fresh installs.
127
- const EMPTY_DOWNLOAD_TEMPLATE = '# See https://ghost.org/docs/themes/routing/#redirects\n301: {}\n302: {}\n';
127
+ const EMPTY_DOWNLOAD_TEMPLATE = '# See https://docs.ghost.org/themes/routing/#redirects\n301: {}\n302: {}\n';
128
128
  const serializeToYaml = (redirects) => {
129
129
  const permanent = [];
130
130
  const temporary = [];
@@ -44,7 +44,7 @@ const dynamic_redirect_manager_1 = __importDefault(require("../lib/dynamic-redir
44
44
  const errify_1 = require("../../../shared/errify");
45
45
  const messages = {
46
46
  redirectsRegister: 'Could not register custom redirects.',
47
- redirectsHelp: 'https://ghost.org/docs/themes/routing/#redirects',
47
+ redirectsHelp: 'https://docs.ghost.org/themes/routing/#redirects',
48
48
  skippedInvalidRedirect: 'Skipped invalid redirect: {context}',
49
49
  rejectedRedirect: 'Could not register redirect: {from} -> {to}',
50
50
  allRedirectsSkipped: 'None of the {total} redirect(s) in the store could be activated. Check the logged errors above.',
@@ -5,7 +5,7 @@ const errors = require('@tryghost/errors');
5
5
  const messages = {
6
6
  redirectsWrongFormat: 'Incorrect redirects file format.',
7
7
  invalidRedirectsFromRegex: 'Incorrect RegEx in redirects file.',
8
- redirectsHelp: 'https://ghost.org/docs/themes/routing/#redirects',
8
+ redirectsHelp: 'https://docs.ghost.org/themes/routing/#redirects',
9
9
  };
10
10
 
11
11
  /**
@@ -1,53 +1,45 @@
1
- const addressparser = require('nodemailer/lib/addressparser');
2
-
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.stringify = exports.parse = void 0;
7
+ const addressparser_1 = __importDefault(require("nodemailer/lib/addressparser"));
3
8
  /**
4
- * @typedef {Object} EmailAddress
5
- * @property {string} address - The email address
6
- * @property {string} [name] - Optional name associated with the email
9
+ * Parse an email string into an EmailAddress object
10
+ * @param email Email string to parse
11
+ * @returns Parsed email or null if invalid
7
12
  */
8
-
9
- module.exports = class EmailAddressParser {
10
- /**
11
- * Parse an email string into an EmailAddress object
12
- * @param {string} email - Email string to parse
13
- * @returns {EmailAddress|null} Parsed email or null if invalid
14
- */
15
- static parse(email) {
13
+ const parse = (email) => {
16
14
  if (!email || typeof email !== 'string' || !email.length) {
17
- return null;
15
+ return null;
18
16
  }
19
-
20
- const parsed = addressparser(email);
21
-
17
+ const parsed = (0, addressparser_1.default)(email);
22
18
  if (parsed.length !== 1) {
23
- return null;
19
+ return null;
24
20
  }
25
21
  const first = parsed[0];
26
-
27
22
  // Check first has a group property
28
23
  if ('group' in first) {
29
- // Unsupported format
30
- return null;
24
+ // Unsupported format
25
+ return null;
31
26
  }
32
-
33
27
  return {
34
- address: first.address,
35
- name: first.name || undefined,
28
+ address: first.address,
29
+ name: first.name || undefined,
36
30
  };
37
- }
38
-
39
- /**
40
- * Convert an EmailAddress object to a string representation
41
- * @param {EmailAddress} email - Email object to stringify
42
- * @returns {string} String representation of the email
43
- */
44
- static stringify(email) {
31
+ };
32
+ exports.parse = parse;
33
+ /**
34
+ * Convert an EmailAddress object to a string representation
35
+ * @param email Email object to stringify
36
+ * @returns String representation of the email
37
+ */
38
+ const stringify = (email) => {
45
39
  if (!email.name) {
46
- return email.address;
40
+ return email.address;
47
41
  }
48
-
49
42
  const escapedName = email.name.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
50
-
51
43
  /**
52
44
  * https://linear.app/ghost/issue/ONC-969
53
45
  *
@@ -65,8 +57,8 @@ module.exports = class EmailAddressParser {
65
57
  * We remove these characters from the name.
66
58
  */
67
59
  const nameCleanedForGmail = escapedName
68
- .replace(/[\u2705\u2713\u2714\u2611\u{1F5F8}]/gu, '')
69
- .trim();
60
+ .replace(/[\u2705\u2713\u2714\u2611\u{1F5F8}]/gu, '')
61
+ .trim();
70
62
  return `"${nameCleanedForGmail}" <${email.address}>`;
71
- }
72
63
  };
64
+ exports.stringify = stringify;
@@ -1,11 +1,44 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
37
  };
5
38
  Object.defineProperty(exports, "__esModule", { value: true });
6
39
  exports.EmailAddressService = void 0;
7
40
  const logging_1 = __importDefault(require("@tryghost/logging"));
8
- const email_address_parser_js_1 = __importDefault(require("./email-address-parser.js"));
41
+ const emailAddressParser = __importStar(require("./email-address-parser"));
9
42
  class EmailAddressService {
10
43
  #getManagedEmailEnabled;
11
44
  #getSendingDomain;
@@ -25,7 +58,7 @@ class EmailAddressService {
25
58
  if (!fallbackAddress) {
26
59
  return null;
27
60
  }
28
- return email_address_parser_js_1.default.parse(fallbackAddress);
61
+ return emailAddressParser.parse(fallbackAddress);
29
62
  };
30
63
  this.#isValidEmailAddress = dependencies.isValidEmailAddress;
31
64
  }
@@ -54,8 +87,8 @@ class EmailAddressService {
54
87
  return transformed.from.address;
55
88
  }
56
89
  getAddressFromString(from, replyTo) {
57
- const parsedFrom = email_address_parser_js_1.default.parse(from);
58
- const parsedReplyTo = replyTo ? email_address_parser_js_1.default.parse(replyTo) : undefined;
90
+ const parsedFrom = emailAddressParser.parse(from);
91
+ const parsedReplyTo = replyTo ? emailAddressParser.parse(replyTo) : undefined;
59
92
  return this.getAddress({
60
93
  from: parsedFrom ?? this.defaultFromEmail,
61
94
  replyTo: parsedReplyTo ?? undefined,
@@ -20,7 +20,6 @@ const constants_1 = require("../member-welcome-emails/constants");
20
20
  const automation_email_analytics_batch_processor_1 = require("./automation-email-analytics-batch-processor");
21
21
  const gift_email_analytics_batch_processor_1 = require("./gift-email-analytics-batch-processor");
22
22
  const start_gift_email_analytics_job_event_1 = require("./events/start-gift-email-analytics-job-event");
23
- const gifts_1 = require("../gifts");
24
23
  const constants_2 = require("../gifts/constants");
25
24
  exports.newsletters = new email_analytics_service_wrapper_1.EmailAnalyticsServiceWrapper({
26
25
  logName: 'newsletters',
@@ -31,7 +30,7 @@ exports.automations = new email_analytics_service_wrapper_1.EmailAnalyticsServic
31
30
  exports.gifts = new email_analytics_service_wrapper_1.EmailAnalyticsServiceWrapper({
32
31
  logName: 'gifts',
33
32
  });
34
- const init = ({ automationsApi, config, db, domainEvents, emailSuppressionList, membersRepository, models: { Email, EmailRecipientFailure, EmailSpamComplaintEvent }, metrics, prometheusClient, settingsCache, }) => {
33
+ const init = ({ automationsApi, config, db, domainEvents, emailSuppressionList, giftDeliveryService, membersRepository, models: { Email, EmailRecipientFailure, EmailSpamComplaintEvent }, metrics, prometheusClient, settingsCache, }) => {
35
34
  const queries = new queries_1.Queries(db.knex);
36
35
  const newsletterEmailEventProcessor = new email_event_processor_1.default({
37
36
  domainEvents,
@@ -133,11 +132,7 @@ const init = ({ automationsApi, config, db, domainEvents, emailSuppressionList,
133
132
  },
134
133
  metrics,
135
134
  settingsCache,
136
- createEventProcessor: () => new gift_email_analytics_batch_processor_1.GiftEmailAnalyticsBatchProcessor({
137
- giftDeliveryService: {
138
- recordOutcome: (data) => gifts_1.deliveryService.recordOutcome(data),
139
- },
140
- }),
135
+ createEventProcessor: () => new gift_email_analytics_batch_processor_1.GiftEmailAnalyticsBatchProcessor({ giftDeliveryService }),
141
136
  });
142
137
  };
143
138
  exports.init = init;
@@ -33,7 +33,6 @@ class BatchSendingService {
33
33
  #models;
34
34
  #db;
35
35
  #sentry;
36
- #debugStorageFilePath;
37
36
  #getRequiredUrlRelations;
38
37
  #shuttingDown = false;
39
38
  #inFlight = new Set();
@@ -68,7 +67,6 @@ class BatchSendingService {
68
67
  * @param {object} [dependencies.BEFORE_RETRY_CONFIG]
69
68
  * @param {object} [dependencies.AFTER_RETRY_CONFIG]
70
69
  * @param {object} [dependencies.MAILGUN_API_RETRY_CONFIG]
71
- * @param {string} [dependencies.debugStorageFilePath]
72
70
  */
73
71
  constructor({
74
72
  emailRenderer,
@@ -83,7 +81,6 @@ class BatchSendingService {
83
81
  BEFORE_RETRY_CONFIG,
84
82
  AFTER_RETRY_CONFIG,
85
83
  MAILGUN_API_RETRY_CONFIG,
86
- debugStorageFilePath,
87
84
  }) {
88
85
  this.#emailRenderer = emailRenderer;
89
86
  this.#sendingService = sendingService;
@@ -93,7 +90,6 @@ class BatchSendingService {
93
90
  this.#models = models;
94
91
  this.#db = db;
95
92
  this.#sentry = sentry;
96
- this.#debugStorageFilePath = debugStorageFilePath;
97
93
  this.#getRequiredUrlRelations = getRequiredUrlRelations;
98
94
 
99
95
  if (BEFORE_RETRY_CONFIG) {