ghost 6.60.0 → 6.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/ghost-storage-base-3.0.0.tgz +0 -0
- package/components/tryghost-adapter-base-cache-0.2.0.tgz +0 -0
- package/components/tryghost-adapter-base-jobs-0.0.0.tgz +0 -0
- package/components/tryghost-adapter-base-redirects-0.0.0.tgz +0 -0
- package/components/tryghost-adapter-base-route-settings-0.0.0.tgz +0 -0
- package/components/tryghost-adapter-base-scheduling-0.2.3.tgz +0 -0
- package/components/tryghost-adapter-base-sso-0.1.3.tgz +0 -0
- package/components/tryghost-admin-api-schema-0.0.0.tgz +0 -0
- package/components/tryghost-checkout-0.0.0.tgz +0 -0
- package/components/tryghost-custom-field-types-0.0.0.tgz +0 -0
- package/components/tryghost-i18n-0.0.0.tgz +0 -0
- package/components/tryghost-kg-card-factory-5.2.4.tgz +0 -0
- package/components/tryghost-kg-clean-basic-html-4.3.4.tgz +0 -0
- package/components/tryghost-kg-converters-1.2.5.tgz +0 -0
- package/components/tryghost-kg-default-cards-10.3.5.tgz +0 -0
- package/components/tryghost-kg-default-nodes-2.2.1.tgz +0 -0
- package/components/tryghost-kg-default-transforms-1.3.4.tgz +0 -0
- package/components/tryghost-kg-html-to-lexical-1.4.0.tgz +0 -0
- package/components/tryghost-kg-lexical-html-renderer-1.5.0.tgz +0 -0
- package/components/tryghost-kg-markdown-html-renderer-7.2.4.tgz +0 -0
- package/components/tryghost-kg-utils-1.1.4.tgz +0 -0
- package/components/tryghost-nql-string-0.0.0.tgz +0 -0
- package/components/tryghost-parse-email-address-0.0.0.tgz +0 -0
- package/content/settings/README.md +1 -1
- package/content/themes/casper/.gitignore +28 -0
- package/content/themes/casper/assets/built/casper.js +1 -1
- package/content/themes/casper/assets/built/screen.css +1 -1
- package/content/themes/casper/assets/css/screen.css +2 -1
- package/content/themes/casper/assets/js/lightbox.js +63 -46
- package/content/themes/casper/package.json +6 -6
- package/content/themes/casper/page.hbs +1 -0
- package/content/themes/casper/post.hbs +1 -0
- package/content/themes/source/.gitignore +28 -0
- package/content/themes/source/assets/built/screen.css +1 -1
- package/content/themes/source/assets/built/source.js +1 -1
- package/content/themes/source/assets/css/screen.css +2 -1
- package/content/themes/source/assets/js/lightbox.js +62 -45
- package/content/themes/source/assets/js/main.js +2 -2
- package/content/themes/source/package.json +4 -4
- package/content/themes/source/partials/feature-image.hbs +1 -0
- package/core/boot.js +62 -21
- package/core/built/admin/assets/Combination-B0l4MKVh.js +41 -0
- package/core/built/admin/assets/InterVariable-DiVDrmQJ.woff2 +0 -0
- package/core/built/admin/assets/InterVariable-Italic-FCBEiFp6.woff2 +0 -0
- package/core/built/admin/assets/{PolarAngleAxis-C4qtHy1B.js → PolarAngleAxis-pkMyqz8g.js} +1 -1
- package/core/built/admin/assets/{RadialBarChart-Bh09Stsj.js → RadialBarChart-JAKoS4KT.js} +1 -1
- package/core/built/admin/assets/{about-BgpmhCuM.js → about-Dyae_UT6.js} +1 -1
- package/core/built/admin/assets/account-migration-CESa0mnX.js +1 -0
- package/core/built/admin/assets/{action-list-lGzZLHc8.js → action-list-C4v0-du8.js} +1 -1
- package/core/built/admin/assets/activitypub/{account-migration-DMHuPnJn.js → account-migration-By69CgCp.js} +16 -16
- package/core/built/admin/assets/activitypub/activitypub.js +9 -10
- package/core/built/admin/assets/activitypub/{avatar-DhTo5D1B.js → avatar-DLPL3Abs.js} +59 -68
- package/core/built/admin/assets/activitypub/{avatar-flipboard-DnVgbEfa.js → avatar-flipboard-C9iDY-QV.js} +2 -2
- package/core/built/admin/assets/activitypub/{bluesky-sharing-BT4zAlW7.js → bluesky-sharing-BJcPMrDd.js} +37 -37
- package/core/built/admin/assets/activitypub/{content-formatters-BeDZ-DIa.js → content-formatters-3rTHg3mp.js} +18 -18
- package/core/built/admin/assets/activitypub/{copy-8sqxUuNd.js → copy-DIAOQoCZ.js} +2 -2
- package/core/built/admin/assets/activitypub/{domain-xQDDu1CS.js → domain-DUR4xSkV.js} +121 -121
- package/core/built/admin/assets/activitypub/{edit-profile-BXdF_r2G.js → edit-profile-BqtfzxCp.js} +40 -40
- package/core/built/admin/assets/activitypub/{explore-CMt7gKlL.js → explore-BxuJd-J4.js} +27 -27
- package/core/built/admin/assets/activitypub/{feed-Bwqdddp_.js → feed-BM1TcksA.js} +51 -51
- package/core/built/admin/assets/activitypub/{field-4co_8FVg.js → field-Dn7HHx2-.js} +3 -3
- package/core/built/admin/assets/activitypub/{hash-DwakMs4X.js → hash-Bm3WxYN4.js} +2 -2
- package/core/built/admin/assets/activitypub/inbox-CCjkuow2.js +1284 -0
- package/core/built/admin/assets/activitypub/{inbox-ckD4wo_r.js → inbox-d8oJRTf4.js} +2 -2
- package/core/built/admin/assets/activitypub/label-1AA_s9Fa.js +16 -0
- package/core/built/admin/assets/activitypub/layout-2-0bw6HN.js +1 -0
- package/core/built/admin/assets/activitypub/{moderation-KCCO7L2J.js → moderation-CnmxEB8w.js} +91 -91
- package/core/built/admin/assets/activitypub/{note-BX_Bz5A0.js → note-ZKc_Bnba.js} +24 -24
- package/core/built/admin/assets/activitypub/{notifications-BQOYGvRv.js → notifications-CB2tJZau.js} +51 -51
- package/core/built/admin/assets/activitypub/{onboarding-CNelD_uF.js → onboarding-BsJ9E5qf.js} +2 -2
- package/core/built/admin/assets/activitypub/{onboarding-mat5Hrl0.js → onboarding-CSUJJIlh.js} +2 -2
- package/core/built/admin/assets/activitypub/{preferences-6h43G9_q.js → preferences-0-JZnUkI.js} +1519 -1519
- package/core/built/admin/assets/activitypub/{profile-BMN9VVZ2.js → profile-C35cFIhM.js} +256 -256
- package/core/built/admin/assets/activitypub/{reply-ZNo04xsO.js → reply-DYK5vVqb.js} +2 -2
- package/core/built/admin/assets/activitypub/{routes-3B9mUQ7i.js → routes-BD4vscyc.js} +796 -790
- package/core/built/admin/assets/activitypub/{separator-D9taVCCa.js → separator-BbQqTm-p.js} +3 -3
- package/core/built/admin/assets/activitypub/settings-BsMROdqh.js +315 -0
- package/core/built/admin/assets/activitypub/{site-DHoMupSB.js → site-O0RL9YCN.js} +2 -2
- package/core/built/admin/assets/activitypub/{step-1-BsGGnBuT.js → step-1-BMSx7c_X.js} +6 -6
- package/core/built/admin/assets/activitypub/{step-2-teosIS0k.js → step-2-DtPQzlTH.js} +6 -6
- package/core/built/admin/assets/activitypub/{step-3-BjD5TokC.js → step-3-CLlOZTyt.js} +11 -11
- package/core/built/admin/assets/activitypub/{tabs-Cvwl1wXU.js → tabs-Dxk-b9M-.js} +306 -306
- package/core/built/admin/assets/activitypub/{topic-filter-C3LZJc2X.js → topic-filter-5yZH6tId.js} +3 -3
- package/core/built/admin/assets/activitypub/{use-activity-pub-queries-Dp9f0gov.js → use-activity-pub-queries-CV50qe03.js} +3 -3
- package/core/built/admin/assets/activitypub/{use-navigate-with-base-path-C4RI0sa9.js → use-navigate-with-base-path-Bmk5h4lW.js} +220 -220
- package/core/built/admin/assets/activitypub/{use-reply-chain-data-C2oNDMUH.js → use-reply-chain-data-Cbvzgjzd.js} +30 -30
- package/core/built/admin/assets/activitypub/{users-CoX6FT_K.js → users-BjcoP_HC.js} +7 -5
- package/core/built/admin/assets/activitypub/{x-Dxm6pV9X.js → x-DbQZOLiI.js} +2 -2
- package/core/built/admin/assets/add-integration-modal-BlF6rs_f.js +1 -0
- package/core/built/admin/assets/add-newsletter-modal-CglVQqah.js +1 -0
- package/core/built/admin/assets/add-recommendation-modal-wz7BsuaG.js +1 -0
- package/core/built/admin/assets/analytics-C4HE1gBg.js +1 -0
- package/core/built/admin/assets/{announcement-bar-modal-BTHiy1ZO.js → announcement-bar-modal-Ci4zz8jO.js} +1 -1
- package/core/built/admin/assets/{api-keys-Boy5pLbD.js → api-keys-Ck-Yteiv.js} +1 -1
- package/core/built/admin/assets/audience-CtbA54Sn.js +1 -0
- package/core/built/admin/assets/{automated-emails-te1D5kq-.js → automated-emails-D5VVMND9.js} +1 -1
- package/core/built/admin/assets/automations-CzKt5fb8.js +1 -0
- package/core/built/admin/assets/bluesky-sharing-BEtJ_gL_.js +1 -0
- package/core/built/admin/assets/{box-By_EgGtm.js → box-CdfQAP_F.js} +1 -1
- package/core/built/admin/assets/{brand-icon-09YqFZjV.js → brand-icon-CrIGOA3Z.js} +1 -1
- package/core/built/admin/assets/{breadcrumb-CcFr_ltt.js → breadcrumb-zUrZrBtW.js} +1 -1
- package/core/built/admin/assets/{button-BshWPHvn.js → button-eNMKQWXr.js} +1 -1
- package/core/built/admin/assets/{card-CiiE7QfM.js → card--VNbfgo3.js} +1 -1
- package/core/built/admin/assets/{chart-BnXyfH11.js → chart-BrhA41Zi.js} +1 -1
- package/core/built/admin/assets/chart-helpers-CfBKt0vT.js +1 -0
- package/core/built/admin/assets/{checkbox-Dwwr_3Py.js → checkbox-CgOn_tKW.js} +1 -1
- package/core/built/admin/assets/{chunk.524.91ecb33e6afc3bd8949b.js → chunk.524.a697dee88db67fdf6021.js} +4 -4
- package/core/built/admin/assets/{chunk.582.512549909741883f960c.js → chunk.582.5ed5d124cfca9c259b9c.js} +6 -6
- package/core/built/admin/assets/{chunk.16.f76a6314082d813d67e0.js → chunk.598.7e056fabb47ce7dbd73f.js} +14 -14
- package/core/built/admin/assets/{code-editor-view-BwIdPy_k.js → code-editor-view-BYNoAoNV.js} +1 -1
- package/core/built/admin/assets/{code-editor-view-CtkF82Fv.js → code-editor-view-K2wI-I5f.js} +1 -1
- package/core/built/admin/assets/color-picker-Ddw80xX6.js +3 -0
- package/core/built/admin/assets/color-picker-field-D9nUhvA7.js +1 -0
- package/core/built/admin/assets/combobox-w9j8PPQT.js +1 -0
- package/core/built/admin/assets/command-BfpHORBv.js +1 -0
- package/core/built/admin/assets/comments-BLmCmyCs.js +1 -0
- package/core/built/admin/assets/confirmation-context-CBM8G0Vj.js +1 -0
- package/core/built/admin/assets/{container-LiZf3XdY.js → container-BuQG1wuP.js} +1 -1
- package/core/built/admin/assets/{content-api-modal-BtpNI92-.js → content-api-modal-TXRz3U7S.js} +1 -1
- package/core/built/admin/assets/context-menu-_QMdd3kp.js +1 -0
- package/core/built/admin/assets/{copy-field-CglgRZyG.js → copy-field-6N01S07E.js} +1 -1
- package/core/built/admin/assets/create-ghost-browse-value-source-qIBymvvf.js +1 -0
- package/core/built/admin/assets/custom-field-type-option-BddFlJFa.js +1 -0
- package/core/built/admin/assets/custom-integration-modal-DmNquxUV.js +1 -0
- package/core/built/admin/assets/{data-list-CupF7bjM.js → data-list-CA2jYGPq.js} +1 -1
- package/core/built/admin/assets/{date-range-select-JPwM0yUj.js → date-range-select-uvz_DtPh.js} +1 -1
- package/core/built/admin/assets/design-and-theme-modal-BSmo12Op.js +2 -0
- package/core/built/admin/assets/{detail-page-D8lx2SdP.js → detail-page-Dnv-CdR1.js} +1 -1
- package/core/built/admin/assets/dirty-confirm-dialog-BZ1iytEd.js +1 -0
- package/core/built/admin/assets/{disabled-sources-indicator-BTJ2ClQu.js → disabled-sources-indicator-DMRrxsiJ.js} +1 -1
- package/core/built/admin/assets/{dist-DzcfoDJ3.js → dist-8YJUlf3B.js} +1 -1
- package/core/built/admin/assets/{dist-Cb5RSHSg.js → dist-B3keLvjj.js} +1 -1
- package/core/built/admin/assets/dist-Dcsslyo72.js +1 -0
- package/core/built/admin/assets/{dist-BT_Z-eCn.js → dist-Dgt2cr6a.js} +1 -1
- package/core/built/admin/assets/domain-BNYrt0aD.js +1 -0
- package/core/built/admin/assets/dropzone-D7nFdAe5.js +5 -0
- package/core/built/admin/assets/edit-profile-C5Asm4LA.js +1 -0
- package/core/built/admin/assets/editor-REokrzci.js +8 -0
- package/core/built/admin/assets/{embed-signup-form-modal-BFTPf04i.js → embed-signup-form-modal-Ds6mPEi5.js} +1 -1
- package/core/built/admin/assets/{empty-indicator-WB1WgT9h.js → empty-indicator-D9QdpuNX.js} +1 -1
- package/core/built/admin/assets/en-B1jX3WMs.js +1 -0
- package/core/built/admin/assets/explore-UY10Egsp.js +1 -0
- package/core/built/admin/assets/feature-image-placeholder-D1iF_8bc.js +1 -0
- package/core/built/admin/assets/feed-81C8mJWR.js +1 -0
- package/core/built/admin/assets/{field-LmNk7wZh.js → field-Dihp5p18.js} +1 -1
- package/core/built/admin/assets/filter-bar-Da1qxybu.js +1 -0
- package/core/built/admin/assets/filter-sources-BO9xUPj7.js +1 -0
- package/core/built/admin/assets/filters-CRUWecfY.js +1 -0
- package/core/built/admin/assets/filters-DirqNXjH.js +1 -0
- package/core/built/admin/assets/first-promoter-modal-CT6MxYZb.js +1 -0
- package/core/built/admin/assets/{ghost-c8807202a07c20030acb719ee0114815.css → ghost-8eabfc1ece81b03cf7b90780d31487e8.css} +1 -1
- package/core/built/admin/assets/{ghost-403cb39badad3df411fc0ba27d220047.js → ghost-c2848508292937415f20f5a830eea59e.js} +31 -28
- package/core/built/admin/assets/{ghost-dark-fbf1e384aaef3ae315e540f0eb7373a7.css → ghost-dark-a7bebe2c561f55369dcf29f4c820f7ff.css} +1 -1
- package/core/built/admin/assets/gift-link-modal-CQVAye17.js +1 -0
- package/core/built/admin/assets/{grid-CUciBfjf.js → grid-Dj29PY05.js} +1 -1
- package/core/built/admin/assets/growth-BWIu-6xj.js +3 -0
- package/core/built/admin/assets/growth-DU29oxeA.js +1 -0
- package/core/built/admin/assets/{heading-CRZZ2FUe.js → heading-Dh5SFVjL.js} +1 -1
- package/core/built/admin/assets/history-modal-CFd1Hvx6.js +1 -0
- package/core/built/admin/assets/html-field-CJBCLTvv.js +1 -0
- package/core/built/admin/assets/{images-C0XvUYMb.js → images-scfkWZiK.js} +1 -1
- package/core/built/admin/assets/{inbox-DZXDUt4s.js → inbox-Mcp4DXZN.js} +14 -14
- package/core/built/admin/assets/index-6MkPdCtr.js +4 -0
- package/core/built/admin/assets/index-Bn7QhcZu.css +2 -0
- package/core/built/admin/assets/index.es-CNnuNH0d.js +1 -0
- package/core/built/admin/assets/{inline-Cw-gigDW.js → inline-BWSs_VzR.js} +1 -1
- package/core/built/admin/assets/{input-group-BPAxETpQ.js → input-group-CMhe2DvY.js} +1 -1
- package/core/built/admin/assets/{input-surface-BdOe4KzO.js → input-surface-BsrIZeSF.js} +1 -1
- package/core/built/admin/assets/{integration-header-B4DyXV06.js → integration-header-Bm6IDb1A.js} +1 -1
- package/core/built/admin/assets/invite-user-modal-DfheMXs0.js +1 -0
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +14 -14
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +3 -3
- package/core/built/admin/assets/koenig-lexical/style.css +1 -1
- package/core/built/admin/assets/{koenig-lexical-60O_8aiO.js → koenig-lexical-DBSqAuiI.js} +3 -3
- package/core/built/admin/assets/koenig-loader-aFQNlJlD.js +2 -0
- package/core/built/admin/assets/kpi-card-DBRMfGOW.js +1 -0
- package/core/built/admin/assets/{kpi-card-fUHZlzBX.js → kpi-card-DFafD1qq.js} +1 -1
- package/core/built/admin/assets/kpi-helpers-Cv8i8hns.js +1 -0
- package/core/built/admin/assets/kpi-tabs-BJItvLYm.js +1 -0
- package/core/built/admin/assets/{label-VIG969IC.js → label-BnSCvffu.js} +1 -1
- package/core/built/admin/assets/label-picker-KVoo91sh.js +1 -0
- package/core/built/admin/assets/layout-Bjv2Ll-5.js +1 -0
- package/core/built/admin/assets/{link-helpers-Dtq9fxQg.js → link-helpers-MVDdnFCY.js} +1 -1
- package/core/built/admin/assets/{list-page-CdsnQR9N.js → list-page-BucXJ0hi.js} +1 -1
- package/core/built/admin/assets/member-custom-fields-DDQV6QeG.js +1 -0
- package/core/built/admin/assets/member-detail-CdJF6Agw.js +1 -0
- package/core/built/admin/assets/members-DjQbq9Z2.js +4 -0
- package/core/built/admin/assets/{modal-page-BMTzFHVO.js → modal-page-xCivTMvI.js} +1 -1
- package/core/built/admin/assets/moderation-AgCIEso4.js +1 -0
- package/core/built/admin/assets/{multi-select-combobox-CGohnsxJ.js → multi-select-combobox-BcITkUVr.js} +1 -1
- package/core/built/admin/assets/navigation-modal-BkT7b1M2.js +1 -0
- package/core/built/admin/assets/newsletter-BMMAuvgq.js +1 -0
- package/core/built/admin/assets/newsletter-detail-modal-0SCJ7Zpm.js +1 -0
- package/core/built/admin/assets/{newsletter-emails-D5ql1rud.js → newsletter-emails-DKzwafuh.js} +1 -1
- package/core/built/admin/assets/newsletters-BRBb_uQC.js +1 -0
- package/core/built/admin/assets/note-DyGHtS9a.js +1 -0
- package/core/built/admin/assets/notifications-ZgWniKna.js +1 -0
- package/core/built/admin/assets/nql-BLpCn7qX.js +21 -0
- package/core/built/admin/assets/offers-container-modal-B-E8TIWr.js +1 -0
- package/core/built/admin/assets/{onboarding-B4YhlZ0i.js → onboarding-CzIsre-d.js} +1 -1
- package/core/built/admin/assets/onboarding-qg8Akovm.js +1 -0
- package/core/built/admin/assets/{onboarding-route-Cu_ROWPn.js → onboarding-route-CaavZulg.js} +1 -1
- package/core/built/admin/assets/overview-BW8GLeYi.js +1 -0
- package/core/built/admin/assets/overview-BkXZNzaZ.js +1 -0
- package/core/built/admin/assets/{page-header-Cfds8pCg.js → page-header-De0VzKBi.js} +1 -1
- package/core/built/admin/assets/pagemenu-B5KKCpbA.js +1 -0
- package/core/built/admin/assets/pages-jgaFm69d.js +1 -0
- package/core/built/admin/assets/pages-route-CIUAQxtY.js +1 -0
- package/core/built/admin/assets/papaparse.min-cQwnxGCG.js +10 -0
- package/core/built/admin/assets/{pintura-modal-TDTrJ89x.js → pintura-modal-BZ2J9w3n.js} +1 -1
- package/core/built/admin/assets/portal-frame-B6Hr9wHc.js +1 -0
- package/core/built/admin/assets/portal-modal-D4ceei3t.js +1 -0
- package/core/built/admin/assets/post-analytics-header-BYCsT0GP.js +1 -0
- package/core/built/admin/assets/post-analytics-ot7f6pih.js +1 -0
- package/core/built/admin/assets/{post-analytics-provider-Cu3jNeFh.js → post-analytics-provider-Bo1gmYaP.js} +1 -1
- package/core/built/admin/assets/{post-share-modal-P1_M6o-H.js → post-share-modal-C-PaYZ_e.js} +1 -1
- package/core/built/admin/assets/posts-DuGazgTb.js +1 -0
- package/core/built/admin/assets/posts-list-screen-CBGGgjjj.js +2 -0
- package/core/built/admin/assets/posts-route-D6xmS7Vf.js +1 -0
- package/core/built/admin/assets/preferences-C5YJLp74.js +5 -0
- package/core/built/admin/assets/{preview-chrome-BOVO6_PE.js → preview-chrome-BljUBlOk.js} +1 -1
- package/core/built/admin/assets/{preview-modal-MlTjP8UU.js → preview-modal-BfeFqi5y.js} +1 -1
- package/core/built/admin/assets/profile-B8mx2yAu.js +1 -0
- package/core/built/admin/assets/{radio-group-CjtmsCPl.js → radio-group-DczlLKOn.js} +1 -1
- package/core/built/admin/assets/{router-provider-CJC58zTy.js → router-provider-B0gZyiGJ.js} +1 -1
- package/core/built/admin/assets/{schemas-CRsC53ls.js → schemas-DppqmpeJ.js} +2 -2
- package/core/built/admin/assets/select-cb0t_TAJ.js +1 -0
- package/core/built/admin/assets/settings-DZqxR0Da.js +1 -0
- package/core/built/admin/assets/settings-DvfTNdHQ.js +4 -0
- package/core/built/admin/assets/{settings-breadcrumbs-sLDNedBW.js → settings-breadcrumbs-DLzbRRSt.js} +1 -1
- package/core/built/admin/assets/{shade-app-F7WxOyfk-nufqw1hd.js → shade-app-CcS3f8MZ-vwURazk8.js} +2 -2
- package/core/built/admin/assets/share-modal-D2-Bz1_I.js +1 -0
- package/core/built/admin/assets/{skeleton-D7hwjdry.js → skeleton-Ce9GgUpf.js} +1 -1
- package/core/built/admin/assets/slack-modal-DYDTUria.js +1 -0
- package/core/built/admin/assets/sort-button-VVeQjjbu.js +1 -0
- package/core/built/admin/assets/{source-icon-BPsD5ees.js → source-icon-Ck5_5Kgq.js} +1 -1
- package/core/built/admin/assets/{stack-CIfOAAVf.js → stack-B2eszIiq.js} +1 -1
- package/core/built/admin/assets/stats-Rjmk5owg.js +1 -0
- package/core/built/admin/assets/stats-view-BGGmkmgv.js +1 -0
- package/core/built/admin/assets/{step-1-CMta6YFO.js → step-1-CsaBjeN4.js} +1 -1
- package/core/built/admin/assets/{step-2-BG04nh5q.js → step-2-D2vnxOOM.js} +1 -1
- package/core/built/admin/assets/{step-3-ZnMaVIPj.js → step-3-wBoLdGEb.js} +2 -2
- package/core/built/admin/assets/{stripe-button-DDoUKN5a.js → stripe-button-CDgLz0S0.js} +1 -1
- package/core/built/admin/assets/stripe-connect-modal-CSjMJetP.js +1 -0
- package/core/built/admin/assets/{switch-C9djUIMO.js → switch-CI4gLWqb.js} +1 -1
- package/core/built/admin/assets/{table-CrqQtkR2.js → table-Do6iQ83Q.js} +1 -1
- package/core/built/admin/assets/{tabs-CGisSbWq.js → tabs-D2yWLMp_.js} +1 -1
- package/core/built/admin/assets/tag-detail-BhXlOsCa.js +2 -0
- package/core/built/admin/assets/tags-ldukRApe.js +1 -0
- package/core/built/admin/assets/testimonials-modal-CtnZBJKl.js +1 -0
- package/core/built/admin/assets/{text-DU9Hv33_.js → text-BQDSDsKs.js} +1 -1
- package/core/built/admin/assets/{textarea-d9qEkMOP.js → textarea-DJ1Q5V39.js} +1 -1
- package/core/built/admin/assets/tier-detail-modal-BOs8e_G8.js +1 -0
- package/core/built/admin/assets/{toggle-group-CtKZURJd.js → toggle-group-ByUJsxwD.js} +1 -1
- package/core/built/admin/assets/{topic-filter-D8JT8Tq1.js → topic-filter-BgC3g5_v.js} +1 -1
- package/core/built/admin/assets/{transistor-modal-6PUf0idx.js → transistor-modal-Drr0SNfo.js} +1 -1
- package/core/built/admin/assets/trend-badge-6ye93YAW.js +1 -0
- package/core/built/admin/assets/{unsplash-modal-BPuDBPja.js → unsplash-modal-p6AoQoWp.js} +1 -1
- package/core/built/admin/assets/{use-analytics-data--opuzwcz.js → use-analytics-data-CWCMAESo.js} +1 -1
- package/core/built/admin/assets/use-check-theme-limit-error-B8bjF-gO.css +1 -0
- package/core/built/admin/assets/use-check-theme-limit-error-Cw3WQHy8.js +2 -0
- package/core/built/admin/assets/use-filter-params-BIni9taJ.js +1 -0
- package/core/built/admin/assets/use-growth-stats-DCVG3s9w.js +1 -0
- package/core/built/admin/assets/{use-limiter-TDSNiHPB.js → use-limiter-D2WRRx0H.js} +1 -1
- package/core/built/admin/assets/{use-navigate-with-base-path-CK989MlC.js → use-navigate-with-base-path-BHPA228f.js} +1 -1
- package/core/built/admin/assets/{use-pintura-config-CnCGrDFk.js → use-pintura-config-h-J0Lvta.js} +1 -1
- package/core/built/admin/assets/{use-pintura-editor-ntphvtUd.js → use-pintura-editor-BfN1UwzH.js} +1 -1
- package/core/built/admin/assets/use-post-referrers-Czg47m8s.js +1 -0
- package/core/built/admin/assets/use-reply-chain-data-ns0caK8k.js +1 -0
- package/core/built/admin/assets/{use-router-history-entry-BwfQS2mq.js → use-router-history-entry-uldn7zJO.js} +1 -1
- package/core/built/admin/assets/{use-setting-group-DQxV42-O.js → use-setting-group-DpcuCUDg.js} +1 -1
- package/core/built/admin/assets/use-settings-navigation-CZjGrhsp.js +1 -0
- package/core/built/admin/assets/{use-simple-pagination-B2TdNX67.js → use-simple-pagination-DzJWobPR.js} +1 -1
- package/core/built/admin/assets/{use-staff-users-QrR9voeC.js → use-staff-users-Csipb-O0.js} +1 -1
- package/core/built/admin/assets/use-tinybird-query-CSnGXzZh.js +1 -0
- package/core/built/admin/assets/use-tinybird-token-DTOKRR7e.js +1 -0
- package/core/built/admin/assets/{use-unsaved-changes-guard-DpYJcj1d.js → use-unsaved-changes-guard-CBzs-KPi.js} +1 -1
- package/core/built/admin/assets/{use-url-input-WnIqckzS.js → use-url-input-DFr8lCbS.js} +1 -1
- package/core/built/admin/assets/user-detail-modal-B_iUClI6.js +1 -0
- package/core/built/admin/assets/users-Cg-OeGzC.js +1 -0
- package/core/built/admin/assets/{virtual-list-D3MfPNOh.js → virtual-list-BW-padMe.js} +1 -1
- package/core/built/admin/assets/web-C1v33ehA.js +2 -0
- package/core/built/admin/assets/web-C4BKzn2T.js +1 -0
- package/core/built/admin/assets/{zapier-modal-BO6PS_Vd.js → zapier-modal-BBFfI6Ml.js} +1 -1
- package/core/built/admin/index.html +24 -30
- package/core/frontend/apps/private-blogging/lib/views/private.hbs +44 -43
- package/core/frontend/helpers/cancel_link.js +2 -2
- package/core/frontend/helpers/pagination.js +2 -2
- package/core/frontend/helpers/social_accounts.js +2 -2
- package/core/frontend/public/ghost.css +1 -1
- package/core/frontend/public/ghost.min.css +1 -1
- package/core/frontend/services/rendering/renderer.js +15 -0
- package/core/frontend/services/sitemap/user-map-generator.js +9 -2
- package/core/server/adapters/storage/LocalStorageBase.js +8 -5
- package/core/server/api/endpoints/db.js +19 -5
- package/core/server/api/endpoints/index.js +6 -2
- package/core/server/api/endpoints/mail.js +1 -1
- package/core/server/api/endpoints/member-metafields.js +89 -0
- package/core/server/api/endpoints/members.js +4 -4
- package/core/server/api/endpoints/posts.js +4 -3
- package/core/server/api/endpoints/tiers-checkout-config.js +59 -0
- package/core/server/api/endpoints/utils/serializers/input/members.js +4 -7
- package/core/server/api/endpoints/utils/serializers/output/config.js +1 -0
- package/core/server/api/endpoints/utils/serializers/output/index.js +6 -2
- package/core/server/api/endpoints/utils/serializers/output/{member-custom-fields.js → member-metafields.js} +2 -4
- package/core/server/api/endpoints/utils/serializers/output/members.js +2 -4
- package/core/server/api/endpoints/utils/serializers/output/tiers-checkout-config.js +12 -0
- package/core/server/api/endpoints/utils/validators/input/invitations.js +0 -5
- package/core/server/api/endpoints/utils/validators/input/pages.js +1 -1
- package/core/server/api/endpoints/utils/validators/input/posts.js +1 -1
- package/core/server/data/exporter/table-lists.js +3 -0
- package/core/server/data/importer/content-files.js +57 -0
- package/core/server/data/importer/handlers/image.js +2 -2
- package/core/server/data/importer/import-archive.js +131 -0
- package/core/server/data/importer/import-manager.js +18 -180
- package/core/server/data/importer/importers/content-file-importer.js +66 -4
- package/core/server/data/importer/importers/data/data-importer.js +3 -3
- package/core/server/data/migrations/utils/migrations.js +1 -1
- package/core/server/data/migrations/versions/6.61/2026-08-19-14-30-20-add-written-by-to-members-custom-field-values.js +42 -0
- package/core/server/data/migrations/versions/6.61/2026-08-19-14-38-53-add-members-custom-field-bindings-table.js +26 -0
- package/core/server/data/migrations/versions/6.61/2026-08-19-14-48-06-add-tier-checkout-field-tables.js +35 -0
- package/core/server/data/schema/schema.js +90 -0
- package/core/server/data/seeders/importers/automation-action-revisions-importer.js +3 -3
- package/core/server/data/seeders/importers/automation-actions-importer.js +3 -3
- package/core/server/data/seeders/importers/automation-run-steps-importer.js +3 -3
- package/core/server/data/seeders/importers/automation-runs-importer.js +5 -5
- package/core/server/data/seeders/importers/automations-importer.js +3 -3
- package/core/server/data/seeders/importers/comment-reports-importer.js +1 -1
- package/core/server/data/seeders/importers/comments-importer.js +1 -1
- package/core/server/data/seeders/importers/email-batches-importer.js +1 -1
- package/core/server/data/seeders/importers/email-recipients-importer.js +1 -1
- package/core/server/data/seeders/importers/emails-importer.js +1 -1
- package/core/server/data/seeders/importers/labels-importer.js +1 -1
- package/core/server/data/seeders/importers/members-click-events-importer.js +1 -1
- package/core/server/data/seeders/importers/members-created-events-importer.js +1 -1
- package/core/server/data/seeders/importers/members-feedback-importer.js +1 -1
- package/core/server/data/seeders/importers/members-importer.js +1 -1
- package/core/server/data/seeders/importers/members-login-events-importer.js +1 -1
- package/core/server/data/seeders/importers/members-products-importer.js +1 -1
- package/core/server/data/seeders/importers/members-status-events-importer.js +1 -1
- package/core/server/data/seeders/importers/members-stripe-customers-importer.js +1 -1
- package/core/server/data/seeders/importers/members-stripe-customers-subscriptions-importer.js +1 -1
- package/core/server/data/seeders/importers/members-subscribe-events-importer.js +1 -1
- package/core/server/data/seeders/importers/members-subscription-created-events-importer.js +1 -1
- package/core/server/data/seeders/importers/offer-redemptions-importer.js +1 -1
- package/core/server/data/seeders/importers/offers-importer.js +1 -1
- package/core/server/data/seeders/importers/posts-importer.js +1 -1
- package/core/server/data/seeders/importers/table-importer.js +2 -2
- package/core/server/data/seeders/importers/tags-importer.js +1 -1
- package/core/server/data/seeders/importers/users-importer.js +1 -1
- package/core/server/data/seeders/importers/web-mentions-importer.js +1 -1
- package/core/server/data/seeders/utils/random.js +3 -3
- package/core/server/ghost-server.js +3 -2
- package/core/server/lib/db-types/boolean.js +18 -0
- package/core/server/lib/image/image-size.js +24 -0
- package/core/server/lib/package-json/parse.js +2 -2
- package/core/server/lib/promise-pool.js +31 -0
- package/core/server/models/member.js +6 -17
- package/core/server/models/post.js +2 -2
- package/core/server/models/relations/authors.js +2 -16
- package/core/server/models/user.js +9 -2
- package/core/server/services/auth/passwordreset.js +13 -0
- package/core/server/services/automations/database-automations-repository.js +26 -26
- package/core/server/services/automations/poll.js +1 -0
- package/core/server/services/comments/comments-controller.js +30 -9
- package/core/server/services/comments/comments-service.js +55 -5
- package/core/server/services/content-import/csv/formula.js +12 -0
- package/core/server/services/content-import/csv/index.js +6 -1
- package/core/server/services/content-import/csv/parse.js +27 -6
- package/core/server/services/content-import/csv/serialize.js +13 -0
- package/core/server/services/content-import/import/assets.js +74 -0
- package/core/server/services/content-import/import/completion-email.js +164 -0
- package/core/server/services/content-import/import/errors-file.js +36 -0
- package/core/server/services/content-import/import/importer.js +204 -54
- package/core/server/services/content-import/import/local-media-url.js +63 -0
- package/core/server/services/content-import/import/media.js +254 -0
- package/core/server/services/content-import/import/post-data.js +1 -1
- package/core/server/services/content-import/import/post-link.js +11 -0
- package/core/server/services/content-import/import/post-repository.js +100 -0
- package/core/server/services/content-import/import/reader.js +9 -2
- package/core/server/services/content-import/import/relations.js +149 -0
- package/core/server/services/content-import/import/report.js +34 -0
- package/core/server/services/content-import/import/row.js +11 -2
- package/core/server/services/content-import/import/schema.js +30 -0
- package/core/server/services/content-import/import/source.js +125 -0
- package/core/server/services/content-import/import/staged-file.js +29 -0
- package/core/server/services/content-import/import/store.js +25 -2
- package/core/server/services/content-import/index.js +58 -34
- package/core/server/services/content-import/jobs/content-csv-import-job.js +20 -0
- package/core/server/services/custom-redirects/redirect-config-parser.js +2 -2
- package/core/server/services/custom-redirects/redirects-service.js +1 -1
- package/core/server/services/custom-redirects/validation.js +1 -1
- package/core/server/services/email-address/email-address-parser.js +30 -38
- package/core/server/services/email-address/email-address-service.js +37 -4
- package/core/server/services/email-analytics/email-analytics-service.js +8 -1
- package/core/server/services/email-analytics/index.js +2 -7
- package/core/server/services/email-analytics/lib/queries.js +7 -1
- package/core/server/services/email-service/batch-sending-service.js +0 -4
- package/core/server/services/email-service/email-renderer.js +14 -4
- package/core/server/services/email-service/email-service-wrapper.js +0 -9
- package/core/server/services/email-service/mailgun-email-provider.js +20 -9
- package/core/server/services/gift-links/schema.js +3 -3
- package/core/server/services/gifts/CONTEXT.md +1 -1
- package/core/server/services/gifts/constants.js +1 -1
- package/core/server/services/gifts/email-templates/gift-delivery.hbs +3 -3
- package/core/server/services/gifts/gift-bookshelf-repository.js +2 -2
- package/core/server/services/gifts/gift-delivery-bookshelf-repository.js +18 -9
- package/core/server/services/gifts/gift-delivery-schema.js +5 -5
- package/core/server/services/gifts/gift-delivery-service.js +4 -0
- package/core/server/services/gifts/gift-email-service.js +0 -1
- package/core/server/services/gifts/gift-schema.js +10 -10
- package/core/server/services/gifts/gift-service.js +4 -2
- package/core/server/services/gifts/index.js +3 -3
- package/core/server/services/gifts/jobs/index.js +4 -4
- package/core/server/services/indexnow-ping/indexnow-ping-service.js +2 -2
- package/core/server/services/invitations/accept.js +4 -2
- package/core/server/services/jobs/job-service.js +0 -9
- package/core/server/services/jobs-service/register-job-handlers.js +25 -15
- package/core/server/services/lib/mailgun-client.js +44 -8
- package/core/server/services/mail/ghost-mailer.js +4 -4
- package/core/server/services/media-inliner/external-media-inliner-job.js +12 -0
- package/core/server/services/media-inliner/external-media-inliner.js +103 -29
- package/core/server/services/media-inliner/service.js +13 -41
- package/core/server/services/media-inliner/types.js +2 -0
- package/core/server/services/member-welcome-emails/service.js +7 -7
- package/core/server/services/members/api.js +1 -0
- package/core/server/services/members/import-export/csv/parse.js +0 -7
- package/core/server/services/members/import-export/export/exporter.js +4 -6
- package/core/server/services/members/import-export/import/completion-email.js +2 -5
- package/core/server/services/members/import-export/import/importer.js +21 -5
- package/core/server/services/members/import-export/import/row.js +0 -3
- package/core/server/services/members/import-export/import/stripe-utils.js +6 -1
- package/core/server/services/members/import-export/index.js +10 -12
- package/core/server/services/members/jobs/clean-expired-comped-job.js +7 -0
- package/core/server/services/members/jobs/clean-expired-comped-task.js +145 -0
- package/core/server/services/members/jobs/index.js +48 -24
- package/core/server/services/members/members-api/controllers/member-controller.js +11 -0
- package/core/server/services/members/members-api/controllers/router-controller.js +3 -6
- package/core/server/services/members/members-api/members-api.js +9 -6
- package/core/server/services/members/members-api/repositories/event-repository.js +0 -4
- package/core/server/services/members/members-api/services/member-bread-service.js +53 -63
- package/core/server/services/members/members-api/services/payments-service.js +47 -1
- package/core/server/services/members/service.js +1 -5
- package/core/server/services/members-custom-fields/actions.js +27 -1
- package/core/server/services/members-custom-fields/bindings-service.js +120 -0
- package/core/server/services/members-custom-fields/codec.js +3 -4
- package/core/server/services/members-custom-fields/definitions-service.js +165 -22
- package/core/server/services/members-custom-fields/filter.js +75 -93
- package/core/server/services/members-custom-fields/index.js +11 -4
- package/core/server/services/members-custom-fields/key.js +2 -1
- package/core/server/services/members-custom-fields/models.js +1 -1
- package/core/server/services/members-custom-fields/queries.js +5 -0
- package/core/server/services/members-custom-fields/schema.js +37 -6
- package/core/server/services/members-custom-fields/serializers.js +3 -5
- package/core/server/services/members-custom-fields/values-service.js +65 -31
- package/core/server/services/mentions/mention-controller.js +23 -21
- package/core/server/services/mentions/process-webmention-job.js +16 -0
- package/core/server/services/mentions/service.js +8 -4
- package/core/server/services/public-config/config.js +7 -0
- package/core/server/services/route-settings/validation-errors.js +1 -1
- package/core/server/services/route-settings/yaml-parser.js +1 -1
- package/core/server/services/settings/settings-service.js +1 -8
- package/core/server/services/settings-helpers/settings-helpers.js +4 -6
- package/core/server/services/slack-ping/slack-ping-service.js +1 -1
- package/core/server/services/staff/staff-service-emails.js +2 -2
- package/core/server/services/stripe/config.js +14 -8
- package/core/server/services/stripe/service.js +10 -1
- package/core/server/services/stripe/services/checkout/completed-session.js +68 -0
- package/core/server/services/stripe/services/checkout/session-options.js +100 -0
- package/core/server/services/stripe/services/webhook/checkout-session-event-service.js +71 -1
- package/core/server/services/stripe/stripe-api.js +31 -0
- package/core/server/services/stripe/stripe-service.js +26 -9
- package/core/server/services/stripe/webhook-controller.js +10 -0
- package/core/server/services/tier-checkout-config/codec.js +99 -0
- package/core/server/services/tier-checkout-config/index.js +26 -0
- package/core/server/services/tier-checkout-config/models.js +63 -0
- package/core/server/services/tier-checkout-config/queries.js +80 -0
- package/core/server/services/tier-checkout-config/schema.js +33 -0
- package/core/server/services/tier-checkout-config/serializers.js +128 -0
- package/core/server/services/tier-checkout-config/service.js +304 -0
- package/core/server/services/tiers/service.js +21 -0
- package/core/server/services/update-check/index.js +13 -13
- package/core/server/services/update-check/jobs/update-check-job.js +7 -0
- package/core/server/services/update-check/update-check-service.js +2 -2
- package/core/server/web/admin/controller.js +1 -1
- package/core/server/web/api/endpoints/admin/routes.js +34 -20
- package/core/server/web/api/middleware/upload.js +2 -2
- package/core/server/web/parent/app.js +5 -0
- package/core/server/web/parent/middleware/filter-query-parameters.js +94 -0
- package/core/server/web/parent/middleware/index.js +1 -0
- package/core/server/web/query-parameter-policy/index.js +9 -0
- package/core/server/web/query-parameter-policy/policy.json +58 -0
- package/core/server/web/query-parameter-policy/schema.js +38 -0
- package/core/shared/config/defaults.json +3 -0
- package/core/shared/config/env/config.testing-mysql.json +4 -1
- package/core/shared/config/env/config.testing.json +3 -0
- package/core/shared/config/overrides.json +4 -2
- package/core/shared/labs.js +9 -15
- package/package.json +25 -25
- package/pnpm-lock.yaml +741 -108
- package/pnpm-workspace.yaml +12 -9
- package/tsconfig.json +2 -3
- package/components/tryghost-kg-default-nodes-2.2.0.tgz +0 -0
- package/core/built/admin/assets/Combination-gnJO3vIw.js +0 -41
- package/core/built/admin/assets/account-migration-8qTEI1i1.js +0 -1
- package/core/built/admin/assets/activitypub/inbox-DQ5CwLma.js +0 -1284
- package/core/built/admin/assets/activitypub/label-B72sfvEU.js +0 -16
- package/core/built/admin/assets/activitypub/layout-CXajhRsL.js +0 -1
- package/core/built/admin/assets/activitypub/settings-71gCm3SO.js +0 -315
- package/core/built/admin/assets/add-integration-modal--YpTq3c0.js +0 -1
- package/core/built/admin/assets/add-newsletter-modal-C8Ix2hol.js +0 -1
- package/core/built/admin/assets/add-recommendation-modal-CScuNFz4.js +0 -1
- package/core/built/admin/assets/alert-dialog-wEbVxANM.js +0 -1
- package/core/built/admin/assets/analytics-Cnji45H5.js +0 -1
- package/core/built/admin/assets/app-utils-D2Wp7ZSS.js +0 -1
- package/core/built/admin/assets/audience-DTLMXAFH.js +0 -1
- package/core/built/admin/assets/automations-BWpRCZ_f.js +0 -1
- package/core/built/admin/assets/bluesky-sharing-DHOpQxff.js +0 -1
- package/core/built/admin/assets/chart-helpers-B3OqQ6Ez.js +0 -1
- package/core/built/admin/assets/color-picker-Bmo1r9Fc.js +0 -3
- package/core/built/admin/assets/color-picker-field-DywowPhF.js +0 -1
- package/core/built/admin/assets/combobox-C4QCh6Yw.js +0 -1
- package/core/built/admin/assets/command-DcLbSifC.js +0 -1
- package/core/built/admin/assets/comments-Bxy_3WyE.js +0 -1
- package/core/built/admin/assets/confirmation-context-CLFHhyyH.js +0 -1
- package/core/built/admin/assets/custom-field-type-option-D0PXoSnP.js +0 -10
- package/core/built/admin/assets/custom-integration-modal-DCIHKN33.js +0 -1
- package/core/built/admin/assets/design-and-theme-modal-CZ-PkW7o.js +0 -23
- package/core/built/admin/assets/dialog-Db7c164G.js +0 -1
- package/core/built/admin/assets/dirty-confirm-dialog-CmARpZQS.js +0 -1
- package/core/built/admin/assets/dist-QLZuGq7o2.js +0 -1
- package/core/built/admin/assets/domain-D0SAtc-T.js +0 -1
- package/core/built/admin/assets/dropzone-CaPOeDRZ.js +0 -5
- package/core/built/admin/assets/edit-profile-By7v5XW5.js +0 -1
- package/core/built/admin/assets/editor-COXn4Atu.js +0 -8
- package/core/built/admin/assets/explore-BsNYrubV.js +0 -1
- package/core/built/admin/assets/feed-8RR1O1bK.js +0 -1
- package/core/built/admin/assets/filter-sources-4C0kF1NU.js +0 -1
- package/core/built/admin/assets/filters-CV5jCb9n.js +0 -1
- package/core/built/admin/assets/filters-Dmr0PoqU.js +0 -1
- package/core/built/admin/assets/first-promoter-modal-OCzSaL3B.js +0 -1
- package/core/built/admin/assets/gift-link-modal-0mzjn5oF.js +0 -1
- package/core/built/admin/assets/growth-55vWlGT_.js +0 -1
- package/core/built/admin/assets/growth-DA5AluYw.js +0 -3
- package/core/built/admin/assets/history-modal-G1s5hHz7.js +0 -1
- package/core/built/admin/assets/html-field-BegxsWpw.js +0 -1
- package/core/built/admin/assets/index-CDP9tIOk.js +0 -4
- package/core/built/admin/assets/index-Dqf2x-ry.css +0 -1
- package/core/built/admin/assets/index.es-BMUCj9TR.js +0 -1
- package/core/built/admin/assets/input-UHrKuvBT.js +0 -1
- package/core/built/admin/assets/invite-user-modal-BrAkxEO3.js +0 -1
- package/core/built/admin/assets/koenig-loader-DwVY_V-H.js +0 -1
- package/core/built/admin/assets/kpi-card-LERqWBoY.js +0 -1
- package/core/built/admin/assets/kpi-helpers-DB3ouhYF.js +0 -1
- package/core/built/admin/assets/kpi-tabs-BGvtMD8S.js +0 -1
- package/core/built/admin/assets/label-picker-BBWykUeA.js +0 -1
- package/core/built/admin/assets/layout-Di5K7doM.js +0 -1
- package/core/built/admin/assets/loading-indicator-SFTqyYVE.js +0 -1
- package/core/built/admin/assets/member-custom-fields-gOv6Hoh3.js +0 -1
- package/core/built/admin/assets/member-detail-D7mZDDp3.js +0 -1
- package/core/built/admin/assets/member-route-0Aa52Ntz.js +0 -1
- package/core/built/admin/assets/members-DvZG9t69.js +0 -2
- package/core/built/admin/assets/moderation-DzzPLDyl.js +0 -1
- package/core/built/admin/assets/navigation-modal-CI8Bx5vn.js +0 -1
- package/core/built/admin/assets/newsletter-Bg3cq5U-.js +0 -1
- package/core/built/admin/assets/newsletter-detail-modal-DQU3r4g2.js +0 -1
- package/core/built/admin/assets/newsletters-DMDfZbMS.js +0 -1
- package/core/built/admin/assets/note-i8k6pjaw.js +0 -1
- package/core/built/admin/assets/notifications-psA_2Ph4.js +0 -1
- package/core/built/admin/assets/offers-container-modal-BWfjSdyg.js +0 -1
- package/core/built/admin/assets/onboarding-DGQuV7Ew.js +0 -1
- package/core/built/admin/assets/overview-C-6xOLaf.js +0 -1
- package/core/built/admin/assets/overview-DaLhpRrC.js +0 -1
- package/core/built/admin/assets/pages-B6vr9F_D.js +0 -1
- package/core/built/admin/assets/popover-CFgqFDvC.js +0 -1
- package/core/built/admin/assets/portal-frame-DjBF-uy2.js +0 -1
- package/core/built/admin/assets/portal-modal-Cf0pBAk8.js +0 -1
- package/core/built/admin/assets/post-analytics-Buz1COoY.js +0 -1
- package/core/built/admin/assets/post-analytics-header-B-P0eFnT.js +0 -1
- package/core/built/admin/assets/posts-KY3aUhVV.js +0 -1
- package/core/built/admin/assets/preferences-Cq1aOiLy.js +0 -5
- package/core/built/admin/assets/profile-D6dHYf2o.js +0 -1
- package/core/built/admin/assets/select-D_RQaXgt.js +0 -1
- package/core/built/admin/assets/settings-B5hJKZ5C.js +0 -1
- package/core/built/admin/assets/settings-DIo_F-MF.js +0 -4
- package/core/built/admin/assets/share-modal-CLBfj377.js +0 -1
- package/core/built/admin/assets/shim-ClF_m5ux.js +0 -1
- package/core/built/admin/assets/slack-modal-Bt9I_tEo.js +0 -1
- package/core/built/admin/assets/sort-button-DMBXF7tP.js +0 -1
- package/core/built/admin/assets/stats-B_YkF7bp.js +0 -1
- package/core/built/admin/assets/stats-view-BOCp9RG8.js +0 -1
- package/core/built/admin/assets/stripe-connect-modal-BeSukI8q.js +0 -1
- package/core/built/admin/assets/tag-detail-2a3BfzTW.js +0 -2
- package/core/built/admin/assets/tags-Dp2_8UzL.js +0 -1
- package/core/built/admin/assets/testimonials-modal-C9nrypNo.js +0 -1
- package/core/built/admin/assets/tier-detail-modal-CxRwgTPR.js +0 -1
- package/core/built/admin/assets/use-check-theme-limit-error-C9-QhGdV.js +0 -1
- package/core/built/admin/assets/use-filter-params-CSpAvgD2.js +0 -1
- package/core/built/admin/assets/use-growth-stats-BOmoPDHJ.js +0 -1
- package/core/built/admin/assets/use-post-referrers-CbXLFIex.js +0 -1
- package/core/built/admin/assets/use-reply-chain-data-JYFKSO83.js +0 -1
- package/core/built/admin/assets/use-settings-navigation-BBzro2-V.js +0 -1
- package/core/built/admin/assets/use-tinybird-query-D2Aeoty5.js +0 -39
- package/core/built/admin/assets/use-tinybird-token-DBuwMmln.js +0 -1
- package/core/built/admin/assets/user-detail-modal-59mBJqxN.js +0 -1
- package/core/built/admin/assets/users-5msE1WMs.js +0 -1
- package/core/built/admin/assets/web-DUuX7nE2.js +0 -2
- package/core/built/admin/assets/web-N8ucs2aG.js +0 -1
- package/core/server/api/endpoints/member-custom-fields.js +0 -100
- package/core/server/services/jobs/worker-model-event-bridge.js +0 -149
- package/core/server/services/members/jobs/clean-expired-comped.js +0 -132
- package/core/server/services/update-check/run-update-check.js +0 -63
- /package/core/server/lib/{db-date.js → db-types/date.js} +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DbCustomFieldLeaf = exports.DbCustomFieldValue = exports.DbCustomField = exports.FieldStatusSchema = exports.FIELD_STATUS = void 0;
|
|
3
|
+
exports.DbBoundField = exports.DbCustomFieldBinding = exports.DbCustomFieldLeaf = exports.DbCustomFieldValue = exports.WrittenBy = exports.DbCustomField = exports.FieldStatusSchema = exports.FIELD_STATUS = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const custom_field_types_1 = require("@tryghost/custom-field-types");
|
|
6
|
-
const
|
|
6
|
+
const date_1 = require("../../lib/db-types/date");
|
|
7
7
|
// `archived` is soft: the field drops out of the values path but stays in the definition
|
|
8
8
|
// list so it can be renamed, restored or deleted. Mirrors schema.js's `isIn` on the
|
|
9
9
|
// column, which is static config and cannot import this.
|
|
@@ -17,9 +17,21 @@ exports.DbCustomField = zod_1.z.object({
|
|
|
17
17
|
name: zod_1.z.string(),
|
|
18
18
|
type: custom_field_types_1.FieldTypeSchema,
|
|
19
19
|
status: exports.FieldStatusSchema,
|
|
20
|
-
created_at:
|
|
21
|
-
updated_at:
|
|
20
|
+
created_at: date_1.DbDate,
|
|
21
|
+
updated_at: date_1.DbDate.nullable(),
|
|
22
22
|
});
|
|
23
|
+
/**
|
|
24
|
+
* How a value arrived, not who caused it: who edited a member's fields is already an
|
|
25
|
+
* action, and Stripe is not a person. `type` is the namespace that makes `id` resolvable —
|
|
26
|
+
* `users`, `integrations`, `members_custom_field_bindings` — so the one writer that
|
|
27
|
+
* resolves in no table is the one with no id to give.
|
|
28
|
+
*/
|
|
29
|
+
exports.WrittenBy = zod_1.z.discriminatedUnion('type', [
|
|
30
|
+
zod_1.z.object({ type: zod_1.z.literal('user'), id: zod_1.z.string() }),
|
|
31
|
+
zod_1.z.object({ type: zod_1.z.literal('integration'), id: zod_1.z.string() }),
|
|
32
|
+
zod_1.z.object({ type: zod_1.z.literal('binding'), id: zod_1.z.string() }),
|
|
33
|
+
zod_1.z.object({ type: zod_1.z.literal('import'), id: zod_1.z.null() }),
|
|
34
|
+
]);
|
|
23
35
|
// One part of a member's value. What a `path` means is storage.ts's business, so the row
|
|
24
36
|
// carries it as a plain string.
|
|
25
37
|
exports.DbCustomFieldValue = zod_1.z.object({
|
|
@@ -30,8 +42,13 @@ exports.DbCustomFieldValue = zod_1.z.object({
|
|
|
30
42
|
// Nullable like the column, though nothing here writes a null: a part with no value
|
|
31
43
|
// has no row.
|
|
32
44
|
value_text: zod_1.z.string().nullable(),
|
|
33
|
-
|
|
34
|
-
|
|
45
|
+
// Plain columns rather than the `WrittenBy` union: the rule holds at the write
|
|
46
|
+
// boundary, so one malformed row cannot throw away a member's whole profile on read.
|
|
47
|
+
written_by_type: zod_1.z.string(),
|
|
48
|
+
// Null for the one writer that resolves nowhere: an import, until runs are tracked.
|
|
49
|
+
written_by_id: zod_1.z.string().nullable(),
|
|
50
|
+
created_at: date_1.DbDate,
|
|
51
|
+
updated_at: date_1.DbDate.nullable(),
|
|
35
52
|
});
|
|
36
53
|
// The field's key travels with the row so a value assembles without a second lookup.
|
|
37
54
|
//
|
|
@@ -45,3 +62,17 @@ exports.DbCustomFieldLeaf = zod_1.z.object({
|
|
|
45
62
|
path: zod_1.z.string(),
|
|
46
63
|
value_text: zod_1.z.string(),
|
|
47
64
|
});
|
|
65
|
+
exports.DbCustomFieldBinding = zod_1.z.object({
|
|
66
|
+
id: zod_1.z.string(),
|
|
67
|
+
product_id: zod_1.z.string(),
|
|
68
|
+
port: zod_1.z.string(),
|
|
69
|
+
custom_field_key: zod_1.z.string(),
|
|
70
|
+
created_at: date_1.DbDate,
|
|
71
|
+
updated_at: date_1.DbDate.nullable(),
|
|
72
|
+
});
|
|
73
|
+
/** A binding joined to the field it points at, which is how a collected value is routed. */
|
|
74
|
+
exports.DbBoundField = zod_1.z.object({
|
|
75
|
+
binding_id: zod_1.z.string(),
|
|
76
|
+
key: zod_1.z.string(),
|
|
77
|
+
type: custom_field_types_1.FieldTypeSchema,
|
|
78
|
+
});
|
|
@@ -4,10 +4,8 @@ exports.toCustomFieldsResponse = void 0;
|
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const case_keys_1 = require("../../lib/case-keys");
|
|
6
6
|
const models_1 = require("./models");
|
|
7
|
-
// Response schema — the field-definition shape the admin endpoints emit. `id` is
|
|
8
|
-
// the DB primary key and deliberately never leaves the API; a field is addressed
|
|
9
|
-
// by its immutable `key`. The `.pipe` below strips id from the mapped output.
|
|
10
7
|
const CustomFieldResource = zod_1.z.object({
|
|
8
|
+
namespace: zod_1.z.string(),
|
|
11
9
|
key: zod_1.z.string(),
|
|
12
10
|
name: zod_1.z.string(),
|
|
13
11
|
type: zod_1.z.string(),
|
|
@@ -15,10 +13,10 @@ const CustomFieldResource = zod_1.z.object({
|
|
|
15
13
|
created_at: zod_1.z.date(),
|
|
16
14
|
updated_at: zod_1.z.date().nullable(),
|
|
17
15
|
});
|
|
18
|
-
const CustomFieldsResponse = zod_1.z.object({
|
|
16
|
+
const CustomFieldsResponse = zod_1.z.object({ members_metafields: zod_1.z.array(CustomFieldResource) });
|
|
19
17
|
exports.toCustomFieldsResponse = zod_1.z
|
|
20
18
|
.array(models_1.CustomField)
|
|
21
19
|
.transform((fields) => ({
|
|
22
|
-
|
|
20
|
+
members_metafields: fields.map((field) => (0, case_keys_1.snakeKeys)(field)),
|
|
23
21
|
}))
|
|
24
22
|
.pipe(CustomFieldsResponse);
|
|
@@ -9,6 +9,7 @@ const errors_1 = __importDefault(require("@tryghost/errors"));
|
|
|
9
9
|
const logging_1 = __importDefault(require("@tryghost/logging"));
|
|
10
10
|
const zod_1 = require("zod");
|
|
11
11
|
const custom_field_types_1 = require("@tryghost/custom-field-types");
|
|
12
|
+
const identity_1 = require("@tryghost/custom-field-types/identity");
|
|
12
13
|
const schema_1 = require("./schema");
|
|
13
14
|
const queries_1 = require("./queries");
|
|
14
15
|
const storage_1 = require("./storage");
|
|
@@ -29,9 +30,9 @@ const MAX_KEY_LENGTH = require('../../data/schema').tables[FIELDS_TABLE].key.max
|
|
|
29
30
|
* go when that lands; until then the alternative is hand-written upsert SQL per engine.
|
|
30
31
|
*/
|
|
31
32
|
const UPSERT_CHUNK = 400;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const
|
|
33
|
+
const MAX_IDENTITY_LENGTH = MAX_KEY_LENGTH * 2 + 1;
|
|
34
|
+
const ValuesInput = zod_1.z.record(zod_1.z.string().max(MAX_IDENTITY_LENGTH), zod_1.z.unknown());
|
|
35
|
+
const wireProperty = (identity) => [identity_1.QUALIFIER, identity].join('.');
|
|
35
36
|
/**
|
|
36
37
|
* What a member holds for each defined field. Separate from the definitions service
|
|
37
38
|
* because a value belongs to the member and a definition belongs to the site's settings,
|
|
@@ -45,22 +46,22 @@ class CustomFieldValuesService {
|
|
|
45
46
|
this.knex = knex;
|
|
46
47
|
this.getMaxDefinitions = getMaxDefinitions;
|
|
47
48
|
}
|
|
48
|
-
async
|
|
49
|
+
async activeFieldsByIdentity(identities) {
|
|
50
|
+
const keys = identities
|
|
51
|
+
.map((identity) => (0, identity_1.parseIdentity)(identity))
|
|
52
|
+
.filter((parsed) => parsed !== null && parsed.namespace === identity_1.CUSTOM_NAMESPACE)
|
|
53
|
+
.map((parsed) => parsed.key);
|
|
49
54
|
if (keys.length === 0) {
|
|
50
55
|
return new Map();
|
|
51
56
|
}
|
|
52
57
|
const fields = await (0, queries_1.activeFields)(this.knex)
|
|
53
58
|
.whereIn('key', keys)
|
|
54
59
|
.select('id', 'key', 'name', 'type');
|
|
55
|
-
return new Map(fields.map((field) => [
|
|
60
|
+
return new Map(fields.map((field) => [
|
|
61
|
+
(0, identity_1.formatIdentity)({ namespace: identity_1.CUSTOM_NAMESPACE, key: field.key, partPath: null }),
|
|
62
|
+
{ ...field, namespace: identity_1.CUSTOM_NAMESPACE },
|
|
63
|
+
]));
|
|
56
64
|
}
|
|
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
65
|
async getValuesForMembers(memberIds) {
|
|
65
66
|
if (memberIds.length === 0) {
|
|
66
67
|
return new Map();
|
|
@@ -80,22 +81,51 @@ class CustomFieldValuesService {
|
|
|
80
81
|
leaves.push(schema_1.DbCustomFieldLeaf.parse(row));
|
|
81
82
|
}
|
|
82
83
|
catch (err) {
|
|
83
|
-
logging_1.default.warn(
|
|
84
|
+
logging_1.default.warn({
|
|
85
|
+
event: { name: 'members.custom_fields.value_unreadable' },
|
|
86
|
+
err,
|
|
87
|
+
customFieldKey: row.key,
|
|
88
|
+
path: row.path,
|
|
89
|
+
}, 'Skipping an unreadable custom field value');
|
|
84
90
|
}
|
|
85
91
|
}
|
|
86
|
-
|
|
92
|
+
const flat = (0, storage_1.valuesFromLeaves)(leaves);
|
|
93
|
+
return new Map(memberIds.map((memberId) => [memberId, { [identity_1.CUSTOM_NAMESPACE]: flat.get(memberId) ?? {} }]));
|
|
87
94
|
}
|
|
88
|
-
/** Shared by every caller so they cannot disagree on what a values object is. */
|
|
89
95
|
parseValues(input) {
|
|
90
96
|
const parsed = ValuesInput.safeParse(input);
|
|
91
97
|
if (!parsed.success) {
|
|
92
98
|
throw new errors_1.default.ValidationError({
|
|
93
|
-
message: 'Custom field values must be an object keyed by field
|
|
94
|
-
property:
|
|
99
|
+
message: 'Custom field values must be an object keyed by field identity.',
|
|
100
|
+
property: identity_1.QUALIFIER,
|
|
95
101
|
});
|
|
96
102
|
}
|
|
97
103
|
return parsed.data;
|
|
98
104
|
}
|
|
105
|
+
unwrapWire(input) {
|
|
106
|
+
if (input === undefined) {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
if (typeof input !== 'object' || input === null || Array.isArray(input)) {
|
|
110
|
+
throw new errors_1.default.ValidationError({
|
|
111
|
+
message: 'Metafields must be an object keyed by namespace.',
|
|
112
|
+
property: identity_1.QUALIFIER,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
const identified = {};
|
|
116
|
+
for (const [namespace, values] of Object.entries(input)) {
|
|
117
|
+
if (typeof values !== 'object' || values === null || Array.isArray(values)) {
|
|
118
|
+
throw new errors_1.default.ValidationError({
|
|
119
|
+
message: 'Metafield values must be an object keyed by field key.',
|
|
120
|
+
property: [identity_1.QUALIFIER, namespace].join('.'),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
for (const [key, raw] of Object.entries(values)) {
|
|
124
|
+
identified[`${namespace}.${key}`] = raw;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return identified;
|
|
128
|
+
}
|
|
99
129
|
/**
|
|
100
130
|
* Whether input names any values. Asks the shape question alone, with no catalog
|
|
101
131
|
* lookup, so it can be asked before a write is known to be permitted.
|
|
@@ -113,27 +143,24 @@ class CustomFieldValuesService {
|
|
|
113
143
|
*/
|
|
114
144
|
async planWrite(input) {
|
|
115
145
|
const values = this.parseValues(input);
|
|
116
|
-
const
|
|
146
|
+
const identities = Object.keys(values);
|
|
117
147
|
// Bounded by the definitions ceiling, which also holds the lookup below inside
|
|
118
148
|
// the driver's bound-parameter limit.
|
|
119
149
|
const maxKeys = this.getMaxDefinitions();
|
|
120
|
-
if (
|
|
150
|
+
if (identities.length > maxKeys) {
|
|
121
151
|
throw new errors_1.default.ValidationError({
|
|
122
152
|
message: `Custom field values are limited to ${maxKeys} fields per request.`,
|
|
123
|
-
property:
|
|
153
|
+
property: identity_1.QUALIFIER,
|
|
124
154
|
});
|
|
125
155
|
}
|
|
126
|
-
const
|
|
156
|
+
const byIdentity = await this.activeFieldsByIdentity(identities);
|
|
127
157
|
const writes = [];
|
|
128
|
-
for (const [
|
|
129
|
-
const field =
|
|
158
|
+
for (const [identity, raw] of Object.entries(values)) {
|
|
159
|
+
const field = byIdentity.get(identity);
|
|
130
160
|
if (!field) {
|
|
131
|
-
// Unknown or archived. Refused rather than ignored: a typo that silently
|
|
132
|
-
// drops what somebody typed is worse than a save that fails. The catalog
|
|
133
|
-
// applies the same rule to the parts of a composite value.
|
|
134
161
|
throw new errors_1.default.ValidationError({
|
|
135
|
-
message: `Unknown custom field: ${
|
|
136
|
-
property:
|
|
162
|
+
message: `Unknown custom field: ${identity}`,
|
|
163
|
+
property: wireProperty(identity),
|
|
137
164
|
});
|
|
138
165
|
}
|
|
139
166
|
// `null` clears any field, and `''` clears one with no parts. For a value
|
|
@@ -152,7 +179,7 @@ class CustomFieldValuesService {
|
|
|
152
179
|
const issue = value.error.issues[0];
|
|
153
180
|
throw new errors_1.default.ValidationError({
|
|
154
181
|
message: issue.message,
|
|
155
|
-
property: [
|
|
182
|
+
property: [wireProperty(identity), ...issue.path].join('.'),
|
|
156
183
|
});
|
|
157
184
|
}
|
|
158
185
|
writes.push({ field, value: value.data });
|
|
@@ -167,10 +194,13 @@ class CustomFieldValuesService {
|
|
|
167
194
|
* them, and saying nothing about a path leaves it alone. There is no whole-value
|
|
168
195
|
* replace, so a caller that does not know about a field cannot erase it.
|
|
169
196
|
*
|
|
197
|
+
* `writtenBy` is required and has no default: every writer has to name itself, so a new
|
|
198
|
+
* one cannot quietly inherit the identity of whichever was written first.
|
|
199
|
+
*
|
|
170
200
|
* Always transactional. Given an executor it joins that transaction, so the importer's
|
|
171
201
|
* failed value write takes its member with it; given none it opens its own.
|
|
172
202
|
*/
|
|
173
|
-
async applyWrite(memberId, writes, { executor = this.knex }
|
|
203
|
+
async applyWrite(memberId, writes, { writtenBy, executor = this.knex }) {
|
|
174
204
|
if (writes.length === 0) {
|
|
175
205
|
return;
|
|
176
206
|
}
|
|
@@ -197,6 +227,8 @@ class CustomFieldValuesService {
|
|
|
197
227
|
custom_field_key: field.key,
|
|
198
228
|
path: leaf.path,
|
|
199
229
|
value_text: leaf.value_text,
|
|
230
|
+
written_by_type: writtenBy.type,
|
|
231
|
+
written_by_id: writtenBy.id,
|
|
200
232
|
created_at: now,
|
|
201
233
|
updated_at: now,
|
|
202
234
|
})));
|
|
@@ -227,7 +259,9 @@ class CustomFieldValuesService {
|
|
|
227
259
|
// Naming the columns rather than giving values takes each from the row
|
|
228
260
|
// that lost the conflict, so every part updates to its own value.
|
|
229
261
|
.onConflict(['member_id', 'custom_field_key', 'path'])
|
|
230
|
-
|
|
262
|
+
// The writer is merged with the value, so a leaf names who wrote what
|
|
263
|
+
// it currently holds rather than who wrote its first value.
|
|
264
|
+
.merge(['value_text', 'written_by_type', 'written_by_id', 'updated_at']);
|
|
231
265
|
}
|
|
232
266
|
};
|
|
233
267
|
// knex's marker for a transactor: join it rather than nesting a savepoint under it.
|
|
@@ -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
|
};
|
|
@@ -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;
|
|
@@ -15,7 +15,7 @@ const urlService = require('../url');
|
|
|
15
15
|
const settingsCache = require('../../../shared/settings-cache');
|
|
16
16
|
const DomainEvents = require('@tryghost/domain-events');
|
|
17
17
|
const logging = require('@tryghost/logging');
|
|
18
|
-
const
|
|
18
|
+
const mentionsJobService = require('../mentions-jobs');
|
|
19
19
|
|
|
20
20
|
// Serializes a post model to the data the URL service needs, loading the
|
|
21
21
|
// relations it reads for filtered collections (event-emitted models don't
|
|
@@ -45,7 +45,7 @@ function makeLoggingJobService() {
|
|
|
45
45
|
return {
|
|
46
46
|
async addJob(name, fn) {
|
|
47
47
|
logging.info(`[Background Job] ${name} queued`);
|
|
48
|
-
|
|
48
|
+
mentionsJobService.addJob({
|
|
49
49
|
name,
|
|
50
50
|
job: async () => {
|
|
51
51
|
const startedAt = Date.now();
|
|
@@ -75,7 +75,11 @@ module.exports = {
|
|
|
75
75
|
/** @type {import('./mention-sending-service')} */
|
|
76
76
|
sendingService: null,
|
|
77
77
|
didInit: false,
|
|
78
|
-
|
|
78
|
+
/**
|
|
79
|
+
* @param {object} deps
|
|
80
|
+
* @param {import('../jobs-service/jobs-service').JobsService} deps.jobsService
|
|
81
|
+
*/
|
|
82
|
+
async init({ jobsService }) {
|
|
79
83
|
if (this.didInit) {
|
|
80
84
|
return;
|
|
81
85
|
}
|
|
@@ -110,7 +114,7 @@ module.exports = {
|
|
|
110
114
|
|
|
111
115
|
this.controller.init({
|
|
112
116
|
api,
|
|
113
|
-
|
|
117
|
+
jobsService,
|
|
114
118
|
mentionResourceService: {
|
|
115
119
|
async getByID(id) {
|
|
116
120
|
if (!id) {
|
|
@@ -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 = '') {
|
|
@@ -4,7 +4,7 @@ const labs = require('../../../shared/labs');
|
|
|
4
4
|
|
|
5
5
|
const messages = {
|
|
6
6
|
remoteWebhooksInDevelopment:
|
|
7
|
-
'Cannot use remote webhooks in development. See https://ghost.org/
|
|
7
|
+
'Cannot use remote webhooks in development. See https://docs.ghost.org/webhooks/#stripe-webhooks for developing with Stripe.',
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
// @TODO Refactor to a class w/ constructor
|
|
@@ -62,16 +62,19 @@ module.exports = {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
const env = config.get('env');
|
|
65
|
-
|
|
65
|
+
const remoteWebhooks = env !== 'production' && config.get('stripeRemoteWebhooks') === true;
|
|
66
|
+
let webhookSecret = remoteWebhooks ? undefined : process.env.WEBHOOK_SECRET;
|
|
66
67
|
|
|
67
|
-
if (env !== 'production') {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
logging.warn(tpl(messages.remoteWebhooksInDevelopment));
|
|
71
|
-
}
|
|
68
|
+
if (env !== 'production' && !remoteWebhooks && !webhookSecret) {
|
|
69
|
+
webhookSecret = 'DEFAULT_WEBHOOK_SECRET';
|
|
70
|
+
logging.warn(tpl(messages.remoteWebhooksInDevelopment));
|
|
72
71
|
}
|
|
73
72
|
|
|
74
|
-
|
|
73
|
+
// Development can tunnel the webhook URL alone while the site stays on localhost.
|
|
74
|
+
const webhookHandlerUrl = new URL(
|
|
75
|
+
config.get('stripeWebhookUrl') || 'members/webhooks/stripe/',
|
|
76
|
+
urlUtils.getSiteUrl(),
|
|
77
|
+
);
|
|
75
78
|
const webhookCustomerIgnoreList = parseIgnoreCustomerList(
|
|
76
79
|
config.get('stripeWebhookCustomerIgnoreList'),
|
|
77
80
|
);
|
|
@@ -88,6 +91,9 @@ module.exports = {
|
|
|
88
91
|
},
|
|
89
92
|
webhookSecret: webhookSecret,
|
|
90
93
|
webhookHandlerUrl: webhookHandlerUrl.href,
|
|
94
|
+
// A development registration points at a tunnel that closes with the process,
|
|
95
|
+
// so it is removed on shutdown rather than kept for the next boot.
|
|
96
|
+
ephemeralWebhook: remoteWebhooks,
|
|
91
97
|
webhookCustomerIgnoreList,
|
|
92
98
|
siteUrl,
|
|
93
99
|
};
|
|
@@ -14,6 +14,12 @@ const giftService = require('../gifts');
|
|
|
14
14
|
const staffService = require('../staff');
|
|
15
15
|
const labs = require('../../../shared/labs');
|
|
16
16
|
const settingsCache = require('../../../shared/settings-cache');
|
|
17
|
+
const tpl = require('@tryghost/tpl');
|
|
18
|
+
|
|
19
|
+
const messages = {
|
|
20
|
+
remoteWebhooksWithoutStripe:
|
|
21
|
+
'stripeRemoteWebhooks is set but Stripe is not connected, so no webhook endpoint was registered. Connect Stripe in Ghost Admin under Settings, then restart.',
|
|
22
|
+
};
|
|
17
23
|
|
|
18
24
|
async function configureApi() {
|
|
19
25
|
const cfg = getConfig({ settingsHelpers, config, urlUtils });
|
|
@@ -84,7 +90,10 @@ function stripeSettingsChanged(model) {
|
|
|
84
90
|
|
|
85
91
|
module.exports.init = async function init() {
|
|
86
92
|
try {
|
|
87
|
-
await configureApi();
|
|
93
|
+
const configured = await configureApi();
|
|
94
|
+
if (!configured && config.get('stripeRemoteWebhooks') === true) {
|
|
95
|
+
logging.warn(tpl(messages.remoteWebhooksWithoutStripe));
|
|
96
|
+
}
|
|
88
97
|
} catch (err) {
|
|
89
98
|
logging.error(err);
|
|
90
99
|
}
|