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
|
@@ -3,20 +3,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.MetafieldValuesService = void 0;
|
|
7
7
|
const bson_objectid_1 = __importDefault(require("bson-objectid"));
|
|
8
8
|
const errors_1 = __importDefault(require("@tryghost/errors"));
|
|
9
9
|
const logging_1 = __importDefault(require("@tryghost/logging"));
|
|
10
10
|
const zod_1 = require("zod");
|
|
11
|
-
const
|
|
11
|
+
const metafield_types_1 = require("@tryghost/metafield-types");
|
|
12
|
+
const identity_1 = require("@tryghost/metafield-types/identity");
|
|
12
13
|
const schema_1 = require("./schema");
|
|
13
14
|
const queries_1 = require("./queries");
|
|
15
|
+
const access_1 = require("./access");
|
|
14
16
|
const storage_1 = require("./storage");
|
|
15
|
-
const FIELDS_TABLE = '
|
|
16
|
-
const VALUES_TABLE = '
|
|
17
|
+
const FIELDS_TABLE = 'members_metafields';
|
|
18
|
+
const VALUES_TABLE = 'members_metafield_values';
|
|
17
19
|
/**
|
|
18
20
|
* From the canonical schema, the same source definitions-service reads, so no key a site
|
|
19
|
-
* could hold is refused and this cannot drift from the `
|
|
21
|
+
* could hold is refused and this cannot drift from the `members_metafields.key` column.
|
|
20
22
|
*/
|
|
21
23
|
const MAX_KEY_LENGTH = require('../../data/schema').tables[FIELDS_TABLE].key.maxlength;
|
|
22
24
|
/**
|
|
@@ -29,15 +31,15 @@ const MAX_KEY_LENGTH = require('../../data/schema').tables[FIELDS_TABLE].key.max
|
|
|
29
31
|
* go when that lands; until then the alternative is hand-written upsert SQL per engine.
|
|
30
32
|
*/
|
|
31
33
|
const UPSERT_CHUNK = 400;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const
|
|
34
|
+
const MAX_IDENTITY_LENGTH = MAX_KEY_LENGTH * 2 + 1;
|
|
35
|
+
const ValuesInput = zod_1.z.record(zod_1.z.string().max(MAX_IDENTITY_LENGTH), zod_1.z.unknown());
|
|
36
|
+
const wireProperty = (identity) => [identity_1.QUALIFIER, identity].join('.');
|
|
35
37
|
/**
|
|
36
38
|
* What a member holds for each defined field. Separate from the definitions service
|
|
37
39
|
* because a value belongs to the member and a definition belongs to the site's settings,
|
|
38
40
|
* which are different aggregates rather than different layers.
|
|
39
41
|
*/
|
|
40
|
-
class
|
|
42
|
+
class MetafieldValuesService {
|
|
41
43
|
knex;
|
|
42
44
|
/** A getter, not a number: the ceiling is an operator setting that changes between requests. */
|
|
43
45
|
getMaxDefinitions;
|
|
@@ -45,23 +47,23 @@ class CustomFieldValuesService {
|
|
|
45
47
|
this.knex = knex;
|
|
46
48
|
this.getMaxDefinitions = getMaxDefinitions;
|
|
47
49
|
}
|
|
48
|
-
async
|
|
50
|
+
async activeFieldsByIdentity(identities) {
|
|
51
|
+
const keys = identities
|
|
52
|
+
.map((identity) => (0, identity_1.parseIdentity)(identity))
|
|
53
|
+
.filter((parsed) => parsed !== null && parsed.namespace === identity_1.CUSTOM_NAMESPACE)
|
|
54
|
+
.map((parsed) => parsed.key);
|
|
49
55
|
if (keys.length === 0) {
|
|
50
56
|
return new Map();
|
|
51
57
|
}
|
|
52
58
|
const fields = await (0, queries_1.activeFields)(this.knex)
|
|
53
59
|
.whereIn('key', keys)
|
|
54
60
|
.select('id', 'key', 'name', 'type');
|
|
55
|
-
return new Map(fields.map((field) => [
|
|
61
|
+
return new Map(fields.map((field) => [
|
|
62
|
+
(0, identity_1.formatIdentity)({ namespace: identity_1.CUSTOM_NAMESPACE, key: field.key, partPath: null }),
|
|
63
|
+
{ ...field, namespace: identity_1.CUSTOM_NAMESPACE },
|
|
64
|
+
]));
|
|
56
65
|
}
|
|
57
|
-
|
|
58
|
-
* Members' values, keyed by member id then field key; anything absent is unset.
|
|
59
|
-
*
|
|
60
|
-
* Archived fields are excluded to match the definitions browse: their values stay in
|
|
61
|
-
* the database and stop being addressable. A row that will not parse is dropped and
|
|
62
|
-
* logged rather than failing the read, so one stale row cannot take down a member.
|
|
63
|
-
*/
|
|
64
|
-
async getValuesForMembers(memberIds) {
|
|
66
|
+
async getValuesForMembers(memberIds, audience) {
|
|
65
67
|
if (memberIds.length === 0) {
|
|
66
68
|
return new Map();
|
|
67
69
|
}
|
|
@@ -69,7 +71,7 @@ class CustomFieldValuesService {
|
|
|
69
71
|
// cannot carry an order. `path` is ordered so composite parts assemble the same
|
|
70
72
|
// way every time.
|
|
71
73
|
const rows = await this.knex(VALUES_TABLE)
|
|
72
|
-
.join(FIELDS_TABLE, `${VALUES_TABLE}.
|
|
74
|
+
.join(FIELDS_TABLE, `${VALUES_TABLE}.metafield_key`, `${FIELDS_TABLE}.key`)
|
|
73
75
|
.whereIn(`${VALUES_TABLE}.member_id`, memberIds)
|
|
74
76
|
.where(`${FIELDS_TABLE}.status`, schema_1.FIELD_STATUS.active)
|
|
75
77
|
.orderBy(`${VALUES_TABLE}.path`, 'asc')
|
|
@@ -77,30 +79,57 @@ class CustomFieldValuesService {
|
|
|
77
79
|
const leaves = [];
|
|
78
80
|
for (const row of rows) {
|
|
79
81
|
try {
|
|
80
|
-
leaves.push(schema_1.
|
|
82
|
+
leaves.push(schema_1.DbMetafieldLeaf.parse(row));
|
|
81
83
|
}
|
|
82
84
|
catch (err) {
|
|
83
85
|
logging_1.default.warn({
|
|
84
|
-
event: { name: 'members.
|
|
86
|
+
event: { name: 'members.metafields.value_unreadable' },
|
|
85
87
|
err,
|
|
86
|
-
|
|
88
|
+
metafieldKey: row.key,
|
|
87
89
|
path: row.path,
|
|
88
|
-
}, 'Skipping an unreadable
|
|
90
|
+
}, 'Skipping an unreadable metafield value');
|
|
89
91
|
}
|
|
90
92
|
}
|
|
91
|
-
|
|
93
|
+
// Narrowed before assembly, not after: a composite is one value spread across
|
|
94
|
+
// several rows, and dropping some of its parts later would hand back half an
|
|
95
|
+
// address rather than no address.
|
|
96
|
+
const flat = (0, storage_1.valuesFromLeaves)((0, access_1.readableFields)(audience, leaves));
|
|
97
|
+
return new Map(memberIds.map((memberId) => [memberId, { [identity_1.CUSTOM_NAMESPACE]: flat.get(memberId) ?? {} }]));
|
|
92
98
|
}
|
|
93
|
-
/** Shared by every caller so they cannot disagree on what a values object is. */
|
|
94
99
|
parseValues(input) {
|
|
95
100
|
const parsed = ValuesInput.safeParse(input);
|
|
96
101
|
if (!parsed.success) {
|
|
97
102
|
throw new errors_1.default.ValidationError({
|
|
98
|
-
message: 'Custom field values must be an object keyed by field
|
|
99
|
-
property:
|
|
103
|
+
message: 'Custom field values must be an object keyed by field identity.',
|
|
104
|
+
property: identity_1.QUALIFIER,
|
|
100
105
|
});
|
|
101
106
|
}
|
|
102
107
|
return parsed.data;
|
|
103
108
|
}
|
|
109
|
+
unwrapWire(input) {
|
|
110
|
+
if (input === undefined) {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
if (typeof input !== 'object' || input === null || Array.isArray(input)) {
|
|
114
|
+
throw new errors_1.default.ValidationError({
|
|
115
|
+
message: 'Metafields must be an object keyed by namespace.',
|
|
116
|
+
property: identity_1.QUALIFIER,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
const identified = {};
|
|
120
|
+
for (const [namespace, values] of Object.entries(input)) {
|
|
121
|
+
if (typeof values !== 'object' || values === null || Array.isArray(values)) {
|
|
122
|
+
throw new errors_1.default.ValidationError({
|
|
123
|
+
message: 'Metafield values must be an object keyed by field key.',
|
|
124
|
+
property: [identity_1.QUALIFIER, namespace].join('.'),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
for (const [key, raw] of Object.entries(values)) {
|
|
128
|
+
identified[`${namespace}.${key}`] = raw;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return identified;
|
|
132
|
+
}
|
|
104
133
|
/**
|
|
105
134
|
* Whether input names any values. Asks the shape question alone, with no catalog
|
|
106
135
|
* lookup, so it can be asked before a write is known to be permitted.
|
|
@@ -116,35 +145,38 @@ class CustomFieldValuesService {
|
|
|
116
145
|
* validate before opening a transaction it would otherwise have to unwind, then apply
|
|
117
146
|
* the same plan without re-resolving it.
|
|
118
147
|
*/
|
|
119
|
-
async planWrite(input) {
|
|
148
|
+
async planWrite(input, audience) {
|
|
120
149
|
const values = this.parseValues(input);
|
|
121
|
-
const
|
|
150
|
+
const identities = Object.keys(values);
|
|
122
151
|
// Bounded by the definitions ceiling, which also holds the lookup below inside
|
|
123
152
|
// the driver's bound-parameter limit.
|
|
124
153
|
const maxKeys = this.getMaxDefinitions();
|
|
125
|
-
if (
|
|
154
|
+
if (identities.length > maxKeys) {
|
|
126
155
|
throw new errors_1.default.ValidationError({
|
|
127
156
|
message: `Custom field values are limited to ${maxKeys} fields per request.`,
|
|
128
|
-
property:
|
|
157
|
+
property: identity_1.QUALIFIER,
|
|
129
158
|
});
|
|
130
159
|
}
|
|
131
|
-
const
|
|
160
|
+
const byIdentity = await this.activeFieldsByIdentity(identities);
|
|
132
161
|
const writes = [];
|
|
133
|
-
for (const [
|
|
134
|
-
const field =
|
|
162
|
+
for (const [identity, raw] of Object.entries(values)) {
|
|
163
|
+
const field = byIdentity.get(identity);
|
|
135
164
|
if (!field) {
|
|
136
|
-
// Unknown or archived. Refused rather than ignored: a typo that silently
|
|
137
|
-
// drops what somebody typed is worse than a save that fails. The catalog
|
|
138
|
-
// applies the same rule to the parts of a composite value.
|
|
139
165
|
throw new errors_1.default.ValidationError({
|
|
140
|
-
message: `Unknown custom field: ${
|
|
141
|
-
property:
|
|
166
|
+
message: `Unknown custom field: ${identity}`,
|
|
167
|
+
property: wireProperty(identity),
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
if (!(0, access_1.canWrite)(audience, field)) {
|
|
171
|
+
throw new errors_1.default.ValidationError({
|
|
172
|
+
message: `Cannot set custom field: ${identity}`,
|
|
173
|
+
property: wireProperty(identity),
|
|
142
174
|
});
|
|
143
175
|
}
|
|
144
176
|
// `null` clears any field, and `''` clears one with no parts. For a value
|
|
145
177
|
// with parts `''` names nothing, so it is left to fail validation rather than
|
|
146
178
|
// being read as a silent delete.
|
|
147
|
-
if (raw === null || (raw === '' && (0,
|
|
179
|
+
if (raw === null || (raw === '' && (0, metafield_types_1.subFieldsOf)(field.type) === null)) {
|
|
148
180
|
writes.push({ field });
|
|
149
181
|
continue;
|
|
150
182
|
}
|
|
@@ -152,12 +184,12 @@ class CustomFieldValuesService {
|
|
|
152
184
|
// `context` when `context` is empty and prepends it when it is not, so
|
|
153
185
|
// anything added here reaches the client glued to the front of the reason.
|
|
154
186
|
// Which field failed rides in `property`.
|
|
155
|
-
const value =
|
|
187
|
+
const value = metafield_types_1.FIELD_TYPES[field.type].value.safeParse(raw);
|
|
156
188
|
if (!value.success) {
|
|
157
189
|
const issue = value.error.issues[0];
|
|
158
190
|
throw new errors_1.default.ValidationError({
|
|
159
191
|
message: issue.message,
|
|
160
|
-
property: [
|
|
192
|
+
property: [wireProperty(identity), ...issue.path].join('.'),
|
|
161
193
|
});
|
|
162
194
|
}
|
|
163
195
|
writes.push({ field, value: value.data });
|
|
@@ -202,7 +234,7 @@ class CustomFieldValuesService {
|
|
|
202
234
|
rows.push(...set.map((leaf) => ({
|
|
203
235
|
id: new bson_objectid_1.default().toHexString(),
|
|
204
236
|
member_id: memberId,
|
|
205
|
-
|
|
237
|
+
metafield_key: field.key,
|
|
206
238
|
path: leaf.path,
|
|
207
239
|
value_text: leaf.value_text,
|
|
208
240
|
written_by_type: writtenBy.type,
|
|
@@ -214,7 +246,7 @@ class CustomFieldValuesService {
|
|
|
214
246
|
if (clearedKeys.length > 0) {
|
|
215
247
|
await trx(VALUES_TABLE)
|
|
216
248
|
.where('member_id', memberId)
|
|
217
|
-
.whereIn('
|
|
249
|
+
.whereIn('metafield_key', clearedKeys)
|
|
218
250
|
.del();
|
|
219
251
|
}
|
|
220
252
|
if (clearedPaths.length > 0) {
|
|
@@ -223,7 +255,7 @@ class CustomFieldValuesService {
|
|
|
223
255
|
.where('member_id', memberId)
|
|
224
256
|
.where((builder) => {
|
|
225
257
|
for (const { fieldKey, paths } of clearedPaths) {
|
|
226
|
-
builder.orWhere((pair) => pair.where('
|
|
258
|
+
builder.orWhere((pair) => pair.where('metafield_key', fieldKey).whereIn('path', paths));
|
|
227
259
|
}
|
|
228
260
|
})
|
|
229
261
|
.del();
|
|
@@ -236,7 +268,7 @@ class CustomFieldValuesService {
|
|
|
236
268
|
.insert(rows.slice(from, from + UPSERT_CHUNK))
|
|
237
269
|
// Naming the columns rather than giving values takes each from the row
|
|
238
270
|
// that lost the conflict, so every part updates to its own value.
|
|
239
|
-
.onConflict(['member_id', '
|
|
271
|
+
.onConflict(['member_id', 'metafield_key', 'path'])
|
|
240
272
|
// The writer is merged with the value, so a leaf names who wrote what
|
|
241
273
|
// it currently holds rather than who wrote its first value.
|
|
242
274
|
.merge(['value_text', 'written_by_type', 'written_by_id', 'updated_at']);
|
|
@@ -251,4 +283,4 @@ class CustomFieldValuesService {
|
|
|
251
283
|
}
|
|
252
284
|
}
|
|
253
285
|
}
|
|
254
|
-
exports.
|
|
286
|
+
exports.MetafieldValuesService = MetafieldValuesService;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const logging = require('@tryghost/logging');
|
|
2
|
+
const ProcessWebmentionJob = require('./process-webmention-job').default;
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* @typedef {import('./mentions-api')} MentionsAPI
|
|
@@ -22,11 +23,6 @@ const logging = require('@tryghost/logging');
|
|
|
22
23
|
* @prop {Resource} resource
|
|
23
24
|
*/
|
|
24
25
|
|
|
25
|
-
/**
|
|
26
|
-
* @typedef {object} IJobService
|
|
27
|
-
* @prop {(name: string, fn: Function) => void} addJob
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
26
|
/**
|
|
31
27
|
* @typedef {object} IMentionResourceService
|
|
32
28
|
* @prop {(id: import('bson-objectid').default) => Promise<MentionResource>} getByID
|
|
@@ -36,8 +32,8 @@ module.exports = class MentionController {
|
|
|
36
32
|
/** @type {import('./mentions-api')} */
|
|
37
33
|
#api;
|
|
38
34
|
|
|
39
|
-
/** @type {
|
|
40
|
-
#
|
|
35
|
+
/** @type {import('../jobs-service/jobs-service').JobsService} */
|
|
36
|
+
#jobsService;
|
|
41
37
|
|
|
42
38
|
/** @type {IMentionResourceService} */
|
|
43
39
|
#mentionResourceService;
|
|
@@ -45,12 +41,12 @@ module.exports = class MentionController {
|
|
|
45
41
|
/**
|
|
46
42
|
* @param {object} deps
|
|
47
43
|
* @param {import('./mentions-api')} deps.api
|
|
48
|
-
* @param {
|
|
44
|
+
* @param {import('../jobs-service/jobs-service').JobsService} deps.jobsService
|
|
49
45
|
* @param {IMentionResourceService} deps.mentionResourceService
|
|
50
46
|
*/
|
|
51
47
|
async init(deps) {
|
|
52
48
|
this.#api = deps.api;
|
|
53
|
-
this.#
|
|
49
|
+
this.#jobsService = deps.jobsService;
|
|
54
50
|
this.#mentionResourceService = deps.mentionResourceService;
|
|
55
51
|
}
|
|
56
52
|
|
|
@@ -127,17 +123,23 @@ module.exports = class MentionController {
|
|
|
127
123
|
*/
|
|
128
124
|
async receive(frame) {
|
|
129
125
|
logging.info('[Webmention] ' + JSON.stringify(frame.data));
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
126
|
+
const { source, target, ...payload } = frame.data;
|
|
127
|
+
await this.#jobsService.dispatch(new ProcessWebmentionJob({ source, target, payload }));
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* @param {import('./process-webmention-job').default} job
|
|
132
|
+
* @returns {Promise<void>}
|
|
133
|
+
*/
|
|
134
|
+
async processWebmention({ source, target, payload }) {
|
|
135
|
+
try {
|
|
136
|
+
await this.#api.processWebmention({
|
|
137
|
+
source: new URL(source),
|
|
138
|
+
target: new URL(target),
|
|
139
|
+
payload,
|
|
140
|
+
});
|
|
141
|
+
} catch (err) {
|
|
142
|
+
logging.error(err, '[Webmention] Failed processing webmention');
|
|
143
|
+
}
|
|
142
144
|
}
|
|
143
145
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const errors = require('@tryghost/errors');
|
|
2
2
|
const logging = require('@tryghost/logging');
|
|
3
|
+
const SendWebmentionsJob = require('./send-webmentions-job').default;
|
|
3
4
|
|
|
4
5
|
module.exports = class MentionSendingService {
|
|
5
6
|
#discoveryService;
|
|
@@ -8,8 +9,12 @@ module.exports = class MentionSendingService {
|
|
|
8
9
|
#getPostData;
|
|
9
10
|
#getPostUrl;
|
|
10
11
|
#isEnabled;
|
|
11
|
-
#
|
|
12
|
+
#jobsService;
|
|
12
13
|
|
|
14
|
+
/**
|
|
15
|
+
* @param {object} deps
|
|
16
|
+
* @param {import('../jobs-service/jobs-service').JobsService} deps.jobsService
|
|
17
|
+
*/
|
|
13
18
|
constructor({
|
|
14
19
|
discoveryService,
|
|
15
20
|
externalRequest,
|
|
@@ -17,7 +22,7 @@ module.exports = class MentionSendingService {
|
|
|
17
22
|
getPostData,
|
|
18
23
|
getPostUrl,
|
|
19
24
|
isEnabled,
|
|
20
|
-
|
|
25
|
+
jobsService,
|
|
21
26
|
}) {
|
|
22
27
|
this.#discoveryService = discoveryService;
|
|
23
28
|
this.#externalRequest = externalRequest;
|
|
@@ -25,7 +30,7 @@ module.exports = class MentionSendingService {
|
|
|
25
30
|
this.#getPostData = getPostData;
|
|
26
31
|
this.#getPostUrl = getPostUrl;
|
|
27
32
|
this.#isEnabled = isEnabled;
|
|
28
|
-
this.#
|
|
33
|
+
this.#jobsService = jobsService;
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
get siteUrl() {
|
|
@@ -82,13 +87,13 @@ module.exports = class MentionSendingService {
|
|
|
82
87
|
// Capture the source URL now, from the event's data, rather than
|
|
83
88
|
// deferring the model into the job.
|
|
84
89
|
const url = new URL(await this.#resolvePostUrl(post));
|
|
85
|
-
await this.#
|
|
86
|
-
|
|
87
|
-
url,
|
|
90
|
+
await this.#jobsService.dispatch(
|
|
91
|
+
new SendWebmentionsJob({
|
|
92
|
+
sourceUrl: url.href,
|
|
88
93
|
html: html,
|
|
89
94
|
previousHtml: previousHtml,
|
|
90
|
-
})
|
|
91
|
-
|
|
95
|
+
}),
|
|
96
|
+
);
|
|
92
97
|
}
|
|
93
98
|
} catch (e) {
|
|
94
99
|
logging.error('Error in webmention sending service post update event handler:');
|
|
@@ -157,11 +162,23 @@ module.exports = class MentionSendingService {
|
|
|
157
162
|
});
|
|
158
163
|
}
|
|
159
164
|
|
|
165
|
+
/**
|
|
166
|
+
* Send the webmentions for a delivered job.
|
|
167
|
+
* @param {import('./send-webmentions-job').default} job
|
|
168
|
+
*/
|
|
169
|
+
async sendWebmentions(job) {
|
|
170
|
+
await this.sendForHTMLResource({
|
|
171
|
+
url: new URL(job.sourceUrl),
|
|
172
|
+
html: job.html,
|
|
173
|
+
previousHtml: job.previousHtml,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
160
177
|
/**
|
|
161
178
|
* Send a webmention call for the links in a resource.
|
|
162
179
|
* @param {object} resource
|
|
163
180
|
* @param {URL} resource.url
|
|
164
|
-
* @param {string} resource.html
|
|
181
|
+
* @param {string|null} resource.html
|
|
165
182
|
* @param {string|null} [resource.previousHtml]
|
|
166
183
|
*/
|
|
167
184
|
async sendForHTMLResource(resource) {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const job_1 = require("../jobs-service/job");
|
|
4
|
+
class ProcessWebmentionJob extends job_1.Job {
|
|
5
|
+
static type = 'process-webmention';
|
|
6
|
+
source;
|
|
7
|
+
target;
|
|
8
|
+
payload;
|
|
9
|
+
constructor({ source, target, payload, }) {
|
|
10
|
+
super();
|
|
11
|
+
this.source = source;
|
|
12
|
+
this.target = target;
|
|
13
|
+
this.payload = payload;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.default = ProcessWebmentionJob;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const job_1 = require("../jobs-service/job");
|
|
4
|
+
// Carries the post's full html twice - the largest job payload in the system;
|
|
5
|
+
// revisit if a durable backend puts size limits on envelopes.
|
|
6
|
+
class SendWebmentionsJob extends job_1.Job {
|
|
7
|
+
static type = 'send-webmentions';
|
|
8
|
+
sourceUrl;
|
|
9
|
+
html;
|
|
10
|
+
previousHtml;
|
|
11
|
+
constructor({ sourceUrl, html, previousHtml, }) {
|
|
12
|
+
super();
|
|
13
|
+
this.sourceUrl = sourceUrl;
|
|
14
|
+
this.html = html ?? null;
|
|
15
|
+
this.previousHtml = previousHtml ?? null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.default = SendWebmentionsJob;
|
|
@@ -14,8 +14,6 @@ const outputSerializerUrlUtil = require('../../../server/api/endpoints/utils/ser
|
|
|
14
14
|
const urlService = require('../url');
|
|
15
15
|
const settingsCache = require('../../../shared/settings-cache');
|
|
16
16
|
const DomainEvents = require('@tryghost/domain-events');
|
|
17
|
-
const logging = require('@tryghost/logging');
|
|
18
|
-
const jobsService = require('../mentions-jobs');
|
|
19
17
|
|
|
20
18
|
// Serializes a post model to the data the URL service needs, loading the
|
|
21
19
|
// relations it reads for filtered collections (event-emitted models don't
|
|
@@ -38,33 +36,6 @@ function getPostUrl(id, postData) {
|
|
|
38
36
|
return jsonModel.url;
|
|
39
37
|
}
|
|
40
38
|
|
|
41
|
-
// Reports the same queued/started/finished/failed lifecycle for every mentions
|
|
42
|
-
// background job. The wrapped callback's result and errors pass through unchanged,
|
|
43
|
-
// so job manager outcomes and retries are unaffected.
|
|
44
|
-
function makeLoggingJobService() {
|
|
45
|
-
return {
|
|
46
|
-
async addJob(name, fn) {
|
|
47
|
-
logging.info(`[Background Job] ${name} queued`);
|
|
48
|
-
jobsService.addJob({
|
|
49
|
-
name,
|
|
50
|
-
job: async () => {
|
|
51
|
-
const startedAt = Date.now();
|
|
52
|
-
logging.info(`[Background Job] ${name} started`);
|
|
53
|
-
try {
|
|
54
|
-
const result = await fn();
|
|
55
|
-
logging.info(`[Background Job] ${name} completed in ${Date.now() - startedAt}ms`);
|
|
56
|
-
return result;
|
|
57
|
-
} catch (err) {
|
|
58
|
-
logging.error(err, `[Background Job] ${name} failed after ${Date.now() - startedAt}ms`);
|
|
59
|
-
throw err;
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
offloaded: false,
|
|
63
|
-
});
|
|
64
|
-
},
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
39
|
module.exports = {
|
|
69
40
|
/** @type {import('./mentions-api')} */
|
|
70
41
|
api: null,
|
|
@@ -75,7 +46,11 @@ module.exports = {
|
|
|
75
46
|
/** @type {import('./mention-sending-service')} */
|
|
76
47
|
sendingService: null,
|
|
77
48
|
didInit: false,
|
|
78
|
-
|
|
49
|
+
/**
|
|
50
|
+
* @param {object} deps
|
|
51
|
+
* @param {import('../jobs-service/jobs-service').JobsService} deps.jobsService
|
|
52
|
+
*/
|
|
53
|
+
async init({ jobsService }) {
|
|
79
54
|
if (this.didInit) {
|
|
80
55
|
return;
|
|
81
56
|
}
|
|
@@ -110,7 +85,7 @@ module.exports = {
|
|
|
110
85
|
|
|
111
86
|
this.controller.init({
|
|
112
87
|
api,
|
|
113
|
-
|
|
88
|
+
jobsService,
|
|
114
89
|
mentionResourceService: {
|
|
115
90
|
async getByID(id) {
|
|
116
91
|
if (!id) {
|
|
@@ -137,7 +112,7 @@ module.exports = {
|
|
|
137
112
|
getPostData: (post) => getPostData(post),
|
|
138
113
|
getPostUrl: (id, data) => getPostUrl(id, data),
|
|
139
114
|
isEnabled: () => !settingsCache.get('is_private'),
|
|
140
|
-
|
|
115
|
+
jobsService,
|
|
141
116
|
});
|
|
142
117
|
sendingService.listen(events);
|
|
143
118
|
|
|
@@ -148,4 +123,3 @@ module.exports = {
|
|
|
148
123
|
// exposed for testing
|
|
149
124
|
module.exports.getPostData = getPostData;
|
|
150
125
|
module.exports.getPostUrl = getPostUrl;
|
|
151
|
-
module.exports.makeLoggingJobService = makeLoggingJobService;
|
|
@@ -14,7 +14,7 @@ const tpl_1 = __importDefault(require("@tryghost/tpl"));
|
|
|
14
14
|
const messages = {
|
|
15
15
|
validationError: 'The following definition "{at}" is invalid: {reason}',
|
|
16
16
|
};
|
|
17
|
-
const DOCS_URL = 'https://ghost.org/
|
|
17
|
+
const DOCS_URL = 'https://docs.ghost.org/themes/routing/';
|
|
18
18
|
const MAX_SHOWN_LENGTH = 40;
|
|
19
19
|
/**
|
|
20
20
|
* Stable, machine-readable codes describing the class of a routes.yaml failure.
|
|
@@ -200,14 +200,7 @@ module.exports = {
|
|
|
200
200
|
type: 'boolean',
|
|
201
201
|
group: 'members',
|
|
202
202
|
fn: settingsHelpers.allowSelfSignup.bind(settingsHelpers),
|
|
203
|
-
dependents: [
|
|
204
|
-
'members_signup_access',
|
|
205
|
-
'portal_plans',
|
|
206
|
-
'stripe_secret_key',
|
|
207
|
-
'stripe_publishable_key',
|
|
208
|
-
'stripe_connect_secret_key',
|
|
209
|
-
'stripe_connect_publishable_key',
|
|
210
|
-
],
|
|
203
|
+
dependents: ['members_signup_access'],
|
|
211
204
|
}),
|
|
212
205
|
);
|
|
213
206
|
fields.push(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const net = require('net');
|
|
2
2
|
const tpl = require('@tryghost/tpl');
|
|
3
3
|
const errors = require('@tryghost/errors');
|
|
4
|
-
const
|
|
4
|
+
const emailAddressParser = require('../email-address/email-address-parser');
|
|
5
5
|
const logging = require('@tryghost/logging');
|
|
6
6
|
const crypto = require('crypto');
|
|
7
7
|
const debug = require('@tryghost/debug')('services:settings-helpers');
|
|
@@ -130,11 +130,9 @@ class SettingsHelpers {
|
|
|
130
130
|
if (!supportAddress) {
|
|
131
131
|
// In the new flow, we make a difference between an empty setting (= use default) and a 'noreply' setting (=use noreply @ domain)
|
|
132
132
|
// Also keep the name of the default email!
|
|
133
|
-
return
|
|
133
|
+
return emailAddressParser.stringify(this.getDefaultEmail());
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
supportAddress = supportAddress || 'noreply';
|
|
137
|
-
|
|
138
136
|
// Any fromAddress without domain uses site domain, like default setting `noreply`
|
|
139
137
|
if (supportAddress.indexOf('@') < 0) {
|
|
140
138
|
return `${supportAddress}@${this.getDefaultEmailDomain()}`;
|
|
@@ -143,7 +141,7 @@ class SettingsHelpers {
|
|
|
143
141
|
}
|
|
144
142
|
|
|
145
143
|
/**
|
|
146
|
-
* @deprecated Use getDefaultEmail().address (without name) or
|
|
144
|
+
* @deprecated Use getDefaultEmail().address (without name) or emailAddressParser.stringify(this.getDefaultEmail()) (with name) instead
|
|
147
145
|
*/
|
|
148
146
|
getNoReplyAddress() {
|
|
149
147
|
return this.getDefaultEmailAddress();
|
|
@@ -157,7 +155,7 @@ class SettingsHelpers {
|
|
|
157
155
|
// parse the email here and remove the sender name
|
|
158
156
|
// E.g. when set to "bar" <from@default.com>
|
|
159
157
|
const configAddress = this.config.get('mail:from');
|
|
160
|
-
const parsed =
|
|
158
|
+
const parsed = emailAddressParser.parse(configAddress);
|
|
161
159
|
if (parsed) {
|
|
162
160
|
return parsed;
|
|
163
161
|
}
|
|
@@ -173,7 +173,7 @@ class SlackPingService {
|
|
|
173
173
|
this.logging.error(new errors_1.default.InternalServerError({
|
|
174
174
|
err: err,
|
|
175
175
|
context: (0, tpl_1.default)(constants_1.messages.requestFailedError, { service: 'slack' }),
|
|
176
|
-
help: (0, tpl_1.default)(constants_1.messages.requestFailedHelp, { url: 'https://ghost.org/
|
|
176
|
+
help: (0, tpl_1.default)(constants_1.messages.requestFailedHelp, { url: 'https://docs.ghost.org/' }),
|
|
177
177
|
}));
|
|
178
178
|
});
|
|
179
179
|
}
|
|
@@ -2,7 +2,7 @@ const { promises: fs, readFileSync } = require('fs');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const moment = require('moment');
|
|
4
4
|
const { globSync } = require('glob');
|
|
5
|
-
const
|
|
5
|
+
const emailAddressParser = require('../email-address/email-address-parser');
|
|
6
6
|
|
|
7
7
|
class StaffServiceEmails {
|
|
8
8
|
constructor({
|
|
@@ -593,7 +593,7 @@ class StaffServiceEmails {
|
|
|
593
593
|
}
|
|
594
594
|
|
|
595
595
|
get fromEmailAddress() {
|
|
596
|
-
return
|
|
596
|
+
return emailAddressParser.stringify(this.settingsHelpers.getDefaultEmail());
|
|
597
597
|
}
|
|
598
598
|
|
|
599
599
|
extractInitials(name = '') {
|