ghost 6.61.0 → 6.63.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-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-limit-service-0.0.0.tgz +0 -0
- package/components/tryghost-metafield-types-0.0.0.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/content/themes/source/partials/post-card.hbs +1 -1
- package/core/boot.js +61 -27
- 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/{about-Bve7IJS2.js → about-C1C3s5-g.js} +1 -1
- package/core/built/admin/assets/accordion-CxGsDKwa.js +1 -0
- package/core/built/admin/assets/account-migration-CbUhW6gk.js +1 -0
- package/core/built/admin/assets/activitypub/{account-migration-C-aej4x_.js → account-migration-KA6Jjf9L.js} +16 -16
- package/core/built/admin/assets/activitypub/activitypub.js +9 -9
- package/core/built/admin/assets/activitypub/{avatar-DLPL3Abs.js → avatar-DVJF5bxP.js} +2 -2
- package/core/built/admin/assets/activitypub/{avatar-flipboard-C9iDY-QV.js → avatar-flipboard-csQaNeYK.js} +2 -2
- package/core/built/admin/assets/activitypub/{bluesky-sharing-BXkA5mqV.js → bluesky-sharing-C7nTDMvw.js} +37 -37
- package/core/built/admin/assets/activitypub/{content-formatters-CHcyMFk4.js → content-formatters-CLcjaBwV.js} +4 -4
- package/core/built/admin/assets/activitypub/{copy-DIAOQoCZ.js → copy-DcOh8kXw.js} +2 -2
- package/core/built/admin/assets/activitypub/{domain-B3ihkPde.js → domain-fZ-X8i4-.js} +121 -121
- package/core/built/admin/assets/activitypub/{edit-profile-DsZM3rTX.js → edit-profile-BqMLQV88.js} +40 -40
- package/core/built/admin/assets/activitypub/{explore-BodNrZgR.js → explore-B4yPoP8E.js} +27 -27
- package/core/built/admin/assets/activitypub/{feed-PwH1iJ84.js → feed-BRC_mvAe.js} +51 -51
- package/core/built/admin/assets/activitypub/{field-D06-kmOJ.js → field-COacNgOt.js} +3 -3
- package/core/built/admin/assets/activitypub/{hash-Bm3WxYN4.js → hash-C7u-irQQ.js} +2 -2
- package/core/built/admin/assets/activitypub/inbox-BW-yvUoN.js +1284 -0
- package/core/built/admin/assets/activitypub/{inbox-d8oJRTf4.js → inbox-CbTTdDQ3.js} +2 -2
- package/core/built/admin/assets/activitypub/label-kPMmYI7l.js +16 -0
- package/core/built/admin/assets/activitypub/layout-BL4_jtuV.js +1 -0
- package/core/built/admin/assets/activitypub/{moderation-D1Yapsod.js → moderation-CuidJzc0.js} +91 -91
- package/core/built/admin/assets/activitypub/{note-C5zjqq5C.js → note-CAMRRSqD.js} +24 -24
- package/core/built/admin/assets/activitypub/{notifications-B9p8eCHD.js → notifications-BmNlXGgp.js} +51 -51
- package/core/built/admin/assets/activitypub/{onboarding-CNelD_uF.js → onboarding-Bqg7fh_L.js} +2 -2
- package/core/built/admin/assets/activitypub/{onboarding-mat5Hrl0.js → onboarding-Dmun9jr_.js} +2 -2
- package/core/built/admin/assets/activitypub/{preferences-BCqUdC3v.js → preferences--oH19wf9.js} +1519 -1519
- package/core/built/admin/assets/activitypub/{profile-BRCWoFem.js → profile-DH_tQx2D.js} +185 -185
- package/core/built/admin/assets/activitypub/{reply-DYK5vVqb.js → reply-Cap9PxSH.js} +2 -2
- package/core/built/admin/assets/activitypub/{routes-BSXT992i.js → routes-DdyY9uFF.js} +744 -735
- package/core/built/admin/assets/activitypub/{separator-BbQqTm-p.js → separator-CAxxu8VV.js} +3 -3
- package/core/built/admin/assets/activitypub/settings-B6EEcVkW.js +315 -0
- package/core/built/admin/assets/activitypub/{site-DHoMupSB.js → site-BYps63oh.js} +2 -2
- package/core/built/admin/assets/activitypub/{step-1-B-YfsVeO.js → step-1-CKjR2KAm.js} +6 -6
- package/core/built/admin/assets/activitypub/{step-2-DtPQzlTH.js → step-2-B6PKfOUQ.js} +6 -6
- package/core/built/admin/assets/activitypub/{step-3-D6BFMXL_.js → step-3-C-qBbcUo.js} +11 -11
- package/core/built/admin/assets/activitypub/{tabs-GpNecvfB.js → tabs-DLhZtVde.js} +306 -306
- package/core/built/admin/assets/activitypub/{topic-filter-BPDeQQys.js → topic-filter-DsUOuu0k.js} +3 -3
- package/core/built/admin/assets/activitypub/{use-activity-pub-queries-BoVOxXkV.js → use-activity-pub-queries-CX9snsLs.js} +3 -3
- package/core/built/admin/assets/activitypub/{use-navigate-with-base-path-Bmk5h4lW.js → use-navigate-with-base-path-DsJTGDSS.js} +988 -959
- package/core/built/admin/assets/activitypub/{use-reply-chain-data-wVBX7swM.js → use-reply-chain-data-AJi9zkzm.js} +30 -30
- package/core/built/admin/assets/activitypub/{users-CoX6FT_K.js → users-inweyKL5.js} +192 -164
- package/core/built/admin/assets/activitypub/{x-DbQZOLiI.js → x-DR8AT3-4.js} +2 -2
- package/core/built/admin/assets/add-integration-modal-BT_onDJy.js +1 -0
- package/core/built/admin/assets/add-newsletter-modal-Cx1kQpiY.js +1 -0
- package/core/built/admin/assets/add-recommendation-modal-B5nvAhvr.js +1 -0
- package/core/built/admin/assets/analytics-DjoJWPI7.js +1 -0
- package/core/built/admin/assets/{announcement-bar-modal-DM3cYOpo.js → announcement-bar-modal-Dwd0EGFP.js} +1 -1
- package/core/built/admin/assets/{api-keys-3-0vJC3Y.js → api-keys-BGPzLHzA.js} +1 -1
- package/core/built/admin/assets/{api-keys-BLm2NDBh.js → api-keys-BoeacM-s.js} +1 -1
- package/core/built/admin/assets/{audience-9mwU5TW6.js → audience-ceV3XVHq.js} +1 -1
- package/core/built/admin/assets/automated-emails-BLesE41L.js +1 -0
- package/core/built/admin/assets/{automations-sAcJ1334.js → automations-BN4u3GR8.js} +1 -1
- package/core/built/admin/assets/automations-C-ZTUwW3.js +1 -0
- package/core/built/admin/assets/bluesky-sharing-vzh-oPXL.js +1 -0
- package/core/built/admin/assets/{breadcrumb-DLiqCyFc.js → breadcrumb-CaLk2b7D.js} +1 -1
- package/core/built/admin/assets/{button-B2jcu6bk.js → button-Dvcv1QSR.js} +1 -1
- package/core/built/admin/assets/calendar-Bl9RLcZX.js +1 -0
- package/core/built/admin/assets/{chart-helpers-Fo3bUL3K.js → chart-helpers-FHywU0pj.js} +1 -1
- package/core/built/admin/assets/{checkbox-BfKktMph.js → checkbox-BtayFtjg.js} +1 -1
- package/core/built/admin/assets/chunk.254.035b85ec456ebbd7336b.js +440 -0
- package/core/built/admin/assets/{chunk.524.60ca4692d91c6022042f.js → chunk.524.e6975095fccdf22d90f8.js} +5 -5
- package/core/built/admin/assets/{chunk.582.525c7617c2d9e94c940a.js → chunk.582.98b485f9b2802f540897.js} +6 -6
- package/core/built/admin/assets/{chunk.492.f24d855d7e3f3aad261c.js → chunk.901.4ccc639821020230bcca.js} +9949 -7921
- package/core/built/admin/assets/{code-editor-view-DCQJxsfU.js → code-editor-view-C3ZfoF1X.js} +1 -1
- package/core/built/admin/assets/{code-editor-view-CYVu4EW6.js → code-editor-view-CAyRWy1s.js} +1 -1
- package/core/built/admin/assets/color-picker-G4kGR7rp.js +3 -0
- package/core/built/admin/assets/color-picker-field-DQFVTNnT.js +1 -0
- package/core/built/admin/assets/combobox-BnYzgEB4.js +1 -0
- package/core/built/admin/assets/command-C_vyTikI.js +1 -0
- package/core/built/admin/assets/comments-aBrxfnZf.js +1 -0
- package/core/built/admin/assets/{config-DOMQDZGZ.js → config-kSHvwdTG.js} +1 -1
- package/core/built/admin/assets/confirmation-context-DwXX_Y5h.js +1 -0
- package/core/built/admin/assets/{content-api-modal-CyQEC3fr.js → content-api-modal-D2G0nJP6.js} +1 -1
- package/core/built/admin/assets/context-menu-DOVB6yaz.js +1 -0
- package/core/built/admin/assets/{copy-field-B3M1s78L.js → copy-field-DCJwh9qf.js} +1 -1
- package/core/built/admin/assets/create-ghost-browse-value-source-5C53jJaX.js +1 -0
- package/core/built/admin/assets/custom-field-type-option-BAuW0F-E.js +1 -0
- package/core/built/admin/assets/custom-integration-modal-AbJGVyKc.js +1 -0
- package/core/built/admin/assets/{date-range-select-DD2RKkgB.js → date-range-select-BY3K-ukj.js} +1 -1
- package/core/built/admin/assets/design-and-theme-modal-BvEy4_pC.js +2 -0
- package/core/built/admin/assets/dirty-confirm-dialog-DVPuGz3U.js +1 -0
- package/core/built/admin/assets/{disabled-sources-indicator-Cvy47bE2.js → disabled-sources-indicator-Cy7Zp4c8.js} +1 -1
- package/core/built/admin/assets/dist-Dcsslyo72.js +1 -0
- package/core/built/admin/assets/domain-Dl61QGuk.js +1 -0
- package/core/built/admin/assets/dropzone-Dtz5Rmjt.js +5 -0
- package/core/built/admin/assets/edit-profile-DNJSMDwm.js +1 -0
- package/core/built/admin/assets/editor-DbAen9zf.js +8 -0
- package/core/built/admin/assets/editor-screen-BFWThIai.js +26 -0
- package/core/built/admin/assets/email-sending-status-context-CWDOD1FN.js +1 -0
- package/core/built/admin/assets/email-sending-status-provider-DCPkDICt.js +1 -0
- package/core/built/admin/assets/emails-vFMk4yYl.js +1 -0
- package/core/built/admin/assets/{embed-signup-form-modal-DeBMLxlL.js → embed-signup-form-modal-DGqsORxS.js} +1 -1
- package/core/built/admin/assets/en-B1jX3WMs.js +1 -0
- package/core/built/admin/assets/explore-nnRr1Fja.js +1 -0
- package/core/built/admin/assets/feature-flag-overrides-context-DQjdJFAk.js +1 -0
- package/core/built/admin/assets/feature-image-placeholder-BrIHmPs8.js +1 -0
- package/core/built/admin/assets/feed-BNUcNu-W.js +1 -0
- package/core/built/admin/assets/feedback-DJ4Zb9rZ.js +1 -0
- package/core/built/admin/assets/{field-Cj8lmDOo.js → field-C93_Mg6j.js} +1 -1
- package/core/built/admin/assets/filter-bar-Da1qxybu.js +1 -0
- package/core/built/admin/assets/filter-sources-CGJb4C5r.js +1 -0
- package/core/built/admin/assets/filters--kKP-EC8.js +1 -0
- package/core/built/admin/assets/filters-DxA_a4FP.js +1 -0
- package/core/built/admin/assets/first-promoter-modal-BYDtrz2S.js +1 -0
- package/core/built/admin/assets/focus-koenig-editor-on-bottom-click-BbSnGOtK.js +1 -0
- package/core/built/admin/assets/{ghost-c8807202a07c20030acb719ee0114815.css → ghost-8fd5bb799356bbefb254210ba7e1236d.css} +1 -1
- package/core/built/admin/assets/{ghost-3894eedcc6968f658578c0abfe942aab.js → ghost-b4e8a403baba61905cd7560e30b9732d.js} +63 -44
- package/core/built/admin/assets/{ghost-dark-fbf1e384aaef3ae315e540f0eb7373a7.css → ghost-dark-cac0cb2d5bb78e9bd14d8d1c2768ed45.css} +1 -1
- package/core/built/admin/assets/gift-link-modal-B7u5bD4e.js +1 -0
- package/core/built/admin/assets/{gift-links-DLDS7ljO.js → gift-links-CfLSnst2.js} +1 -1
- package/core/built/admin/assets/{growth-D6mhcx3q.js → growth-Cd1uO9d2.js} +1 -1
- package/core/built/admin/assets/growth-aG32xfdE.js +3 -0
- package/core/built/admin/assets/history-modal-Df8lW8h-.js +1 -0
- package/core/built/admin/assets/hooks-Cy_-oZ4o.js +2 -0
- package/core/built/admin/assets/{html-field-C8qVGGC1.js → html-field-DA4eU7eq.js} +1 -1
- package/core/built/admin/assets/{images-h8VZEQ9k.js → images-KXmyO3Ss.js} +1 -1
- package/core/built/admin/assets/{inbox-BYd1M06Q.js → inbox-gJHG7_xd.js} +14 -14
- package/core/built/admin/assets/index-BHHXtR5C.css +2 -0
- package/core/built/admin/assets/index-CgMCwsxN.js +4 -0
- package/core/built/admin/assets/index.es-CY6-yuw9.js +1 -0
- package/core/built/admin/assets/{input-group-D8sCXRF5.js → input-group-BE8rM2y1.js} +1 -1
- package/core/built/admin/assets/{integrations-Bjbu86Z0.js → integrations-B4kuRBFY.js} +1 -1
- package/core/built/admin/assets/invite-user-modal-B4CuNcx4.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-_-IsVI7E.js → koenig-lexical-CGXb0F8o.js} +3 -3
- package/core/built/admin/assets/koenig-loader-BeM5rFPX.js +2 -0
- package/core/built/admin/assets/{kpi-card-DZQk_0W8.js → kpi-card-B21aToe8.js} +1 -1
- package/core/built/admin/assets/{kpi-card-DW_2y3ug.js → kpi-card-pz6Wv4Ae.js} +1 -1
- package/core/built/admin/assets/{kpi-helpers-PueTKuA6.js → kpi-helpers-Dq5jelmP.js} +1 -1
- package/core/built/admin/assets/{kpi-tabs-CojDs-Qz.js → kpi-tabs-DEZHpKUt.js} +1 -1
- package/core/built/admin/assets/{label-DjbT91GM.js → label-OLCzze8N.js} +1 -1
- package/core/built/admin/assets/label-picker-BigOvMPV.js +1 -0
- package/core/built/admin/assets/{labels-CH3Kn8RV.js → labels-Dr0SgUQD.js} +1 -1
- package/core/built/admin/assets/layout-DUTL8SH5.js +1 -0
- package/core/built/admin/assets/lib-7QPTI0FS.js +1 -0
- package/core/built/admin/assets/link-helpers-BRAg9SCj.js +1 -0
- package/core/built/admin/assets/links-BDHPTlyj.js +1 -0
- package/core/built/admin/assets/member-custom-fields-TRTHCAz9.js +1 -0
- package/core/built/admin/assets/member-detail-b6dRwc3C.js +1 -0
- package/core/built/admin/assets/members-Czt5lJSc.js +4 -0
- package/core/built/admin/assets/moderation-ZWefD9uH.js +1 -0
- package/core/built/admin/assets/{multi-select-combobox-B6LiRzDO.js → multi-select-combobox-CT13MTo-.js} +1 -1
- package/core/built/admin/assets/navigation-modal-C8FEhBK5.js +1 -0
- package/core/built/admin/assets/newsletter-5VYW4RyJ.js +1 -0
- package/core/built/admin/assets/newsletter-detail-modal-ChjC0ZqH.js +1 -0
- package/core/built/admin/assets/{newsletter-emails-CFeLlt4z.js → newsletter-emails-DZH6I-PY.js} +1 -1
- package/core/built/admin/assets/newsletters-DOC9KBcX.js +1 -0
- package/core/built/admin/assets/newsletters-Rq1M3GD-.js +1 -0
- package/core/built/admin/assets/note-DIV-Pojr.js +1 -0
- package/core/built/admin/assets/notifications-s20-H49V.js +1 -0
- package/core/built/admin/assets/nql-BLpCn7qX.js +21 -0
- package/core/built/admin/assets/{offers-9J1CSiLy.js → offers--e2nGvkW.js} +1 -1
- package/core/built/admin/assets/offers-container-modal-BmG5M5Tv.js +1 -0
- package/core/built/admin/assets/onboarding-CUuy9unR.js +1 -0
- package/core/built/admin/assets/{onboarding-B4YhlZ0i.js → onboarding-pXyct0Jm.js} +1 -1
- package/core/built/admin/assets/{onboarding-route-Dmc4IPm3.js → onboarding-route-CK4pcXoR.js} +1 -1
- package/core/built/admin/assets/overview-CaPsciMs.js +1 -0
- package/core/built/admin/assets/overview-a8GfcsKX.js +1 -0
- package/core/built/admin/assets/{page-header-BR_nbIPp.js → page-header-DM_KyoFI.js} +1 -1
- package/core/built/admin/assets/pagemenu-vgZVUVKR.js +1 -0
- package/core/built/admin/assets/pages-CjDY2CBI.js +1 -0
- package/core/built/admin/assets/pages-route-BzKZYdV5.js +1 -0
- package/core/built/admin/assets/papaparse.min-cQwnxGCG.js +10 -0
- package/core/built/admin/assets/{pintura-modal-BR9hEvS8.js → pintura-modal-DExCF1ii.js} +1 -1
- package/core/built/admin/assets/portal-frame-Cqanidq4.js +1 -0
- package/core/built/admin/assets/portal-modal-oinBgA27.js +1 -0
- package/core/built/admin/assets/post-analytics-C5oJ1dWV.js +1 -0
- package/core/built/admin/assets/post-analytics-header-OATo3X_r.js +1 -0
- package/core/built/admin/assets/post-analytics-provider-tOpIVGT5.js +1 -0
- package/core/built/admin/assets/post-helpers-C88JBa4D.js +1 -0
- package/core/built/admin/assets/post-share-modal-DvhC1XgV.js +1 -0
- package/core/built/admin/assets/post-utils-DKF4mfuo.js +1 -0
- package/core/built/admin/assets/posts-list-screen-o4ZjbgS3.js +2 -0
- package/core/built/admin/assets/posts-pCPrhQeR.js +1 -0
- package/core/built/admin/assets/posts-route-9F--xdIb.js +1 -0
- package/core/built/admin/assets/preferences--vNubsqD.js +5 -0
- package/core/built/admin/assets/{preview-modal-C-BL-F9k.js → preview-modal-YYbzlYdO.js} +1 -1
- package/core/built/admin/assets/profile-BllKV3dR.js +1 -0
- package/core/built/admin/assets/{radio-group-Bgz60i81.js → radio-group-DL8GI8rt.js} +1 -1
- package/core/built/admin/assets/{referrers-CnhCMWCs.js → referrers-D8oHPmDB.js} +1 -1
- package/core/built/admin/assets/router-provider-BSvTXgZY.js +1 -0
- package/core/built/admin/assets/schemas-BoYdB6YU.js +64 -0
- package/core/built/admin/assets/select-v5YbA3Mw.js +1 -0
- package/core/built/admin/assets/settings-PEsZupw1.js +4 -0
- package/core/built/admin/assets/{settings-breadcrumbs-CyP_9zTo.js → settings-breadcrumbs-NwPnCTC7.js} +1 -1
- package/core/built/admin/assets/settings-u_s1CRkr.js +1 -0
- package/core/built/admin/assets/share-modal-SskCmVGL.js +1 -0
- package/core/built/admin/assets/slack-modal-XxSJiYgo.js +1 -0
- package/core/built/admin/assets/{sort-button-Cc-Z96sA.js → sort-button-Cx1KtINE.js} +1 -1
- package/core/built/admin/assets/{source-icon-v6PUnmyM.js → source-icon-Bdp9Im_5.js} +1 -1
- package/core/built/admin/assets/stats-D9PDLS3x.js +1 -0
- package/core/built/admin/assets/stats-view-W2g6Jsd-.js +1 -0
- package/core/built/admin/assets/{step-1-DSRp2vBj.js → step-1-BQYzvBzr.js} +1 -1
- package/core/built/admin/assets/{step-2-COqv2g0u.js → step-2-xES32xJV.js} +1 -1
- package/core/built/admin/assets/{step-3-6W1NMVQc.js → step-3-DA_XK5kW.js} +2 -2
- package/core/built/admin/assets/{stripe-button-D2K42Uty.js → stripe-button-CVsLHelt.js} +1 -1
- package/core/built/admin/assets/stripe-connect-modal-ClmLOMGS.js +1 -0
- package/core/built/admin/assets/style-Wd9nQubI.css +1 -0
- package/core/built/admin/assets/{table-B2pIKjVh.js → table-BenqVupI.js} +1 -1
- package/core/built/admin/assets/{tabs-SaW_UT-Q.js → tabs-eBBlxPp8.js} +1 -1
- package/core/built/admin/assets/tag-detail-Ce8Se2qd.js +2 -0
- package/core/built/admin/assets/tag-picker-C3UR-uJ-.js +1 -0
- package/core/built/admin/assets/tags-B-kJxCs7.js +1 -0
- package/core/built/admin/assets/{tags-zTFiKRpb.js → tags-ChfdwJyS.js} +1 -1
- package/core/built/admin/assets/testimonials-modal-9Q6fT06V.js +1 -0
- package/core/built/admin/assets/tier-detail-modal-CDyYdqK7.js +1 -0
- package/core/built/admin/assets/tiers-BCpIOGQr.js +1 -0
- package/core/built/admin/assets/{toggle-group-EM9WpESu.js → toggle-group-CviIkyok.js} +1 -1
- package/core/built/admin/assets/{topic-filter-DY4gNHn2.js → topic-filter-I2jCBGxm.js} +1 -1
- package/core/built/admin/assets/{transistor-modal-CpyPG-MH.js → transistor-modal-p53u3W8y.js} +1 -1
- package/core/built/admin/assets/{trend-badge-ByMkuAuH.js → trend-badge-CideVzQd.js} +1 -1
- package/core/built/admin/assets/{unsplash-modal-Cv2Q6GtY.js → unsplash-modal-DY8UcKcE.js} +1 -1
- package/core/built/admin/assets/{use-analytics-data-CHvjMYuT.js → use-analytics-data-DAIGcr2f.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-Qv4SVXqw.js → use-check-theme-limit-error-DRUjK4YM.js} +1 -1
- package/core/built/admin/assets/use-filter-params-JkZhIS8L.js +1 -0
- package/core/built/admin/assets/{use-filterable-api-CzXcpUh8.js → use-filterable-api-BVEVMrhZ.js} +1 -1
- package/core/built/admin/assets/use-growth-stats-937CUj6j.js +1 -0
- package/core/built/admin/assets/use-host-limits-D0Dv3tKA.js +1 -0
- package/core/built/admin/assets/{use-limiter-cwJvsNBo.js → use-limiter-CohWfzvK.js} +1 -1
- package/core/built/admin/assets/{use-navigate-with-base-path-BHPA228f.js → use-navigate-with-base-path-BkxcPj5l.js} +1 -1
- package/core/built/admin/assets/use-pintura-config-xgytjU35.js +1 -0
- package/core/built/admin/assets/{use-pintura-editor-BDBXWUYq.js → use-pintura-editor-CaV1mbfO.js} +1 -1
- package/core/built/admin/assets/{use-post-referrers-DbY-mzci.js → use-post-referrers-BCQI7fDg.js} +1 -1
- package/core/built/admin/assets/use-reply-chain-data-CYRhoaxY.js +1 -0
- package/core/built/admin/assets/{use-router-history-entry-Bg6BhBQQ.js → use-router-history-entry-NOKcd--l.js} +1 -1
- package/core/built/admin/assets/{use-setting-group-VM7FQwMY.js → use-setting-group-bLKMwoBT.js} +1 -1
- package/core/built/admin/assets/use-settings-navigation-B-qrriKD.js +1 -0
- package/core/built/admin/assets/{use-simple-pagination-Dum6Irbs.js → use-simple-pagination-CNPd6Rf6.js} +1 -1
- package/core/built/admin/assets/use-staff-users-pRIMIyiW.js +1 -0
- package/core/built/admin/assets/use-tinybird-query-CmdbCS9X.js +1 -0
- package/core/built/admin/assets/use-tinybird-token-KLne235s.js +1 -0
- package/core/built/admin/assets/{use-unsaved-changes-guard-BAy0RANR.js → use-unsaved-changes-guard-7-ug0JdH.js} +1 -1
- package/core/built/admin/assets/use-upgrade-route-Dm_qqKr0.js +1 -0
- package/core/built/admin/assets/{use-url-input-Df5QzNa7.js → use-url-input-fvp-TpPx.js} +1 -1
- package/core/built/admin/assets/user-detail-modal-D3KlGYv-.js +1 -0
- package/core/built/admin/assets/users-DVNWrqg9.js +1 -0
- package/core/built/admin/assets/{vendor-5753232c7d6ffb3c44e1eb0a02133953.js → vendor-2dd263291938d407802568d3357ec69e.js} +19 -17
- package/core/built/admin/assets/{virtual-list-DEx8WgiO.js → virtual-list-CZ3RK2Yf.js} +1 -1
- package/core/built/admin/assets/web-ClEJsCAj.js +2 -0
- package/core/built/admin/assets/web-X9rdnrtq.js +1 -0
- package/core/built/admin/assets/{zapier-modal-Cw3BTBUu.js → zapier-modal-DfVhV17j.js} +1 -1
- package/core/built/admin/index.html +23 -27
- 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/sitemap/user-map-generator.js +9 -2
- package/core/server/adapters/jobs/InMemoryJobsBackend.js +74 -29
- package/core/server/api/endpoints/authentication.js +1 -2
- package/core/server/api/endpoints/authors-public.js +15 -5
- package/core/server/api/endpoints/emails.js +13 -0
- package/core/server/api/endpoints/index.js +10 -2
- package/core/server/api/endpoints/mail.js +1 -1
- package/core/server/api/endpoints/member-metafields-members.js +23 -0
- package/core/server/api/endpoints/member-metafields.js +102 -0
- package/core/server/api/endpoints/members-account.js +42 -0
- package/core/server/api/endpoints/members.js +4 -4
- package/core/server/api/endpoints/newsletters-public.js +10 -1
- package/core/server/api/endpoints/pages-public.js +15 -5
- package/core/server/api/endpoints/posts-public.js +15 -5
- package/core/server/api/endpoints/posts.js +3 -3
- package/core/server/api/endpoints/tags-public.js +22 -3
- package/core/server/api/endpoints/tiers-checkout-config.js +2 -2
- package/core/server/api/endpoints/tiers-public.js +38 -1
- package/core/server/api/endpoints/users.js +2 -2
- package/core/server/api/endpoints/utils/api-filter-utils.js +170 -3
- package/core/server/api/endpoints/utils/public-cache-keys.js +3 -0
- package/core/server/api/endpoints/utils/serializers/input/authors.js +2 -0
- package/core/server/api/endpoints/utils/serializers/input/members.js +20 -9
- package/core/server/api/endpoints/utils/serializers/input/pages.js +2 -0
- package/core/server/api/endpoints/utils/serializers/input/posts.js +2 -0
- package/core/server/api/endpoints/utils/serializers/input/tags.js +2 -0
- package/core/server/api/endpoints/utils/serializers/output/emails.js +7 -0
- package/core/server/api/endpoints/utils/serializers/output/index.js +6 -2
- package/core/server/api/endpoints/utils/serializers/output/member-metafields.js +18 -0
- package/core/server/api/endpoints/utils/serializers/output/members-account.js +19 -0
- package/core/server/api/endpoints/utils/serializers/output/members-csv-transform.js +1 -1
- package/core/server/api/endpoints/utils/serializers/output/members.js +2 -4
- package/core/server/api/endpoints/utils/serializers/output/tiers.js +10 -2
- package/core/server/api/endpoints/utils/serializers/output/users.js +0 -10
- 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 -3
- 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.53/2026-07-15-20-22-53-add-members-custom-field-values.js +1 -1
- package/core/server/data/migrations/versions/6.57/2026-08-04-18-00-00-store-custom-field-values-as-leaf-rows.js +10 -1
- package/core/server/data/migrations/versions/6.63/2026-09-03-10-07-03-rename-custom-field-tables-to-metafields.js +169 -0
- package/core/server/data/migrations/versions/6.63/2026-09-03-11-03-31-remove-member-custom-field-read-permissions.js +30 -0
- package/core/server/data/schema/fixtures/fixtures.json +0 -11
- package/core/server/data/schema/lib/default-index-name.js +8 -11
- package/core/server/data/schema/schema.js +18 -18
- package/core/server/data/seeders/README.md +48 -0
- package/core/server/data/tinybird/pipes/mv_hits.pipe +86 -50
- package/core/server/lib/db-types/count.js +16 -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/validate-password.js +81 -120
- package/core/server/models/action.js +4 -4
- package/core/server/models/base/plugins/filtered-collection.js +16 -0
- package/core/server/models/member.js +10 -21
- package/core/server/models/post.js +2 -2
- package/core/server/models/relations/authors.js +2 -16
- package/core/server/models/user.js +10 -3
- package/core/server/services/auth/passwordreset.js +13 -0
- package/core/server/services/automations/automations-api.js +1 -1
- package/core/server/services/automations/database-automations-repository.js +11 -4
- 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/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 +160 -53
- 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 +0 -1
- package/core/server/services/content-import/import/post-link.js +11 -0
- package/core/server/services/content-import/import/post-repository.js +25 -3
- package/core/server/services/content-import/import/reader.js +9 -2
- package/core/server/services/content-import/import/report.js +34 -0
- package/core/server/services/content-import/import/row.js +0 -2
- package/core/server/services/content-import/import/schema.js +1 -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 +52 -6
- 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/index.js +2 -7
- package/core/server/services/email-service/CONTEXT.md +37 -0
- package/core/server/services/email-service/README.md +42 -0
- package/core/server/services/email-service/batch-sending-service.js +2 -4
- package/core/server/services/email-service/email-controller.js +18 -2
- package/core/server/services/email-service/email-renderer.js +14 -4
- package/core/server/services/email-service/email-service-wrapper.js +3 -9
- package/core/server/services/email-service/mailgun-email-provider.js +20 -9
- package/core/server/services/email-service/sending-status-schema.js +21 -0
- package/core/server/services/email-service/sending-status-serializers.js +33 -0
- package/core/server/services/email-service/sending-status-service.js +47 -0
- package/core/server/services/email-service/sending-status.js +111 -0
- package/core/server/services/email-suppression-list/email-suppression-list.js +0 -33
- package/core/server/services/email-suppression-list/mailgun-email-suppression-list.js +6 -7
- package/core/server/services/gifts/README.md +2 -2
- 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-email-service.js +0 -1
- package/core/server/services/gifts/gift-service.js +19 -57
- package/core/server/services/gifts/index.js +3 -5
- 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/index.js +8 -0
- package/core/server/services/jobs-service/jobs-service.js +52 -3
- package/core/server/services/jobs-service/register-job-handlers.js +32 -11
- package/core/server/services/mail/ghost-mailer.js +4 -4
- package/core/server/services/member-welcome-emails/service.js +7 -7
- package/core/server/services/members/account-service.js +98 -0
- package/core/server/services/members/api.js +4 -3
- package/core/server/services/members/import-export/csv/parse.js +0 -7
- package/core/server/services/members/import-export/export/exporter.js +20 -20
- package/core/server/services/members/import-export/import/completion-email.js +8 -11
- package/core/server/services/members/import-export/import/importer.js +13 -13
- package/core/server/services/members/import-export/import/row.js +0 -3
- package/core/server/services/members/import-export/index.js +10 -17
- 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 +26 -8
- package/core/server/services/members/members-api/repositories/event-repository.js +0 -4
- package/core/server/services/members/members-api/repositories/member-repository.js +4 -4
- package/core/server/services/members/members-api/services/member-bread-service.js +62 -84
- package/core/server/services/members/members-api/services/payments-service.js +1 -1
- package/core/server/services/members/members-ssr.js +18 -0
- package/core/server/services/members/middleware.js +95 -81
- package/core/server/services/members/service.js +71 -47
- package/core/server/services/members/utils.js +9 -0
- package/core/server/services/members-metafields/access.js +28 -0
- package/core/server/services/{members-custom-fields → members-metafields}/actions.js +5 -5
- package/core/server/services/members-metafields/bindings-service.js +147 -0
- package/core/server/services/members-metafields/codec.js +14 -0
- package/core/server/services/{members-custom-fields → members-metafields}/config.js +1 -1
- package/core/server/services/{members-custom-fields → members-metafields}/definitions-service.js +68 -22
- package/core/server/services/members-metafields/filter.js +181 -0
- package/core/server/services/{members-custom-fields → members-metafields}/index.js +16 -7
- package/core/server/services/{members-custom-fields → members-metafields}/key.js +2 -1
- package/core/server/services/{members-custom-fields → members-metafields}/models.js +5 -5
- package/core/server/services/members-metafields/namespaces.js +34 -0
- package/core/server/services/{members-custom-fields → members-metafields}/queries.js +1 -1
- package/core/server/services/{members-custom-fields → members-metafields}/schema.js +16 -12
- package/core/server/services/members-metafields/serializers.js +22 -0
- package/core/server/services/{members-custom-fields → members-metafields}/values-service.js +80 -48
- package/core/server/services/mentions/mention-controller.js +23 -21
- package/core/server/services/mentions/mention-sending-service.js +26 -9
- package/core/server/services/mentions/process-webmention-job.js +16 -0
- package/core/server/services/mentions/send-webmentions-job.js +18 -0
- package/core/server/services/mentions/service.js +7 -33
- 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 +2 -2
- package/core/server/services/stripe/services/checkout/session-options.js +18 -15
- package/core/server/services/stripe/services/webhook/checkout-session-event-service.js +28 -7
- package/core/server/services/stripe/stripe-api.js +2 -0
- package/core/server/services/stripe/stripe-service.js +24 -14
- package/core/server/services/stripe/webhook-controller.js +10 -0
- package/core/server/services/tier-checkout-config/codec.js +11 -7
- package/core/server/services/tier-checkout-config/index.js +2 -1
- package/core/server/services/tier-checkout-config/models.js +11 -5
- package/core/server/services/tier-checkout-config/queries.js +12 -12
- package/core/server/services/tier-checkout-config/serializers.js +73 -10
- package/core/server/services/tier-checkout-config/service.js +14 -13
- package/core/server/services/tiers/service.js +3 -3
- 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/services/url/router-filter.js +8 -10
- package/core/server/services/users.js +1 -19
- package/core/server/web/admin/controller.js +1 -1
- package/core/server/web/api/endpoints/admin/routes.js +20 -16
- package/core/server/web/members/account/index.js +2 -0
- package/core/server/web/members/account/routes.js +46 -0
- package/core/server/web/members/app.js +4 -18
- package/core/shared/config/defaults.json +1 -1
- package/core/shared/config/env/config.testing-mysql.json +1 -1
- package/core/shared/labs.js +7 -2
- package/package.json +42 -41
- package/pnpm-lock.yaml +1159 -582
- package/pnpm-workspace.yaml +18 -15
- package/components/tryghost-custom-field-types-0.0.0.tgz +0 -0
- package/components/tryghost-kg-default-nodes-2.2.0.tgz +0 -0
- package/core/built/admin/assets/Combination-5fYEzgbs.js +0 -41
- package/core/built/admin/assets/account-migration-DRhAehfw.js +0 -1
- package/core/built/admin/assets/activitypub/inbox-BluD2ucT.js +0 -1284
- package/core/built/admin/assets/activitypub/label-FHSh6ZAw.js +0 -16
- package/core/built/admin/assets/activitypub/layout-Cq4NG0Xr.js +0 -1
- package/core/built/admin/assets/activitypub/settings-DQDkr06X.js +0 -315
- package/core/built/admin/assets/add-integration-modal-BC0jExDZ.js +0 -1
- package/core/built/admin/assets/add-newsletter-modal-DchTkA7l.js +0 -1
- package/core/built/admin/assets/add-recommendation-modal-DMvaJZKp.js +0 -1
- package/core/built/admin/assets/alert-dialog-QhXzdHfc.js +0 -1
- package/core/built/admin/assets/analytics-No1DDY3A.js +0 -1
- package/core/built/admin/assets/automated-emails-te1D5kq-.js +0 -1
- package/core/built/admin/assets/automations-DpUNUdcZ.js +0 -1
- package/core/built/admin/assets/bluesky-sharing-Cjrv_f62.js +0 -1
- package/core/built/admin/assets/chunk.896.435fe0637944d4a69810.js +0 -366
- package/core/built/admin/assets/color-picker-BTY_NdEm.js +0 -3
- package/core/built/admin/assets/color-picker-field-CPlkzOH0.js +0 -1
- package/core/built/admin/assets/combobox-DrMtv_4P.js +0 -1
- package/core/built/admin/assets/command-ZdgYJpoI.js +0 -1
- package/core/built/admin/assets/comments-kidj60-h.js +0 -1
- package/core/built/admin/assets/confirmation-context-BhbmQQEl.js +0 -1
- package/core/built/admin/assets/custom-field-type-option-CsGIZk1J.js +0 -10
- package/core/built/admin/assets/custom-integration-modal-BY37O_9X.js +0 -1
- package/core/built/admin/assets/design-and-theme-modal-DUSKM4uC.js +0 -22
- package/core/built/admin/assets/dialog-B44iRwlc.js +0 -1
- package/core/built/admin/assets/dirty-confirm-dialog-BxgQgQ6H.js +0 -1
- package/core/built/admin/assets/dist-Cy8tfrp_.js +0 -1
- package/core/built/admin/assets/domain-Ca6KhoQt.js +0 -1
- package/core/built/admin/assets/dropzone-Bb-5zQTk.js +0 -5
- package/core/built/admin/assets/edit-profile-BdupLlus.js +0 -1
- package/core/built/admin/assets/editor-BP883Lpn.js +0 -8
- package/core/built/admin/assets/explore-FB-CimXw.js +0 -1
- package/core/built/admin/assets/feed-C1GxsmI2.js +0 -1
- package/core/built/admin/assets/filter-sources-D5n5bFA2.js +0 -1
- package/core/built/admin/assets/filters-DJEzkMUK.js +0 -1
- package/core/built/admin/assets/filters-MZXvdH5D.js +0 -1
- package/core/built/admin/assets/first-promoter-modal-CGTGLCr5.js +0 -1
- package/core/built/admin/assets/gift-link-modal-B6v0tnRN.js +0 -1
- package/core/built/admin/assets/growth-BGAJD1rs.js +0 -3
- package/core/built/admin/assets/history-modal-iKwUY3XR.js +0 -1
- package/core/built/admin/assets/hooks-CuEZV2-q.js +0 -2
- package/core/built/admin/assets/index-DjQe-e5s.js +0 -4
- package/core/built/admin/assets/index-Dqf2x-ry.css +0 -1
- package/core/built/admin/assets/index.es-VihPwfeH.js +0 -1
- package/core/built/admin/assets/input--W-rCTrX.js +0 -1
- package/core/built/admin/assets/invite-user-modal-MdImLCaJ.js +0 -1
- package/core/built/admin/assets/koenig-loader-DYZpm6El.js +0 -2
- package/core/built/admin/assets/label-picker-cB51xl1r.js +0 -1
- package/core/built/admin/assets/layout-c_B_1hax.js +0 -1
- package/core/built/admin/assets/link-helpers-MVDdnFCY.js +0 -1
- package/core/built/admin/assets/loading-indicator-BpFWTVgh.js +0 -1
- package/core/built/admin/assets/member-custom-fields-qs0dIkxM.js +0 -1
- package/core/built/admin/assets/member-detail-B6uec2a6.js +0 -1
- package/core/built/admin/assets/members-BQF3CqhI.js +0 -2
- package/core/built/admin/assets/moderation-DY4wF1Q3.js +0 -1
- package/core/built/admin/assets/navigation-modal-DX-gNF3X.js +0 -1
- package/core/built/admin/assets/newsletter-CyQA7m3m.js +0 -1
- package/core/built/admin/assets/newsletter-detail-modal-BDrptuxn.js +0 -1
- package/core/built/admin/assets/newsletters-DXuNmC42.js +0 -1
- package/core/built/admin/assets/newsletters-DhNigJUh.js +0 -1
- package/core/built/admin/assets/note-Cgo2LCJ6.js +0 -1
- package/core/built/admin/assets/notifications-BC50AMku.js +0 -1
- package/core/built/admin/assets/offers-container-modal-DWycIMzT.js +0 -1
- package/core/built/admin/assets/onboarding-DGQuV7Ew.js +0 -1
- package/core/built/admin/assets/overview-CVbFtn-k.js +0 -1
- package/core/built/admin/assets/overview-YKj7SZaK.js +0 -1
- package/core/built/admin/assets/pages-B6vr9F_D.js +0 -1
- package/core/built/admin/assets/popover-CCy0h5rq.js +0 -1
- package/core/built/admin/assets/portal-frame-dc4XKr0e.js +0 -1
- package/core/built/admin/assets/portal-modal-BvvdF_B9.js +0 -1
- package/core/built/admin/assets/post-analytics-DX470WRG.js +0 -1
- package/core/built/admin/assets/post-analytics-header-CXpJmdDv.js +0 -1
- package/core/built/admin/assets/post-analytics-provider-CLfKGWZy.js +0 -1
- package/core/built/admin/assets/post-helpers-C5OQMBoi.js +0 -1
- package/core/built/admin/assets/post-share-modal-Cl0NXRJr.js +0 -1
- package/core/built/admin/assets/posts-KY3aUhVV.js +0 -1
- package/core/built/admin/assets/preferences-DO0UUWFp.js +0 -5
- package/core/built/admin/assets/profile-CxT-0l4d.js +0 -1
- package/core/built/admin/assets/router-provider-B0gZyiGJ.js +0 -1
- package/core/built/admin/assets/schemas-4UPic-oD.js +0 -64
- package/core/built/admin/assets/select-DuDUFdPq.js +0 -1
- package/core/built/admin/assets/settings-BjCii7BM.js +0 -1
- package/core/built/admin/assets/settings-b8kNzZSQ.js +0 -4
- package/core/built/admin/assets/share-modal-BV70mr9k.js +0 -1
- package/core/built/admin/assets/shim-ClF_m5ux.js +0 -1
- package/core/built/admin/assets/slack-modal-Be2_KK-z.js +0 -1
- package/core/built/admin/assets/stats-C4reGh9O.js +0 -1
- package/core/built/admin/assets/stats-view-DP9pQ62k.js +0 -1
- package/core/built/admin/assets/stripe-connect-modal-Z-UT_BGc.js +0 -1
- package/core/built/admin/assets/tag-detail-Dc0nTOtU.js +0 -2
- package/core/built/admin/assets/tags-BLaXBwnb.js +0 -1
- package/core/built/admin/assets/testimonials-modal-sFwRnNLh.js +0 -1
- package/core/built/admin/assets/tier-detail-modal-BCFpWwUS.js +0 -1
- package/core/built/admin/assets/tiers-Nd_z4BZY.js +0 -1
- package/core/built/admin/assets/use-filter-params-CAvfDvf1.js +0 -1
- package/core/built/admin/assets/use-growth-stats-D6mZXGhK.js +0 -1
- package/core/built/admin/assets/use-host-limits-DZtR08oa.js +0 -1
- package/core/built/admin/assets/use-pintura-config-CzTfnufz.js +0 -1
- package/core/built/admin/assets/use-reply-chain-data-BeQwz8oF.js +0 -1
- package/core/built/admin/assets/use-settings-navigation-BbrSUVcf.js +0 -1
- package/core/built/admin/assets/use-staff-users-cZg4ugOF.js +0 -1
- package/core/built/admin/assets/use-tinybird-query-B1IMyAcv.js +0 -39
- package/core/built/admin/assets/use-tinybird-token-Bow0Zwn8.js +0 -1
- package/core/built/admin/assets/use-upgrade-route-DhRSo7at.js +0 -1
- package/core/built/admin/assets/user-detail-modal-yipSoQfv.js +0 -1
- package/core/built/admin/assets/users-5msE1WMs.js +0 -1
- package/core/built/admin/assets/web-CKcXAu86.js +0 -1
- package/core/built/admin/assets/web-DR4TqM3E.js +0 -2
- package/core/server/api/endpoints/member-custom-fields.js +0 -90
- package/core/server/api/endpoints/utils/serializers/output/member-custom-fields.js +0 -20
- package/core/server/services/email-suppression-list/in-memory-email-suppression-list.js +0 -39
- 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/members-custom-fields/bindings-service.js +0 -119
- package/core/server/services/members-custom-fields/codec.js +0 -15
- package/core/server/services/members-custom-fields/filter.js +0 -199
- package/core/server/services/members-custom-fields/serializers.js +0 -24
- package/core/server/services/stripe/services/checkout/allowed-countries.js +0 -267
- package/core/server/services/stripe/services/checkout/field-ports.js +0 -34
- package/core/server/services/tier-checkout-config/destinations.js +0 -17
- package/core/server/services/update-check/run-update-check.js +0 -63
- /package/core/built/admin/assets/{chunk.492.f24d855d7e3f3aad261c.js.LICENSE.txt → chunk.901.4ccc639821020230bcca.js.LICENSE.txt} +0 -0
- /package/core/server/services/{members-custom-fields → members-metafields}/storage.js +0 -0
|
@@ -6,8 +6,8 @@ transactions, or Stripe objects.
|
|
|
6
6
|
|
|
7
7
|
## Interface
|
|
8
8
|
|
|
9
|
-
- `startCheckout(input)` owns the
|
|
10
|
-
|
|
9
|
+
- `startCheckout(input)` owns the duration catalogue, Portal plan gate,
|
|
10
|
+
tier/cadence validation, authoritative price,
|
|
11
11
|
token, success parameters, metadata, customer, and one-time payment.
|
|
12
12
|
- `preparePaidContinuation(input)` validates an active gift and returns the
|
|
13
13
|
stable tier/cadence/trial decision consumed by the normal subscription
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.GIFT_DELIVERY_EMAIL_TAG = exports.GIFT_DELIVERY_STALE_AFTER_MS = exports.GIFT_REMINDER_FLOOR_DAYS = exports.GIFT_REMINDER_LEAD_DAYS = exports.GIFT_SEND_HOUR = exports.GIFT_MAX_SCHEDULE_DAYS = exports.GIFT_EXPIRY_DAYS = void 0;
|
|
4
4
|
exports.GIFT_EXPIRY_DAYS = 365;
|
|
5
5
|
// How far ahead a delivery may be scheduled. Portal's picker carries its own
|
|
6
|
-
// copy (GIFT_MAX_SCHEDULE_DAYS in
|
|
6
|
+
// copy (GIFT_MAX_SCHEDULE_DAYS in gift-page.tsx) since Portal ships
|
|
7
7
|
// separately — change them together.
|
|
8
8
|
exports.GIFT_MAX_SCHEDULE_DAYS = 365;
|
|
9
9
|
// Site-local hour a scheduled delivery is sent at. Portal never derives
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
<tr>
|
|
32
32
|
<td align="left" style="padding-bottom: 22px; text-align: left;">
|
|
33
33
|
{{#if siteIconUrl}}
|
|
34
|
-
<
|
|
34
|
+
<img src="{{siteIconUrl}}" alt="{{siteTitle}}" border="0" width="48" height="48" style="border-radius: 4px;">
|
|
35
35
|
{{else}}
|
|
36
|
-
<
|
|
36
|
+
<span style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 17px; font-weight: 700; color: {{accentColor}};">{{siteTitle}}</span>
|
|
37
37
|
{{/if}}
|
|
38
38
|
</td>
|
|
39
39
|
</tr>
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
</tr>
|
|
93
93
|
<tr>
|
|
94
94
|
<td style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 14px; vertical-align: top; padding-top: 40px;">
|
|
95
|
-
<p class="small" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; line-height: 16px; font-size: 11px; color: #738A94; font-weight: normal; margin: 0;">{{t 'This message was sent from {siteDomain} to {email} on behalf of {buyerName} ({buyerEmail}).' siteDomain=
|
|
95
|
+
<p class="small" style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; line-height: 16px; font-size: 11px; color: #738A94; font-weight: normal; margin: 0;">{{t 'This message was sent from {siteDomain} to {email} on behalf of {buyerName} ({buyerEmail}).' siteDomain=siteDomain email=toEmail buyerName=buyerName buyerEmail=buyerEmail}}</p>
|
|
96
96
|
</td>
|
|
97
97
|
</tr>
|
|
98
98
|
</table>
|
|
@@ -182,7 +182,6 @@ class GiftEmailService {
|
|
|
182
182
|
const giftLink = `${siteUrl.replace(/\/$/, '')}/gift/${token}`;
|
|
183
183
|
const { html, text } = await this.renderer.renderDelivery({
|
|
184
184
|
siteTitle,
|
|
185
|
-
siteUrl,
|
|
186
185
|
siteIconUrl: this.blogIcon.getIconUrl({ absolute: true, fallbackToDefault: false }),
|
|
187
186
|
siteDomain,
|
|
188
187
|
accentColor: this.accentColor,
|
|
@@ -95,40 +95,22 @@ class GiftService {
|
|
|
95
95
|
this.deps = deps;
|
|
96
96
|
}
|
|
97
97
|
async startCheckout(input) {
|
|
98
|
-
const customizationEnabled = this.deps.labsService.isSet('giftSubCustomization');
|
|
99
|
-
const populatedDeliveryFields = [
|
|
100
|
-
input.recipientEmail,
|
|
101
|
-
input.recipientName,
|
|
102
|
-
input.buyerName,
|
|
103
|
-
input.personalMessage,
|
|
104
|
-
input.deliveryDate,
|
|
105
|
-
].some((value) => value !== undefined && value !== null && value !== '');
|
|
106
|
-
if (!customizationEnabled && (input.deliveryMethod === 'email' || populatedDeliveryFields)) {
|
|
107
|
-
throw new errors_1.default.BadRequestError({
|
|
108
|
-
message: 'Bad Request.',
|
|
109
|
-
context: 'Gift email delivery is not available',
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
98
|
const parsedBuyerEmail = CheckoutBuyerEmailSchema.safeParse(input.buyer.email);
|
|
113
|
-
if (
|
|
99
|
+
if (!parsedBuyerEmail.success) {
|
|
114
100
|
throw new errors_1.default.BadRequestError({
|
|
115
101
|
message: 'Bad Request.',
|
|
116
102
|
context: `Invalid gift buyer email: ${parsedBuyerEmail.error.issues[0].message}`,
|
|
117
103
|
});
|
|
118
104
|
}
|
|
119
105
|
const buyerEmail = parsedBuyerEmail.success ? parsedBuyerEmail.data : input.buyer.email;
|
|
120
|
-
const parsedDelivery = GiftCheckoutDeliverySchema.safeParse(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
: {
|
|
130
|
-
deliveryMethod: 'link',
|
|
131
|
-
});
|
|
106
|
+
const parsedDelivery = GiftCheckoutDeliverySchema.safeParse({
|
|
107
|
+
deliveryMethod: input.deliveryMethod ?? 'link',
|
|
108
|
+
recipientEmail: input.recipientEmail,
|
|
109
|
+
recipientName: input.recipientName,
|
|
110
|
+
buyerName: input.buyerName,
|
|
111
|
+
personalMessage: input.personalMessage,
|
|
112
|
+
deliveryDate: input.deliveryDate,
|
|
113
|
+
});
|
|
132
114
|
if (!parsedDelivery.success) {
|
|
133
115
|
const issue = parsedDelivery.error.issues[0];
|
|
134
116
|
throw new errors_1.default.BadRequestError({
|
|
@@ -150,22 +132,7 @@ class GiftService {
|
|
|
150
132
|
context: 'Expected offerId or tierId, received none',
|
|
151
133
|
});
|
|
152
134
|
}
|
|
153
|
-
|
|
154
|
-
let cadence;
|
|
155
|
-
if (customizationEnabled) {
|
|
156
|
-
resolvedDuration = (0, gift_checkout_offer_1.resolveGiftDuration)(input);
|
|
157
|
-
cadence = resolvedDuration.cadence;
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
if (input.cadence !== 'month' && input.cadence !== 'year') {
|
|
161
|
-
const receivedCadence = input.cadence ? `"${input.cadence}"` : input.cadence;
|
|
162
|
-
throw new errors_1.default.BadRequestError({
|
|
163
|
-
message: 'Bad Request.',
|
|
164
|
-
context: `Expected cadence to be "month" or "year", received ${receivedCadence}`,
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
cadence = input.cadence;
|
|
168
|
-
}
|
|
135
|
+
const resolvedDuration = (0, gift_checkout_offer_1.resolveGiftDuration)(input);
|
|
169
136
|
let tier;
|
|
170
137
|
try {
|
|
171
138
|
tier = await this.deps.tiersService.api.read(input.tierId);
|
|
@@ -185,20 +152,15 @@ class GiftService {
|
|
|
185
152
|
message: 'This tier is archived.',
|
|
186
153
|
});
|
|
187
154
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
cadence = plan.cadence;
|
|
198
|
-
duration = plan.duration;
|
|
199
|
-
totalMonths = plan.totalMonths;
|
|
200
|
-
amount = plan.amount;
|
|
201
|
-
}
|
|
155
|
+
const plan = (0, gift_checkout_offer_1.validateGiftCheckoutOffer)({
|
|
156
|
+
tier,
|
|
157
|
+
portalPlans: this.deps.settingsCache.get('portal_plans'),
|
|
158
|
+
offer: resolvedDuration,
|
|
159
|
+
});
|
|
160
|
+
const cadence = plan.cadence;
|
|
161
|
+
const duration = plan.duration;
|
|
162
|
+
const totalMonths = plan.totalMonths;
|
|
163
|
+
const amount = plan.amount;
|
|
202
164
|
const tierId = typeof tier.id === 'string' ? tier.id : tier.id.toHexString();
|
|
203
165
|
const token = this.generateToken();
|
|
204
166
|
const successUrl = new URL(input.successUrl);
|
|
@@ -14,7 +14,7 @@ const send_gift_delivery_event_1 = require("./events/send-gift-delivery-event");
|
|
|
14
14
|
// Persistent scheduling adapters keep their queue across restarts and opt out
|
|
15
15
|
// of boot-time rebuilds (same contract post scheduling honours in boot.js).
|
|
16
16
|
let rescheduleDeliveriesOnBoot = true;
|
|
17
|
-
|
|
17
|
+
function init(options) {
|
|
18
18
|
if (exports.service) {
|
|
19
19
|
return;
|
|
20
20
|
}
|
|
@@ -34,10 +34,9 @@ async function init(options) {
|
|
|
34
34
|
const MailgunClient = require('../lib/mailgun-client');
|
|
35
35
|
const config = require('../../../shared/config');
|
|
36
36
|
const settingsCache = require('../../../shared/settings-cache');
|
|
37
|
-
const labsService = require('../../../shared/labs');
|
|
38
37
|
const urlUtils = require('../../../shared/url-utils').default;
|
|
39
38
|
const settingsHelpers = require('../settings-helpers');
|
|
40
|
-
const
|
|
39
|
+
const emailAddressParser = require('../email-address/email-address-parser');
|
|
41
40
|
const { blogIcon } = require('../../../server/lib/image');
|
|
42
41
|
const { t } = require('../i18n');
|
|
43
42
|
const repository = new gift_bookshelf_repository_1.GiftBookshelfRepository({
|
|
@@ -57,7 +56,7 @@ async function init(options) {
|
|
|
57
56
|
bulkMailer: new MailgunClient({ config, settings: settingsCache }),
|
|
58
57
|
settingsCache,
|
|
59
58
|
urlUtils,
|
|
60
|
-
getFromAddress: () =>
|
|
59
|
+
getFromAddress: () => emailAddressParser.stringify(settingsHelpers.getDefaultEmail()),
|
|
61
60
|
getReplyToAddress: () => settingsHelpers.getMembersSupportAddress(),
|
|
62
61
|
blogIcon,
|
|
63
62
|
t,
|
|
@@ -110,7 +109,6 @@ async function init(options) {
|
|
|
110
109
|
},
|
|
111
110
|
giftReminderScheduler,
|
|
112
111
|
checkoutAdapter,
|
|
113
|
-
labsService,
|
|
114
112
|
settingsCache,
|
|
115
113
|
});
|
|
116
114
|
exports.service = giftService;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const logging = require('@tryghost/logging');
|
|
3
|
-
const
|
|
3
|
+
const jobManager = require('../../jobs');
|
|
4
4
|
const CleanGiftsJob = require('./clean-gifts-job').default;
|
|
5
5
|
|
|
6
6
|
let hasScheduled = {
|
|
@@ -31,7 +31,7 @@ function scheduleJob(key, name, jobFile) {
|
|
|
31
31
|
const at = randomOffPeakDailyCron();
|
|
32
32
|
|
|
33
33
|
logging.info(`[Background Job] ${name} scheduled at ${at}`);
|
|
34
|
-
|
|
34
|
+
jobManager.addJob({
|
|
35
35
|
at,
|
|
36
36
|
job: path.resolve(__dirname, jobFile),
|
|
37
37
|
name,
|
|
@@ -43,14 +43,14 @@ function scheduleJob(key, name, jobFile) {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
module.exports = {
|
|
46
|
-
async scheduleGiftCleanupJob(
|
|
46
|
+
async scheduleGiftCleanupJob(jobsService) {
|
|
47
47
|
if (alreadyScheduledOrTest('cleanup')) {
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
const cron = randomOffPeakDailyCron();
|
|
52
52
|
logging.info(`[Background Job] clean-gifts scheduled at ${cron}`);
|
|
53
|
-
await
|
|
53
|
+
await jobsService.scheduleRecurring(new CleanGiftsJob(), { cron });
|
|
54
54
|
|
|
55
55
|
hasScheduled.cleanup = true;
|
|
56
56
|
},
|
|
@@ -160,7 +160,7 @@ class IndexNowPingService {
|
|
|
160
160
|
err,
|
|
161
161
|
message: err.message,
|
|
162
162
|
context: (0, tpl_1.default)(constants_1.messages.requestFailedError, { service: 'IndexNow' }),
|
|
163
|
-
help: (0, tpl_1.default)(constants_1.messages.requestFailedHelp, { url: 'https://ghost.org/
|
|
163
|
+
help: (0, tpl_1.default)(constants_1.messages.requestFailedHelp, { url: 'https://docs.ghost.org/' }),
|
|
164
164
|
}),
|
|
165
165
|
};
|
|
166
166
|
}
|
|
@@ -181,7 +181,7 @@ class IndexNowPingService {
|
|
|
181
181
|
err,
|
|
182
182
|
message: err.message,
|
|
183
183
|
context: (0, tpl_1.default)(constants_1.messages.requestFailedError, { service: 'IndexNow' }),
|
|
184
|
-
help: (0, tpl_1.default)(constants_1.messages.requestFailedHelp, { url: 'https://ghost.org/
|
|
184
|
+
help: (0, tpl_1.default)(constants_1.messages.requestFailedHelp, { url: 'https://docs.ghost.org/' }),
|
|
185
185
|
}),
|
|
186
186
|
};
|
|
187
187
|
}
|
|
@@ -30,7 +30,9 @@ async function accept(invitation) {
|
|
|
30
30
|
throw new errors.NotFoundError({ message: tpl(messages.inviteExpired) });
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
const email = invite.get('email');
|
|
34
|
+
|
|
35
|
+
let user = await models.User.findOne({ email }, options);
|
|
34
36
|
if (user) {
|
|
35
37
|
throw new errors.ValidationError({
|
|
36
38
|
message: tpl(messages.inviteEmailAlreadyExist.message),
|
|
@@ -45,7 +47,7 @@ async function accept(invitation) {
|
|
|
45
47
|
|
|
46
48
|
await models.User.add(
|
|
47
49
|
{
|
|
48
|
-
email
|
|
50
|
+
email,
|
|
49
51
|
name: data.name,
|
|
50
52
|
password: data.password,
|
|
51
53
|
roles: [roleId],
|
|
@@ -9,22 +9,13 @@ const models = require('../../models');
|
|
|
9
9
|
const sentry = require('../../../shared/sentry');
|
|
10
10
|
const domainEvents = require('@tryghost/domain-events');
|
|
11
11
|
const config = require('../../../shared/config');
|
|
12
|
-
const WorkerModelEventBridge = require('./worker-model-event-bridge');
|
|
13
12
|
const errorHandler = (error, workerMeta) => {
|
|
14
13
|
logging.error(error, `[Background Job] ${workerMeta.name} failed`);
|
|
15
14
|
sentry.captureException(error);
|
|
16
15
|
};
|
|
17
16
|
const events = require('../../lib/common/events');
|
|
18
|
-
const workerModelEventBridge = new WorkerModelEventBridge({ models, events, logging, sentry });
|
|
19
17
|
|
|
20
18
|
const workerMessageHandler = ({ name, message }) => {
|
|
21
|
-
if (workerModelEventBridge.isModelEventMessage(message)) {
|
|
22
|
-
// Carries its own `eventName` rather than job-manager's reserved `event` key,
|
|
23
|
-
// so it routes through the bridge instead of being dispatched as a raw domain event.
|
|
24
|
-
workerModelEventBridge.handle(message, { jobName: name });
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
19
|
if (typeof message === 'string' && !['done', 'cancelled'].includes(message)) {
|
|
29
20
|
logging.info(`[Background Job] ${name}: ${message}`);
|
|
30
21
|
}
|
|
@@ -10,6 +10,14 @@ const errors_1 = __importDefault(require("@tryghost/errors"));
|
|
|
10
10
|
const jobs_service_1 = require("./jobs-service");
|
|
11
11
|
let instance;
|
|
12
12
|
function init() {
|
|
13
|
+
// The instance lives for the whole process: the didInit-guarded mentions
|
|
14
|
+
// service captures it in MentionController and MentionSendingService, so
|
|
15
|
+
// an in-process restart (test harness) must revive the same object rather
|
|
16
|
+
// than strand those references on a stopped queue.
|
|
17
|
+
if (instance) {
|
|
18
|
+
instance.clearHandlers();
|
|
19
|
+
return instance;
|
|
20
|
+
}
|
|
13
21
|
const adapterManager = require('../adapter-manager').default;
|
|
14
22
|
const logging = require('@tryghost/logging');
|
|
15
23
|
const sentry = require('../../../shared/sentry');
|
|
@@ -11,12 +11,14 @@ class JobsService {
|
|
|
11
11
|
#logging;
|
|
12
12
|
#sentry;
|
|
13
13
|
#registry = new Map();
|
|
14
|
+
#queueByType = new Map();
|
|
15
|
+
#queues = new Map();
|
|
14
16
|
constructor({ backend, logging, sentry }) {
|
|
15
17
|
this.#backend = backend;
|
|
16
18
|
this.#logging = logging;
|
|
17
19
|
this.#sentry = sentry;
|
|
18
20
|
}
|
|
19
|
-
handle(JobClass, handler) {
|
|
21
|
+
handle(JobClass, handler, options) {
|
|
20
22
|
const type = JobClass.type;
|
|
21
23
|
if (typeof type !== 'string' || type.length === 0) {
|
|
22
24
|
throw new errors_1.default.IncorrectUsageError({
|
|
@@ -28,14 +30,52 @@ class JobsService {
|
|
|
28
30
|
message: `A handler for job type "${type}" is already registered.`,
|
|
29
31
|
});
|
|
30
32
|
}
|
|
33
|
+
this.#declareQueue(type, options);
|
|
31
34
|
this.#registry.set(type, (payload) => handler(new JobClass(JSON.parse(payload))));
|
|
32
35
|
}
|
|
36
|
+
#declareQueue(type, options) {
|
|
37
|
+
if (!options) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const { queue, concurrency } = options;
|
|
41
|
+
if (typeof queue !== 'string' || queue.length === 0) {
|
|
42
|
+
throw new errors_1.default.IncorrectUsageError({
|
|
43
|
+
message: `Invalid queue for job type "${type}": ${JSON.stringify(queue)}. Expected a non-empty string.`,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
// "default" is the backend's shared lane for types that declare no queue;
|
|
47
|
+
// declaring it would silently re-size that lane for every unrouted type.
|
|
48
|
+
if (queue === 'default') {
|
|
49
|
+
throw new errors_1.default.IncorrectUsageError({
|
|
50
|
+
message: `Queue name "default" is reserved for the shared lane; job type "${type}" must omit options to use it.`,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if (!Number.isInteger(concurrency) || concurrency < 1) {
|
|
54
|
+
throw new errors_1.default.IncorrectUsageError({
|
|
55
|
+
message: `Invalid concurrency for job type "${type}": ${JSON.stringify(concurrency)}. Expected a positive integer.`,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const existing = this.#queues.get(queue);
|
|
59
|
+
if (existing && existing.concurrency !== concurrency) {
|
|
60
|
+
throw new errors_1.default.IncorrectUsageError({
|
|
61
|
+
message: `Conflicting concurrency for queue "${queue}": ${existing.concurrency} is already declared, job type "${type}" declares ${concurrency}.`,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
this.#queues.set(queue, { concurrency });
|
|
65
|
+
this.#queueByType.set(type, queue);
|
|
66
|
+
}
|
|
67
|
+
#routingFor(type) {
|
|
68
|
+
const queue = this.#queueByType.get(type);
|
|
69
|
+
return queue === undefined ? undefined : { queue };
|
|
70
|
+
}
|
|
33
71
|
async dispatch(job) {
|
|
34
|
-
|
|
72
|
+
const envelope = this.#buildEnvelope(job);
|
|
73
|
+
await this.#backend.enqueue(envelope, this.#routingFor(envelope.type));
|
|
35
74
|
}
|
|
36
75
|
async scheduleRecurring(job, schedule) {
|
|
37
76
|
this.#assertValidCron(schedule.cron);
|
|
38
|
-
|
|
77
|
+
const envelope = this.#buildEnvelope(job);
|
|
78
|
+
await this.#backend.scheduleRecurring(envelope, schedule, this.#routingFor(envelope.type));
|
|
39
79
|
}
|
|
40
80
|
// later.parse.cron does not strictly validate: it silently coerces a
|
|
41
81
|
// malformed expression into a bogus schedule (garbage -> every minute,
|
|
@@ -55,11 +95,20 @@ class JobsService {
|
|
|
55
95
|
async start() {
|
|
56
96
|
await this.#backend.start({
|
|
57
97
|
processor: (envelope) => this.#process(envelope),
|
|
98
|
+
queues: Object.fromEntries(this.#queues),
|
|
58
99
|
});
|
|
59
100
|
}
|
|
60
101
|
async shutdown(options) {
|
|
61
102
|
await this.#backend.shutdown(options);
|
|
62
103
|
}
|
|
104
|
+
// An in-process restart (test harness) re-runs handler registration on the
|
|
105
|
+
// same instance, so all registration state resets - handlers and queue
|
|
106
|
+
// declarations alike. The duplicate-type guard still holds within a boot.
|
|
107
|
+
clearHandlers() {
|
|
108
|
+
this.#registry.clear();
|
|
109
|
+
this.#queueByType.clear();
|
|
110
|
+
this.#queues.clear();
|
|
111
|
+
}
|
|
63
112
|
#buildEnvelope(job) {
|
|
64
113
|
return { type: this.#typeOf(job), payload: JSON.stringify(job) };
|
|
65
114
|
}
|
|
@@ -37,25 +37,46 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.default = registerJobHandlers;
|
|
40
|
-
const errors_1 = __importDefault(require("@tryghost/errors"));
|
|
41
40
|
const clean_tokens_job_1 = __importDefault(require("../members/jobs/clean-tokens-job"));
|
|
42
|
-
const
|
|
43
|
-
const gifts = __importStar(require("../gifts"));
|
|
41
|
+
const clean_expired_comped_job_1 = __importDefault(require("../members/jobs/clean-expired-comped-job"));
|
|
44
42
|
const clean_gifts_job_1 = __importDefault(require("../gifts/jobs/clean-gifts-job"));
|
|
45
43
|
const external_media_inliner_job_1 = __importDefault(require("../media-inliner/external-media-inliner-job"));
|
|
46
|
-
|
|
44
|
+
const content_csv_import_job_1 = __importDefault(require("../content-import/jobs/content-csv-import-job"));
|
|
45
|
+
const contentImport = __importStar(require("../content-import"));
|
|
46
|
+
const update_check_job_1 = __importDefault(require("../update-check/jobs/update-check-job"));
|
|
47
|
+
const process_webmention_job_1 = __importDefault(require("../mentions/process-webmention-job"));
|
|
48
|
+
const send_webmentions_job_1 = __importDefault(require("../mentions/send-webmentions-job"));
|
|
49
|
+
const updateCheck = require('../update-check');
|
|
50
|
+
// Webmention processing fetches external pages and is triggered by
|
|
51
|
+
// unauthenticated requests, so webmention jobs run in their own lane where a
|
|
52
|
+
// flood cannot occupy the shared workers. The concurrency matches the old
|
|
53
|
+
// dedicated mentions job queue. Every webmention job type must register with
|
|
54
|
+
// this shared declaration so none can declare the queue with a different
|
|
55
|
+
// concurrency.
|
|
56
|
+
const WEBMENTIONS_QUEUE = { queue: 'webmentions', concurrency: 3 };
|
|
57
|
+
function registerJobHandlers({ jobsService, memberJobs, giftService, mediaInliner, mentionsController, mentionsSendingService, }) {
|
|
47
58
|
jobsService.handle(clean_tokens_job_1.default, async () => {
|
|
48
|
-
await
|
|
59
|
+
await memberJobs.cleanTokens();
|
|
60
|
+
});
|
|
61
|
+
jobsService.handle(clean_expired_comped_job_1.default, async () => {
|
|
62
|
+
await memberJobs.cleanExpiredComped();
|
|
49
63
|
});
|
|
50
64
|
jobsService.handle(clean_gifts_job_1.default, async () => {
|
|
51
|
-
|
|
52
|
-
throw new errors_1.default.IncorrectUsageError({
|
|
53
|
-
message: 'clean-gifts ran before the gifts service was initialised',
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
await gifts.service.cleanup();
|
|
65
|
+
await giftService.cleanup();
|
|
57
66
|
});
|
|
58
67
|
jobsService.handle(external_media_inliner_job_1.default, async (job) => {
|
|
59
68
|
await mediaInliner.inline(job.domains);
|
|
60
69
|
});
|
|
70
|
+
jobsService.handle(content_csv_import_job_1.default, async (job) => {
|
|
71
|
+
await contentImport.handleJob(job);
|
|
72
|
+
});
|
|
73
|
+
jobsService.handle(update_check_job_1.default, async () => {
|
|
74
|
+
await updateCheck({ rethrowErrors: true });
|
|
75
|
+
});
|
|
76
|
+
jobsService.handle(process_webmention_job_1.default, async (job) => {
|
|
77
|
+
await mentionsController.processWebmention(job);
|
|
78
|
+
}, WEBMENTIONS_QUEUE);
|
|
79
|
+
jobsService.handle(send_webmentions_job_1.default, async (job) => {
|
|
80
|
+
await mentionsSendingService.sendWebmentions(job);
|
|
81
|
+
}, WEBMENTIONS_QUEUE);
|
|
61
82
|
}
|
|
@@ -17,7 +17,7 @@ const messages = {
|
|
|
17
17
|
reason: ' Reason: {reason}.',
|
|
18
18
|
messageSent: 'Message sent. Double check inbox and spam folder!',
|
|
19
19
|
};
|
|
20
|
-
const
|
|
20
|
+
const emailAddressParser = require('../email-address/email-address-parser');
|
|
21
21
|
const DEFAULT_TAGS = ['ghost-email', 'transactional-email'];
|
|
22
22
|
const MAX_MAILGUN_TAGS = 10;
|
|
23
23
|
|
|
@@ -54,8 +54,8 @@ function getFromAddress(requestedFromAddress, requestedReplyToAddress) {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
return {
|
|
57
|
-
from:
|
|
58
|
-
replyTo: addresses.replyTo ?
|
|
57
|
+
from: emailAddressParser.stringify(addresses.from),
|
|
58
|
+
replyTo: addresses.replyTo ? emailAddressParser.stringify(addresses.replyTo) : null,
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
61
|
|
|
@@ -100,7 +100,7 @@ function createMessage(message) {
|
|
|
100
100
|
*/
|
|
101
101
|
function createMailError({ message, err, ignoreDefaultMessage } = { message: '' }) {
|
|
102
102
|
const helpMessage = tpl(messages.checkEmailConfigInstructions, {
|
|
103
|
-
url: 'https://ghost.org/
|
|
103
|
+
url: 'https://docs.ghost.org/config/#mail',
|
|
104
104
|
});
|
|
105
105
|
const defaultErrorMessage = tpl(messages.failedSendingEmailError);
|
|
106
106
|
|
|
@@ -7,7 +7,7 @@ const MagicLink = require('../lib/magic-link/magic-link');
|
|
|
7
7
|
const sentry = require('../../../shared/sentry');
|
|
8
8
|
const emailAddressService = require('../email-address');
|
|
9
9
|
const settingsHelpers = require('../settings-helpers');
|
|
10
|
-
const
|
|
10
|
+
const emailAddressParser = require('../email-address/email-address-parser');
|
|
11
11
|
const mail = require('../mail');
|
|
12
12
|
const MailgunClient = require('../lib/mailgun-client');
|
|
13
13
|
const config = require('../../../shared/config');
|
|
@@ -152,7 +152,7 @@ class MemberWelcomeEmailService {
|
|
|
152
152
|
},
|
|
153
153
|
});
|
|
154
154
|
|
|
155
|
-
const from =
|
|
155
|
+
const from = emailAddressParser.stringify(fromAddresses.from);
|
|
156
156
|
const replyToSetting = newsletter.get('sender_reply_to');
|
|
157
157
|
let replyTo = null;
|
|
158
158
|
|
|
@@ -173,7 +173,7 @@ class MemberWelcomeEmailService {
|
|
|
173
173
|
});
|
|
174
174
|
|
|
175
175
|
if (addresses.replyTo) {
|
|
176
|
-
replyTo =
|
|
176
|
+
replyTo = emailAddressParser.stringify(addresses.replyTo);
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
|
|
@@ -199,10 +199,10 @@ class MemberWelcomeEmailService {
|
|
|
199
199
|
async #getEffectiveSenderOptions(automatedSender = {}) {
|
|
200
200
|
const defaultOptions = await this.#getSenderOptions();
|
|
201
201
|
const defaultFrom =
|
|
202
|
-
|
|
202
|
+
emailAddressParser.parse(defaultOptions.from || '') ||
|
|
203
203
|
emailAddressService.service.defaultFromEmail;
|
|
204
204
|
const defaultReplyTo = defaultOptions.replyTo
|
|
205
|
-
?
|
|
205
|
+
? emailAddressParser.parse(defaultOptions.replyTo)
|
|
206
206
|
: undefined;
|
|
207
207
|
|
|
208
208
|
const senderName = trimValue(automatedSender.senderName) || defaultFrom?.name || undefined;
|
|
@@ -218,10 +218,10 @@ class MemberWelcomeEmailService {
|
|
|
218
218
|
});
|
|
219
219
|
|
|
220
220
|
return {
|
|
221
|
-
from:
|
|
221
|
+
from: emailAddressParser.stringify(addresses.from),
|
|
222
222
|
...(addresses.replyTo
|
|
223
223
|
? {
|
|
224
|
-
replyTo:
|
|
224
|
+
replyTo: emailAddressParser.stringify(addresses.replyTo),
|
|
225
225
|
}
|
|
226
226
|
: {}),
|
|
227
227
|
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MemberAccountService = void 0;
|
|
7
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
8
|
+
const members_metafields_1 = require("../members-metafields");
|
|
9
|
+
/**
|
|
10
|
+
* A member's own account: what they are shown about themselves, and what they may
|
|
11
|
+
* change.
|
|
12
|
+
*
|
|
13
|
+
* Separate from the request handlers that used to hold this, because none of it is
|
|
14
|
+
* a question about HTTP. Which fields a member may set is a fact about members, and
|
|
15
|
+
* the answer is the same whoever is asking.
|
|
16
|
+
*
|
|
17
|
+
* Takes a member id rather than a member. Everything here either writes or reads
|
|
18
|
+
* afresh, and a record loaded before a write is stale by the time the answer is
|
|
19
|
+
* built, so there is nothing a caller could usefully hand over.
|
|
20
|
+
*/
|
|
21
|
+
/** What a member is allowed to change about themselves. */
|
|
22
|
+
const WRITABLE_FIELDS = [
|
|
23
|
+
'name',
|
|
24
|
+
'expertise',
|
|
25
|
+
'subscribed',
|
|
26
|
+
'newsletters',
|
|
27
|
+
'enable_comment_notifications',
|
|
28
|
+
'enable_updates_and_announcements',
|
|
29
|
+
];
|
|
30
|
+
/**
|
|
31
|
+
* The relations a write needs loaded to work out what it is changing.
|
|
32
|
+
*
|
|
33
|
+
* Newsletters because the older `subscribed` flag is stored as a list of them, and
|
|
34
|
+
* the subscription chain because changing what a member is entitled to has to
|
|
35
|
+
* reconcile against what they are paying for.
|
|
36
|
+
*/
|
|
37
|
+
const WRITE_RELATIONS = [
|
|
38
|
+
'stripeSubscriptions',
|
|
39
|
+
'stripeSubscriptions.customer',
|
|
40
|
+
'stripeSubscriptions.stripePrice',
|
|
41
|
+
'newsletters',
|
|
42
|
+
];
|
|
43
|
+
class MemberAccountService {
|
|
44
|
+
#memberBREADService;
|
|
45
|
+
#members;
|
|
46
|
+
#emailSuppressionList;
|
|
47
|
+
#metafieldValues;
|
|
48
|
+
constructor({ memberBREADService, members, emailSuppressionList, metafieldValues, }) {
|
|
49
|
+
this.#memberBREADService = memberBREADService;
|
|
50
|
+
this.#members = members;
|
|
51
|
+
this.#emailSuppressionList = emailSuppressionList;
|
|
52
|
+
this.#metafieldValues = metafieldValues;
|
|
53
|
+
}
|
|
54
|
+
/** Everything a member is shown about themselves. */
|
|
55
|
+
async read(memberId) {
|
|
56
|
+
// As the member rather than as staff: how much of the extra fields a publisher
|
|
57
|
+
// defines is answered depends on which side of Ghost is asking.
|
|
58
|
+
return this.#memberBREADService.read({ id: memberId }, { metafieldsFor: members_metafields_1.MEMBERS });
|
|
59
|
+
}
|
|
60
|
+
/** Apply what a member asked to change about themselves, and say what they now hold. */
|
|
61
|
+
async edit(data, memberId) {
|
|
62
|
+
// Worked out before the member is touched, so a value the catalog refuses fails
|
|
63
|
+
// the whole request rather than leaving a member renamed with their answers
|
|
64
|
+
// rejected. The write below reconciles subscriptions with Stripe and sends
|
|
65
|
+
// events, none of which giving up halfway could undo.
|
|
66
|
+
const plannedMetafields = data.metafields === undefined
|
|
67
|
+
? null
|
|
68
|
+
: await this.#metafieldValues.planWrite(this.#metafieldValues.unwrapWire(data.metafields), members_metafields_1.MEMBERS);
|
|
69
|
+
await this.#members.update(lodash_1.default.pick(data, WRITABLE_FIELDS), {
|
|
70
|
+
id: memberId,
|
|
71
|
+
withRelated: WRITE_RELATIONS,
|
|
72
|
+
});
|
|
73
|
+
if (plannedMetafields) {
|
|
74
|
+
// A member is recorded as the author of their own answers, and is the one
|
|
75
|
+
// writer whose changes leave nothing in the staff action log: that log
|
|
76
|
+
// records what staff did.
|
|
77
|
+
await this.#metafieldValues.applyWrite(memberId, plannedMetafields, {
|
|
78
|
+
writtenBy: { type: 'member', id: memberId },
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
// Read back rather than returning what was written: a member is told what
|
|
82
|
+
// Ghost now holds, which is not always what they sent. Setting the older
|
|
83
|
+
// `subscribed` flag, for one, is stored as a list of newsletters.
|
|
84
|
+
return this.read(memberId);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Let Ghost email this member again.
|
|
88
|
+
*
|
|
89
|
+
* Two records rather than one: the address is on a list the email provider also
|
|
90
|
+
* writes to, and the member carries a flag of their own. A member asking to hear
|
|
91
|
+
* from a site again means both.
|
|
92
|
+
*/
|
|
93
|
+
async allowEmail(memberId, email) {
|
|
94
|
+
await this.#emailSuppressionList.removeEmail(email);
|
|
95
|
+
await this.#members.update({ email_disabled: false }, { id: memberId });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
exports.MemberAccountService = MemberAccountService;
|