ghost 6.60.0 → 6.61.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 (399) hide show
  1. package/components/tryghost-adapter-base-scheduling-0.2.3.tgz +0 -0
  2. package/components/tryghost-adapter-base-sso-0.1.3.tgz +0 -0
  3. package/components/tryghost-custom-field-types-0.0.0.tgz +0 -0
  4. package/components/tryghost-kg-default-cards-10.3.5.tgz +0 -0
  5. package/core/boot.js +13 -4
  6. package/core/built/admin/assets/{Combination-gnJO3vIw.js → Combination-5fYEzgbs.js} +1 -1
  7. package/core/built/admin/assets/{PolarAngleAxis-C4qtHy1B.js → PolarAngleAxis-pkMyqz8g.js} +1 -1
  8. package/core/built/admin/assets/{RadialBarChart-Bh09Stsj.js → RadialBarChart-JAKoS4KT.js} +1 -1
  9. package/core/built/admin/assets/{about-BgpmhCuM.js → about-Bve7IJS2.js} +1 -1
  10. package/core/built/admin/assets/{account-migration-8qTEI1i1.js → account-migration-DRhAehfw.js} +1 -1
  11. package/core/built/admin/assets/{action-list-lGzZLHc8.js → action-list-C4v0-du8.js} +1 -1
  12. package/core/built/admin/assets/activitypub/{account-migration-DMHuPnJn.js → account-migration-C-aej4x_.js} +7 -7
  13. package/core/built/admin/assets/activitypub/activitypub.js +3 -4
  14. package/core/built/admin/assets/activitypub/{avatar-DhTo5D1B.js → avatar-DLPL3Abs.js} +59 -68
  15. package/core/built/admin/assets/activitypub/{avatar-flipboard-DnVgbEfa.js → avatar-flipboard-C9iDY-QV.js} +2 -2
  16. package/core/built/admin/assets/activitypub/{bluesky-sharing-BT4zAlW7.js → bluesky-sharing-BXkA5mqV.js} +8 -8
  17. package/core/built/admin/assets/activitypub/{content-formatters-BeDZ-DIa.js → content-formatters-CHcyMFk4.js} +17 -17
  18. package/core/built/admin/assets/activitypub/{copy-8sqxUuNd.js → copy-DIAOQoCZ.js} +2 -2
  19. package/core/built/admin/assets/activitypub/{domain-xQDDu1CS.js → domain-B3ihkPde.js} +8 -8
  20. package/core/built/admin/assets/activitypub/{edit-profile-BXdF_r2G.js → edit-profile-DsZM3rTX.js} +5 -5
  21. package/core/built/admin/assets/activitypub/{explore-CMt7gKlL.js → explore-BodNrZgR.js} +8 -8
  22. package/core/built/admin/assets/activitypub/{feed-Bwqdddp_.js → feed-PwH1iJ84.js} +9 -9
  23. package/core/built/admin/assets/activitypub/{field-4co_8FVg.js → field-D06-kmOJ.js} +3 -3
  24. package/core/built/admin/assets/activitypub/{hash-DwakMs4X.js → hash-Bm3WxYN4.js} +2 -2
  25. package/core/built/admin/assets/activitypub/{inbox-DQ5CwLma.js → inbox-BluD2ucT.js} +16 -16
  26. package/core/built/admin/assets/activitypub/{inbox-ckD4wo_r.js → inbox-d8oJRTf4.js} +2 -2
  27. package/core/built/admin/assets/activitypub/{label-B72sfvEU.js → label-FHSh6ZAw.js} +3 -3
  28. package/core/built/admin/assets/activitypub/layout-Cq4NG0Xr.js +1 -0
  29. package/core/built/admin/assets/activitypub/{moderation-KCCO7L2J.js → moderation-D1Yapsod.js} +9 -9
  30. package/core/built/admin/assets/activitypub/{note-BX_Bz5A0.js → note-C5zjqq5C.js} +8 -8
  31. package/core/built/admin/assets/activitypub/{notifications-BQOYGvRv.js → notifications-B9p8eCHD.js} +9 -9
  32. package/core/built/admin/assets/activitypub/{preferences-6h43G9_q.js → preferences-BCqUdC3v.js} +9 -9
  33. package/core/built/admin/assets/activitypub/{profile-BMN9VVZ2.js → profile-BRCWoFem.js} +178 -178
  34. package/core/built/admin/assets/activitypub/{reply-ZNo04xsO.js → reply-DYK5vVqb.js} +2 -2
  35. package/core/built/admin/assets/activitypub/{routes-3B9mUQ7i.js → routes-BSXT992i.js} +81 -84
  36. package/core/built/admin/assets/activitypub/{separator-D9taVCCa.js → separator-BbQqTm-p.js} +3 -3
  37. package/core/built/admin/assets/activitypub/{settings-71gCm3SO.js → settings-DQDkr06X.js} +6 -6
  38. package/core/built/admin/assets/activitypub/{step-1-BsGGnBuT.js → step-1-B-YfsVeO.js} +5 -5
  39. package/core/built/admin/assets/activitypub/{step-2-teosIS0k.js → step-2-DtPQzlTH.js} +6 -6
  40. package/core/built/admin/assets/activitypub/{step-3-BjD5TokC.js → step-3-D6BFMXL_.js} +10 -10
  41. package/core/built/admin/assets/activitypub/{tabs-Cvwl1wXU.js → tabs-GpNecvfB.js} +6 -6
  42. package/core/built/admin/assets/activitypub/{topic-filter-C3LZJc2X.js → topic-filter-BPDeQQys.js} +3 -3
  43. package/core/built/admin/assets/activitypub/{use-activity-pub-queries-Dp9f0gov.js → use-activity-pub-queries-BoVOxXkV.js} +2 -2
  44. package/core/built/admin/assets/activitypub/{use-navigate-with-base-path-C4RI0sa9.js → use-navigate-with-base-path-Bmk5h4lW.js} +220 -220
  45. package/core/built/admin/assets/activitypub/{use-reply-chain-data-C2oNDMUH.js → use-reply-chain-data-wVBX7swM.js} +5 -5
  46. package/core/built/admin/assets/activitypub/{x-Dxm6pV9X.js → x-DbQZOLiI.js} +2 -2
  47. package/core/built/admin/assets/{add-integration-modal--YpTq3c0.js → add-integration-modal-BC0jExDZ.js} +1 -1
  48. package/core/built/admin/assets/{add-newsletter-modal-C8Ix2hol.js → add-newsletter-modal-DchTkA7l.js} +1 -1
  49. package/core/built/admin/assets/{add-recommendation-modal-CScuNFz4.js → add-recommendation-modal-DMvaJZKp.js} +1 -1
  50. package/core/built/admin/assets/alert-dialog-QhXzdHfc.js +1 -0
  51. package/core/built/admin/assets/{analytics-Cnji45H5.js → analytics-No1DDY3A.js} +1 -1
  52. package/core/built/admin/assets/{announcement-bar-modal-BTHiy1ZO.js → announcement-bar-modal-DM3cYOpo.js} +1 -1
  53. package/core/built/admin/assets/{api-keys-Boy5pLbD.js → api-keys-BLm2NDBh.js} +1 -1
  54. package/core/built/admin/assets/audience-9mwU5TW6.js +1 -0
  55. package/core/built/admin/assets/{automations-BWpRCZ_f.js → automations-DpUNUdcZ.js} +1 -1
  56. package/core/built/admin/assets/{bluesky-sharing-DHOpQxff.js → bluesky-sharing-Cjrv_f62.js} +1 -1
  57. package/core/built/admin/assets/{box-By_EgGtm.js → box-CdfQAP_F.js} +1 -1
  58. package/core/built/admin/assets/{brand-icon-09YqFZjV.js → brand-icon-CrIGOA3Z.js} +1 -1
  59. package/core/built/admin/assets/{breadcrumb-CcFr_ltt.js → breadcrumb-DLiqCyFc.js} +1 -1
  60. package/core/built/admin/assets/{button-BshWPHvn.js → button-B2jcu6bk.js} +1 -1
  61. package/core/built/admin/assets/{card-CiiE7QfM.js → card--VNbfgo3.js} +1 -1
  62. package/core/built/admin/assets/{chart-BnXyfH11.js → chart-BrhA41Zi.js} +1 -1
  63. package/core/built/admin/assets/chart-helpers-Fo3bUL3K.js +1 -0
  64. package/core/built/admin/assets/{checkbox-Dwwr_3Py.js → checkbox-BfKktMph.js} +1 -1
  65. package/core/built/admin/assets/{chunk.524.91ecb33e6afc3bd8949b.js → chunk.524.60ca4692d91c6022042f.js} +4 -4
  66. package/core/built/admin/assets/{chunk.582.512549909741883f960c.js → chunk.582.525c7617c2d9e94c940a.js} +6 -6
  67. package/core/built/admin/assets/{chunk.16.f76a6314082d813d67e0.js → chunk.896.435fe0637944d4a69810.js} +3 -3
  68. package/core/built/admin/assets/{code-editor-view-BwIdPy_k.js → code-editor-view-CYVu4EW6.js} +1 -1
  69. package/core/built/admin/assets/{code-editor-view-CtkF82Fv.js → code-editor-view-DCQJxsfU.js} +1 -1
  70. package/core/built/admin/assets/{color-picker-Bmo1r9Fc.js → color-picker-BTY_NdEm.js} +1 -1
  71. package/core/built/admin/assets/{color-picker-field-DywowPhF.js → color-picker-field-CPlkzOH0.js} +1 -1
  72. package/core/built/admin/assets/{combobox-C4QCh6Yw.js → combobox-DrMtv_4P.js} +1 -1
  73. package/core/built/admin/assets/command-ZdgYJpoI.js +1 -0
  74. package/core/built/admin/assets/comments-kidj60-h.js +1 -0
  75. package/core/built/admin/assets/{confirmation-context-CLFHhyyH.js → confirmation-context-BhbmQQEl.js} +1 -1
  76. package/core/built/admin/assets/{container-LiZf3XdY.js → container-BuQG1wuP.js} +1 -1
  77. package/core/built/admin/assets/{content-api-modal-BtpNI92-.js → content-api-modal-CyQEC3fr.js} +1 -1
  78. package/core/built/admin/assets/{copy-field-CglgRZyG.js → copy-field-B3M1s78L.js} +1 -1
  79. package/core/built/admin/assets/{custom-field-type-option-D0PXoSnP.js → custom-field-type-option-CsGIZk1J.js} +1 -1
  80. package/core/built/admin/assets/{custom-integration-modal-DCIHKN33.js → custom-integration-modal-BY37O_9X.js} +1 -1
  81. package/core/built/admin/assets/{data-list-CupF7bjM.js → data-list-CA2jYGPq.js} +1 -1
  82. package/core/built/admin/assets/{date-range-select-JPwM0yUj.js → date-range-select-DD2RKkgB.js} +1 -1
  83. package/core/built/admin/assets/design-and-theme-modal-DUSKM4uC.js +22 -0
  84. package/core/built/admin/assets/{detail-page-D8lx2SdP.js → detail-page-Dnv-CdR1.js} +1 -1
  85. package/core/built/admin/assets/dialog-B44iRwlc.js +1 -0
  86. package/core/built/admin/assets/{dirty-confirm-dialog-CmARpZQS.js → dirty-confirm-dialog-BxgQgQ6H.js} +1 -1
  87. package/core/built/admin/assets/{disabled-sources-indicator-BTJ2ClQu.js → disabled-sources-indicator-Cvy47bE2.js} +1 -1
  88. package/core/built/admin/assets/{dist-DzcfoDJ3.js → dist-8YJUlf3B.js} +1 -1
  89. package/core/built/admin/assets/{dist-Cb5RSHSg.js → dist-B3keLvjj.js} +1 -1
  90. package/core/built/admin/assets/{dist-QLZuGq7o2.js → dist-Cy8tfrp_.js} +1 -1
  91. package/core/built/admin/assets/{dist-BT_Z-eCn.js → dist-Dgt2cr6a.js} +1 -1
  92. package/core/built/admin/assets/{domain-D0SAtc-T.js → domain-Ca6KhoQt.js} +1 -1
  93. package/core/built/admin/assets/{dropzone-CaPOeDRZ.js → dropzone-Bb-5zQTk.js} +1 -1
  94. package/core/built/admin/assets/edit-profile-BdupLlus.js +1 -0
  95. package/core/built/admin/assets/{editor-COXn4Atu.js → editor-BP883Lpn.js} +3 -3
  96. package/core/built/admin/assets/{embed-signup-form-modal-BFTPf04i.js → embed-signup-form-modal-DeBMLxlL.js} +1 -1
  97. package/core/built/admin/assets/{empty-indicator-WB1WgT9h.js → empty-indicator-D9QdpuNX.js} +1 -1
  98. package/core/built/admin/assets/{explore-BsNYrubV.js → explore-FB-CimXw.js} +1 -1
  99. package/core/built/admin/assets/{feed-8RR1O1bK.js → feed-C1GxsmI2.js} +1 -1
  100. package/core/built/admin/assets/{field-LmNk7wZh.js → field-Cj8lmDOo.js} +1 -1
  101. package/core/built/admin/assets/{filter-sources-4C0kF1NU.js → filter-sources-D5n5bFA2.js} +1 -1
  102. package/core/built/admin/assets/{filters-CV5jCb9n.js → filters-DJEzkMUK.js} +1 -1
  103. package/core/built/admin/assets/{filters-Dmr0PoqU.js → filters-MZXvdH5D.js} +1 -1
  104. package/core/built/admin/assets/{first-promoter-modal-OCzSaL3B.js → first-promoter-modal-CGTGLCr5.js} +1 -1
  105. package/core/built/admin/assets/{ghost-403cb39badad3df411fc0ba27d220047.js → ghost-3894eedcc6968f658578c0abfe942aab.js} +2 -2
  106. package/core/built/admin/assets/{gift-link-modal-0mzjn5oF.js → gift-link-modal-B6v0tnRN.js} +1 -1
  107. package/core/built/admin/assets/{grid-CUciBfjf.js → grid-Dj29PY05.js} +1 -1
  108. package/core/built/admin/assets/growth-BGAJD1rs.js +3 -0
  109. package/core/built/admin/assets/growth-D6mhcx3q.js +1 -0
  110. package/core/built/admin/assets/{heading-CRZZ2FUe.js → heading-Dh5SFVjL.js} +1 -1
  111. package/core/built/admin/assets/history-modal-iKwUY3XR.js +1 -0
  112. package/core/built/admin/assets/html-field-C8qVGGC1.js +1 -0
  113. package/core/built/admin/assets/{images-C0XvUYMb.js → images-h8VZEQ9k.js} +1 -1
  114. package/core/built/admin/assets/{inbox-DZXDUt4s.js → inbox-BYd1M06Q.js} +13 -13
  115. package/core/built/admin/assets/index-DjQe-e5s.js +4 -0
  116. package/core/built/admin/assets/{index.es-BMUCj9TR.js → index.es-VihPwfeH.js} +1 -1
  117. package/core/built/admin/assets/{inline-Cw-gigDW.js → inline-BWSs_VzR.js} +1 -1
  118. package/core/built/admin/assets/{input-UHrKuvBT.js → input--W-rCTrX.js} +1 -1
  119. package/core/built/admin/assets/{input-group-BPAxETpQ.js → input-group-D8sCXRF5.js} +1 -1
  120. package/core/built/admin/assets/{input-surface-BdOe4KzO.js → input-surface-BsrIZeSF.js} +1 -1
  121. package/core/built/admin/assets/{integration-header-B4DyXV06.js → integration-header-Bm6IDb1A.js} +1 -1
  122. package/core/built/admin/assets/{invite-user-modal-BrAkxEO3.js → invite-user-modal-MdImLCaJ.js} +1 -1
  123. package/core/built/admin/assets/{koenig-lexical-60O_8aiO.js → koenig-lexical-_-IsVI7E.js} +1 -1
  124. package/core/built/admin/assets/koenig-loader-DYZpm6El.js +2 -0
  125. package/core/built/admin/assets/{kpi-card-fUHZlzBX.js → kpi-card-DW_2y3ug.js} +1 -1
  126. package/core/built/admin/assets/kpi-card-DZQk_0W8.js +1 -0
  127. package/core/built/admin/assets/kpi-helpers-PueTKuA6.js +1 -0
  128. package/core/built/admin/assets/kpi-tabs-CojDs-Qz.js +1 -0
  129. package/core/built/admin/assets/{label-VIG969IC.js → label-DjbT91GM.js} +1 -1
  130. package/core/built/admin/assets/{label-picker-BBWykUeA.js → label-picker-cB51xl1r.js} +1 -1
  131. package/core/built/admin/assets/layout-c_B_1hax.js +1 -0
  132. package/core/built/admin/assets/{link-helpers-Dtq9fxQg.js → link-helpers-MVDdnFCY.js} +1 -1
  133. package/core/built/admin/assets/{list-page-CdsnQR9N.js → list-page-BucXJ0hi.js} +1 -1
  134. package/core/built/admin/assets/{loading-indicator-SFTqyYVE.js → loading-indicator-BpFWTVgh.js} +1 -1
  135. package/core/built/admin/assets/{member-custom-fields-gOv6Hoh3.js → member-custom-fields-qs0dIkxM.js} +1 -1
  136. package/core/built/admin/assets/member-detail-B6uec2a6.js +1 -0
  137. package/core/built/admin/assets/members-BQF3CqhI.js +2 -0
  138. package/core/built/admin/assets/{modal-page-BMTzFHVO.js → modal-page-xCivTMvI.js} +1 -1
  139. package/core/built/admin/assets/{moderation-DzzPLDyl.js → moderation-DY4wF1Q3.js} +1 -1
  140. package/core/built/admin/assets/{multi-select-combobox-CGohnsxJ.js → multi-select-combobox-B6LiRzDO.js} +1 -1
  141. package/core/built/admin/assets/navigation-modal-DX-gNF3X.js +1 -0
  142. package/core/built/admin/assets/newsletter-CyQA7m3m.js +1 -0
  143. package/core/built/admin/assets/{newsletter-detail-modal-DQU3r4g2.js → newsletter-detail-modal-BDrptuxn.js} +1 -1
  144. package/core/built/admin/assets/{newsletter-emails-D5ql1rud.js → newsletter-emails-CFeLlt4z.js} +1 -1
  145. package/core/built/admin/assets/newsletters-DXuNmC42.js +1 -0
  146. package/core/built/admin/assets/{note-i8k6pjaw.js → note-Cgo2LCJ6.js} +1 -1
  147. package/core/built/admin/assets/notifications-BC50AMku.js +1 -0
  148. package/core/built/admin/assets/{offers-container-modal-BWfjSdyg.js → offers-container-modal-DWycIMzT.js} +1 -1
  149. package/core/built/admin/assets/{onboarding-route-Cu_ROWPn.js → onboarding-route-Dmc4IPm3.js} +1 -1
  150. package/core/built/admin/assets/overview-CVbFtn-k.js +1 -0
  151. package/core/built/admin/assets/overview-YKj7SZaK.js +1 -0
  152. package/core/built/admin/assets/{page-header-Cfds8pCg.js → page-header-BR_nbIPp.js} +1 -1
  153. package/core/built/admin/assets/{pintura-modal-TDTrJ89x.js → pintura-modal-BR9hEvS8.js} +1 -1
  154. package/core/built/admin/assets/popover-CCy0h5rq.js +1 -0
  155. package/core/built/admin/assets/{portal-frame-DjBF-uy2.js → portal-frame-dc4XKr0e.js} +1 -1
  156. package/core/built/admin/assets/portal-modal-BvvdF_B9.js +1 -0
  157. package/core/built/admin/assets/{post-analytics-Buz1COoY.js → post-analytics-DX470WRG.js} +1 -1
  158. package/core/built/admin/assets/{post-analytics-header-B-P0eFnT.js → post-analytics-header-CXpJmdDv.js} +1 -1
  159. package/core/built/admin/assets/{post-analytics-provider-Cu3jNeFh.js → post-analytics-provider-CLfKGWZy.js} +1 -1
  160. package/core/built/admin/assets/{post-share-modal-P1_M6o-H.js → post-share-modal-Cl0NXRJr.js} +1 -1
  161. package/core/built/admin/assets/{preferences-Cq1aOiLy.js → preferences-DO0UUWFp.js} +2 -2
  162. package/core/built/admin/assets/{preview-chrome-BOVO6_PE.js → preview-chrome-BljUBlOk.js} +1 -1
  163. package/core/built/admin/assets/{preview-modal-MlTjP8UU.js → preview-modal-C-BL-F9k.js} +1 -1
  164. package/core/built/admin/assets/profile-CxT-0l4d.js +1 -0
  165. package/core/built/admin/assets/radio-group-Bgz60i81.js +1 -0
  166. package/core/built/admin/assets/{router-provider-CJC58zTy.js → router-provider-B0gZyiGJ.js} +1 -1
  167. package/core/built/admin/assets/{schemas-CRsC53ls.js → schemas-4UPic-oD.js} +2 -2
  168. package/core/built/admin/assets/select-DuDUFdPq.js +1 -0
  169. package/core/built/admin/assets/{settings-B5hJKZ5C.js → settings-BjCii7BM.js} +1 -1
  170. package/core/built/admin/assets/settings-b8kNzZSQ.js +4 -0
  171. package/core/built/admin/assets/{settings-breadcrumbs-sLDNedBW.js → settings-breadcrumbs-CyP_9zTo.js} +1 -1
  172. package/core/built/admin/assets/{shade-app-F7WxOyfk-nufqw1hd.js → shade-app-CcS3f8MZ-vwURazk8.js} +2 -2
  173. package/core/built/admin/assets/{share-modal-CLBfj377.js → share-modal-BV70mr9k.js} +1 -1
  174. package/core/built/admin/assets/{skeleton-D7hwjdry.js → skeleton-Ce9GgUpf.js} +1 -1
  175. package/core/built/admin/assets/{slack-modal-Bt9I_tEo.js → slack-modal-Be2_KK-z.js} +1 -1
  176. package/core/built/admin/assets/sort-button-Cc-Z96sA.js +1 -0
  177. package/core/built/admin/assets/{source-icon-BPsD5ees.js → source-icon-v6PUnmyM.js} +1 -1
  178. package/core/built/admin/assets/{stack-CIfOAAVf.js → stack-B2eszIiq.js} +1 -1
  179. package/core/built/admin/assets/{stats-B_YkF7bp.js → stats-C4reGh9O.js} +1 -1
  180. package/core/built/admin/assets/{stats-view-BOCp9RG8.js → stats-view-DP9pQ62k.js} +1 -1
  181. package/core/built/admin/assets/{step-1-CMta6YFO.js → step-1-DSRp2vBj.js} +1 -1
  182. package/core/built/admin/assets/{step-2-BG04nh5q.js → step-2-COqv2g0u.js} +1 -1
  183. package/core/built/admin/assets/{step-3-ZnMaVIPj.js → step-3-6W1NMVQc.js} +2 -2
  184. package/core/built/admin/assets/{stripe-button-DDoUKN5a.js → stripe-button-D2K42Uty.js} +1 -1
  185. package/core/built/admin/assets/{stripe-connect-modal-BeSukI8q.js → stripe-connect-modal-Z-UT_BGc.js} +1 -1
  186. package/core/built/admin/assets/{switch-C9djUIMO.js → switch-CI4gLWqb.js} +1 -1
  187. package/core/built/admin/assets/{table-CrqQtkR2.js → table-B2pIKjVh.js} +1 -1
  188. package/core/built/admin/assets/{tabs-CGisSbWq.js → tabs-SaW_UT-Q.js} +1 -1
  189. package/core/built/admin/assets/tag-detail-Dc0nTOtU.js +2 -0
  190. package/core/built/admin/assets/tags-BLaXBwnb.js +1 -0
  191. package/core/built/admin/assets/testimonials-modal-sFwRnNLh.js +1 -0
  192. package/core/built/admin/assets/{text-DU9Hv33_.js → text-BQDSDsKs.js} +1 -1
  193. package/core/built/admin/assets/{textarea-d9qEkMOP.js → textarea-DJ1Q5V39.js} +1 -1
  194. package/core/built/admin/assets/{tier-detail-modal-CxRwgTPR.js → tier-detail-modal-BCFpWwUS.js} +1 -1
  195. package/core/built/admin/assets/{toggle-group-CtKZURJd.js → toggle-group-EM9WpESu.js} +1 -1
  196. package/core/built/admin/assets/{topic-filter-D8JT8Tq1.js → topic-filter-DY4gNHn2.js} +1 -1
  197. package/core/built/admin/assets/{transistor-modal-6PUf0idx.js → transistor-modal-CpyPG-MH.js} +1 -1
  198. package/core/built/admin/assets/trend-badge-ByMkuAuH.js +1 -0
  199. package/core/built/admin/assets/{unsplash-modal-BPuDBPja.js → unsplash-modal-Cv2Q6GtY.js} +1 -1
  200. package/core/built/admin/assets/{use-analytics-data--opuzwcz.js → use-analytics-data-CHvjMYuT.js} +1 -1
  201. package/core/built/admin/assets/use-check-theme-limit-error-Qv4SVXqw.js +2 -0
  202. package/core/built/admin/assets/use-filter-params-CAvfDvf1.js +1 -0
  203. package/core/built/admin/assets/use-growth-stats-D6mZXGhK.js +1 -0
  204. package/core/built/admin/assets/{use-limiter-TDSNiHPB.js → use-limiter-cwJvsNBo.js} +1 -1
  205. package/core/built/admin/assets/{use-navigate-with-base-path-CK989MlC.js → use-navigate-with-base-path-BHPA228f.js} +1 -1
  206. package/core/built/admin/assets/{use-pintura-config-CnCGrDFk.js → use-pintura-config-CzTfnufz.js} +1 -1
  207. package/core/built/admin/assets/{use-pintura-editor-ntphvtUd.js → use-pintura-editor-BDBXWUYq.js} +1 -1
  208. package/core/built/admin/assets/{use-post-referrers-CbXLFIex.js → use-post-referrers-DbY-mzci.js} +1 -1
  209. package/core/built/admin/assets/{use-reply-chain-data-JYFKSO83.js → use-reply-chain-data-BeQwz8oF.js} +1 -1
  210. package/core/built/admin/assets/{use-router-history-entry-BwfQS2mq.js → use-router-history-entry-Bg6BhBQQ.js} +1 -1
  211. package/core/built/admin/assets/{use-setting-group-DQxV42-O.js → use-setting-group-VM7FQwMY.js} +1 -1
  212. package/core/built/admin/assets/{use-settings-navigation-BBzro2-V.js → use-settings-navigation-BbrSUVcf.js} +1 -1
  213. package/core/built/admin/assets/{use-simple-pagination-B2TdNX67.js → use-simple-pagination-Dum6Irbs.js} +1 -1
  214. package/core/built/admin/assets/{use-staff-users-QrR9voeC.js → use-staff-users-cZg4ugOF.js} +1 -1
  215. package/core/built/admin/assets/{use-tinybird-query-D2Aeoty5.js → use-tinybird-query-B1IMyAcv.js} +1 -1
  216. package/core/built/admin/assets/{use-tinybird-token-DBuwMmln.js → use-tinybird-token-Bow0Zwn8.js} +1 -1
  217. package/core/built/admin/assets/{use-unsaved-changes-guard-DpYJcj1d.js → use-unsaved-changes-guard-BAy0RANR.js} +1 -1
  218. package/core/built/admin/assets/{use-url-input-WnIqckzS.js → use-url-input-Df5QzNa7.js} +1 -1
  219. package/core/built/admin/assets/user-detail-modal-yipSoQfv.js +1 -0
  220. package/core/built/admin/assets/{virtual-list-D3MfPNOh.js → virtual-list-DEx8WgiO.js} +1 -1
  221. package/core/built/admin/assets/web-CKcXAu86.js +1 -0
  222. package/core/built/admin/assets/web-DR4TqM3E.js +2 -0
  223. package/core/built/admin/assets/{zapier-modal-BO6PS_Vd.js → zapier-modal-Cw3BTBUu.js} +1 -1
  224. package/core/built/admin/index.html +24 -25
  225. package/core/frontend/services/rendering/renderer.js +15 -0
  226. package/core/server/adapters/storage/LocalStorageBase.js +8 -5
  227. package/core/server/api/endpoints/db.js +19 -5
  228. package/core/server/api/endpoints/index.js +4 -0
  229. package/core/server/api/endpoints/member-custom-fields.js +4 -14
  230. package/core/server/api/endpoints/posts.js +1 -0
  231. package/core/server/api/endpoints/tiers-checkout-config.js +59 -0
  232. package/core/server/api/endpoints/utils/serializers/output/config.js +1 -0
  233. package/core/server/api/endpoints/utils/serializers/output/index.js +4 -0
  234. package/core/server/api/endpoints/utils/serializers/output/tiers-checkout-config.js +12 -0
  235. package/core/server/data/exporter/table-lists.js +3 -0
  236. package/core/server/data/importer/content-files.js +57 -0
  237. package/core/server/data/importer/handlers/image.js +2 -2
  238. package/core/server/data/importer/import-archive.js +131 -0
  239. package/core/server/data/importer/import-manager.js +18 -180
  240. package/core/server/data/importer/importers/content-file-importer.js +66 -4
  241. package/core/server/data/migrations/versions/6.61/2026-08-19-14-30-20-add-written-by-to-members-custom-field-values.js +42 -0
  242. package/core/server/data/migrations/versions/6.61/2026-08-19-14-38-53-add-members-custom-field-bindings-table.js +26 -0
  243. package/core/server/data/migrations/versions/6.61/2026-08-19-14-48-06-add-tier-checkout-field-tables.js +35 -0
  244. package/core/server/data/schema/schema.js +90 -0
  245. package/core/server/data/seeders/importers/automation-action-revisions-importer.js +3 -3
  246. package/core/server/data/seeders/importers/automation-actions-importer.js +3 -3
  247. package/core/server/data/seeders/importers/automation-run-steps-importer.js +3 -3
  248. package/core/server/data/seeders/importers/automation-runs-importer.js +5 -5
  249. package/core/server/data/seeders/importers/automations-importer.js +3 -3
  250. package/core/server/data/seeders/importers/comment-reports-importer.js +1 -1
  251. package/core/server/data/seeders/importers/comments-importer.js +1 -1
  252. package/core/server/data/seeders/importers/email-batches-importer.js +1 -1
  253. package/core/server/data/seeders/importers/email-recipients-importer.js +1 -1
  254. package/core/server/data/seeders/importers/emails-importer.js +1 -1
  255. package/core/server/data/seeders/importers/labels-importer.js +1 -1
  256. package/core/server/data/seeders/importers/members-click-events-importer.js +1 -1
  257. package/core/server/data/seeders/importers/members-created-events-importer.js +1 -1
  258. package/core/server/data/seeders/importers/members-feedback-importer.js +1 -1
  259. package/core/server/data/seeders/importers/members-importer.js +1 -1
  260. package/core/server/data/seeders/importers/members-login-events-importer.js +1 -1
  261. package/core/server/data/seeders/importers/members-products-importer.js +1 -1
  262. package/core/server/data/seeders/importers/members-status-events-importer.js +1 -1
  263. package/core/server/data/seeders/importers/members-stripe-customers-importer.js +1 -1
  264. package/core/server/data/seeders/importers/members-stripe-customers-subscriptions-importer.js +1 -1
  265. package/core/server/data/seeders/importers/members-subscribe-events-importer.js +1 -1
  266. package/core/server/data/seeders/importers/members-subscription-created-events-importer.js +1 -1
  267. package/core/server/data/seeders/importers/offer-redemptions-importer.js +1 -1
  268. package/core/server/data/seeders/importers/offers-importer.js +1 -1
  269. package/core/server/data/seeders/importers/posts-importer.js +1 -1
  270. package/core/server/data/seeders/importers/table-importer.js +2 -2
  271. package/core/server/data/seeders/importers/tags-importer.js +1 -1
  272. package/core/server/data/seeders/importers/users-importer.js +1 -1
  273. package/core/server/data/seeders/importers/web-mentions-importer.js +1 -1
  274. package/core/server/data/seeders/utils/random.js +3 -3
  275. package/core/server/ghost-server.js +3 -2
  276. package/core/server/lib/db-types/boolean.js +18 -0
  277. package/core/server/lib/promise-pool.js +31 -0
  278. package/core/server/services/automations/database-automations-repository.js +26 -26
  279. package/core/server/services/automations/poll.js +1 -0
  280. package/core/server/services/content-import/import/assets.js +74 -0
  281. package/core/server/services/content-import/import/importer.js +57 -14
  282. package/core/server/services/content-import/import/post-data.js +1 -0
  283. package/core/server/services/content-import/import/post-repository.js +78 -0
  284. package/core/server/services/content-import/import/relations.js +149 -0
  285. package/core/server/services/content-import/import/row.js +11 -0
  286. package/core/server/services/content-import/import/schema.js +29 -0
  287. package/core/server/services/content-import/import/source.js +125 -0
  288. package/core/server/services/content-import/index.js +6 -28
  289. package/core/server/services/email-analytics/email-analytics-service.js +8 -1
  290. package/core/server/services/email-analytics/lib/queries.js +7 -1
  291. package/core/server/services/gift-links/schema.js +3 -3
  292. package/core/server/services/gifts/CONTEXT.md +1 -1
  293. package/core/server/services/gifts/constants.js +1 -1
  294. package/core/server/services/gifts/gift-bookshelf-repository.js +2 -2
  295. package/core/server/services/gifts/gift-delivery-bookshelf-repository.js +18 -9
  296. package/core/server/services/gifts/gift-delivery-schema.js +5 -5
  297. package/core/server/services/gifts/gift-delivery-service.js +4 -0
  298. package/core/server/services/gifts/gift-schema.js +10 -10
  299. package/core/server/services/gifts/gift-service.js +4 -2
  300. package/core/server/services/jobs-service/register-job-handlers.js +5 -5
  301. package/core/server/services/lib/mailgun-client.js +44 -8
  302. package/core/server/services/media-inliner/external-media-inliner-job.js +12 -0
  303. package/core/server/services/media-inliner/external-media-inliner.js +103 -29
  304. package/core/server/services/media-inliner/service.js +13 -41
  305. package/core/server/services/media-inliner/types.js +2 -0
  306. package/core/server/services/members/import-export/export/exporter.js +4 -6
  307. package/core/server/services/members/import-export/import/importer.js +21 -5
  308. package/core/server/services/members/import-export/import/stripe-utils.js +6 -1
  309. package/core/server/services/members/import-export/index.js +6 -1
  310. package/core/server/services/members/members-api/members-api.js +5 -0
  311. package/core/server/services/members/members-api/services/member-bread-service.js +19 -1
  312. package/core/server/services/members/members-api/services/payments-service.js +47 -1
  313. package/core/server/services/members-custom-fields/actions.js +27 -1
  314. package/core/server/services/members-custom-fields/bindings-service.js +119 -0
  315. package/core/server/services/members-custom-fields/definitions-service.js +104 -13
  316. package/core/server/services/members-custom-fields/index.js +11 -4
  317. package/core/server/services/members-custom-fields/queries.js +5 -0
  318. package/core/server/services/members-custom-fields/schema.js +37 -6
  319. package/core/server/services/members-custom-fields/values-service.js +15 -3
  320. package/core/server/services/public-config/config.js +7 -0
  321. package/core/server/services/stripe/services/checkout/allowed-countries.js +267 -0
  322. package/core/server/services/stripe/services/checkout/completed-session.js +68 -0
  323. package/core/server/services/stripe/services/checkout/field-ports.js +34 -0
  324. package/core/server/services/stripe/services/checkout/session-options.js +97 -0
  325. package/core/server/services/stripe/services/webhook/checkout-session-event-service.js +49 -0
  326. package/core/server/services/stripe/stripe-api.js +29 -0
  327. package/core/server/services/stripe/stripe-service.js +7 -0
  328. package/core/server/services/tier-checkout-config/codec.js +95 -0
  329. package/core/server/services/tier-checkout-config/destinations.js +17 -0
  330. package/core/server/services/tier-checkout-config/index.js +26 -0
  331. package/core/server/services/tier-checkout-config/models.js +57 -0
  332. package/core/server/services/tier-checkout-config/queries.js +80 -0
  333. package/core/server/services/tier-checkout-config/schema.js +33 -0
  334. package/core/server/services/tier-checkout-config/serializers.js +122 -0
  335. package/core/server/services/tier-checkout-config/service.js +303 -0
  336. package/core/server/services/tiers/service.js +21 -0
  337. package/core/server/web/api/endpoints/admin/routes.js +24 -13
  338. package/core/server/web/api/middleware/upload.js +2 -2
  339. package/core/server/web/parent/app.js +5 -0
  340. package/core/server/web/parent/middleware/filter-query-parameters.js +94 -0
  341. package/core/server/web/parent/middleware/index.js +1 -0
  342. package/core/server/web/query-parameter-policy/index.js +9 -0
  343. package/core/server/web/query-parameter-policy/policy.json +58 -0
  344. package/core/server/web/query-parameter-policy/schema.js +38 -0
  345. package/core/shared/config/defaults.json +3 -0
  346. package/core/shared/config/env/config.testing-mysql.json +3 -0
  347. package/core/shared/config/env/config.testing.json +3 -0
  348. package/core/shared/config/overrides.json +4 -2
  349. package/core/shared/labs.js +5 -14
  350. package/package.json +12 -13
  351. package/pnpm-lock.yaml +44 -46
  352. package/pnpm-workspace.yaml +6 -6
  353. package/tsconfig.json +2 -3
  354. package/core/built/admin/assets/activitypub/layout-CXajhRsL.js +0 -1
  355. package/core/built/admin/assets/alert-dialog-wEbVxANM.js +0 -1
  356. package/core/built/admin/assets/app-utils-D2Wp7ZSS.js +0 -1
  357. package/core/built/admin/assets/audience-DTLMXAFH.js +0 -1
  358. package/core/built/admin/assets/chart-helpers-B3OqQ6Ez.js +0 -1
  359. package/core/built/admin/assets/command-DcLbSifC.js +0 -1
  360. package/core/built/admin/assets/comments-Bxy_3WyE.js +0 -1
  361. package/core/built/admin/assets/design-and-theme-modal-CZ-PkW7o.js +0 -23
  362. package/core/built/admin/assets/dialog-Db7c164G.js +0 -1
  363. package/core/built/admin/assets/edit-profile-By7v5XW5.js +0 -1
  364. package/core/built/admin/assets/growth-55vWlGT_.js +0 -1
  365. package/core/built/admin/assets/growth-DA5AluYw.js +0 -3
  366. package/core/built/admin/assets/history-modal-G1s5hHz7.js +0 -1
  367. package/core/built/admin/assets/html-field-BegxsWpw.js +0 -1
  368. package/core/built/admin/assets/index-CDP9tIOk.js +0 -4
  369. package/core/built/admin/assets/koenig-loader-DwVY_V-H.js +0 -1
  370. package/core/built/admin/assets/kpi-card-LERqWBoY.js +0 -1
  371. package/core/built/admin/assets/kpi-helpers-DB3ouhYF.js +0 -1
  372. package/core/built/admin/assets/kpi-tabs-BGvtMD8S.js +0 -1
  373. package/core/built/admin/assets/layout-Di5K7doM.js +0 -1
  374. package/core/built/admin/assets/member-detail-D7mZDDp3.js +0 -1
  375. package/core/built/admin/assets/member-route-0Aa52Ntz.js +0 -1
  376. package/core/built/admin/assets/members-DvZG9t69.js +0 -2
  377. package/core/built/admin/assets/navigation-modal-CI8Bx5vn.js +0 -1
  378. package/core/built/admin/assets/newsletter-Bg3cq5U-.js +0 -1
  379. package/core/built/admin/assets/newsletters-DMDfZbMS.js +0 -1
  380. package/core/built/admin/assets/notifications-psA_2Ph4.js +0 -1
  381. package/core/built/admin/assets/overview-C-6xOLaf.js +0 -1
  382. package/core/built/admin/assets/overview-DaLhpRrC.js +0 -1
  383. package/core/built/admin/assets/popover-CFgqFDvC.js +0 -1
  384. package/core/built/admin/assets/portal-modal-Cf0pBAk8.js +0 -1
  385. package/core/built/admin/assets/profile-D6dHYf2o.js +0 -1
  386. package/core/built/admin/assets/radio-group-CjtmsCPl.js +0 -1
  387. package/core/built/admin/assets/select-D_RQaXgt.js +0 -1
  388. package/core/built/admin/assets/settings-DIo_F-MF.js +0 -4
  389. package/core/built/admin/assets/sort-button-DMBXF7tP.js +0 -1
  390. package/core/built/admin/assets/tag-detail-2a3BfzTW.js +0 -2
  391. package/core/built/admin/assets/tags-Dp2_8UzL.js +0 -1
  392. package/core/built/admin/assets/testimonials-modal-C9nrypNo.js +0 -1
  393. package/core/built/admin/assets/use-check-theme-limit-error-C9-QhGdV.js +0 -1
  394. package/core/built/admin/assets/use-filter-params-CSpAvgD2.js +0 -1
  395. package/core/built/admin/assets/use-growth-stats-BOmoPDHJ.js +0 -1
  396. package/core/built/admin/assets/user-detail-modal-59mBJqxN.js +0 -1
  397. package/core/built/admin/assets/web-DUuX7nE2.js +0 -2
  398. package/core/built/admin/assets/web-N8ucs2aG.js +0 -1
  399. /package/core/server/lib/{db-date.js → db-types/date.js} +0 -0
