ghost 6.60.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.
- package/components/ghost-storage-base-3.0.0.tgz +0 -0
- package/components/tryghost-adapter-base-cache-0.2.0.tgz +0 -0
- package/components/tryghost-adapter-base-jobs-0.0.0.tgz +0 -0
- package/components/tryghost-adapter-base-redirects-0.0.0.tgz +0 -0
- package/components/tryghost-adapter-base-route-settings-0.0.0.tgz +0 -0
- package/components/tryghost-adapter-base-scheduling-0.2.3.tgz +0 -0
- package/components/tryghost-adapter-base-sso-0.1.3.tgz +0 -0
- package/components/tryghost-admin-api-schema-0.0.0.tgz +0 -0
- package/components/tryghost-checkout-0.0.0.tgz +0 -0
- package/components/tryghost-custom-field-types-0.0.0.tgz +0 -0
- package/components/tryghost-i18n-0.0.0.tgz +0 -0
- package/components/tryghost-kg-card-factory-5.2.4.tgz +0 -0
- package/components/tryghost-kg-clean-basic-html-4.3.4.tgz +0 -0
- package/components/tryghost-kg-converters-1.2.5.tgz +0 -0
- package/components/tryghost-kg-default-cards-10.3.5.tgz +0 -0
- package/components/tryghost-kg-default-nodes-2.2.1.tgz +0 -0
- package/components/tryghost-kg-default-transforms-1.3.4.tgz +0 -0
- package/components/tryghost-kg-html-to-lexical-1.4.0.tgz +0 -0
- package/components/tryghost-kg-lexical-html-renderer-1.5.0.tgz +0 -0
- package/components/tryghost-kg-markdown-html-renderer-7.2.4.tgz +0 -0
- package/components/tryghost-kg-utils-1.1.4.tgz +0 -0
- package/components/tryghost-nql-string-0.0.0.tgz +0 -0
- package/components/tryghost-parse-email-address-0.0.0.tgz +0 -0
- package/content/settings/README.md +1 -1
- package/content/themes/casper/.gitignore +28 -0
- package/content/themes/casper/assets/built/casper.js +1 -1
- package/content/themes/casper/assets/built/screen.css +1 -1
- package/content/themes/casper/assets/css/screen.css +2 -1
- package/content/themes/casper/assets/js/lightbox.js +63 -46
- package/content/themes/casper/package.json +6 -6
- package/content/themes/casper/page.hbs +1 -0
- package/content/themes/casper/post.hbs +1 -0
- package/content/themes/source/.gitignore +28 -0
- package/content/themes/source/assets/built/screen.css +1 -1
- package/content/themes/source/assets/built/source.js +1 -1
- package/content/themes/source/assets/css/screen.css +2 -1
- package/content/themes/source/assets/js/lightbox.js +62 -45
- package/content/themes/source/assets/js/main.js +2 -2
- package/content/themes/source/package.json +4 -4
- package/content/themes/source/partials/feature-image.hbs +1 -0
- package/core/boot.js +62 -21
- package/core/built/admin/assets/Combination-B0l4MKVh.js +41 -0
- package/core/built/admin/assets/InterVariable-DiVDrmQJ.woff2 +0 -0
- package/core/built/admin/assets/InterVariable-Italic-FCBEiFp6.woff2 +0 -0
- package/core/built/admin/assets/{PolarAngleAxis-C4qtHy1B.js → PolarAngleAxis-pkMyqz8g.js} +1 -1
- package/core/built/admin/assets/{RadialBarChart-Bh09Stsj.js → RadialBarChart-JAKoS4KT.js} +1 -1
- package/core/built/admin/assets/{about-BgpmhCuM.js → about-Dyae_UT6.js} +1 -1
- package/core/built/admin/assets/account-migration-CESa0mnX.js +1 -0
- package/core/built/admin/assets/{action-list-lGzZLHc8.js → action-list-C4v0-du8.js} +1 -1
- package/core/built/admin/assets/activitypub/{account-migration-DMHuPnJn.js → account-migration-By69CgCp.js} +16 -16
- package/core/built/admin/assets/activitypub/activitypub.js +9 -10
- package/core/built/admin/assets/activitypub/{avatar-DhTo5D1B.js → avatar-DLPL3Abs.js} +59 -68
- package/core/built/admin/assets/activitypub/{avatar-flipboard-DnVgbEfa.js → avatar-flipboard-C9iDY-QV.js} +2 -2
- package/core/built/admin/assets/activitypub/{bluesky-sharing-BT4zAlW7.js → bluesky-sharing-BJcPMrDd.js} +37 -37
- package/core/built/admin/assets/activitypub/{content-formatters-BeDZ-DIa.js → content-formatters-3rTHg3mp.js} +18 -18
- package/core/built/admin/assets/activitypub/{copy-8sqxUuNd.js → copy-DIAOQoCZ.js} +2 -2
- package/core/built/admin/assets/activitypub/{domain-xQDDu1CS.js → domain-DUR4xSkV.js} +121 -121
- package/core/built/admin/assets/activitypub/{edit-profile-BXdF_r2G.js → edit-profile-BqtfzxCp.js} +40 -40
- package/core/built/admin/assets/activitypub/{explore-CMt7gKlL.js → explore-BxuJd-J4.js} +27 -27
- package/core/built/admin/assets/activitypub/{feed-Bwqdddp_.js → feed-BM1TcksA.js} +51 -51
- package/core/built/admin/assets/activitypub/{field-4co_8FVg.js → field-Dn7HHx2-.js} +3 -3
- package/core/built/admin/assets/activitypub/{hash-DwakMs4X.js → hash-Bm3WxYN4.js} +2 -2
- package/core/built/admin/assets/activitypub/inbox-CCjkuow2.js +1284 -0
- package/core/built/admin/assets/activitypub/{inbox-ckD4wo_r.js → inbox-d8oJRTf4.js} +2 -2
- package/core/built/admin/assets/activitypub/label-1AA_s9Fa.js +16 -0
- package/core/built/admin/assets/activitypub/layout-2-0bw6HN.js +1 -0
- package/core/built/admin/assets/activitypub/{moderation-KCCO7L2J.js → moderation-CnmxEB8w.js} +91 -91
- package/core/built/admin/assets/activitypub/{note-BX_Bz5A0.js → note-ZKc_Bnba.js} +24 -24
- package/core/built/admin/assets/activitypub/{notifications-BQOYGvRv.js → notifications-CB2tJZau.js} +51 -51
- package/core/built/admin/assets/activitypub/{onboarding-CNelD_uF.js → onboarding-BsJ9E5qf.js} +2 -2
- package/core/built/admin/assets/activitypub/{onboarding-mat5Hrl0.js → onboarding-CSUJJIlh.js} +2 -2
- package/core/built/admin/assets/activitypub/{preferences-6h43G9_q.js → preferences-0-JZnUkI.js} +1519 -1519
- package/core/built/admin/assets/activitypub/{profile-BMN9VVZ2.js → profile-C35cFIhM.js} +256 -256
- package/core/built/admin/assets/activitypub/{reply-ZNo04xsO.js → reply-DYK5vVqb.js} +2 -2
- package/core/built/admin/assets/activitypub/{routes-3B9mUQ7i.js → routes-BD4vscyc.js} +796 -790
- package/core/built/admin/assets/activitypub/{separator-D9taVCCa.js → separator-BbQqTm-p.js} +3 -3
- package/core/built/admin/assets/activitypub/settings-BsMROdqh.js +315 -0
- package/core/built/admin/assets/activitypub/{site-DHoMupSB.js → site-O0RL9YCN.js} +2 -2
- package/core/built/admin/assets/activitypub/{step-1-BsGGnBuT.js → step-1-BMSx7c_X.js} +6 -6
- package/core/built/admin/assets/activitypub/{step-2-teosIS0k.js → step-2-DtPQzlTH.js} +6 -6
- package/core/built/admin/assets/activitypub/{step-3-BjD5TokC.js → step-3-CLlOZTyt.js} +11 -11
- package/core/built/admin/assets/activitypub/{tabs-Cvwl1wXU.js → tabs-Dxk-b9M-.js} +306 -306
- package/core/built/admin/assets/activitypub/{topic-filter-C3LZJc2X.js → topic-filter-5yZH6tId.js} +3 -3
- package/core/built/admin/assets/activitypub/{use-activity-pub-queries-Dp9f0gov.js → use-activity-pub-queries-CV50qe03.js} +3 -3
- package/core/built/admin/assets/activitypub/{use-navigate-with-base-path-C4RI0sa9.js → use-navigate-with-base-path-Bmk5h4lW.js} +220 -220
- package/core/built/admin/assets/activitypub/{use-reply-chain-data-C2oNDMUH.js → use-reply-chain-data-Cbvzgjzd.js} +30 -30
- package/core/built/admin/assets/activitypub/{users-CoX6FT_K.js → users-BjcoP_HC.js} +7 -5
- package/core/built/admin/assets/activitypub/{x-Dxm6pV9X.js → x-DbQZOLiI.js} +2 -2
- package/core/built/admin/assets/add-integration-modal-BlF6rs_f.js +1 -0
- package/core/built/admin/assets/add-newsletter-modal-CglVQqah.js +1 -0
- package/core/built/admin/assets/add-recommendation-modal-wz7BsuaG.js +1 -0
- package/core/built/admin/assets/analytics-C4HE1gBg.js +1 -0
- package/core/built/admin/assets/{announcement-bar-modal-BTHiy1ZO.js → announcement-bar-modal-Ci4zz8jO.js} +1 -1
- package/core/built/admin/assets/{api-keys-Boy5pLbD.js → api-keys-Ck-Yteiv.js} +1 -1
- package/core/built/admin/assets/audience-CtbA54Sn.js +1 -0
- package/core/built/admin/assets/{automated-emails-te1D5kq-.js → automated-emails-D5VVMND9.js} +1 -1
- package/core/built/admin/assets/automations-CzKt5fb8.js +1 -0
- package/core/built/admin/assets/bluesky-sharing-BEtJ_gL_.js +1 -0
- package/core/built/admin/assets/{box-By_EgGtm.js → box-CdfQAP_F.js} +1 -1
- package/core/built/admin/assets/{brand-icon-09YqFZjV.js → brand-icon-CrIGOA3Z.js} +1 -1
- package/core/built/admin/assets/{breadcrumb-CcFr_ltt.js → breadcrumb-zUrZrBtW.js} +1 -1
- package/core/built/admin/assets/{button-BshWPHvn.js → button-eNMKQWXr.js} +1 -1
- package/core/built/admin/assets/{card-CiiE7QfM.js → card--VNbfgo3.js} +1 -1
- package/core/built/admin/assets/{chart-BnXyfH11.js → chart-BrhA41Zi.js} +1 -1
- package/core/built/admin/assets/chart-helpers-CfBKt0vT.js +1 -0
- package/core/built/admin/assets/{checkbox-Dwwr_3Py.js → checkbox-CgOn_tKW.js} +1 -1
- package/core/built/admin/assets/{chunk.524.91ecb33e6afc3bd8949b.js → chunk.524.a697dee88db67fdf6021.js} +4 -4
- package/core/built/admin/assets/{chunk.582.512549909741883f960c.js → chunk.582.5ed5d124cfca9c259b9c.js} +6 -6
- package/core/built/admin/assets/{chunk.16.f76a6314082d813d67e0.js → chunk.598.7e056fabb47ce7dbd73f.js} +14 -14
- package/core/built/admin/assets/{code-editor-view-BwIdPy_k.js → code-editor-view-BYNoAoNV.js} +1 -1
- package/core/built/admin/assets/{code-editor-view-CtkF82Fv.js → code-editor-view-K2wI-I5f.js} +1 -1
- package/core/built/admin/assets/color-picker-Ddw80xX6.js +3 -0
- package/core/built/admin/assets/color-picker-field-D9nUhvA7.js +1 -0
- package/core/built/admin/assets/combobox-w9j8PPQT.js +1 -0
- package/core/built/admin/assets/command-BfpHORBv.js +1 -0
- package/core/built/admin/assets/comments-BLmCmyCs.js +1 -0
- package/core/built/admin/assets/confirmation-context-CBM8G0Vj.js +1 -0
- package/core/built/admin/assets/{container-LiZf3XdY.js → container-BuQG1wuP.js} +1 -1
- package/core/built/admin/assets/{content-api-modal-BtpNI92-.js → content-api-modal-TXRz3U7S.js} +1 -1
- package/core/built/admin/assets/context-menu-_QMdd3kp.js +1 -0
- package/core/built/admin/assets/{copy-field-CglgRZyG.js → copy-field-6N01S07E.js} +1 -1
- package/core/built/admin/assets/create-ghost-browse-value-source-qIBymvvf.js +1 -0
- package/core/built/admin/assets/custom-field-type-option-BddFlJFa.js +1 -0
- package/core/built/admin/assets/custom-integration-modal-DmNquxUV.js +1 -0
- package/core/built/admin/assets/{data-list-CupF7bjM.js → data-list-CA2jYGPq.js} +1 -1
- package/core/built/admin/assets/{date-range-select-JPwM0yUj.js → date-range-select-uvz_DtPh.js} +1 -1
- package/core/built/admin/assets/design-and-theme-modal-BSmo12Op.js +2 -0
- package/core/built/admin/assets/{detail-page-D8lx2SdP.js → detail-page-Dnv-CdR1.js} +1 -1
- package/core/built/admin/assets/dirty-confirm-dialog-BZ1iytEd.js +1 -0
- package/core/built/admin/assets/{disabled-sources-indicator-BTJ2ClQu.js → disabled-sources-indicator-DMRrxsiJ.js} +1 -1
- package/core/built/admin/assets/{dist-DzcfoDJ3.js → dist-8YJUlf3B.js} +1 -1
- package/core/built/admin/assets/{dist-Cb5RSHSg.js → dist-B3keLvjj.js} +1 -1
- package/core/built/admin/assets/dist-Dcsslyo72.js +1 -0
- package/core/built/admin/assets/{dist-BT_Z-eCn.js → dist-Dgt2cr6a.js} +1 -1
- package/core/built/admin/assets/domain-BNYrt0aD.js +1 -0
- package/core/built/admin/assets/dropzone-D7nFdAe5.js +5 -0
- package/core/built/admin/assets/edit-profile-C5Asm4LA.js +1 -0
- package/core/built/admin/assets/editor-REokrzci.js +8 -0
- package/core/built/admin/assets/{embed-signup-form-modal-BFTPf04i.js → embed-signup-form-modal-Ds6mPEi5.js} +1 -1
- package/core/built/admin/assets/{empty-indicator-WB1WgT9h.js → empty-indicator-D9QdpuNX.js} +1 -1
- package/core/built/admin/assets/en-B1jX3WMs.js +1 -0
- package/core/built/admin/assets/explore-UY10Egsp.js +1 -0
- package/core/built/admin/assets/feature-image-placeholder-D1iF_8bc.js +1 -0
- package/core/built/admin/assets/feed-81C8mJWR.js +1 -0
- package/core/built/admin/assets/{field-LmNk7wZh.js → field-Dihp5p18.js} +1 -1
- package/core/built/admin/assets/filter-bar-Da1qxybu.js +1 -0
- package/core/built/admin/assets/filter-sources-BO9xUPj7.js +1 -0
- package/core/built/admin/assets/filters-CRUWecfY.js +1 -0
- package/core/built/admin/assets/filters-DirqNXjH.js +1 -0
- package/core/built/admin/assets/first-promoter-modal-CT6MxYZb.js +1 -0
- package/core/built/admin/assets/{ghost-c8807202a07c20030acb719ee0114815.css → ghost-8eabfc1ece81b03cf7b90780d31487e8.css} +1 -1
- package/core/built/admin/assets/{ghost-403cb39badad3df411fc0ba27d220047.js → ghost-c2848508292937415f20f5a830eea59e.js} +31 -28
- package/core/built/admin/assets/{ghost-dark-fbf1e384aaef3ae315e540f0eb7373a7.css → ghost-dark-a7bebe2c561f55369dcf29f4c820f7ff.css} +1 -1
- package/core/built/admin/assets/gift-link-modal-CQVAye17.js +1 -0
- package/core/built/admin/assets/{grid-CUciBfjf.js → grid-Dj29PY05.js} +1 -1
- package/core/built/admin/assets/growth-BWIu-6xj.js +3 -0
- package/core/built/admin/assets/growth-DU29oxeA.js +1 -0
- package/core/built/admin/assets/{heading-CRZZ2FUe.js → heading-Dh5SFVjL.js} +1 -1
- package/core/built/admin/assets/history-modal-CFd1Hvx6.js +1 -0
- package/core/built/admin/assets/html-field-CJBCLTvv.js +1 -0
- package/core/built/admin/assets/{images-C0XvUYMb.js → images-scfkWZiK.js} +1 -1
- package/core/built/admin/assets/{inbox-DZXDUt4s.js → inbox-Mcp4DXZN.js} +14 -14
- package/core/built/admin/assets/index-6MkPdCtr.js +4 -0
- package/core/built/admin/assets/index-Bn7QhcZu.css +2 -0
- package/core/built/admin/assets/index.es-CNnuNH0d.js +1 -0
- package/core/built/admin/assets/{inline-Cw-gigDW.js → inline-BWSs_VzR.js} +1 -1
- package/core/built/admin/assets/{input-group-BPAxETpQ.js → input-group-CMhe2DvY.js} +1 -1
- package/core/built/admin/assets/{input-surface-BdOe4KzO.js → input-surface-BsrIZeSF.js} +1 -1
- package/core/built/admin/assets/{integration-header-B4DyXV06.js → integration-header-Bm6IDb1A.js} +1 -1
- package/core/built/admin/assets/invite-user-modal-DfheMXs0.js +1 -0
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +14 -14
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +3 -3
- package/core/built/admin/assets/koenig-lexical/style.css +1 -1
- package/core/built/admin/assets/{koenig-lexical-60O_8aiO.js → koenig-lexical-DBSqAuiI.js} +3 -3
- package/core/built/admin/assets/koenig-loader-aFQNlJlD.js +2 -0
- package/core/built/admin/assets/kpi-card-DBRMfGOW.js +1 -0
- package/core/built/admin/assets/{kpi-card-fUHZlzBX.js → kpi-card-DFafD1qq.js} +1 -1
- package/core/built/admin/assets/kpi-helpers-Cv8i8hns.js +1 -0
- package/core/built/admin/assets/kpi-tabs-BJItvLYm.js +1 -0
- package/core/built/admin/assets/{label-VIG969IC.js → label-BnSCvffu.js} +1 -1
- package/core/built/admin/assets/label-picker-KVoo91sh.js +1 -0
- package/core/built/admin/assets/layout-Bjv2Ll-5.js +1 -0
- package/core/built/admin/assets/{link-helpers-Dtq9fxQg.js → link-helpers-MVDdnFCY.js} +1 -1
- package/core/built/admin/assets/{list-page-CdsnQR9N.js → list-page-BucXJ0hi.js} +1 -1
- package/core/built/admin/assets/member-custom-fields-DDQV6QeG.js +1 -0
- package/core/built/admin/assets/member-detail-CdJF6Agw.js +1 -0
- package/core/built/admin/assets/members-DjQbq9Z2.js +4 -0
- package/core/built/admin/assets/{modal-page-BMTzFHVO.js → modal-page-xCivTMvI.js} +1 -1
- package/core/built/admin/assets/moderation-AgCIEso4.js +1 -0
- package/core/built/admin/assets/{multi-select-combobox-CGohnsxJ.js → multi-select-combobox-BcITkUVr.js} +1 -1
- package/core/built/admin/assets/navigation-modal-BkT7b1M2.js +1 -0
- package/core/built/admin/assets/newsletter-BMMAuvgq.js +1 -0
- package/core/built/admin/assets/newsletter-detail-modal-0SCJ7Zpm.js +1 -0
- package/core/built/admin/assets/{newsletter-emails-D5ql1rud.js → newsletter-emails-DKzwafuh.js} +1 -1
- package/core/built/admin/assets/newsletters-BRBb_uQC.js +1 -0
- package/core/built/admin/assets/note-DyGHtS9a.js +1 -0
- package/core/built/admin/assets/notifications-ZgWniKna.js +1 -0
- package/core/built/admin/assets/nql-BLpCn7qX.js +21 -0
- package/core/built/admin/assets/offers-container-modal-B-E8TIWr.js +1 -0
- package/core/built/admin/assets/{onboarding-B4YhlZ0i.js → onboarding-CzIsre-d.js} +1 -1
- package/core/built/admin/assets/onboarding-qg8Akovm.js +1 -0
- package/core/built/admin/assets/{onboarding-route-Cu_ROWPn.js → onboarding-route-CaavZulg.js} +1 -1
- package/core/built/admin/assets/overview-BW8GLeYi.js +1 -0
- package/core/built/admin/assets/overview-BkXZNzaZ.js +1 -0
- package/core/built/admin/assets/{page-header-Cfds8pCg.js → page-header-De0VzKBi.js} +1 -1
- package/core/built/admin/assets/pagemenu-B5KKCpbA.js +1 -0
- package/core/built/admin/assets/pages-jgaFm69d.js +1 -0
- package/core/built/admin/assets/pages-route-CIUAQxtY.js +1 -0
- package/core/built/admin/assets/papaparse.min-cQwnxGCG.js +10 -0
- package/core/built/admin/assets/{pintura-modal-TDTrJ89x.js → pintura-modal-BZ2J9w3n.js} +1 -1
- package/core/built/admin/assets/portal-frame-B6Hr9wHc.js +1 -0
- package/core/built/admin/assets/portal-modal-D4ceei3t.js +1 -0
- package/core/built/admin/assets/post-analytics-header-BYCsT0GP.js +1 -0
- package/core/built/admin/assets/post-analytics-ot7f6pih.js +1 -0
- package/core/built/admin/assets/{post-analytics-provider-Cu3jNeFh.js → post-analytics-provider-Bo1gmYaP.js} +1 -1
- package/core/built/admin/assets/{post-share-modal-P1_M6o-H.js → post-share-modal-C-PaYZ_e.js} +1 -1
- package/core/built/admin/assets/posts-DuGazgTb.js +1 -0
- package/core/built/admin/assets/posts-list-screen-CBGGgjjj.js +2 -0
- package/core/built/admin/assets/posts-route-D6xmS7Vf.js +1 -0
- package/core/built/admin/assets/preferences-C5YJLp74.js +5 -0
- package/core/built/admin/assets/{preview-chrome-BOVO6_PE.js → preview-chrome-BljUBlOk.js} +1 -1
- package/core/built/admin/assets/{preview-modal-MlTjP8UU.js → preview-modal-BfeFqi5y.js} +1 -1
- package/core/built/admin/assets/profile-B8mx2yAu.js +1 -0
- package/core/built/admin/assets/{radio-group-CjtmsCPl.js → radio-group-DczlLKOn.js} +1 -1
- package/core/built/admin/assets/{router-provider-CJC58zTy.js → router-provider-B0gZyiGJ.js} +1 -1
- package/core/built/admin/assets/{schemas-CRsC53ls.js → schemas-DppqmpeJ.js} +2 -2
- package/core/built/admin/assets/select-cb0t_TAJ.js +1 -0
- package/core/built/admin/assets/settings-DZqxR0Da.js +1 -0
- package/core/built/admin/assets/settings-DvfTNdHQ.js +4 -0
- package/core/built/admin/assets/{settings-breadcrumbs-sLDNedBW.js → settings-breadcrumbs-DLzbRRSt.js} +1 -1
- package/core/built/admin/assets/{shade-app-F7WxOyfk-nufqw1hd.js → shade-app-CcS3f8MZ-vwURazk8.js} +2 -2
- package/core/built/admin/assets/share-modal-D2-Bz1_I.js +1 -0
- package/core/built/admin/assets/{skeleton-D7hwjdry.js → skeleton-Ce9GgUpf.js} +1 -1
- package/core/built/admin/assets/slack-modal-DYDTUria.js +1 -0
- package/core/built/admin/assets/sort-button-VVeQjjbu.js +1 -0
- package/core/built/admin/assets/{source-icon-BPsD5ees.js → source-icon-Ck5_5Kgq.js} +1 -1
- package/core/built/admin/assets/{stack-CIfOAAVf.js → stack-B2eszIiq.js} +1 -1
- package/core/built/admin/assets/stats-Rjmk5owg.js +1 -0
- package/core/built/admin/assets/stats-view-BGGmkmgv.js +1 -0
- package/core/built/admin/assets/{step-1-CMta6YFO.js → step-1-CsaBjeN4.js} +1 -1
- package/core/built/admin/assets/{step-2-BG04nh5q.js → step-2-D2vnxOOM.js} +1 -1
- package/core/built/admin/assets/{step-3-ZnMaVIPj.js → step-3-wBoLdGEb.js} +2 -2
- package/core/built/admin/assets/{stripe-button-DDoUKN5a.js → stripe-button-CDgLz0S0.js} +1 -1
- package/core/built/admin/assets/stripe-connect-modal-CSjMJetP.js +1 -0
- package/core/built/admin/assets/{switch-C9djUIMO.js → switch-CI4gLWqb.js} +1 -1
- package/core/built/admin/assets/{table-CrqQtkR2.js → table-Do6iQ83Q.js} +1 -1
- package/core/built/admin/assets/{tabs-CGisSbWq.js → tabs-D2yWLMp_.js} +1 -1
- package/core/built/admin/assets/tag-detail-BhXlOsCa.js +2 -0
- package/core/built/admin/assets/tags-ldukRApe.js +1 -0
- package/core/built/admin/assets/testimonials-modal-CtnZBJKl.js +1 -0
- package/core/built/admin/assets/{text-DU9Hv33_.js → text-BQDSDsKs.js} +1 -1
- package/core/built/admin/assets/{textarea-d9qEkMOP.js → textarea-DJ1Q5V39.js} +1 -1
- package/core/built/admin/assets/tier-detail-modal-BOs8e_G8.js +1 -0
- package/core/built/admin/assets/{toggle-group-CtKZURJd.js → toggle-group-ByUJsxwD.js} +1 -1
- package/core/built/admin/assets/{topic-filter-D8JT8Tq1.js → topic-filter-BgC3g5_v.js} +1 -1
- package/core/built/admin/assets/{transistor-modal-6PUf0idx.js → transistor-modal-Drr0SNfo.js} +1 -1
- package/core/built/admin/assets/trend-badge-6ye93YAW.js +1 -0
- package/core/built/admin/assets/{unsplash-modal-BPuDBPja.js → unsplash-modal-p6AoQoWp.js} +1 -1
- package/core/built/admin/assets/{use-analytics-data--opuzwcz.js → use-analytics-data-CWCMAESo.js} +1 -1
- package/core/built/admin/assets/use-check-theme-limit-error-B8bjF-gO.css +1 -0
- package/core/built/admin/assets/use-check-theme-limit-error-Cw3WQHy8.js +2 -0
- package/core/built/admin/assets/use-filter-params-BIni9taJ.js +1 -0
- package/core/built/admin/assets/use-growth-stats-DCVG3s9w.js +1 -0
- package/core/built/admin/assets/{use-limiter-TDSNiHPB.js → use-limiter-D2WRRx0H.js} +1 -1
- package/core/built/admin/assets/{use-navigate-with-base-path-CK989MlC.js → use-navigate-with-base-path-BHPA228f.js} +1 -1
- package/core/built/admin/assets/{use-pintura-config-CnCGrDFk.js → use-pintura-config-h-J0Lvta.js} +1 -1
- package/core/built/admin/assets/{use-pintura-editor-ntphvtUd.js → use-pintura-editor-BfN1UwzH.js} +1 -1
- package/core/built/admin/assets/use-post-referrers-Czg47m8s.js +1 -0
- package/core/built/admin/assets/use-reply-chain-data-ns0caK8k.js +1 -0
- package/core/built/admin/assets/{use-router-history-entry-BwfQS2mq.js → use-router-history-entry-uldn7zJO.js} +1 -1
- package/core/built/admin/assets/{use-setting-group-DQxV42-O.js → use-setting-group-DpcuCUDg.js} +1 -1
- package/core/built/admin/assets/use-settings-navigation-CZjGrhsp.js +1 -0
- package/core/built/admin/assets/{use-simple-pagination-B2TdNX67.js → use-simple-pagination-DzJWobPR.js} +1 -1
- package/core/built/admin/assets/{use-staff-users-QrR9voeC.js → use-staff-users-Csipb-O0.js} +1 -1
- package/core/built/admin/assets/use-tinybird-query-CSnGXzZh.js +1 -0
- package/core/built/admin/assets/use-tinybird-token-DTOKRR7e.js +1 -0
- package/core/built/admin/assets/{use-unsaved-changes-guard-DpYJcj1d.js → use-unsaved-changes-guard-CBzs-KPi.js} +1 -1
- package/core/built/admin/assets/{use-url-input-WnIqckzS.js → use-url-input-DFr8lCbS.js} +1 -1
- package/core/built/admin/assets/user-detail-modal-B_iUClI6.js +1 -0
- package/core/built/admin/assets/users-Cg-OeGzC.js +1 -0
- package/core/built/admin/assets/{virtual-list-D3MfPNOh.js → virtual-list-BW-padMe.js} +1 -1
- package/core/built/admin/assets/web-C1v33ehA.js +2 -0
- package/core/built/admin/assets/web-C4BKzn2T.js +1 -0
- package/core/built/admin/assets/{zapier-modal-BO6PS_Vd.js → zapier-modal-BBFfI6Ml.js} +1 -1
- package/core/built/admin/index.html +24 -30
- package/core/frontend/apps/private-blogging/lib/views/private.hbs +44 -43
- package/core/frontend/helpers/cancel_link.js +2 -2
- package/core/frontend/helpers/pagination.js +2 -2
- package/core/frontend/helpers/social_accounts.js +2 -2
- package/core/frontend/public/ghost.css +1 -1
- package/core/frontend/public/ghost.min.css +1 -1
- package/core/frontend/services/rendering/renderer.js +15 -0
- package/core/frontend/services/sitemap/user-map-generator.js +9 -2
- package/core/server/adapters/storage/LocalStorageBase.js +8 -5
- package/core/server/api/endpoints/db.js +19 -5
- package/core/server/api/endpoints/index.js +6 -2
- package/core/server/api/endpoints/mail.js +1 -1
- package/core/server/api/endpoints/member-metafields.js +89 -0
- package/core/server/api/endpoints/members.js +4 -4
- package/core/server/api/endpoints/posts.js +4 -3
- package/core/server/api/endpoints/tiers-checkout-config.js +59 -0
- package/core/server/api/endpoints/utils/serializers/input/members.js +4 -7
- package/core/server/api/endpoints/utils/serializers/output/config.js +1 -0
- package/core/server/api/endpoints/utils/serializers/output/index.js +6 -2
- package/core/server/api/endpoints/utils/serializers/output/{member-custom-fields.js → member-metafields.js} +2 -4
- package/core/server/api/endpoints/utils/serializers/output/members.js +2 -4
- package/core/server/api/endpoints/utils/serializers/output/tiers-checkout-config.js +12 -0
- package/core/server/api/endpoints/utils/validators/input/invitations.js +0 -5
- package/core/server/api/endpoints/utils/validators/input/pages.js +1 -1
- package/core/server/api/endpoints/utils/validators/input/posts.js +1 -1
- package/core/server/data/exporter/table-lists.js +3 -0
- package/core/server/data/importer/content-files.js +57 -0
- package/core/server/data/importer/handlers/image.js +2 -2
- package/core/server/data/importer/import-archive.js +131 -0
- package/core/server/data/importer/import-manager.js +18 -180
- package/core/server/data/importer/importers/content-file-importer.js +66 -4
- package/core/server/data/importer/importers/data/data-importer.js +3 -3
- package/core/server/data/migrations/utils/migrations.js +1 -1
- 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
- package/core/server/data/migrations/versions/6.61/2026-08-19-14-38-53-add-members-custom-field-bindings-table.js +26 -0
- package/core/server/data/migrations/versions/6.61/2026-08-19-14-48-06-add-tier-checkout-field-tables.js +35 -0
- package/core/server/data/schema/schema.js +90 -0
- package/core/server/data/seeders/importers/automation-action-revisions-importer.js +3 -3
- package/core/server/data/seeders/importers/automation-actions-importer.js +3 -3
- package/core/server/data/seeders/importers/automation-run-steps-importer.js +3 -3
- package/core/server/data/seeders/importers/automation-runs-importer.js +5 -5
- package/core/server/data/seeders/importers/automations-importer.js +3 -3
- package/core/server/data/seeders/importers/comment-reports-importer.js +1 -1
- package/core/server/data/seeders/importers/comments-importer.js +1 -1
- package/core/server/data/seeders/importers/email-batches-importer.js +1 -1
- package/core/server/data/seeders/importers/email-recipients-importer.js +1 -1
- package/core/server/data/seeders/importers/emails-importer.js +1 -1
- package/core/server/data/seeders/importers/labels-importer.js +1 -1
- package/core/server/data/seeders/importers/members-click-events-importer.js +1 -1
- package/core/server/data/seeders/importers/members-created-events-importer.js +1 -1
- package/core/server/data/seeders/importers/members-feedback-importer.js +1 -1
- package/core/server/data/seeders/importers/members-importer.js +1 -1
- package/core/server/data/seeders/importers/members-login-events-importer.js +1 -1
- package/core/server/data/seeders/importers/members-products-importer.js +1 -1
- package/core/server/data/seeders/importers/members-status-events-importer.js +1 -1
- package/core/server/data/seeders/importers/members-stripe-customers-importer.js +1 -1
- package/core/server/data/seeders/importers/members-stripe-customers-subscriptions-importer.js +1 -1
- package/core/server/data/seeders/importers/members-subscribe-events-importer.js +1 -1
- package/core/server/data/seeders/importers/members-subscription-created-events-importer.js +1 -1
- package/core/server/data/seeders/importers/offer-redemptions-importer.js +1 -1
- package/core/server/data/seeders/importers/offers-importer.js +1 -1
- package/core/server/data/seeders/importers/posts-importer.js +1 -1
- package/core/server/data/seeders/importers/table-importer.js +2 -2
- package/core/server/data/seeders/importers/tags-importer.js +1 -1
- package/core/server/data/seeders/importers/users-importer.js +1 -1
- package/core/server/data/seeders/importers/web-mentions-importer.js +1 -1
- package/core/server/data/seeders/utils/random.js +3 -3
- package/core/server/ghost-server.js +3 -2
- package/core/server/lib/db-types/boolean.js +18 -0
- package/core/server/lib/image/image-size.js +24 -0
- package/core/server/lib/package-json/parse.js +2 -2
- package/core/server/lib/promise-pool.js +31 -0
- package/core/server/models/member.js +6 -17
- package/core/server/models/post.js +2 -2
- package/core/server/models/relations/authors.js +2 -16
- package/core/server/models/user.js +9 -2
- package/core/server/services/auth/passwordreset.js +13 -0
- package/core/server/services/automations/database-automations-repository.js +26 -26
- package/core/server/services/automations/poll.js +1 -0
- package/core/server/services/comments/comments-controller.js +30 -9
- package/core/server/services/comments/comments-service.js +55 -5
- package/core/server/services/content-import/csv/formula.js +12 -0
- package/core/server/services/content-import/csv/index.js +6 -1
- package/core/server/services/content-import/csv/parse.js +27 -6
- package/core/server/services/content-import/csv/serialize.js +13 -0
- package/core/server/services/content-import/import/assets.js +74 -0
- package/core/server/services/content-import/import/completion-email.js +164 -0
- package/core/server/services/content-import/import/errors-file.js +36 -0
- package/core/server/services/content-import/import/importer.js +204 -54
- package/core/server/services/content-import/import/local-media-url.js +63 -0
- package/core/server/services/content-import/import/media.js +254 -0
- package/core/server/services/content-import/import/post-data.js +1 -1
- package/core/server/services/content-import/import/post-link.js +11 -0
- package/core/server/services/content-import/import/post-repository.js +100 -0
- package/core/server/services/content-import/import/reader.js +9 -2
- package/core/server/services/content-import/import/relations.js +149 -0
- package/core/server/services/content-import/import/report.js +34 -0
- package/core/server/services/content-import/import/row.js +11 -2
- package/core/server/services/content-import/import/schema.js +30 -0
- package/core/server/services/content-import/import/source.js +125 -0
- package/core/server/services/content-import/import/staged-file.js +29 -0
- package/core/server/services/content-import/import/store.js +25 -2
- package/core/server/services/content-import/index.js +58 -34
- package/core/server/services/content-import/jobs/content-csv-import-job.js +20 -0
- package/core/server/services/custom-redirects/redirect-config-parser.js +2 -2
- package/core/server/services/custom-redirects/redirects-service.js +1 -1
- package/core/server/services/custom-redirects/validation.js +1 -1
- package/core/server/services/email-address/email-address-parser.js +30 -38
- package/core/server/services/email-address/email-address-service.js +37 -4
- package/core/server/services/email-analytics/email-analytics-service.js +8 -1
- package/core/server/services/email-analytics/index.js +2 -7
- package/core/server/services/email-analytics/lib/queries.js +7 -1
- package/core/server/services/email-service/batch-sending-service.js +0 -4
- package/core/server/services/email-service/email-renderer.js +14 -4
- package/core/server/services/email-service/email-service-wrapper.js +0 -9
- package/core/server/services/email-service/mailgun-email-provider.js +20 -9
- package/core/server/services/gift-links/schema.js +3 -3
- package/core/server/services/gifts/CONTEXT.md +1 -1
- package/core/server/services/gifts/constants.js +1 -1
- package/core/server/services/gifts/email-templates/gift-delivery.hbs +3 -3
- package/core/server/services/gifts/gift-bookshelf-repository.js +2 -2
- package/core/server/services/gifts/gift-delivery-bookshelf-repository.js +18 -9
- package/core/server/services/gifts/gift-delivery-schema.js +5 -5
- package/core/server/services/gifts/gift-delivery-service.js +4 -0
- package/core/server/services/gifts/gift-email-service.js +0 -1
- package/core/server/services/gifts/gift-schema.js +10 -10
- package/core/server/services/gifts/gift-service.js +4 -2
- package/core/server/services/gifts/index.js +3 -3
- package/core/server/services/gifts/jobs/index.js +4 -4
- package/core/server/services/indexnow-ping/indexnow-ping-service.js +2 -2
- package/core/server/services/invitations/accept.js +4 -2
- package/core/server/services/jobs/job-service.js +0 -9
- package/core/server/services/jobs-service/register-job-handlers.js +25 -15
- package/core/server/services/lib/mailgun-client.js +44 -8
- package/core/server/services/mail/ghost-mailer.js +4 -4
- package/core/server/services/media-inliner/external-media-inliner-job.js +12 -0
- package/core/server/services/media-inliner/external-media-inliner.js +103 -29
- package/core/server/services/media-inliner/service.js +13 -41
- package/core/server/services/media-inliner/types.js +2 -0
- package/core/server/services/member-welcome-emails/service.js +7 -7
- package/core/server/services/members/api.js +1 -0
- package/core/server/services/members/import-export/csv/parse.js +0 -7
- package/core/server/services/members/import-export/export/exporter.js +4 -6
- package/core/server/services/members/import-export/import/completion-email.js +2 -5
- package/core/server/services/members/import-export/import/importer.js +21 -5
- package/core/server/services/members/import-export/import/row.js +0 -3
- package/core/server/services/members/import-export/import/stripe-utils.js +6 -1
- package/core/server/services/members/import-export/index.js +10 -12
- package/core/server/services/members/jobs/clean-expired-comped-job.js +7 -0
- package/core/server/services/members/jobs/clean-expired-comped-task.js +145 -0
- package/core/server/services/members/jobs/index.js +48 -24
- package/core/server/services/members/members-api/controllers/member-controller.js +11 -0
- package/core/server/services/members/members-api/controllers/router-controller.js +3 -6
- package/core/server/services/members/members-api/members-api.js +9 -6
- package/core/server/services/members/members-api/repositories/event-repository.js +0 -4
- package/core/server/services/members/members-api/services/member-bread-service.js +53 -63
- package/core/server/services/members/members-api/services/payments-service.js +47 -1
- package/core/server/services/members/service.js +1 -5
- package/core/server/services/members-custom-fields/actions.js +27 -1
- package/core/server/services/members-custom-fields/bindings-service.js +120 -0
- package/core/server/services/members-custom-fields/codec.js +3 -4
- package/core/server/services/members-custom-fields/definitions-service.js +165 -22
- package/core/server/services/members-custom-fields/filter.js +75 -93
- package/core/server/services/members-custom-fields/index.js +11 -4
- package/core/server/services/members-custom-fields/key.js +2 -1
- package/core/server/services/members-custom-fields/models.js +1 -1
- package/core/server/services/members-custom-fields/queries.js +5 -0
- package/core/server/services/members-custom-fields/schema.js +37 -6
- package/core/server/services/members-custom-fields/serializers.js +3 -5
- package/core/server/services/members-custom-fields/values-service.js +65 -31
- package/core/server/services/mentions/mention-controller.js +23 -21
- package/core/server/services/mentions/process-webmention-job.js +16 -0
- package/core/server/services/mentions/service.js +8 -4
- package/core/server/services/public-config/config.js +7 -0
- package/core/server/services/route-settings/validation-errors.js +1 -1
- package/core/server/services/route-settings/yaml-parser.js +1 -1
- package/core/server/services/settings/settings-service.js +1 -8
- package/core/server/services/settings-helpers/settings-helpers.js +4 -6
- package/core/server/services/slack-ping/slack-ping-service.js +1 -1
- package/core/server/services/staff/staff-service-emails.js +2 -2
- package/core/server/services/stripe/config.js +14 -8
- package/core/server/services/stripe/service.js +10 -1
- package/core/server/services/stripe/services/checkout/completed-session.js +68 -0
- package/core/server/services/stripe/services/checkout/session-options.js +100 -0
- package/core/server/services/stripe/services/webhook/checkout-session-event-service.js +71 -1
- package/core/server/services/stripe/stripe-api.js +31 -0
- package/core/server/services/stripe/stripe-service.js +26 -9
- package/core/server/services/stripe/webhook-controller.js +10 -0
- package/core/server/services/tier-checkout-config/codec.js +99 -0
- package/core/server/services/tier-checkout-config/index.js +26 -0
- package/core/server/services/tier-checkout-config/models.js +63 -0
- package/core/server/services/tier-checkout-config/queries.js +80 -0
- package/core/server/services/tier-checkout-config/schema.js +33 -0
- package/core/server/services/tier-checkout-config/serializers.js +128 -0
- package/core/server/services/tier-checkout-config/service.js +304 -0
- package/core/server/services/tiers/service.js +21 -0
- package/core/server/services/update-check/index.js +13 -13
- package/core/server/services/update-check/jobs/update-check-job.js +7 -0
- package/core/server/services/update-check/update-check-service.js +2 -2
- package/core/server/web/admin/controller.js +1 -1
- package/core/server/web/api/endpoints/admin/routes.js +34 -20
- package/core/server/web/api/middleware/upload.js +2 -2
- package/core/server/web/parent/app.js +5 -0
- package/core/server/web/parent/middleware/filter-query-parameters.js +94 -0
- package/core/server/web/parent/middleware/index.js +1 -0
- package/core/server/web/query-parameter-policy/index.js +9 -0
- package/core/server/web/query-parameter-policy/policy.json +58 -0
- package/core/server/web/query-parameter-policy/schema.js +38 -0
- package/core/shared/config/defaults.json +3 -0
- package/core/shared/config/env/config.testing-mysql.json +4 -1
- package/core/shared/config/env/config.testing.json +3 -0
- package/core/shared/config/overrides.json +4 -2
- package/core/shared/labs.js +9 -15
- package/package.json +25 -25
- package/pnpm-lock.yaml +741 -108
- package/pnpm-workspace.yaml +12 -9
- package/tsconfig.json +2 -3
- package/components/tryghost-kg-default-nodes-2.2.0.tgz +0 -0
- package/core/built/admin/assets/Combination-gnJO3vIw.js +0 -41
- package/core/built/admin/assets/account-migration-8qTEI1i1.js +0 -1
- package/core/built/admin/assets/activitypub/inbox-DQ5CwLma.js +0 -1284
- package/core/built/admin/assets/activitypub/label-B72sfvEU.js +0 -16
- package/core/built/admin/assets/activitypub/layout-CXajhRsL.js +0 -1
- package/core/built/admin/assets/activitypub/settings-71gCm3SO.js +0 -315
- package/core/built/admin/assets/add-integration-modal--YpTq3c0.js +0 -1
- package/core/built/admin/assets/add-newsletter-modal-C8Ix2hol.js +0 -1
- package/core/built/admin/assets/add-recommendation-modal-CScuNFz4.js +0 -1
- package/core/built/admin/assets/alert-dialog-wEbVxANM.js +0 -1
- package/core/built/admin/assets/analytics-Cnji45H5.js +0 -1
- package/core/built/admin/assets/app-utils-D2Wp7ZSS.js +0 -1
- package/core/built/admin/assets/audience-DTLMXAFH.js +0 -1
- package/core/built/admin/assets/automations-BWpRCZ_f.js +0 -1
- package/core/built/admin/assets/bluesky-sharing-DHOpQxff.js +0 -1
- package/core/built/admin/assets/chart-helpers-B3OqQ6Ez.js +0 -1
- package/core/built/admin/assets/color-picker-Bmo1r9Fc.js +0 -3
- package/core/built/admin/assets/color-picker-field-DywowPhF.js +0 -1
- package/core/built/admin/assets/combobox-C4QCh6Yw.js +0 -1
- package/core/built/admin/assets/command-DcLbSifC.js +0 -1
- package/core/built/admin/assets/comments-Bxy_3WyE.js +0 -1
- package/core/built/admin/assets/confirmation-context-CLFHhyyH.js +0 -1
- package/core/built/admin/assets/custom-field-type-option-D0PXoSnP.js +0 -10
- package/core/built/admin/assets/custom-integration-modal-DCIHKN33.js +0 -1
- package/core/built/admin/assets/design-and-theme-modal-CZ-PkW7o.js +0 -23
- package/core/built/admin/assets/dialog-Db7c164G.js +0 -1
- package/core/built/admin/assets/dirty-confirm-dialog-CmARpZQS.js +0 -1
- package/core/built/admin/assets/dist-QLZuGq7o2.js +0 -1
- package/core/built/admin/assets/domain-D0SAtc-T.js +0 -1
- package/core/built/admin/assets/dropzone-CaPOeDRZ.js +0 -5
- package/core/built/admin/assets/edit-profile-By7v5XW5.js +0 -1
- package/core/built/admin/assets/editor-COXn4Atu.js +0 -8
- package/core/built/admin/assets/explore-BsNYrubV.js +0 -1
- package/core/built/admin/assets/feed-8RR1O1bK.js +0 -1
- package/core/built/admin/assets/filter-sources-4C0kF1NU.js +0 -1
- package/core/built/admin/assets/filters-CV5jCb9n.js +0 -1
- package/core/built/admin/assets/filters-Dmr0PoqU.js +0 -1
- package/core/built/admin/assets/first-promoter-modal-OCzSaL3B.js +0 -1
- package/core/built/admin/assets/gift-link-modal-0mzjn5oF.js +0 -1
- package/core/built/admin/assets/growth-55vWlGT_.js +0 -1
- package/core/built/admin/assets/growth-DA5AluYw.js +0 -3
- package/core/built/admin/assets/history-modal-G1s5hHz7.js +0 -1
- package/core/built/admin/assets/html-field-BegxsWpw.js +0 -1
- package/core/built/admin/assets/index-CDP9tIOk.js +0 -4
- package/core/built/admin/assets/index-Dqf2x-ry.css +0 -1
- package/core/built/admin/assets/index.es-BMUCj9TR.js +0 -1
- package/core/built/admin/assets/input-UHrKuvBT.js +0 -1
- package/core/built/admin/assets/invite-user-modal-BrAkxEO3.js +0 -1
- package/core/built/admin/assets/koenig-loader-DwVY_V-H.js +0 -1
- package/core/built/admin/assets/kpi-card-LERqWBoY.js +0 -1
- package/core/built/admin/assets/kpi-helpers-DB3ouhYF.js +0 -1
- package/core/built/admin/assets/kpi-tabs-BGvtMD8S.js +0 -1
- package/core/built/admin/assets/label-picker-BBWykUeA.js +0 -1
- package/core/built/admin/assets/layout-Di5K7doM.js +0 -1
- package/core/built/admin/assets/loading-indicator-SFTqyYVE.js +0 -1
- package/core/built/admin/assets/member-custom-fields-gOv6Hoh3.js +0 -1
- package/core/built/admin/assets/member-detail-D7mZDDp3.js +0 -1
- package/core/built/admin/assets/member-route-0Aa52Ntz.js +0 -1
- package/core/built/admin/assets/members-DvZG9t69.js +0 -2
- package/core/built/admin/assets/moderation-DzzPLDyl.js +0 -1
- package/core/built/admin/assets/navigation-modal-CI8Bx5vn.js +0 -1
- package/core/built/admin/assets/newsletter-Bg3cq5U-.js +0 -1
- package/core/built/admin/assets/newsletter-detail-modal-DQU3r4g2.js +0 -1
- package/core/built/admin/assets/newsletters-DMDfZbMS.js +0 -1
- package/core/built/admin/assets/note-i8k6pjaw.js +0 -1
- package/core/built/admin/assets/notifications-psA_2Ph4.js +0 -1
- package/core/built/admin/assets/offers-container-modal-BWfjSdyg.js +0 -1
- package/core/built/admin/assets/onboarding-DGQuV7Ew.js +0 -1
- package/core/built/admin/assets/overview-C-6xOLaf.js +0 -1
- package/core/built/admin/assets/overview-DaLhpRrC.js +0 -1
- package/core/built/admin/assets/pages-B6vr9F_D.js +0 -1
- package/core/built/admin/assets/popover-CFgqFDvC.js +0 -1
- package/core/built/admin/assets/portal-frame-DjBF-uy2.js +0 -1
- package/core/built/admin/assets/portal-modal-Cf0pBAk8.js +0 -1
- package/core/built/admin/assets/post-analytics-Buz1COoY.js +0 -1
- package/core/built/admin/assets/post-analytics-header-B-P0eFnT.js +0 -1
- package/core/built/admin/assets/posts-KY3aUhVV.js +0 -1
- package/core/built/admin/assets/preferences-Cq1aOiLy.js +0 -5
- package/core/built/admin/assets/profile-D6dHYf2o.js +0 -1
- package/core/built/admin/assets/select-D_RQaXgt.js +0 -1
- package/core/built/admin/assets/settings-B5hJKZ5C.js +0 -1
- package/core/built/admin/assets/settings-DIo_F-MF.js +0 -4
- package/core/built/admin/assets/share-modal-CLBfj377.js +0 -1
- package/core/built/admin/assets/shim-ClF_m5ux.js +0 -1
- package/core/built/admin/assets/slack-modal-Bt9I_tEo.js +0 -1
- package/core/built/admin/assets/sort-button-DMBXF7tP.js +0 -1
- package/core/built/admin/assets/stats-B_YkF7bp.js +0 -1
- package/core/built/admin/assets/stats-view-BOCp9RG8.js +0 -1
- package/core/built/admin/assets/stripe-connect-modal-BeSukI8q.js +0 -1
- package/core/built/admin/assets/tag-detail-2a3BfzTW.js +0 -2
- package/core/built/admin/assets/tags-Dp2_8UzL.js +0 -1
- package/core/built/admin/assets/testimonials-modal-C9nrypNo.js +0 -1
- package/core/built/admin/assets/tier-detail-modal-CxRwgTPR.js +0 -1
- package/core/built/admin/assets/use-check-theme-limit-error-C9-QhGdV.js +0 -1
- package/core/built/admin/assets/use-filter-params-CSpAvgD2.js +0 -1
- package/core/built/admin/assets/use-growth-stats-BOmoPDHJ.js +0 -1
- package/core/built/admin/assets/use-post-referrers-CbXLFIex.js +0 -1
- package/core/built/admin/assets/use-reply-chain-data-JYFKSO83.js +0 -1
- package/core/built/admin/assets/use-settings-navigation-BBzro2-V.js +0 -1
- package/core/built/admin/assets/use-tinybird-query-D2Aeoty5.js +0 -39
- package/core/built/admin/assets/use-tinybird-token-DBuwMmln.js +0 -1
- package/core/built/admin/assets/user-detail-modal-59mBJqxN.js +0 -1
- package/core/built/admin/assets/users-5msE1WMs.js +0 -1
- package/core/built/admin/assets/web-DUuX7nE2.js +0 -2
- package/core/built/admin/assets/web-N8ucs2aG.js +0 -1
- package/core/server/api/endpoints/member-custom-fields.js +0 -100
- package/core/server/services/jobs/worker-model-event-bridge.js +0 -149
- package/core/server/services/members/jobs/clean-expired-comped.js +0 -132
- package/core/server/services/update-check/run-update-check.js +0 -63
- /package/core/server/lib/{db-date.js → db-types/date.js} +0 -0
|
@@ -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
|
|
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
|
|
63
|
-
|
|
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
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
13
|
-
|
|
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
|
-
|
|
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
|
|
|
@@ -99,7 +99,7 @@ DataImporter = {
|
|
|
99
99
|
return Promise.reject(
|
|
100
100
|
new IncorrectUsageError({
|
|
101
101
|
message: 'Wrong importer structure. `meta` is missing.',
|
|
102
|
-
help: 'https://ghost.org/
|
|
102
|
+
help: 'https://docs.ghost.org/migration/custom/',
|
|
103
103
|
}),
|
|
104
104
|
);
|
|
105
105
|
}
|
|
@@ -108,7 +108,7 @@ DataImporter = {
|
|
|
108
108
|
return Promise.reject(
|
|
109
109
|
new IncorrectUsageError({
|
|
110
110
|
message: 'Wrong importer structure. `meta.version` is missing.',
|
|
111
|
-
help: 'https://ghost.org/
|
|
111
|
+
help: 'https://docs.ghost.org/migration/custom/',
|
|
112
112
|
}),
|
|
113
113
|
);
|
|
114
114
|
}
|
|
@@ -119,7 +119,7 @@ DataImporter = {
|
|
|
119
119
|
return Promise.reject(
|
|
120
120
|
new IncorrectUsageError({
|
|
121
121
|
message: 'Detected unsupported file structure.',
|
|
122
|
-
help: 'Please install Ghost 1.0, import the file and then update your blog to the latest Ghost version.\nVisit https://ghost.org/
|
|
122
|
+
help: 'Please install Ghost 1.0, import the file and then update your blog to the latest Ghost version.\nVisit https://docs.ghost.org/update/ or ask for help in our https://forum.ghost.org.',
|
|
123
123
|
}),
|
|
124
124
|
);
|
|
125
125
|
}
|
|
@@ -117,7 +117,7 @@ function createFinalMigration(major) {
|
|
|
117
117
|
async function up() {
|
|
118
118
|
throw new errors.InternalServerError({
|
|
119
119
|
message: `Unable to run migrations`,
|
|
120
|
-
context: `You must be on the latest v${major}.x to update across major versions - https://ghost.org/
|
|
120
|
+
context: `You must be on the latest v${major}.x to update across major versions - https://docs.ghost.org/update/`,
|
|
121
121
|
help: `Run 'ghost update v${major}' to get the latest v${major}.x version, then run 'ghost update' to get to the latest.`,
|
|
122
122
|
});
|
|
123
123
|
},
|
|
@@ -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
|
+
);
|
|
@@ -1064,6 +1064,79 @@ module.exports = {
|
|
|
1064
1064
|
created_at: { type: 'dateTime', nullable: false },
|
|
1065
1065
|
updated_at: { type: 'dateTime', nullable: true },
|
|
1066
1066
|
},
|
|
1067
|
+
// Where a source sends what it collected. The source is who collects, the port is that
|
|
1068
|
+
// source's own name for the thing, and the destination is the publisher's field, which
|
|
1069
|
+
// they can repoint without the source knowing. The row is the collecting: there is one
|
|
1070
|
+
// and the source writes through it, or there is none and it does not.
|
|
1071
|
+
//
|
|
1072
|
+
// A second kind of source becomes a `source_type` beside a widened id. What it must not
|
|
1073
|
+
// become is a second table holding destinations.
|
|
1074
|
+
members_custom_field_bindings: {
|
|
1075
|
+
id: { type: 'string', maxlength: 24, nullable: false, primary: true },
|
|
1076
|
+
product_id: {
|
|
1077
|
+
type: 'string',
|
|
1078
|
+
maxlength: 24,
|
|
1079
|
+
nullable: false,
|
|
1080
|
+
references: 'products.id',
|
|
1081
|
+
cascadeDelete: true,
|
|
1082
|
+
},
|
|
1083
|
+
port: { type: 'string', maxlength: 191, nullable: false },
|
|
1084
|
+
// Indexed rather than unique: several sources landing in one field is expected.
|
|
1085
|
+
custom_field_key: {
|
|
1086
|
+
type: 'string',
|
|
1087
|
+
maxlength: 191,
|
|
1088
|
+
nullable: false,
|
|
1089
|
+
references: 'members_custom_fields.key',
|
|
1090
|
+
cascadeDelete: true,
|
|
1091
|
+
},
|
|
1092
|
+
created_at: { type: 'dateTime', nullable: false },
|
|
1093
|
+
updated_at: { type: 'dateTime', nullable: true },
|
|
1094
|
+
'@@UNIQUE_CONSTRAINTS@@': [
|
|
1095
|
+
{ columns: ['product_id', 'port'], indexName: 'members_custom_field_bindings_unique' },
|
|
1096
|
+
],
|
|
1097
|
+
'@@INDEXES@@': [['custom_field_key']],
|
|
1098
|
+
},
|
|
1099
|
+
// How a tier's checkout question is asked. Where the answer lands is the binding it
|
|
1100
|
+
// hangs off.
|
|
1101
|
+
products_checkout_fields: {
|
|
1102
|
+
id: { type: 'string', maxlength: 24, nullable: false, primary: true },
|
|
1103
|
+
binding_id: {
|
|
1104
|
+
type: 'string',
|
|
1105
|
+
maxlength: 24,
|
|
1106
|
+
nullable: false,
|
|
1107
|
+
unique: true,
|
|
1108
|
+
references: 'members_custom_field_bindings.id',
|
|
1109
|
+
cascadeDelete: true,
|
|
1110
|
+
},
|
|
1111
|
+
sort_order: { type: 'integer', nullable: false, unsigned: true, defaultTo: 0 },
|
|
1112
|
+
// Processors cap a label far shorter than a field name may be. Null asks under the
|
|
1113
|
+
// field's own name.
|
|
1114
|
+
label: { type: 'string', maxlength: 191, nullable: true },
|
|
1115
|
+
optional: { type: 'boolean', nullable: false, defaultTo: true },
|
|
1116
|
+
created_at: { type: 'dateTime', nullable: false },
|
|
1117
|
+
updated_at: { type: 'dateTime', nullable: true },
|
|
1118
|
+
},
|
|
1119
|
+
// The options a tier's collection needs, and the one thing it collects without keeping.
|
|
1120
|
+
// Whether it collects anything it *does* keep is the binding above.
|
|
1121
|
+
products_checkout_config: {
|
|
1122
|
+
id: { type: 'string', maxlength: 24, nullable: false, primary: true },
|
|
1123
|
+
product_id: {
|
|
1124
|
+
type: 'string',
|
|
1125
|
+
maxlength: 24,
|
|
1126
|
+
nullable: false,
|
|
1127
|
+
unique: true,
|
|
1128
|
+
references: 'products.id',
|
|
1129
|
+
cascadeDelete: true,
|
|
1130
|
+
},
|
|
1131
|
+
// ISO 3166-1 alpha-2, comma-joined. A processor will not render an address form
|
|
1132
|
+
// without them, and a wrong code fails the session create.
|
|
1133
|
+
shipping_allowed_countries: { type: 'string', maxlength: 2000, nullable: true },
|
|
1134
|
+
// Stripe keeps a tax number against the customer it invoices, so there is no
|
|
1135
|
+
// destination to bind and nothing to record but whether to ask.
|
|
1136
|
+
tax_number_collect: { type: 'boolean', nullable: false, defaultTo: false },
|
|
1137
|
+
created_at: { type: 'dateTime', nullable: false },
|
|
1138
|
+
updated_at: { type: 'dateTime', nullable: true },
|
|
1139
|
+
},
|
|
1067
1140
|
members_custom_field_values: {
|
|
1068
1141
|
id: { type: 'string', maxlength: 24, nullable: false, primary: true },
|
|
1069
1142
|
// The field's stable key, not its id: a value is addressed by key everywhere it
|
|
@@ -1096,6 +1169,23 @@ module.exports = {
|
|
|
1096
1169
|
// column a fresh install bounds at 65,535 bytes. The bound matching long_text's
|
|
1097
1170
|
// exactly is worth more than the schema restating what the write path enforces.
|
|
1098
1171
|
value_text: { type: 'text', maxlength: 65535, nullable: true },
|
|
1172
|
+
// Who wrote the value that is here now.
|
|
1173
|
+
//
|
|
1174
|
+
// Shaped like `actions`: a type and an id, no foreign key. A type because not every
|
|
1175
|
+
// write comes through a binding — a person edits a member's fields, an import reads a
|
|
1176
|
+
// file — and an id so the writer can be resolved back rather than merely named. A
|
|
1177
|
+
// binding id resolves to the tier, the port and the field it routed into, which is
|
|
1178
|
+
// everything worth knowing about how a value got here.
|
|
1179
|
+
//
|
|
1180
|
+
// No foreign key, because provenance has to outlive its cause: that a value arrived
|
|
1181
|
+
// through a tier's shipping port stays true after someone deletes that binding, even
|
|
1182
|
+
// though it stops being joinable.
|
|
1183
|
+
//
|
|
1184
|
+
// The type is the namespace the id resolves in, so every row carries one. The id is
|
|
1185
|
+
// nullable for the one writer that resolves in no table: an import has none to give
|
|
1186
|
+
// until runs are tracked.
|
|
1187
|
+
written_by_type: { type: 'string', maxlength: 50, nullable: false },
|
|
1188
|
+
written_by_id: { type: 'string', maxlength: 24, nullable: true },
|
|
1099
1189
|
created_at: { type: 'dateTime', nullable: false },
|
|
1100
1190
|
updated_at: { type: 'dateTime', nullable: true },
|
|
1101
1191
|
// Named, because the name knex derives from the table and all three columns
|
|
@@ -7,7 +7,7 @@ exports.AutomationActionRevisionsImporter = void 0;
|
|
|
7
7
|
const faker_1 = require("@faker-js/faker");
|
|
8
8
|
const errors_1 = __importDefault(require("@tryghost/errors"));
|
|
9
9
|
const table_importer_1 = require("./table-importer");
|
|
10
|
-
const
|
|
10
|
+
const date_1 = require("../../../lib/db-types/date");
|
|
11
11
|
const constants_1 = require("../../../services/member-welcome-emails/constants");
|
|
12
12
|
class AutomationActionRevisionsImporter extends table_importer_1.TableImporter {
|
|
13
13
|
static table = 'automation_action_revisions';
|
|
@@ -48,12 +48,12 @@ class AutomationActionRevisionsImporter extends table_importer_1.TableImporter {
|
|
|
48
48
|
message: 'Cannot generate automation action revision without an action',
|
|
49
49
|
});
|
|
50
50
|
}
|
|
51
|
-
const createdAt = (0,
|
|
51
|
+
const createdAt = (0, date_1.fromDatabaseDate)(this.#action.created_at);
|
|
52
52
|
createdAt.setSeconds(createdAt.getSeconds() + this.#revisionIndex);
|
|
53
53
|
this.#revisionIndex += 1;
|
|
54
54
|
const common = {
|
|
55
55
|
id: this.fastFakeObjectId(),
|
|
56
|
-
created_at: (0,
|
|
56
|
+
created_at: (0, date_1.toDatabaseDate)(createdAt),
|
|
57
57
|
action_id: this.#action.id,
|
|
58
58
|
email_sent_count: null,
|
|
59
59
|
email_opened_count: null,
|