@@ -0,0 +1,131 @@
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
+ const node_crypto_1 = __importDefault(require("node:crypto"));
7
+ const node_os_1 = __importDefault(require("node:os"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const fs_extra_1 = __importDefault(require("fs-extra"));
10
+ const glob_1 = require("glob");
11
+ const { extract } = require('@tryghost/zip');
12
+ const tpl = require('@tryghost/tpl');
13
+ const errors = require('@tryghost/errors');
14
+ const messages = {
15
+ noContentToImport: 'Zip did not include any content to import.',
16
+ invalidZipStructure: 'Invalid zip file structure.',
17
+ invalidZipFileBaseDirectory: 'Invalid zip file: base directory read failed',
18
+ invalidZipFileNameEncoding: 'The uploaded zip could not be read',
19
+ invalidZipFileNameEncodingContext: 'The filename was too long or contained invalid characters',
20
+ invalidZipFileNameEncodingHelp: 'Remove any special characters from the file name, or alternatively try another archiving tool if using MacOS Archive Utility',
21
+ };
22
+ const ROOT_ONLY = 0;
23
+ const ROOT_OR_SINGLE_DIR = 1;
24
+ const ALL_DIRS = 2;
25
+ class ImportArchive {
26
+ extensions;
27
+ directories;
28
+ extractArchive;
29
+ constructor({ extensions, directories }, { extract: extractArchive = extract } = {}) {
30
+ this.extensions = extensions;
31
+ this.directories = directories;
32
+ this.extractArchive = extractArchive;
33
+ }
34
+ getGlobPattern(items) {
35
+ return `+(${items.join('|')})`;
36
+ }
37
+ getExtensionGlob(extensions, level) {
38
+ const prefix = level === ALL_DIRS ? '**/*' : level === ROOT_OR_SINGLE_DIR ? '{*/*,*}' : '*';
39
+ return prefix + this.getGlobPattern(extensions);
40
+ }
41
+ getDirectoryGlob(directories, level) {
42
+ const prefix = level === ALL_DIRS ? '**/' : level === ROOT_OR_SINGLE_DIR ? '{*/,}' : '';
43
+ return prefix + this.getGlobPattern(directories);
44
+ }
45
+ isValid(directory) {
46
+ const extMatchesBase = (0, glob_1.globSync)(this.getExtensionGlob(this.extensions, ROOT_OR_SINGLE_DIR), {
47
+ cwd: directory,
48
+ nocase: true,
49
+ });
50
+ const extMatchesAll = (0, glob_1.globSync)(this.getExtensionGlob(this.extensions, ALL_DIRS), {
51
+ cwd: directory,
52
+ nocase: true,
53
+ });
54
+ const dirMatches = this.directories.length
55
+ ? (0, glob_1.globSync)(this.getDirectoryGlob(this.directories, ROOT_OR_SINGLE_DIR), {
56
+ cwd: directory,
57
+ })
58
+ : [];
59
+ if (extMatchesBase.length > 0 || (dirMatches.length > 0 && extMatchesAll.length > 0)) {
60
+ return true;
61
+ }
62
+ if (extMatchesAll.length < 1) {
63
+ throw new errors.UnsupportedMediaTypeError({ message: tpl(messages.noContentToImport) });
64
+ }
65
+ throw new errors.UnsupportedMediaTypeError({ message: tpl(messages.invalidZipStructure) });
66
+ }
67
+ getBaseDirectory(directory) {
68
+ const extMatches = (0, glob_1.globSync)(this.getExtensionGlob(this.extensions, ROOT_ONLY), {
69
+ cwd: directory,
70
+ nocase: true,
71
+ });
72
+ const dirMatches = this.directories.length
73
+ ? (0, glob_1.globSync)(this.getDirectoryGlob(this.directories, ROOT_ONLY), {
74
+ cwd: directory,
75
+ nocase: true,
76
+ })
77
+ : [];
78
+ if (extMatches.length > 0 || dirMatches.length > 0) {
79
+ return;
80
+ }
81
+ const extMatchesAll = (0, glob_1.globSync)(this.getExtensionGlob(this.extensions, ALL_DIRS), {
82
+ cwd: directory,
83
+ nocase: true,
84
+ });
85
+ const firstMatch = extMatchesAll[0];
86
+ if (!firstMatch) {
87
+ throw new errors.ValidationError({ message: tpl(messages.invalidZipFileBaseDirectory) });
88
+ }
89
+ return firstMatch.split('/')[0];
90
+ }
91
+ getFiles(directory, extensions) {
92
+ const globPattern = this.getExtensionGlob(extensions, ALL_DIRS);
93
+ return (0, glob_1.globSync)(globPattern, { cwd: directory, nocase: true }).map((file) => ({
94
+ name: file,
95
+ path: node_path_1.default.join(directory, file),
96
+ }));
97
+ }
98
+ async extract(filePath) {
99
+ const tmpDir = node_path_1.default.join(node_os_1.default.tmpdir(), node_crypto_1.default.randomUUID());
100
+ try {
101
+ await this.extractArchive(filePath, tmpDir);
102
+ const files = (0, glob_1.globSync)('**/*', { cwd: tmpDir, nodir: true });
103
+ await Promise.all(files.map((file) => fs_extra_1.default.chmod(node_path_1.default.join(tmpDir, file), 0o644)));
104
+ }
105
+ catch (error) {
106
+ await fs_extra_1.default.remove(tmpDir).catch(() => { });
107
+ const message = messageOf(error);
108
+ if (message.startsWith('ENAMETOOLONG:')) {
109
+ throw new errors.UnsupportedMediaTypeError({
110
+ message: tpl(messages.invalidZipFileNameEncoding),
111
+ context: tpl(messages.invalidZipFileNameEncodingContext),
112
+ help: tpl(messages.invalidZipFileNameEncodingHelp),
113
+ code: 'INVALID_ZIP_FILE_NAME_ENCODING',
114
+ });
115
+ }
116
+ if (message.includes('end of central directory record signature not found') ||
117
+ message.includes('invalid comment length')) {
118
+ throw new errors.UnsupportedMediaTypeError({
119
+ message: tpl(messages.invalidZipFileNameEncoding),
120
+ code: 'INVALID_ZIP_FILE',
121
+ });
122
+ }
123
+ throw error;
124
+ }
125
+ return tmpDir;
126
+ }
127
+ }
128
+ exports.default = ImportArchive;
129
+ function messageOf(error) {
130
+ return error instanceof Error ? error.message : '';
131
+ }
@@ -1,31 +1,21 @@
1
1
  const _ = require('lodash');
2
2
  const fs = require('fs-extra');
3
3
  const path = require('path');
4
- const os = require('os');
5
- const { globSync } = require('glob');
6
- const crypto = require('crypto');
7
4
  const config = require('../../../shared/config');
8
- const { extract } = require('@tryghost/zip');
9
5
  const tpl = require('@tryghost/tpl');
10
6
  const debug = require('@tryghost/debug')('import-manager');
11
7
  const logging = require('@tryghost/logging');
12
8
  const errors = require('@tryghost/errors');
13
- const ImageHandler = require('./handlers/image');
14
- const ImporterContentFileHandler = require('./handlers/importer-content-file-handler');
15
9
  const RevueHandler = require('./handlers/revue');
16
10
  const JSONHandler = require('./handlers/json');
17
11
  const MarkdownHandler = require('./handlers/markdown');
18
- const ContentFileImporter = require('./importers/content-file-importer');
19
12
  const RevueImporter = require('./importers/importer-revue');
20
13
  const DataImporter = require('./importers/data');
21
14
  const urlUtils = require('../../../shared/url-utils').default;
22
15
  const { GhostMailer } = require('../../services/mail');
23
16
  const jobManager = require('../../services/jobs');
24
- const adapterManager = require('../../services/adapter-manager').default;
25
-
26
- const mediaStorage = adapterManager.getAdapter('storage:media');
27
- const imageStorage = adapterManager.getAdapter('storage:images');
28
- const fileStorage = adapterManager.getAdapter('storage:files');
17
+ const ImportArchive = require('./import-archive').default;
18
+ const { createContentFileHandlers, createContentFileImporters } = require('./content-files');
29
19
 
30
20
  const { emailTemplate } = require('./email-template');
31
21
  const ghostMailer = new GhostMailer();
@@ -36,21 +26,9 @@ const messages = {
36
26
  context: 'Your site will continue to work as expected',
37
27
  },
38
28
  noContentToImport: 'Zip did not include any content to import.',
39
- invalidZipStructure: 'Invalid zip file structure.',
40
- invalidZipFileBaseDirectory: 'Invalid zip file: base directory read failed',
41
29
  zipContainsMultipleDataFormats:
42
30
  'Zip file contains multiple data formats. Please split up and import separately.',
43
- invalidZipFileNameEncoding: 'The uploaded zip could not be read',
44
- invalidZipFileNameEncodingContext: 'The filename was too long or contained invalid characters',
45
- invalidZipFileNameEncodingHelp:
46
- 'Remove any special characters from the file name, or alternatively try another archiving tool if using MacOS Archive Utility',
47
31
  };
48
-
49
- // Glob levels
50
- const ROOT_ONLY = 0;
51
-
52
- const ROOT_OR_SINGLE_DIR = 1;
53
- const ALL_DIRS = 2;
54
32
  let defaults = {
55
33
  extensions: ['.zip'],
56
34
  contentTypes: ['application/zip', 'application/x-zip-compressed'],
@@ -59,68 +37,23 @@ let defaults = {
59
37
 
60
38
  class ImportManager {
61
39
  constructor() {
62
- const mediaHandler = new ImporterContentFileHandler({
63
- type: 'media',
64
- // @NOTE: making the second parameter strict folder "content/media" brakes the glob pattern
65
- // in the importer, so we need to keep it as general "content" unless
66
- // it becomes a strict requirement
67
- directories: ['media', 'content'],
68
- ignoreRootFolderFiles: true,
69
- extensions: config.get('uploads').media.extensions,
70
- contentTypes: config.get('uploads').media.contentTypes,
71
- urlUtils: urlUtils,
72
- storage: mediaStorage,
73
- });
74
-
75
- const filesHandler = new ImporterContentFileHandler({
76
- type: 'files',
77
- // @NOTE: making the second parameter strict folder "content/files" brakes the glob pattern
78
- // in the importer, so we need to keep it as general "content" unless
79
- // it becomes a strict requirement
80
- directories: ['files', 'content'],
81
- ignoreRootFolderFiles: true,
82
- extensions: config.get('uploads').files.extensions,
83
- contentTypes: config.get('uploads').files.contentTypes,
84
- urlUtils: urlUtils,
85
- storage: fileStorage,
86
- });
87
-
88
- const imageImporter = new ContentFileImporter({
89
- type: 'images',
90
- store: imageStorage,
91
- });
92
- const mediaImporter = new ContentFileImporter({
93
- type: 'media',
94
- store: mediaStorage,
95
- });
96
-
97
- const contentFilesImporter = new ContentFileImporter({
98
- type: 'files',
99
- store: fileStorage,
100
- });
40
+ const contentFileHandlers = createContentFileHandlers();
41
+ const contentFileImporters = createContentFileImporters();
101
42
 
102
43
  /**
103
44
  * @type {Importer[]} importers
104
45
  */
105
- this.importers = [
106
- imageImporter,
107
- mediaImporter,
108
- contentFilesImporter,
109
- RevueImporter,
110
- DataImporter,
111
- ];
46
+ this.importers = [...contentFileImporters, RevueImporter, DataImporter];
112
47
 
113
48
  /**
114
49
  * @type {Handler[]}
115
50
  */
116
- this.handlers = [
117
- ImageHandler,
118
- mediaHandler,
119
- filesHandler,
120
- RevueHandler,
121
- JSONHandler,
122
- MarkdownHandler,
123
- ];
51
+ this.handlers = [...contentFileHandlers, RevueHandler, JSONHandler, MarkdownHandler];
52
+
53
+ this.archive = new ImportArchive({
54
+ extensions: this.getExtensions(),
55
+ directories: this.getDirectories(),
56
+ });
124
57
 
125
58
  // Keep track of file to cleanup at the end
126
59
  /**
@@ -159,17 +92,7 @@ class ImportManager {
159
92
  * @returns {string}
160
93
  */
161
94
  getGlobPattern(items) {
162
- return (
163
- '+(' +
164
- _.reduce(
165
- items,
166
- function (memo, ext) {
167
- return memo !== '' ? memo + '|' + ext : ext;
168
- },
169
- '',
170
- ) +
171
- ')'
172
- );
95
+ return this.archive.getGlobPattern(items);
173
96
  }
174
97
 
175
98
  /**
@@ -178,9 +101,7 @@ class ImportManager {
178
101
  * @returns {string}
179
102
  */
180
103
  getExtensionGlob(extensions, level) {
181
- const prefix = level === ALL_DIRS ? '**/*' : level === ROOT_OR_SINGLE_DIR ? '{*/*,*}' : '*';
182
-
183
- return prefix + this.getGlobPattern(extensions);
104
+ return this.archive.getExtensionGlob(extensions, level);
184
105
  }
185
106
 
186
107
  /**
@@ -190,9 +111,7 @@ class ImportManager {
190
111
  * @returns {string}
191
112
  */
192
113
  getDirectoryGlob(directories, level) {
193
- const prefix = level === ALL_DIRS ? '**/' : level === ROOT_OR_SINGLE_DIR ? '{*/,}' : '';
194
-
195
- return prefix + this.getGlobPattern(directories);
114
+ return this.archive.getDirectoryGlob(directories, level);
196
115
  }
197
116
 
198
117
  /**
@@ -212,31 +131,7 @@ class ImportManager {
212
131
  * @returns {boolean}
213
132
  */
214
133
  isValidZip(directory) {
215
- // Globs match content in the root or inside a single directory
216
- const extMatchesBase = globSync(
217
- this.getExtensionGlob(this.getExtensions(), ROOT_OR_SINGLE_DIR),
218
- { cwd: directory, nocase: true },
219
- );
220
-
221
- const extMatchesAll = globSync(this.getExtensionGlob(this.getExtensions(), ALL_DIRS), {
222
- cwd: directory,
223
- nocase: true,
224
- });
225
-
226
- const dirMatches = globSync(this.getDirectoryGlob(this.getDirectories(), ROOT_OR_SINGLE_DIR), {
227
- cwd: directory,
228
- });
229
-
230
- // If this folder contains importable files or a content or images directory
231
- if (extMatchesBase.length > 0 || (dirMatches.length > 0 && extMatchesAll.length > 0)) {
232
- return true;
233
- }
234
-
235
- if (extMatchesAll.length < 1) {
236
- throw new errors.UnsupportedMediaTypeError({ message: tpl(messages.noContentToImport) });
237
- }
238
-
239
- throw new errors.UnsupportedMediaTypeError({ message: tpl(messages.invalidZipStructure) });
134
+ return this.archive.isValid(directory);
240
135
  }
241
136
 
242
137
  /**
@@ -245,37 +140,8 @@ class ImportManager {
245
140
  * @returns {Promise<string>} full path to the extracted folder
246
141
  */
247
142
  async extractZip(filePath) {
248
- const tmpDir = path.join(os.tmpdir(), crypto.randomUUID());
143
+ const tmpDir = await this.archive.extract(filePath);
249
144
  this.fileToDelete = tmpDir;
250
-
251
- try {
252
- await extract(filePath, tmpDir);
253
-
254
- // Set permissions for all extracted files
255
- const files = globSync('**/*', { cwd: tmpDir, nodir: true });
256
- await Promise.all(files.map((file) => fs.chmod(path.join(tmpDir, file), 0o644)));
257
- } catch (err) {
258
- if (err.message.startsWith('ENAMETOOLONG:')) {
259
- // The file was probably zipped with MacOS zip utility. Which doesn't correctly set UTF-8 encoding flag.
260
- // This causes ENAMETOOLONG error on Linux, because the resulting filename length is too long when decoded using the default string encoder.
261
- throw new errors.UnsupportedMediaTypeError({
262
- message: tpl(messages.invalidZipFileNameEncoding),
263
- context: tpl(messages.invalidZipFileNameEncodingContext),
264
- help: tpl(messages.invalidZipFileNameEncodingHelp),
265
- code: 'INVALID_ZIP_FILE_NAME_ENCODING',
266
- });
267
- } else if (
268
- err.message.includes('end of central directory record signature not found') ||
269
- err.message.includes('invalid comment length')
270
- ) {
271
- // This comes from Yauzl when the zip is invalid
272
- throw new errors.UnsupportedMediaTypeError({
273
- message: tpl(messages.invalidZipFileNameEncoding),
274
- code: 'INVALID_ZIP_FILE',
275
- });
276
- }
277
- throw err;
278
- }
279
145
  return tmpDir;
280
146
  }
281
147
 
@@ -287,10 +153,7 @@ class ImportManager {
287
153
  * @returns {File[]} Files
288
154
  */
289
155
  getFilesFromZip(handler, directory) {
290
- const globPattern = this.getExtensionGlob(handler.extensions, ALL_DIRS);
291
- return _.map(globSync(globPattern, { cwd: directory, nocase: true }), function (file) {
292
- return { name: file, path: path.join(directory, file) };
293
- });
156
+ return this.archive.getFiles(directory, handler.extensions);
294
157
  }
295
158
 
296
159
  /**
@@ -299,32 +162,7 @@ class ImportManager {
299
162
  * @returns {string}
300
163
  */
301
164
  getBaseDirectory(directory) {
302
- // Globs match root level only
303
- const extMatches = globSync(this.getExtensionGlob(this.getExtensions(), ROOT_ONLY), {
304
- cwd: directory,
305
- nocase: true,
306
- });
307
-
308
- const dirMatches = globSync(this.getDirectoryGlob(this.getDirectories(), ROOT_ONLY), {
309
- cwd: directory,
310
- nocase: true,
311
- });
312
- let extMatchesAll;
313
-
314
- // There is no base directory
315
- if (extMatches.length > 0 || dirMatches.length > 0) {
316
- return;
317
- }
318
- // There is a base directory, grab it from any ext match
319
- extMatchesAll = globSync(this.getExtensionGlob(this.getExtensions(), ALL_DIRS), {
320
- cwd: directory,
321
- nocase: true,
322
- });
323
- if (extMatchesAll.length < 1 || extMatchesAll[0].split('/').length < 1) {
324
- throw new errors.ValidationError({ message: tpl(messages.invalidZipFileBaseDirectory) });
325
- }
326
-
327
- return extMatchesAll[0].split('/')[0];
165
+ return this.archive.getBaseDirectory(directory);
328
166
  }
329
167
 
330
168
  /**
@@ -1,4 +1,5 @@
1
1
  const _ = require('lodash');
2
+ const path = require('node:path');
2
3
  let replaceImage;
3
4
  let preProcessPosts;
4
5
  let preProcessTags;
@@ -9,8 +10,19 @@ replaceImage = function (markdown, image) {
9
10
  return;
10
11
  }
11
12
 
12
- // Normalizes to include a trailing slash if there was one
13
- const regex = new RegExp('(/)?' + image.originalPath, 'gm');
13
+ const originalPaths = [image.originalPath];
14
+ if (image.originalPath.startsWith('content/')) {
15
+ originalPaths.push(image.originalPath.slice('content/'.length));
16
+ } else {
17
+ originalPaths.unshift(`content/${image.originalPath}`);
18
+ }
19
+
20
+ // Match canonical /content/{type} paths before their shorter archive path so
21
+ // replacing images/image.jpg cannot leave an extra /content prefix behind.
22
+ // Consume __GHOST_URL__ too: newPath already contains the configured subdir
23
+ // and the model will normalize it back to transform-ready form on write.
24
+ const escapedPaths = originalPaths.map((originalPath) => _.escapeRegExp(originalPath));
25
+ const regex = new RegExp(`(?:__GHOST_URL__)?/?(?:${escapedPaths.join('|')})`, 'gm');
14
26
 
15
27
  return markdown.replace(regex, image.newPath);
16
28
  };
@@ -31,6 +43,12 @@ preProcessPosts = function (data, contentFile) {
31
43
  if (post.feature_image) {
32
44
  post.feature_image = replaceImage(post.feature_image, contentFile);
33
45
  }
46
+ if (post.og_image) {
47
+ post.og_image = replaceImage(post.og_image, contentFile);
48
+ }
49
+ if (post.twitter_image) {
50
+ post.twitter_image = replaceImage(post.twitter_image, contentFile);
51
+ }
34
52
  });
35
53
  };
36
54
 
@@ -114,10 +132,10 @@ class ContentFileImporter {
114
132
  * @param {Object[]} contentFilesData
115
133
  * @returns
116
134
  */
117
- doImport(contentFilesData) {
135
+ async doImport(contentFilesData) {
118
136
  const store = this.#store;
119
137
 
120
- return Promise.all(
138
+ const results = await Promise.allSettled(
121
139
  contentFilesData.map(function (contentFile) {
122
140
  return store.save(contentFile, contentFile.targetDir).then(function (result) {
123
141
  return {
@@ -128,6 +146,50 @@ class ContentFileImporter {
128
146
  });
129
147
  }),
130
148
  );
149
+
150
+ const failure = results.find((result) => result.status === 'rejected');
151
+ if (failure) {
152
+ const storedFiles = results.flatMap((result) =>
153
+ result.status === 'fulfilled' ? [result.value] : [],
154
+ );
155
+ try {
156
+ await this.rollback(storedFiles);
157
+ } catch (rollbackFailure) {
158
+ // AggregateError is the native error for preserving both storage failures;
159
+ // it is not a GhostError and therefore does not accept an options object.
160
+ // eslint-disable-next-line ghost/ghost-custom/ghost-error-usage
161
+ throw new AggregateError(
162
+ [failure.reason, rollbackFailure],
163
+ 'Asset storage failed and rollback was incomplete.',
164
+ { cause: failure.reason },
165
+ );
166
+ }
167
+ throw failure.reason;
168
+ }
169
+
170
+ return results.map((result) => result.value);
171
+ }
172
+
173
+ /**
174
+ * @param {{stored: string}[]} storedFiles
175
+ * @returns {Promise<void>}
176
+ */
177
+ async rollback(storedFiles) {
178
+ const store = this.#store;
179
+ const results = await Promise.allSettled(
180
+ storedFiles.map(function (storedFile) {
181
+ const storedPath = store.urlToPath(storedFile.stored);
182
+ const targetDir = path.posix.dirname(storedPath);
183
+ return store.delete(
184
+ path.posix.basename(storedPath),
185
+ targetDir === '.' ? undefined : targetDir,
186
+ );
187
+ }),
188
+ );
189
+ const failure = results.find((result) => result.status === 'rejected');
190
+ if (failure) {
191
+ throw failure.reason;
192
+ }
131
193
  }
132
194
  }
133
195
 
@@ -0,0 +1,42 @@
1
+ const logging = require('@tryghost/logging');
2
+ const {
3
+ combineNonTransactionalMigrations,
4
+ createAddColumnMigration,
5
+ createNonTransactionalMigration,
6
+ } = require('../../utils');
7
+
8
+ const TABLE = 'members_custom_field_values';
9
+
10
+ // Who wrote the value that is here now: a type and an id, the way `actions` records an
11
+ // actor. The type is required because it is the namespace the id resolves in, and a value
12
+ // nobody can be traced to is not a record of provenance. The id is nullable for the one
13
+ // writer that resolves in no table — an import, until runs are tracked.
14
+ //
15
+ // Existing rows have a writer nobody can recover, so they go rather than get backfilled:
16
+ // the feature is behind the `membersCustomFields` flag with no released data, and adding
17
+ // a required column over them ends either in an error, as SQLite refuses one with no
18
+ // default, or in an invented writer wherever the engine supplies its own empty string.
19
+ module.exports = combineNonTransactionalMigrations(
20
+ createNonTransactionalMigration(
21
+ async function up(knex) {
22
+ if (!(await knex.schema.hasColumn(TABLE, 'written_by_type'))) {
23
+ logging.info(`Clearing ${TABLE} of values with no recorded writer`);
24
+ await knex(TABLE).del();
25
+ }
26
+ },
27
+ async function down() {
28
+ // Nothing to undo: the rows are gone, and dropping the columns below is what a
29
+ // rollback is for.
30
+ },
31
+ ),
32
+ createAddColumnMigration(TABLE, 'written_by_type', {
33
+ type: 'string',
34
+ maxlength: 50,
35
+ nullable: false,
36
+ }),
37
+ createAddColumnMigration(TABLE, 'written_by_id', {
38
+ type: 'string',
39
+ maxlength: 24,
40
+ nullable: true,
41
+ }),
42
+ );
@@ -0,0 +1,26 @@
1
+ const { addTable } = require('../../utils');
2
+
3
+ module.exports = addTable('members_custom_field_bindings', {
4
+ id: { type: 'string', maxlength: 24, nullable: false, primary: true },
5
+ product_id: {
6
+ type: 'string',
7
+ maxlength: 24,
8
+ nullable: false,
9
+ references: 'products.id',
10
+ cascadeDelete: true,
11
+ },
12
+ port: { type: 'string', maxlength: 191, nullable: false },
13
+ custom_field_key: {
14
+ type: 'string',
15
+ maxlength: 191,
16
+ nullable: false,
17
+ references: 'members_custom_fields.key',
18
+ cascadeDelete: true,
19
+ },
20
+ created_at: { type: 'dateTime', nullable: false },
21
+ updated_at: { type: 'dateTime', nullable: true },
22
+ '@@UNIQUE_CONSTRAINTS@@': [
23
+ { columns: ['product_id', 'port'], indexName: 'members_custom_field_bindings_unique' },
24
+ ],
25
+ '@@INDEXES@@': [['custom_field_key']],
26
+ });
@@ -0,0 +1,35 @@
1
+ const { combineNonTransactionalMigrations, addTable } = require('../../utils');
2
+
3
+ module.exports = combineNonTransactionalMigrations(
4
+ addTable('products_checkout_fields', {
5
+ id: { type: 'string', maxlength: 24, nullable: false, primary: true },
6
+ binding_id: {
7
+ type: 'string',
8
+ maxlength: 24,
9
+ nullable: false,
10
+ unique: true,
11
+ references: 'members_custom_field_bindings.id',
12
+ cascadeDelete: true,
13
+ },
14
+ sort_order: { type: 'integer', nullable: false, unsigned: true, defaultTo: 0 },
15
+ label: { type: 'string', maxlength: 191, nullable: true },
16
+ optional: { type: 'boolean', nullable: false, defaultTo: true },
17
+ created_at: { type: 'dateTime', nullable: false },
18
+ updated_at: { type: 'dateTime', nullable: true },
19
+ }),
20
+ addTable('products_checkout_config', {
21
+ id: { type: 'string', maxlength: 24, nullable: false, primary: true },
22
+ product_id: {
23
+ type: 'string',
24
+ maxlength: 24,
25
+ nullable: false,
26
+ unique: true,
27
+ references: 'products.id',
28
+ cascadeDelete: true,
29
+ },
30
+ shipping_allowed_countries: { type: 'string', maxlength: 2000, nullable: true },
31
+ tax_number_collect: { type: 'boolean', nullable: false, defaultTo: false },
32
+ created_at: { type: 'dateTime', nullable: false },
33
+ updated_at: { type: 'dateTime', nullable: true },
34
+ }),
35
+ );