ghost 6.64.0 → 6.65.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/bin/create-migration.js +15 -0
- package/components/tryghost-adapter-base-scheduling-0.2.4.tgz +0 -0
- package/components/tryghost-api-framework-0.0.0.tgz +0 -0
- package/components/tryghost-i18n-0.0.0.tgz +0 -0
- package/components/tryghost-kg-default-cards-10.3.6.tgz +0 -0
- package/components/tryghost-kg-lexical-html-renderer-1.5.1.tgz +0 -0
- package/components/tryghost-metafield-types-0.0.0.tgz +0 -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 +15 -2
- package/content/themes/casper/assets/js/init.js +37 -9
- package/content/themes/casper/package.json +8 -8
- 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 +14 -1
- package/content/themes/source/assets/js/main.js +24 -4
- package/content/themes/source/package.json +7 -7
- package/core/boot.js +22 -16
- package/core/bridge.js +1 -1
- package/core/built/admin/assets/Combination-DQ6f9A5P.js +41 -0
- package/core/built/admin/assets/{PolarAngleAxis-a81ieQUO.js → PolarAngleAxis-BBaU7PRV.js} +1 -1
- package/core/built/admin/assets/RadialBarChart-Bp20JPnA.js +1 -0
- package/core/built/admin/assets/{about-39CAfroa.js → about-Dp43j18M.js} +1 -1
- package/core/built/admin/assets/accordion-h62UzFhj.js +1 -0
- package/core/built/admin/assets/account-migration-CBTbtX6Q.js +1 -0
- package/core/built/admin/assets/action-list-DC9QpX-l.js +1 -0
- package/core/built/admin/assets/activitypub/{account-migration-KA6Jjf9L.js → account-migration-B1DUZS4Q.js} +8 -8
- package/core/built/admin/assets/activitypub/activitypub.js +24 -11
- package/core/built/admin/assets/activitypub/avatar-CRGud8yf.js +153 -0
- package/core/built/admin/assets/activitypub/{avatar-flipboard-csQaNeYK.js → avatar-flipboard-BZNFAXfm.js} +3 -3
- package/core/built/admin/assets/activitypub/{bluesky-sharing-C7nTDMvw.js → bluesky-sharing-Cg_v-LwS.js} +30 -31
- package/core/built/admin/assets/activitypub/{chunk-KS7C4IRE-Ck3O4oo2.js → chunk-KS7C4IRE-CTUL98Lc.js} +2498 -1885
- package/core/built/admin/assets/activitypub/{content-formatters-CLcjaBwV.js → content-formatters-D7GWP7nH.js} +23 -24
- package/core/built/admin/assets/activitypub/{copy-DcOh8kXw.js → copy-CgzTvoeR.js} +2 -2
- package/core/built/admin/assets/activitypub/{domain-fZ-X8i4-.js → domain-C3G_nkHU.js} +46 -46
- package/core/built/admin/assets/activitypub/{edit-profile-BqMLQV88.js → edit-profile-C8cCY-AK.js} +927 -928
- package/core/built/admin/assets/activitypub/{explore-B4yPoP8E.js → explore-NlDT4inq.js} +11 -11
- package/core/built/admin/assets/activitypub/{feed-BRC_mvAe.js → feed-DF22jCTV.js} +10 -10
- package/core/built/admin/assets/activitypub/{field-COacNgOt.js → field-95-iuTte.js} +4 -4
- package/core/built/admin/assets/activitypub/{hash-C7u-irQQ.js → hash-R7LMLnhY.js} +2 -2
- package/core/built/admin/assets/activitypub/{inbox-CbTTdDQ3.js → inbox-DUJUiV6x.js} +2 -2
- package/core/built/admin/assets/activitypub/{inbox-BW-yvUoN.js → inbox-DerExBzA.js} +416 -414
- package/core/built/admin/assets/activitypub/{label-kPMmYI7l.js → label-EwCn1QYc.js} +4 -4
- package/core/built/admin/assets/activitypub/layout-Dy6NnW1G.js +1 -0
- package/core/built/admin/assets/activitypub/{moderation-CuidJzc0.js → moderation-BSkfiVYo.js} +73 -75
- package/core/built/admin/assets/activitypub/{note-CAMRRSqD.js → note-DOnAJTXK.js} +9 -9
- package/core/built/admin/assets/activitypub/{notifications-BmNlXGgp.js → notifications-DZc6XTjG.js} +27 -27
- package/core/built/admin/assets/activitypub/{onboarding-Dmun9jr_.js → onboarding-8vEIwYTH.js} +3 -3
- package/core/built/admin/assets/activitypub/{onboarding-Bqg7fh_L.js → onboarding-DYVqbNmp.js} +2 -2
- package/core/built/admin/assets/activitypub/{preferences--oH19wf9.js → preferences-DDok6F2N.js} +1418 -1390
- package/core/built/admin/assets/activitypub/{profile-DH_tQx2D.js → profile-DjVa2hUk.js} +254 -255
- package/core/built/admin/assets/activitypub/{reply-Cap9PxSH.js → reply-DtXBpHxu.js} +2 -2
- package/core/built/admin/assets/activitypub/routes-Cw302e1c.js +4946 -0
- package/core/built/admin/assets/activitypub/{separator-CAxxu8VV.js → separator-FpRpVDd3.js} +8 -9
- package/core/built/admin/assets/activitypub/settings-yK-puALn.js +314 -0
- package/core/built/admin/assets/activitypub/{site-BYps63oh.js → site-CHw0R2PA.js} +2 -2
- package/core/built/admin/assets/activitypub/{step-1-CKjR2KAm.js → step-1-737bnvxk.js} +7 -7
- package/core/built/admin/assets/activitypub/{step-2-B6PKfOUQ.js → step-2-DBaIsAsM.js} +7 -7
- package/core/built/admin/assets/activitypub/{step-3-C-qBbcUo.js → step-3-BBmy9m9V.js} +23 -23
- package/core/built/admin/assets/activitypub/tabs-LQ2xirdm.js +1101 -0
- package/core/built/admin/assets/activitypub/{topic-filter-DsUOuu0k.js → topic-filter-75Nu0CKj.js} +4 -4
- package/core/built/admin/assets/activitypub/{use-activity-pub-queries-CX9snsLs.js → use-activity-pub-queries-CYI2QJMs.js} +58 -58
- package/core/built/admin/assets/activitypub/{use-navigate-with-base-path-DsJTGDSS.js → use-navigate-with-base-path-B4jZ8hyg.js} +3924 -1403
- package/core/built/admin/assets/activitypub/{use-reply-chain-data-AJi9zkzm.js → use-reply-chain-data-BHmFxc3U.js} +6 -6
- package/core/built/admin/assets/activitypub/users-CSjOwpT9.js +886 -0
- package/core/built/admin/assets/activitypub/{x-DR8AT3-4.js → x-B9ptWCds.js} +2 -2
- package/core/built/admin/assets/{add-integration-modal-B12oRifD.js → add-integration-modal-BwePhq95.js} +1 -1
- package/core/built/admin/assets/add-newsletter-modal-Zv0I7Msm.js +1 -0
- package/core/built/admin/assets/{add-recommendation-modal-CJf92edY.js → add-recommendation-modal-cdLv0wHy.js} +1 -1
- package/core/built/admin/assets/analytics-DY8_SaP7.js +1 -0
- package/core/built/admin/assets/announcement-bar-modal-C-2yWwag.js +1 -0
- package/core/built/admin/assets/api-keys-BHKATUqQ.js +1 -0
- package/core/built/admin/assets/{audience-6GXevic-.js → audience-wRcSN0jV.js} +1 -1
- package/core/built/admin/assets/{automated-emails-DJQ4uNZo.js → automated-emails-CzUa3v4d.js} +1 -1
- package/core/built/admin/assets/automations-DupSsSOr.js +1 -0
- package/core/built/admin/assets/badge-CI1Z0xyG.js +1 -0
- package/core/built/admin/assets/bluesky-sharing-B8PC1SBj.js +1 -0
- package/core/built/admin/assets/box-LUuYRT-1.js +1 -0
- package/core/built/admin/assets/brand-icon-CrmbX86T.js +1 -0
- package/core/built/admin/assets/breadcrumb-DDDpzLyo.js +1 -0
- package/core/built/admin/assets/button-D414TI3B.js +1 -0
- package/core/built/admin/assets/calendar-Cp_opo3i.js +1 -0
- package/core/built/admin/assets/card-C2dfd5u0.js +1 -0
- package/core/built/admin/assets/chart-B_UNLXse.js +63 -0
- package/core/built/admin/assets/chart-helpers-Czu_9QpJ.js +1 -0
- package/core/built/admin/assets/checkbox-CFFqf0Nh.js +1 -0
- package/core/built/admin/assets/{chunk.368.22ce1b732c0b40abd3f1.js → chunk.201.6961b57ed7a281ac193e.js} +23 -19
- package/core/built/admin/assets/chunk.524.0b850e72ec49a0fa3882.js +25 -0
- package/core/built/admin/assets/chunk.582.db2ae9e968256e8d58ac.js +27 -0
- package/core/built/admin/assets/code-editor-view-Bd_nnHKk.js +1 -0
- package/core/built/admin/assets/code-editor-view-BeU3Yf9M.js +1 -0
- package/core/built/admin/assets/color-picker-Bzm1V7qg.js +3 -0
- package/core/built/admin/assets/color-picker-field-DP0moHz9.js +1 -0
- package/core/built/admin/assets/combobox-6_ruuTuj.js +1 -0
- package/core/built/admin/assets/command-B5wfm6pd.js +1 -0
- package/core/built/admin/assets/comments-BB26dUSl.js +1 -0
- package/core/built/admin/assets/confirmation-context-znVJD4pX.js +1 -0
- package/core/built/admin/assets/container-CHHif8km.js +1 -0
- package/core/built/admin/assets/{content-api-modal-0ZjuLcQ8.js → content-api-modal-DOHwl0yZ.js} +1 -1
- package/core/built/admin/assets/context-menu-BpY46Dlb.js +1 -0
- package/core/built/admin/assets/copy-field-DRBx6Ady.js +1 -0
- package/core/built/admin/assets/create-ghost-browse-value-source-eIXo5Qws.js +1 -0
- package/core/built/admin/assets/custom-field-type-option-DrSlETOI.js +1 -0
- package/core/built/admin/assets/custom-integration-modal-Dgo425Ec.js +1 -0
- package/core/built/admin/assets/data-list-DM8yqpXi.js +1 -0
- package/core/built/admin/assets/date-range-select-DdC23c13.js +1 -0
- package/core/built/admin/assets/design-and-theme-modal-CbSu9IT4.js +2 -0
- package/core/built/admin/assets/detail-page-CN4NdhpV.js +1 -0
- package/core/built/admin/assets/dirty-confirm-dialog-BT_Vq9TD.js +1 -0
- package/core/built/admin/assets/{disabled-sources-indicator-CLZhMv8J.js → disabled-sources-indicator-C5xtW0Q2.js} +1 -1
- package/core/built/admin/assets/dist-B40T-RCQ.js +1 -0
- package/core/built/admin/assets/dist-CrlaEoaK.js +1 -0
- package/core/built/admin/assets/domain-BPReCZa8.js +1 -0
- package/core/built/admin/assets/dropzone-B2auMkf2.js +5 -0
- package/core/built/admin/assets/edit-profile-B7XTBzKe.js +1 -0
- package/core/built/admin/assets/editor-BcaC9dqm.js +8 -0
- package/core/built/admin/assets/editor-screen-FuMpItC8.js +27 -0
- package/core/built/admin/assets/email-sending-status-provider-9d81o1C2.js +1 -0
- package/core/built/admin/assets/embed-signup-form-modal-CbVbMsxl.js +8 -0
- package/core/built/admin/assets/empty-indicator-CSQts7GV.js +1 -0
- package/core/built/admin/assets/explore-DbSXFTJN.js +1 -0
- package/core/built/admin/assets/feature-image-placeholder-DFXA4vfJ.js +1 -0
- package/core/built/admin/assets/feed-W7RlF-Gp.js +1 -0
- package/core/built/admin/assets/field-BXEh3ptU.js +1 -0
- package/core/built/admin/assets/filter-sources-DHK2IoCk.js +1 -0
- package/core/built/admin/assets/filters-0SYNTqyQ.js +1 -0
- package/core/built/admin/assets/filters-DTtZKQyq.js +1 -0
- package/core/built/admin/assets/{first-promoter-modal-wr73Dldc.js → first-promoter-modal-DcoN_OXu.js} +1 -1
- package/core/built/admin/assets/{ghost-a1e6e172c6917e8ef8fa6b0007756d9b.js → ghost-25495154132af7305cb7b646fd83f48f.js} +562 -514
- package/core/built/admin/assets/gift-link-modal-BX-Q1TOk.js +1 -0
- package/core/built/admin/assets/grid-BEUIDQX7.js +1 -0
- package/core/built/admin/assets/growth-G6PLO4aF.js +1 -0
- package/core/built/admin/assets/growth-tkD-fBOY.js +3 -0
- package/core/built/admin/assets/heading-ih-fOVqF.js +1 -0
- package/core/built/admin/assets/history-modal-Ca-gStoq.js +1 -0
- package/core/built/admin/assets/html-field-B3CrKV9Y.js +1 -0
- package/core/built/admin/assets/images-H-BIm8OQ.js +1 -0
- package/core/built/admin/assets/{inbox-DgSZ6w2p.js → inbox-DBbDVMPz.js} +14 -14
- package/core/built/admin/assets/index-DOF2jDq0.js +4 -0
- package/core/built/admin/assets/index-JrrNchW1.css +2 -0
- package/core/built/admin/assets/input-group-CvH-3d3F.js +1 -0
- package/core/built/admin/assets/input-surface-CL23Mlh8.js +1 -0
- package/core/built/admin/assets/integration-header-C7GXGis_.js +1 -0
- package/core/built/admin/assets/invite-user-modal-EJ2_6RpV.js +1 -0
- package/core/built/admin/assets/isPlainObject-BzzgUf1E.js +1 -0
- package/core/built/admin/assets/{koenig-lexical-CXVgQFUk.js → koenig-lexical-Dkwee5FG.js} +1 -1
- package/core/built/admin/assets/koenig-loader-BzXCXHoA.js +2 -0
- package/core/built/admin/assets/kpi-card-iCDUTgOR.js +1 -0
- package/core/built/admin/assets/kpi-card-jTnpLKGr.js +1 -0
- package/core/built/admin/assets/kpi-helpers-Criu0YAf.js +1 -0
- package/core/built/admin/assets/kpi-tabs-DbOmmyOo.js +1 -0
- package/core/built/admin/assets/label-Du0yqMqL.js +1 -0
- package/core/built/admin/assets/label-picker-Bq1XXr1D.js +1 -0
- package/core/built/admin/assets/{labels-KMkFoRG6.js → labels-0x2NfLtC.js} +1 -1
- package/core/built/admin/assets/layout-Ckwzsnsu.js +1 -0
- package/core/built/admin/assets/lib-CCz2mjm8.js +2 -0
- package/core/built/admin/assets/link-helpers-o9GgBTni.js +1 -0
- package/core/built/admin/assets/{links-FwNCVyVe.js → links-Ctujreuh.js} +1 -1
- package/core/built/admin/assets/list-page-CH_wnDC3.js +1 -0
- package/core/built/admin/assets/member-activity-CsAh6MxK.js +1 -0
- package/core/built/admin/assets/member-activity-feed-0ytsQbtY.js +1 -0
- package/core/built/admin/assets/member-custom-fields-CTFGnnYv.js +1 -0
- package/core/built/admin/assets/member-detail-QU3vB1ML.js +1 -0
- package/core/built/admin/assets/members-CtMVO_AB.js +4 -0
- package/core/built/admin/assets/modal-page-8Ipfl51B.js +1 -0
- package/core/built/admin/assets/moderation-B8VtA-W0.js +1 -0
- package/core/built/admin/assets/multi-select-combobox-_9wEYmGv.js +1 -0
- package/core/built/admin/assets/navigation-modal-CGcjJvkc.js +1 -0
- package/core/built/admin/assets/newsletter-BpHjjqmq.js +1 -0
- package/core/built/admin/assets/newsletter-detail-modal-DzTbGOyo.js +1 -0
- package/core/built/admin/assets/newsletter-emails-BMKH4Osp.js +1 -0
- package/core/built/admin/assets/newsletters-BxC84_cL.js +1 -0
- package/core/built/admin/assets/note-BPtEzzZS.js +1 -0
- package/core/built/admin/assets/notifications-ng3ulEdp.js +1 -0
- package/core/built/admin/assets/offers-container-modal-CwqnRa3T.js +1 -0
- package/core/built/admin/assets/onboarding-route-CplZzd7F.js +1 -0
- package/core/built/admin/assets/overview-B0yD9OoX.js +1 -0
- package/core/built/admin/assets/overview-C4eJzQqi.js +1 -0
- package/core/built/admin/assets/page-header-CdCpekG9.js +1 -0
- package/core/built/admin/assets/pagemenu-CKQD9hoP.js +1 -0
- package/core/built/admin/assets/pages-route-CKsnxIvw.js +1 -0
- package/core/built/admin/assets/{pintura-modal-BljM7hf8.js → pintura-modal-C5jzeyGk.js} +1 -1
- package/core/built/admin/assets/portal-frame-DYo0bh0E.js +1 -0
- package/core/built/admin/assets/portal-modal-C0d8xjKa.js +1 -0
- package/core/built/admin/assets/post-analytics-C5C7IyAm.js +1 -0
- package/core/built/admin/assets/post-analytics-header-DKWHwoK2.js +1 -0
- package/core/built/admin/assets/{post-analytics-provider-CgreZDjS.js → post-analytics-provider-BqCPPxmW.js} +1 -1
- package/core/built/admin/assets/post-share-modal-wxmqbAv_.js +1 -0
- package/core/built/admin/assets/posts-list-screen-B978ZO0R.js +2 -0
- package/core/built/admin/assets/posts-route-CDqxKazl.js +1 -0
- package/core/built/admin/assets/preferences-CnejTRc4.js +5 -0
- package/core/built/admin/assets/preview-chrome-C7yZWVLZ.js +1 -0
- package/core/built/admin/assets/preview-modal-CFUxUGHp.js +1 -0
- package/core/built/admin/assets/profile-ClRGiOqA.js +1 -0
- package/core/built/admin/assets/radio-group-CTmLo0h9.js +1 -0
- package/core/built/admin/assets/router-provider-DDZvgS3V.js +1 -0
- package/core/built/admin/assets/select-D_4xWFYv.js +1 -0
- package/core/built/admin/assets/settings-BRl7-7a9.js +1 -0
- package/core/built/admin/assets/settings-BoQcPa-y.js +4 -0
- package/core/built/admin/assets/settings-breadcrumbs-C9Yxl81q.js +1 -0
- package/core/built/admin/assets/{dist-BXHrDV19.js → shade-scope-Cccj-c7I-D0XwkdKQ.js} +5 -3
- package/core/built/admin/assets/share-modal-DBqZobuR.js +1 -0
- package/core/built/admin/assets/simple-pagination-D5t_ox6x.js +1 -0
- package/core/built/admin/assets/skeleton-CPcTiTSX.js +1 -0
- package/core/built/admin/assets/{slack-modal-D7W_fNON.js → slack-modal-BF9ex8cd.js} +1 -1
- package/core/built/admin/assets/sort-button-C0EXGjnS.js +1 -0
- package/core/built/admin/assets/{source-icon-CQboPZQ3.js → source-icon-BzzftCQ2.js} +1 -1
- package/core/built/admin/assets/stats-view-CzpGoHzF.js +1 -0
- package/core/built/admin/assets/{step-1-BKhjy0PV.js → step-1-CBUYUPPF.js} +1 -1
- package/core/built/admin/assets/{step-2-PxA1OM7R.js → step-2-CEIXUwQa.js} +1 -1
- package/core/built/admin/assets/{step-3-BJbAiq16.js → step-3-C1HA5i1N.js} +2 -2
- package/core/built/admin/assets/stripe-button-DMFsLs80.js +1 -0
- package/core/built/admin/assets/stripe-connect-modal-CEvxCUTv.js +1 -0
- package/core/built/admin/assets/switch-DoOJF2yg.js +1 -0
- package/core/built/admin/assets/table-BDYbUHJz.js +1 -0
- package/core/built/admin/assets/tabs-BZyz4ZCH.js +1 -0
- package/core/built/admin/assets/tag-detail-CFzaz_9E.js +2 -0
- package/core/built/admin/assets/tag-picker-BKUCZuRc.js +1 -0
- package/core/built/admin/assets/tags-Bs1FiD7m.js +1 -0
- package/core/built/admin/assets/{testimonials-modal-Dkt6ODLW.js → testimonials-modal-CVm0_7E-.js} +1 -1
- package/core/built/admin/assets/text-BLI0C8Mc.js +1 -0
- package/core/built/admin/assets/textarea-C5qolByg.js +1 -0
- package/core/built/admin/assets/tier-detail-modal-Cmwzi-e7.js +1 -0
- package/core/built/admin/assets/toggle-group-BTL1QsWY.js +1 -0
- package/core/built/admin/assets/{topic-filter-DVOe3D-b.js → topic-filter-BMjhquv7.js} +1 -1
- package/core/built/admin/assets/transistor-modal-hMv53jF8.js +1 -0
- package/core/built/admin/assets/trend-badge-1w_HEzkG.js +1 -0
- package/core/built/admin/assets/{unsplash-modal-DXt7Brum.js → unsplash-modal-jzC8lEB2.js} +1 -1
- package/core/built/admin/assets/use-analytics-data-B3lGOxsC.js +1 -0
- package/core/built/admin/assets/use-availability-DnKqOyqd.js +1 -0
- package/core/built/admin/assets/{use-check-theme-limit-error-JD-J5aaZ.js → use-check-theme-limit-error-C1tc2P4N.js} +2 -2
- package/core/built/admin/assets/use-filter-params-DU-aiaTb.js +1 -0
- package/core/built/admin/assets/{use-filterable-api-CEMSAYPg.js → use-filterable-api-CxCrnPxG.js} +1 -1
- package/core/built/admin/assets/use-growth-stats-E13rMQUE.js +1 -0
- package/core/built/admin/assets/use-limiter-DlL7au90.js +19 -0
- package/core/built/admin/assets/{use-navigate-with-base-path-88EQpw2k.js → use-navigate-with-base-path-BzgNwMAx.js} +1 -1
- package/core/built/admin/assets/{use-pintura-config-BmU45Ruy.js → use-pintura-config-CtEV1JQY.js} +1 -1
- package/core/built/admin/assets/{use-pintura-editor-Bz2bZ4iT.js → use-pintura-editor-CaxE64kD.js} +1 -1
- package/core/built/admin/assets/use-reply-chain-data-BST2OgCM.js +1 -0
- package/core/built/admin/assets/use-sending-eta-DR9ueMH8.js +1 -0
- package/core/built/admin/assets/use-setting-group-ldtX1Vsk.js +1 -0
- package/core/built/admin/assets/use-settings-navigation-CzGU4sus.js +1 -0
- package/core/built/admin/assets/use-staff-users-DoeXaPsb.js +1 -0
- package/core/built/admin/assets/use-tinybird-query-BaBNCaj0.js +1 -0
- package/core/built/admin/assets/{use-tinybird-token-Lk1RSn0t.js → use-tinybird-token-CnZ19NDf.js} +1 -1
- package/core/built/admin/assets/{use-url-input-DpmbDppC.js → use-url-input-C5KHJw79.js} +1 -1
- package/core/built/admin/assets/user-detail-modal-Dm0KfPeR.js +1 -0
- package/core/built/admin/assets/{vendor-2dd263291938d407802568d3357ec69e.js → vendor-97e91ff8dd1457c668f9ef103ee1a77b.js} +2748 -2977
- package/core/built/admin/assets/virtual-list-tAuPUICw.js +1 -0
- package/core/built/admin/assets/web-BQlKcW2x.js +2 -0
- package/core/built/admin/assets/web-NTT5DkEz.js +1 -0
- package/core/built/admin/assets/{zapier-modal-BafLUO4R.js → zapier-modal-DsHG9Oev.js} +1 -1
- package/core/built/admin/index.html +22 -24
- package/core/frontend/apps/private-blogging/index.js +2 -2
- package/core/frontend/apps/private-blogging/lib/middleware.js +1 -1
- package/core/frontend/apps/private-blogging/lib/router.js +1 -1
- package/core/frontend/helpers/cancel_link.js +3 -3
- package/core/frontend/helpers/content.js +2 -2
- package/core/frontend/helpers/content_api_url.js +1 -1
- package/core/frontend/helpers/date.js +1 -1
- package/core/frontend/helpers/foreach.js +5 -5
- package/core/frontend/helpers/get.js +7 -4
- package/core/frontend/helpers/ghost_head.js +2 -2
- package/core/frontend/helpers/has.js +1 -3
- package/core/frontend/helpers/link.js +7 -7
- package/core/frontend/helpers/link_class.js +2 -2
- package/core/frontend/helpers/navigation.js +1 -2
- package/core/frontend/helpers/recommendations.js +5 -6
- package/core/frontend/helpers/tiers.js +1 -1
- package/core/frontend/helpers/total_members.js +1 -1
- package/core/frontend/helpers/total_paid_members.js +1 -1
- package/core/frontend/meta/author-url.js +1 -1
- package/core/frontend/meta/modified-date.js +1 -1
- package/core/frontend/meta/published-date.js +1 -1
- package/core/frontend/meta/schema.js +3 -8
- package/core/frontend/meta/structured-data.js +1 -2
- package/core/frontend/services/assets-minification/minifier.js +1 -1
- package/core/frontend/services/data/entry-lookup.js +1 -1
- package/core/frontend/services/data/fetch-data.js +2 -2
- package/core/frontend/services/rendering/format-response.js +1 -1
- package/core/frontend/services/rendering/renderer.js +3 -0
- package/core/frontend/services/rendering/templates.js +1 -1
- package/core/frontend/services/routing/controllers/static.js +1 -1
- package/core/frontend/services/routing/parent-router.js +1 -1
- package/core/frontend/services/routing/registry.js +1 -1
- package/core/frontend/services/sitemap/base-site-map-generator.js +68 -97
- package/core/frontend/services/sitemap/site-map-index-generator.js +16 -21
- package/core/frontend/services/sitemap/site-map-manager.js +82 -43
- package/core/frontend/services/sitemap/sitemap-xml.js +72 -0
- package/core/frontend/services/theme-engine/handlebars/utils.js +8 -8
- package/core/frontend/services/theme-engine/i18n/i18n.js +4 -5
- package/core/frontend/services/theme-engine/middleware/update-global-template-options.js +1 -1
- package/core/frontend/services/theme-engine/preview.js +1 -1
- package/core/frontend/utils/member-count.js +2 -2
- package/core/frontend/web/routers/serve-public-file.js +1 -1
- package/core/server/adapters/scheduling/README.md +4 -0
- package/core/server/adapters/scheduling/get-scheduler-idempotency-key.js +21 -0
- package/core/server/adapters/storage/LocalStorageBase.js +2 -1
- package/core/server/api/endpoints/automated-emails.js +8 -2
- package/core/server/api/endpoints/db.js +1 -1
- package/core/server/api/endpoints/emails.js +3 -3
- package/core/server/api/endpoints/mail.js +1 -1
- package/core/server/api/endpoints/member-signin-urls.js +1 -1
- package/core/server/api/endpoints/members.js +3 -3
- package/core/server/api/endpoints/oembed.js +1 -1
- package/core/server/api/endpoints/posts.js +1 -1
- package/core/server/api/endpoints/settings.js +2 -2
- package/core/server/api/endpoints/themes.js +5 -5
- package/core/server/api/endpoints/utils/serializers/input/pages.js +2 -2
- package/core/server/api/endpoints/utils/serializers/input/posts.js +2 -2
- package/core/server/api/endpoints/utils/serializers/input/tags.js +1 -1
- package/core/server/api/endpoints/utils/serializers/input/utils/slug-filter-order.js +4 -4
- package/core/server/api/endpoints/utils/serializers/output/mappers/comments.js +8 -5
- package/core/server/api/endpoints/utils/serializers/output/mappers/posts.js +1 -1
- package/core/server/api/endpoints/utils/serializers/output/pages.js +4 -4
- package/core/server/api/endpoints/utils/serializers/output/posts.js +4 -4
- package/core/server/api/endpoints/utils/serializers/output/search-index.js +11 -11
- package/core/server/api/endpoints/utils/serializers/output/settings.js +1 -1
- package/core/server/api/endpoints/utils/serializers/output/utils/extra-attrs.js +3 -3
- package/core/server/api/endpoints/utils/validators/input/automated_emails.js +23 -33
- package/core/server/api/endpoints/utils/validators/input/settings.js +3 -3
- package/core/server/data/exporter/exporter.js +1 -2
- package/core/server/data/exporter/table-lists.js +1 -0
- package/core/server/data/importer/handlers/image.js +1 -2
- package/core/server/data/importer/handlers/json.js +1 -3
- package/core/server/data/importer/handlers/markdown.js +4 -8
- package/core/server/data/importer/import-manager.js +1 -1
- package/core/server/data/importer/importers/content-file-importer.js +4 -8
- package/core/server/data/importer/importers/data/base.js +10 -10
- package/core/server/data/importer/importers/data/custom-theme-settings-importer.js +1 -1
- package/core/server/data/importer/importers/data/data-importer.js +3 -4
- package/core/server/data/importer/importers/data/posts-importer.js +10 -10
- package/core/server/data/importer/importers/data/products-importer.js +3 -3
- package/core/server/data/importer/importers/data/settings-importer.js +2 -2
- package/core/server/data/importer/importers/data/stripe-prices-importer.js +1 -1
- package/core/server/data/importer/importers/data/stripe-products-importer.js +1 -1
- package/core/server/data/importer/importers/data/tags-importer.js +1 -1
- package/core/server/data/importer/importers/data/users-importer.js +2 -2
- package/core/server/data/importer/importers/json-to-html.js +12 -9
- package/core/server/data/migrations/versions/5.0/2022-05-11-13-12-rename-settings.js +1 -1
- package/core/server/data/migrations/versions/6.65/2026-09-16-15-35-26-add-members-metafield-change-events.js +17 -0
- package/core/server/data/schema/fixtures/fixture-manager.js +3 -3
- package/core/server/data/schema/index.js +1 -1
- package/core/server/data/schema/schema.js +26 -0
- package/core/server/data/schema/validator.js +96 -123
- package/core/server/data/seeders/importers/email-recipients-importer.js +2 -2
- package/core/server/data/seeders/importers/members-login-events-importer.js +1 -1
- package/core/server/data/seeders/importers/members-newsletters-importer.js +1 -1
- package/core/server/data/seeders/importers/members-paid-subscription-events-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 +2 -2
- package/core/server/data/seeders/importers/members-subscription-created-events-importer.js +1 -1
- package/core/server/data/tinybird/pipes/mv_hits.pipe +25 -20
- package/core/server/data/tinybird/scripts/docker-analytics-manager.js +2 -2
- package/core/server/ghost-server.js +1 -19
- package/core/server/lib/image/image-size.js +1 -3
- package/core/server/lib/request-external.js +53 -117
- package/core/server/models/base/plugins/actions.js +2 -3
- package/core/server/models/base/plugins/crud.js +1 -2
- package/core/server/models/base/plugins/events.js +4 -4
- package/core/server/models/base/plugins/raw-knex.js +3 -3
- package/core/server/models/base/plugins/sanitize.js +1 -1
- package/core/server/models/benefit.js +1 -1
- package/core/server/models/collection.js +1 -1
- package/core/server/models/comment.js +3 -3
- package/core/server/models/invite.js +2 -5
- package/core/server/models/label.js +3 -6
- package/core/server/models/member.js +7 -10
- package/core/server/models/newsletter.js +1 -1
- package/core/server/models/permission.js +3 -6
- package/core/server/models/post.js +20 -23
- package/core/server/models/product.js +4 -1
- package/core/server/models/relations/authors.js +9 -12
- package/core/server/models/role.js +2 -5
- package/core/server/models/settings.js +3 -3
- package/core/server/models/tag.js +2 -5
- package/core/server/models/user.js +8 -10
- package/core/server/models/webhook.js +2 -4
- package/core/server/notify.js +2 -2
- package/core/server/services/adapter-manager/utils.js +6 -1
- package/core/server/services/api-version-compatibility/legacy-api-path-match.js +2 -2
- package/core/server/services/auth/api-key/admin.js +2 -2
- package/core/server/services/auth/api-key/content.js +1 -1
- package/core/server/services/auth/passwordreset.js +1 -1
- package/core/server/services/auth/setup.js +1 -3
- package/core/server/services/automations/README.md +19 -0
- package/core/server/services/automations/poll.js +3 -1
- package/core/server/services/automations/service.js +2 -2
- package/core/server/services/automations/welcome-email-automation-poll.js +199 -293
- package/core/server/services/comments/comments-controller.js +9 -30
- package/core/server/services/comments/comments-service-email-renderer.js +1 -1
- package/core/server/services/comments/comments-service-emails.js +1 -1
- package/core/server/services/comments/comments-service.js +27 -58
- package/core/server/services/comments/comments-stats-service.js +1 -1
- package/core/server/services/content-import/import/staged-file.js +9 -9
- package/core/server/services/content-import/index.js +1 -1
- package/core/server/services/custom-redirects/validation.js +1 -1
- package/core/server/services/email-analytics/email-analytics-service-wrapper.js +23 -55
- package/core/server/services/email-analytics/index.js +35 -19
- package/core/server/services/email-analytics/jobs/email-analytics-job-scheduler.js +31 -60
- package/core/server/services/email-service/README.md +35 -0
- package/core/server/services/email-service/batch-sending-service.js +13 -14
- package/core/server/services/email-service/email-renderer.js +50 -14
- package/core/server/services/email-service/email-service-wrapper.js +3 -2
- package/core/server/services/email-service/email-service.js +33 -8
- package/core/server/services/email-service/email-templates/partials/feedback-button.hbs +2 -1
- package/core/server/services/email-service/email-templates/partials/styles.hbs +0 -6
- package/core/server/services/email-service/email-templates/template.hbs +1 -1
- package/core/server/services/email-service/jobs/send-email-job.js +12 -0
- package/core/server/services/email-service/mailgun-email-provider.js +7 -2
- package/core/server/services/email-service/sending-service.js +1 -1
- package/core/server/services/gifts/gift-service.js +12 -3
- package/core/server/services/gifts/index.js +0 -2
- package/core/server/services/gifts/jobs/index.js +12 -24
- package/core/server/services/gifts/jobs/send-gift-reminders-job.js +6 -46
- package/core/server/services/invitations/accept.js +2 -2
- package/core/server/services/jobs/job-service.js +0 -28
- package/core/server/services/jobs-service/jobs-service.js +5 -0
- package/core/server/services/jobs-service/register-job-handlers.js +17 -1
- package/core/server/services/lib/mailgun-client.js +16 -1
- package/core/server/services/lib/mailgun-recipient-message-id.js +49 -0
- package/core/server/services/limits.js +1 -1
- package/core/server/services/mail/ghost-mailer.js +1 -1
- package/core/server/services/member-attribution/member-attribution-service.js +1 -1
- package/core/server/services/member-attribution/referrer-translator.js +1 -1
- package/core/server/services/members/account-service.js +3 -3
- package/core/server/services/members/api.js +1 -1
- package/core/server/services/members/import-export/import/importer.js +25 -16
- package/core/server/services/members/import-export/import/spool.js +11 -15
- package/core/server/services/members/import-export/index.js +6 -4
- package/core/server/services/members/jobs/index.js +1 -1
- package/core/server/services/members/jobs/members-import-job.js +18 -0
- package/core/server/services/members/member-avatar.js +18 -0
- package/core/server/services/members/members-api/controllers/member-controller.js +2 -2
- package/core/server/services/members/members-api/members-api.js +4 -4
- package/core/server/services/members/members-api/repositories/event-repository.js +36 -1
- package/core/server/services/members/members-api/repositories/member-repository.js +55 -17
- package/core/server/services/members/members-api/repositories/product-repository.js +1 -1
- package/core/server/services/members/members-api/services/member-bread-service.js +4 -7
- package/core/server/services/members/service.js +7 -2
- package/core/server/services/members/stats/members-stats.js +2 -2
- package/core/server/services/members-events/event-storage.js +2 -2
- package/core/server/services/members-metafields/actions.js +23 -2
- package/core/server/services/members-metafields/bindings-service.js +5 -5
- package/core/server/services/members-metafields/definitions-service.js +2 -7
- package/core/server/services/members-metafields/index.js +2 -1
- package/core/server/services/members-metafields/queries.js +7 -1
- package/core/server/services/members-metafields/schema.js +49 -1
- package/core/server/services/members-metafields/values-service.js +112 -10
- package/core/server/services/mentions/mention-sending-service.js +2 -2
- package/core/server/services/mentions/mention.js +3 -4
- package/core/server/services/mentions/mentions-api.js +4 -1
- package/core/server/services/mentions-jobs/job-service.js +0 -28
- package/core/server/services/milestones/milestones-service.js +1 -1
- package/core/server/services/newsletters/newsletters-service.js +1 -1
- package/core/server/services/notifications/notifications.js +3 -3
- package/core/server/services/oembed/oembed-service.js +79 -3
- package/core/server/services/permissions/can-this.js +1 -2
- package/core/server/services/post-scheduling/post-scheduling.js +8 -1
- package/core/server/services/posts/post-scheduling.js +7 -0
- package/core/server/services/settings/settings-bread-service.js +3 -3
- package/core/server/services/settings/settings-utils.js +1 -1
- package/core/server/services/settings-helpers/settings-helpers.js +1 -1
- package/core/server/services/staff/staff-service-emails.js +9 -9
- package/core/server/services/stats/posts-stats-service.js +10 -10
- package/core/server/services/stats/referrers-stats-service.js +1 -1
- package/core/server/services/stats/subscription-stats-service.js +3 -3
- package/core/server/services/stats/utils/tinybird.js +8 -1
- package/core/server/services/stripe/stripe-api.js +3 -3
- package/core/server/services/stripe/stripe-migrations.js +6 -6
- package/core/server/services/themes/storage.js +21 -26
- package/core/server/services/themes/theme-storage.js +2 -2
- package/core/server/services/tiers/tier.js +15 -15
- package/core/server/services/tinybird-sync/index.js +3 -0
- package/core/server/services/tinybird-sync/tinybird-sync-service.js +7 -2
- package/core/server/services/update-check/update-check-service.js +3 -3
- package/core/server/services/webhooks/serialize.js +1 -1
- package/core/server/web/api/app.js +0 -5
- package/core/server/web/api/middleware/upload.js +29 -2
- package/core/server/web/parent/middleware/index.js +1 -1
- package/core/server/web/parent/middleware/log-request.js +5 -0
- package/core/server/web/parent/middleware/queue-request.js +104 -59
- package/core/server/web/shared/middleware/api/spam-prevention.js +2 -2
- package/core/shared/config/defaults.json +6 -1
- package/core/shared/custom-theme-settings-cache/custom-theme-settings-service.js +1 -1
- package/core/shared/labs.js +3 -2
- package/core/shared/settings-cache/cache-manager.js +1 -1
- package/nodemon.json +1 -1
- package/package.json +6 -7
- package/pnpm-lock.yaml +126 -728
- package/pnpm-workspace.yaml +4 -7
- package/tsconfig.json +1 -1
- package/components/tryghost-adapter-base-scheduling-0.2.3.tgz +0 -0
- package/core/built/admin/assets/Combination-DWfJPcz9.js +0 -41
- package/core/built/admin/assets/RadialBarChart-CHRBhiBN.js +0 -1
- package/core/built/admin/assets/_baseAssignValue-DcPokYW8.js +0 -1
- package/core/built/admin/assets/accordion-CJmRaqK7.js +0 -1
- package/core/built/admin/assets/account-migration-DYf7skbb.js +0 -1
- package/core/built/admin/assets/action-list-Crnh-_UI.js +0 -1
- package/core/built/admin/assets/activitypub/avatar-DVJF5bxP.js +0 -261
- package/core/built/admin/assets/activitypub/layout-BL4_jtuV.js +0 -1
- package/core/built/admin/assets/activitypub/routes-DdyY9uFF.js +0 -7181
- package/core/built/admin/assets/activitypub/settings-B6EEcVkW.js +0 -315
- package/core/built/admin/assets/activitypub/tabs-DLhZtVde.js +0 -1083
- package/core/built/admin/assets/activitypub/users-inweyKL5.js +0 -1499
- package/core/built/admin/assets/add-newsletter-modal-CTvXiIqY.js +0 -1
- package/core/built/admin/assets/analytics-PHR1Fggi.js +0 -1
- package/core/built/admin/assets/announcement-bar-modal-Bql0CXdp.js +0 -1
- package/core/built/admin/assets/api-keys-CubH-7_H.js +0 -1
- package/core/built/admin/assets/automations-DcZSLFDU.js +0 -1
- package/core/built/admin/assets/badge-qP06OT7C.js +0 -1
- package/core/built/admin/assets/bluesky-sharing-CJw4d4Mf.js +0 -1
- package/core/built/admin/assets/box-CZ_LSVSy.js +0 -1
- package/core/built/admin/assets/brand-icon-D3ffDYaC.js +0 -1
- package/core/built/admin/assets/breadcrumb-Chn1Ip_q.js +0 -1
- package/core/built/admin/assets/button-DvIh2Bq-.js +0 -1
- package/core/built/admin/assets/calendar-1QGoStFM.js +0 -1
- package/core/built/admin/assets/card-FHQ4D10L.js +0 -1
- package/core/built/admin/assets/chart-helpers-CNpA7re_.js +0 -1
- package/core/built/admin/assets/chart-jVz9Nf9t.js +0 -63
- package/core/built/admin/assets/checkbox-DKht9xMl.js +0 -1
- package/core/built/admin/assets/chunk.524.cc9be98e44890cedc8c8.js +0 -25
- package/core/built/admin/assets/chunk.582.e6fe742b3217207b11a6.js +0 -27
- package/core/built/admin/assets/code-editor-view-BLQIV85-.js +0 -1
- package/core/built/admin/assets/code-editor-view-Cg5eJxcr.js +0 -1
- package/core/built/admin/assets/color-picker-DQoghc0t.js +0 -3
- package/core/built/admin/assets/color-picker-field-BbeK5RRs.js +0 -1
- package/core/built/admin/assets/combobox-weO4FBbv.js +0 -1
- package/core/built/admin/assets/command-DlLrCm9V.js +0 -1
- package/core/built/admin/assets/comments-BjTitLmP.js +0 -1
- package/core/built/admin/assets/confirmation-context-IyqoXVk-.js +0 -1
- package/core/built/admin/assets/container-DAimjOF_.js +0 -1
- package/core/built/admin/assets/context-menu-BtioYFrg.js +0 -1
- package/core/built/admin/assets/copy-field-C6ujqJlP.js +0 -1
- package/core/built/admin/assets/create-ghost-browse-value-source-DAZMWZNq.js +0 -1
- package/core/built/admin/assets/custom-integration-modal-Dm8QI_J4.js +0 -1
- package/core/built/admin/assets/data-list-C0CKkeWW.js +0 -1
- package/core/built/admin/assets/date-range-select-DrjHQdgz.js +0 -1
- package/core/built/admin/assets/design-and-theme-modal-CXVOzBWu.js +0 -2
- package/core/built/admin/assets/detail-page-QpLIL-EO.js +0 -1
- package/core/built/admin/assets/dirty-confirm-dialog-DWwxREGh.js +0 -1
- package/core/built/admin/assets/dist-Bf-HQtVL.js +0 -1
- package/core/built/admin/assets/dist-CUwte9v_.js +0 -1
- package/core/built/admin/assets/dist-FEQQAwTe.js +0 -1
- package/core/built/admin/assets/domain-DBrBic6q.js +0 -1
- package/core/built/admin/assets/dropzone-D61QVcEY.js +0 -5
- package/core/built/admin/assets/edit-profile-jCqJBxqw.js +0 -1
- package/core/built/admin/assets/editor-8Fm4UBEd.js +0 -8
- package/core/built/admin/assets/editor-screen-BSX_uC2B.js +0 -27
- package/core/built/admin/assets/email-sending-status-provider-DnNhlIvt.js +0 -1
- package/core/built/admin/assets/embed-signup-form-modal-DqtBs1WE.js +0 -8
- package/core/built/admin/assets/empty-indicator-L4Ql5Db7.js +0 -1
- package/core/built/admin/assets/en-Cx75dJv5.js +0 -1
- package/core/built/admin/assets/explore-DXhDCtKw.js +0 -1
- package/core/built/admin/assets/feature-image-placeholder-e2q6TcH6.js +0 -1
- package/core/built/admin/assets/feed-mmt4noNL.js +0 -1
- package/core/built/admin/assets/field-p7KnP98B.js +0 -1
- package/core/built/admin/assets/filter-bar-CiIKBg3D.js +0 -1
- package/core/built/admin/assets/filter-sources-I-dRaQxl.js +0 -1
- package/core/built/admin/assets/filters-1injvyxJ.js +0 -1
- package/core/built/admin/assets/filters-DnpO6GWX.js +0 -1
- package/core/built/admin/assets/gift-link-modal-C3H7YFXO.js +0 -1
- package/core/built/admin/assets/grid-5vplBYri.js +0 -1
- package/core/built/admin/assets/growth-B1og1kQp.js +0 -1
- package/core/built/admin/assets/growth-Bf6OHZlK.js +0 -3
- package/core/built/admin/assets/heading-BB21QAbb.js +0 -1
- package/core/built/admin/assets/history-modal-t_qEnxPx.js +0 -1
- package/core/built/admin/assets/html-field-COLQbV4r.js +0 -1
- package/core/built/admin/assets/images-4mvoc3lB.js +0 -1
- package/core/built/admin/assets/index-B3HZU2i8.css +0 -2
- package/core/built/admin/assets/index-DDd-zhNL.js +0 -4
- package/core/built/admin/assets/inline-B8H6NzIw.js +0 -1
- package/core/built/admin/assets/input-group-CLIN2ykI.js +0 -1
- package/core/built/admin/assets/input-surface-wSO5CRy5.js +0 -1
- package/core/built/admin/assets/integration-header-CKGrXNVP.js +0 -1
- package/core/built/admin/assets/invite-user-modal-BaN2mdhI.js +0 -1
- package/core/built/admin/assets/koenig-loader-B1XPPY5C.js +0 -2
- package/core/built/admin/assets/kpi-card-CRLPVlFW.js +0 -1
- package/core/built/admin/assets/kpi-card-CRPbW8NZ.js +0 -1
- package/core/built/admin/assets/kpi-helpers-D7zT96bp.js +0 -1
- package/core/built/admin/assets/kpi-tabs-DE_yh9Go.js +0 -1
- package/core/built/admin/assets/label-CgeBxy4o.js +0 -1
- package/core/built/admin/assets/label-picker-DGDp4Vwr.js +0 -1
- package/core/built/admin/assets/layout-DWnOMly4.js +0 -1
- package/core/built/admin/assets/lib-_QYaUU89.js +0 -2
- package/core/built/admin/assets/link-helpers-8J7ixADV.js +0 -1
- package/core/built/admin/assets/list-page-DLMP0PxC.js +0 -1
- package/core/built/admin/assets/member-activity-ClMWFyvN.js +0 -1
- package/core/built/admin/assets/member-activity-feed-BQY5Rwaj.js +0 -1
- package/core/built/admin/assets/member-custom-fields-Dd_ie1zG.js +0 -1
- package/core/built/admin/assets/member-detail-DjwkGVne.js +0 -1
- package/core/built/admin/assets/members--N9lhk1N.js +0 -4
- package/core/built/admin/assets/modal-page-Dz-9TP4E.js +0 -1
- package/core/built/admin/assets/moderation-DfYBKq9s.js +0 -1
- package/core/built/admin/assets/multi-select-combobox-BcBEzUW_.js +0 -1
- package/core/built/admin/assets/navigation-modal-Cd-scywg.js +0 -1
- package/core/built/admin/assets/newsletter-detail-modal-CFRY6vg_.js +0 -1
- package/core/built/admin/assets/newsletter-emails-4ntck1AC.js +0 -1
- package/core/built/admin/assets/newsletter-o6eCJtab.js +0 -1
- package/core/built/admin/assets/newsletters-Bmlv0edG.js +0 -1
- package/core/built/admin/assets/note-CWs3LF-0.js +0 -1
- package/core/built/admin/assets/notifications-BjSvTJqh.js +0 -1
- package/core/built/admin/assets/offers-container-modal-Bc9A196w.js +0 -1
- package/core/built/admin/assets/onboarding-route-Di1LJYEE.js +0 -1
- package/core/built/admin/assets/overview-DE7NHZQN.js +0 -1
- package/core/built/admin/assets/overview-DEF-ZY6x.js +0 -1
- package/core/built/admin/assets/page-header-B-G_g42C.js +0 -1
- package/core/built/admin/assets/pagemenu-CnkTDO71.js +0 -1
- package/core/built/admin/assets/pages-route-VT7r7YhG.js +0 -1
- package/core/built/admin/assets/portal-frame-D9V8iq5x.js +0 -1
- package/core/built/admin/assets/portal-modal-B5OOR9ZD.js +0 -1
- package/core/built/admin/assets/post-analytics-header-J0WciLx6.js +0 -1
- package/core/built/admin/assets/post-analytics-rGb-PgD-.js +0 -1
- package/core/built/admin/assets/post-share-modal-D0BbTo4W.js +0 -1
- package/core/built/admin/assets/posts-list-screen-CO5jAWoU.js +0 -2
- package/core/built/admin/assets/posts-route-DV-CXWK9.js +0 -1
- package/core/built/admin/assets/preferences-Tac29oG6.js +0 -5
- package/core/built/admin/assets/preview-chrome-C2lQgZBZ.js +0 -1
- package/core/built/admin/assets/preview-modal-CjRbBr8U.js +0 -1
- package/core/built/admin/assets/profile-yiM1f_Og.js +0 -1
- package/core/built/admin/assets/radio-group-CKROWsw4.js +0 -1
- package/core/built/admin/assets/router-provider-CU87qxXw.js +0 -1
- package/core/built/admin/assets/select-CKaC4ggu.js +0 -1
- package/core/built/admin/assets/settings-81kxUa28.js +0 -1
- package/core/built/admin/assets/settings-BVXFqBVK.js +0 -4
- package/core/built/admin/assets/settings-breadcrumbs-czGRx-iu.js +0 -1
- package/core/built/admin/assets/shade-app-CcS3f8MZ-D5BnfHck.js +0 -3
- package/core/built/admin/assets/share-modal-BL-16PiB.js +0 -1
- package/core/built/admin/assets/skeleton-DwCva0-b.js +0 -1
- package/core/built/admin/assets/sort-button-Dquc83jY.js +0 -1
- package/core/built/admin/assets/stack-BURz77VS.js +0 -1
- package/core/built/admin/assets/stats-view-NDja_g96.js +0 -1
- package/core/built/admin/assets/stripe-button-C3cfCAou.js +0 -1
- package/core/built/admin/assets/stripe-connect-modal-FyE3Ey2c.js +0 -1
- package/core/built/admin/assets/switch-zfUUy9Jh.js +0 -1
- package/core/built/admin/assets/table-dE4GTIRT.js +0 -1
- package/core/built/admin/assets/tabs-B3XK93sR.js +0 -1
- package/core/built/admin/assets/tag-detail-D4P-tZdM.js +0 -2
- package/core/built/admin/assets/tag-picker-BNSZ6Qxw.js +0 -1
- package/core/built/admin/assets/tags-BsZcaJ6h.js +0 -1
- package/core/built/admin/assets/text-DC-ot6u2.js +0 -1
- package/core/built/admin/assets/textarea-B4FffFmE.js +0 -1
- package/core/built/admin/assets/tier-detail-modal-a77Z2VMH.js +0 -1
- package/core/built/admin/assets/toggle-group-D2p4okmJ.js +0 -1
- package/core/built/admin/assets/transistor-modal-C8RMkhOD.js +0 -1
- package/core/built/admin/assets/trend-badge-B9v7kMF8.js +0 -1
- package/core/built/admin/assets/types-uYQ1HgqL.js +0 -1
- package/core/built/admin/assets/use-analytics-data-ChHqiZXv.js +0 -1
- package/core/built/admin/assets/use-availability-hPdeG76y.js +0 -1
- package/core/built/admin/assets/use-filter-params-BSFigDIn.js +0 -1
- package/core/built/admin/assets/use-growth-stats-CqqdnESN.js +0 -1
- package/core/built/admin/assets/use-limiter-DBGjYqu7.js +0 -19
- package/core/built/admin/assets/use-reply-chain-data-DmD2yX5D.js +0 -1
- package/core/built/admin/assets/use-sending-eta-CQeG6OP_.js +0 -1
- package/core/built/admin/assets/use-setting-group-Dza6bQ7W.js +0 -1
- package/core/built/admin/assets/use-settings-navigation-BIjI5mL3.js +0 -1
- package/core/built/admin/assets/use-simple-pagination-DwVxe-Lo.js +0 -1
- package/core/built/admin/assets/use-staff-users-i_Mq9OGR.js +0 -1
- package/core/built/admin/assets/use-tinybird-query-DXoF74NM.js +0 -1
- package/core/built/admin/assets/user-detail-modal-BU4QCHE7.js +0 -1
- package/core/built/admin/assets/virtual-list-DScLNuU8.js +0 -1
- package/core/built/admin/assets/web-BZS-t4H0.js +0 -1
- package/core/built/admin/assets/web-DxAUxnK3.js +0 -2
- package/core/frontend/services/sitemap/utils.js +0 -17
- package/core/server/services/automations/get-scheduler-idempotency-key.js +0 -13
- package/core/server/web/api/testmode/index.js +0 -1
- package/core/server/web/api/testmode/jobs/cpu-hog.js +0 -15
- package/core/server/web/api/testmode/jobs/graceful-job.js +0 -50
- package/core/server/web/api/testmode/jobs/say-hello.js +0 -17
- package/core/server/web/api/testmode/routes.js +0 -120
|
@@ -81,8 +81,8 @@ module.exports = class MentionSendingService {
|
|
|
81
81
|
return;
|
|
82
82
|
}
|
|
83
83
|
// make sure we have something to parse before we create a job
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
const html = post.get('status') === 'published' ? post.get('html') : null;
|
|
85
|
+
const previousHtml = post.previous('status') === 'published' ? post.previous('html') : null;
|
|
86
86
|
if (html || previousHtml) {
|
|
87
87
|
// Capture the source URL now, from the event's data, rather than
|
|
88
88
|
// deferring the model into the job.
|
|
@@ -309,12 +309,11 @@ module.exports = class Mention {
|
|
|
309
309
|
timestamp = new Date();
|
|
310
310
|
}
|
|
311
311
|
|
|
312
|
-
|
|
313
|
-
payload = data.payload ? JSON.parse(JSON.stringify(data.payload)) : null;
|
|
312
|
+
const payload = data.payload ? JSON.parse(JSON.stringify(data.payload)) : null;
|
|
314
313
|
|
|
315
314
|
/** @type boolean */
|
|
316
|
-
|
|
317
|
-
verified = isNew ? false : !!data.verified;
|
|
315
|
+
|
|
316
|
+
const verified = isNew ? false : !!data.verified;
|
|
318
317
|
|
|
319
318
|
/** @type {ObjectID | null} */
|
|
320
319
|
let resourceId = null;
|
|
@@ -321,7 +321,10 @@ module.exports = class MentionsAPI {
|
|
|
321
321
|
* @returns {Promise<Mention>}
|
|
322
322
|
*/
|
|
323
323
|
async processWebmention(webmention) {
|
|
324
|
-
|
|
324
|
+
const mention = await this.#repository.getBySourceAndTarget(
|
|
325
|
+
webmention.source,
|
|
326
|
+
webmention.target,
|
|
327
|
+
);
|
|
325
328
|
|
|
326
329
|
return await this.#updateWebmention(mention, webmention);
|
|
327
330
|
}
|
|
@@ -20,33 +20,6 @@ const workerMessageHandler = ({ name, message }) => {
|
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
-
const initTestMode = () => {
|
|
24
|
-
// Output job queue length every 5 seconds
|
|
25
|
-
setInterval(() => {
|
|
26
|
-
logging.warn(
|
|
27
|
-
`${jobManager.inlineQueue.length()} jobs in the queue. Idle: ${jobManager.inlineQueue.idle()}`,
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
const runningScheduledjobs = Object.keys(jobManager.bree.workers);
|
|
31
|
-
if (Object.keys(jobManager.bree.workers).length) {
|
|
32
|
-
logging.warn(
|
|
33
|
-
`${Object.keys(jobManager.bree.workers).length} jobs running: ${runningScheduledjobs}`,
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const scheduledJobs = Object.keys(jobManager.bree.intervals);
|
|
38
|
-
if (Object.keys(jobManager.bree.intervals).length) {
|
|
39
|
-
logging.warn(
|
|
40
|
-
`${Object.keys(jobManager.bree.intervals).length} scheduled jobs: ${scheduledJobs}`,
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (runningScheduledjobs.length === 0 && scheduledJobs.length === 0) {
|
|
45
|
-
logging.warn('No scheduled or running jobs');
|
|
46
|
-
}
|
|
47
|
-
}, 5000);
|
|
48
|
-
};
|
|
49
|
-
|
|
50
23
|
const jobManager = new JobManager({
|
|
51
24
|
errorHandler,
|
|
52
25
|
workerMessageHandler,
|
|
@@ -56,4 +29,3 @@ const jobManager = new JobManager({
|
|
|
56
29
|
});
|
|
57
30
|
|
|
58
31
|
module.exports = jobManager;
|
|
59
|
-
module.exports.initTestMode = initTestMode;
|
|
@@ -300,7 +300,7 @@ module.exports = class MilestonesService {
|
|
|
300
300
|
const membersMilestones = this.#milestonesConfig.members;
|
|
301
301
|
|
|
302
302
|
// get the closest milestone we're over now
|
|
303
|
-
|
|
303
|
+
const achievedMilestones = this.#getMatchedMilestones(membersMilestones, membersCount);
|
|
304
304
|
|
|
305
305
|
// check for previously achieved milestones. We do not send an email when no
|
|
306
306
|
// previous milestones exist
|
|
@@ -37,7 +37,7 @@ class Notifications {
|
|
|
37
37
|
* @returns {Object[]} - all notifications
|
|
38
38
|
*/
|
|
39
39
|
fetchAllNotifications() {
|
|
40
|
-
|
|
40
|
+
const allNotifications = this.settingsCache.get('notifications');
|
|
41
41
|
|
|
42
42
|
// @TODO: this check can be removed to improve read operation perf. It's here only because
|
|
43
43
|
// reads are done often and this gives a possibility to self-heal any broken records.
|
|
@@ -67,7 +67,7 @@ class Notifications {
|
|
|
67
67
|
* @returns {boolean}
|
|
68
68
|
*/
|
|
69
69
|
areNotificationsValid(notifications) {
|
|
70
|
-
if (!
|
|
70
|
+
if (!Array.isArray(notifications)) {
|
|
71
71
|
return false;
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -151,7 +151,7 @@ class Notifications {
|
|
|
151
151
|
addedAt: moment().toDate(),
|
|
152
152
|
};
|
|
153
153
|
|
|
154
|
-
|
|
154
|
+
const notificationsToCheck = notifications;
|
|
155
155
|
let notificationsToAdd = [];
|
|
156
156
|
|
|
157
157
|
const allNotifications = this.fetchAllNotifications();
|
|
@@ -90,15 +90,15 @@ const findUrlWithProvider = (url) => {
|
|
|
90
90
|
|
|
91
91
|
// build up a list of URL variations to test against because the oembed
|
|
92
92
|
// providers list is not always up to date with scheme or www vs non-www
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
const baseUrl = url.replace(/^\/\/|^https?:\/\/(?:www\.)?/, '');
|
|
94
|
+
const testUrls = [
|
|
95
95
|
`https://${baseUrl}`,
|
|
96
96
|
`https://www.${baseUrl}`,
|
|
97
97
|
`http://${baseUrl}`,
|
|
98
98
|
`http://www.${baseUrl}`,
|
|
99
99
|
];
|
|
100
100
|
|
|
101
|
-
for (
|
|
101
|
+
for (const testUrl of testUrls) {
|
|
102
102
|
provider = hasProvider(testUrl);
|
|
103
103
|
if (provider) {
|
|
104
104
|
url = testUrl;
|
|
@@ -394,6 +394,80 @@ class OEmbedService {
|
|
|
394
394
|
};
|
|
395
395
|
}
|
|
396
396
|
|
|
397
|
+
/**
|
|
398
|
+
* Requests a URL through this.externalRequest and resolves with the response
|
|
399
|
+
* and at most the first chunk of its body, aborting the rest of the download.
|
|
400
|
+
*
|
|
401
|
+
* @param {string} url
|
|
402
|
+
* @returns {Promise<{response: import('got').Response, chunk?: Buffer}>}
|
|
403
|
+
*/
|
|
404
|
+
fetchFirstChunk(url) {
|
|
405
|
+
return new Promise((resolve, reject) => {
|
|
406
|
+
const stream = this.externalRequest.stream(url, {
|
|
407
|
+
headers: {
|
|
408
|
+
'user-agent': USER_AGENT,
|
|
409
|
+
range: 'bytes=0-0',
|
|
410
|
+
},
|
|
411
|
+
timeout: {
|
|
412
|
+
request: DEFAULT_REQUEST_TIMEOUT,
|
|
413
|
+
},
|
|
414
|
+
decompress: false,
|
|
415
|
+
throwHttpErrors: false,
|
|
416
|
+
});
|
|
417
|
+
let response;
|
|
418
|
+
|
|
419
|
+
stream.on('response', (res) => {
|
|
420
|
+
response = res;
|
|
421
|
+
});
|
|
422
|
+
stream.once('data', (chunk) => {
|
|
423
|
+
stream.destroy();
|
|
424
|
+
resolve({ response, chunk });
|
|
425
|
+
});
|
|
426
|
+
stream.once('end', () => resolve({ response }));
|
|
427
|
+
stream.on('error', reject);
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Checks that a favicon candidate is reachable and looks like an image.
|
|
433
|
+
*
|
|
434
|
+
* Replaces metascraper-logo-favicon's default resolver, which probes via
|
|
435
|
+
* reachable-url. reachable-url bundles got 11, which ignores the `dnsLookup`
|
|
436
|
+
* externalRequest installs to validate the resolved IP at connection time,
|
|
437
|
+
* leaving those probes open to DNS rebinding. Mirrors the default resolver's
|
|
438
|
+
* checks otherwise.
|
|
439
|
+
*
|
|
440
|
+
* @param {string} faviconUrl
|
|
441
|
+
* @param {Array<string|string[]>} [contentTypes] - allowed content types for the icon's extension
|
|
442
|
+
* @returns {Promise<{url: string} | undefined>}
|
|
443
|
+
*/
|
|
444
|
+
async resolveFaviconUrl(faviconUrl, contentTypes) {
|
|
445
|
+
let result;
|
|
446
|
+
try {
|
|
447
|
+
result = await this.fetchFirstChunk(faviconUrl);
|
|
448
|
+
} catch {
|
|
449
|
+
return undefined;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
const { response, chunk } = result;
|
|
453
|
+
if (!response || response.statusCode < 200 || response.statusCode >= 300) {
|
|
454
|
+
return undefined;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
if (contentTypes) {
|
|
458
|
+
const contentType = response.headers['content-type']?.split(';')[0].toLowerCase();
|
|
459
|
+
if (!contentType || !contentTypes.some((ct) => contentType.includes(ct))) {
|
|
460
|
+
return undefined;
|
|
461
|
+
}
|
|
462
|
+
// An empty body or one starting with '<' (60) is markup, not an image
|
|
463
|
+
if (!chunk?.length || chunk[0] === 60) {
|
|
464
|
+
return undefined;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return { url: response.url };
|
|
469
|
+
}
|
|
470
|
+
|
|
397
471
|
/**
|
|
398
472
|
* @param {string} url
|
|
399
473
|
* @param {string} html
|
|
@@ -477,6 +551,8 @@ class OEmbedService {
|
|
|
477
551
|
require('metascraper-logo-favicon')({
|
|
478
552
|
gotOpts,
|
|
479
553
|
pickFn,
|
|
554
|
+
resolveFaviconUrl: (faviconUrl, contentTypes) =>
|
|
555
|
+
this.resolveFaviconUrl(faviconUrl, contentTypes),
|
|
480
556
|
}),
|
|
481
557
|
require('metascraper-logo')(),
|
|
482
558
|
];
|
|
@@ -132,7 +132,6 @@ class CanThisResult {
|
|
|
132
132
|
const self = this;
|
|
133
133
|
let userPermissionLoad;
|
|
134
134
|
let apiKeyPermissionLoad;
|
|
135
|
-
let permissionsLoad;
|
|
136
135
|
|
|
137
136
|
// Get context.user, context.api_key and context.app
|
|
138
137
|
context = parseContext(context);
|
|
@@ -158,7 +157,7 @@ class CanThisResult {
|
|
|
158
157
|
}
|
|
159
158
|
|
|
160
159
|
// Wait for both user and api key permissions to load
|
|
161
|
-
permissionsLoad = Promise.all([userPermissionLoad, apiKeyPermissionLoad]).then(
|
|
160
|
+
const permissionsLoad = Promise.all([userPermissionLoad, apiKeyPermissionLoad]).then(
|
|
162
161
|
function (result) {
|
|
163
162
|
return {
|
|
164
163
|
user: result[0],
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const moment_1 = __importDefault(require("moment"));
|
|
7
7
|
const logging_1 = __importDefault(require("@tryghost/logging"));
|
|
8
8
|
const build_signed_job_1 = require("../../adapters/scheduling/build-signed-job");
|
|
9
|
+
const get_scheduler_idempotency_key_1 = require("../../adapters/scheduling/get-scheduler-idempotency-key");
|
|
9
10
|
// CJS-only modules — typed loosely below. models is the Bookshelf registry
|
|
10
11
|
// without TS declarations; the rest are JS modules without types.
|
|
11
12
|
const models = require('../../models');
|
|
@@ -111,14 +112,20 @@ class PostScheduling {
|
|
|
111
112
|
const resource = `${resourceType}s`;
|
|
112
113
|
const publishedAt = event === 'unscheduled' ? model.previous('published_at') : model.get('published_at');
|
|
113
114
|
const previousPublishedAt = model.previous('published_at');
|
|
115
|
+
const time = (0, moment_1.default)(publishedAt).valueOf();
|
|
114
116
|
return (0, build_signed_job_1.buildSignedJob)({
|
|
115
117
|
apiUrl: this.#apiUrl,
|
|
116
118
|
path: ['schedules', resource, `${model.get('id')}/`],
|
|
117
|
-
time
|
|
119
|
+
time,
|
|
118
120
|
key,
|
|
119
121
|
extra: {
|
|
120
122
|
oldTime: previousPublishedAt ? (0, moment_1.default)(previousPublishedAt).valueOf() : null,
|
|
121
123
|
},
|
|
124
|
+
// The key identifies one job: the URL already carries the resource
|
|
125
|
+
// and a token signed for this fire time under the current signing key,
|
|
126
|
+
// so re-registering the same job (e.g. a boot rebuild) yields the same
|
|
127
|
+
// key, while a reschedule or key rotation yields a new one.
|
|
128
|
+
getIdempotencyKey: (url) => (0, get_scheduler_idempotency_key_1.getSchedulerIdempotencyKey)({ namespace: 'post-scheduling', date: new Date(time), url }),
|
|
122
129
|
});
|
|
123
130
|
}
|
|
124
131
|
}
|
|
@@ -65,6 +65,13 @@ const publishNow = async (resourceType, id, force, options) => {
|
|
|
65
65
|
throw err;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
// The read above is filtered to scheduled resources, so a resource that an
|
|
69
|
+
// earlier delivery has already published normally surfaces as NotFound.
|
|
70
|
+
// Keep an explicit check so the outcome doesn't depend on that filter.
|
|
71
|
+
if (preScheduledResource.status !== 'scheduled') {
|
|
72
|
+
return NO_OP;
|
|
73
|
+
}
|
|
74
|
+
|
|
68
75
|
const publishedAtMoment = moment(preScheduledResource.published_at);
|
|
69
76
|
|
|
70
77
|
if (publishedAtMoment.diff(moment(), 'minutes') > publishAPostBySchedulerToleranceInMinutes) {
|
|
@@ -128,7 +128,7 @@ class SettingsBREADService {
|
|
|
128
128
|
* @returns
|
|
129
129
|
*/
|
|
130
130
|
browse(context) {
|
|
131
|
-
|
|
131
|
+
const settings = this.settingsCache.getAll();
|
|
132
132
|
|
|
133
133
|
return this._formatBrowse(settings, context);
|
|
134
134
|
}
|
|
@@ -199,7 +199,7 @@ class SettingsBREADService {
|
|
|
199
199
|
* @returns
|
|
200
200
|
*/
|
|
201
201
|
async edit(settings, options, stripeConnectData) {
|
|
202
|
-
|
|
202
|
+
const filteredSettings = settings.filter((setting) => {
|
|
203
203
|
// The `stripe_connect_integration_token` "setting" is only used to set the `stripe_connect_*` settings.
|
|
204
204
|
return (
|
|
205
205
|
![
|
|
@@ -488,7 +488,7 @@ class SettingsBREADService {
|
|
|
488
488
|
if (process.env.NODE_ENV !== 'production') {
|
|
489
489
|
logging.warn(message.text);
|
|
490
490
|
}
|
|
491
|
-
|
|
491
|
+
const msg = Object.assign(
|
|
492
492
|
{
|
|
493
493
|
from: fromEmail,
|
|
494
494
|
subject: 'Verify email address',
|
|
@@ -41,7 +41,7 @@ let SITE_UUID;
|
|
|
41
41
|
function getOrGenerateSiteUuid() {
|
|
42
42
|
if (!SITE_UUID) {
|
|
43
43
|
try {
|
|
44
|
-
|
|
44
|
+
const configuredSiteUuid = config.get('site_uuid');
|
|
45
45
|
if (configuredSiteUuid && validator.isUUID(configuredSiteUuid)) {
|
|
46
46
|
SITE_UUID = configuredSiteUuid.toLowerCase();
|
|
47
47
|
logging.info(`Setting site_uuid to configured value: ${SITE_UUID}`);
|
|
@@ -125,7 +125,7 @@ class SettingsHelpers {
|
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
getMembersSupportAddress() {
|
|
128
|
-
|
|
128
|
+
const supportAddress = this.settingsCache.get('members_support_address');
|
|
129
129
|
|
|
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)
|
|
@@ -44,7 +44,7 @@ class StaffServiceEmails {
|
|
|
44
44
|
attributionTitle = 'Homepage';
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
const staffUrl = this.urlUtils.urlJoin(
|
|
48
48
|
this.urlUtils.urlFor('admin', true),
|
|
49
49
|
'#',
|
|
50
50
|
`/settings/staff/${user.slug}/email-notifications`,
|
|
@@ -101,7 +101,7 @@ class StaffServiceEmails {
|
|
|
101
101
|
startedOn: this.getFormattedDate(subscription.startDate),
|
|
102
102
|
};
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
const offerData = this.getOfferData(offer);
|
|
105
105
|
|
|
106
106
|
if (!offerData && subscription?.trialEnd) {
|
|
107
107
|
const trialEnd = moment(subscription.trialEnd);
|
|
@@ -118,7 +118,7 @@ class StaffServiceEmails {
|
|
|
118
118
|
attributionTitle = 'Homepage';
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
const staffUrl = this.urlUtils.urlJoin(
|
|
122
122
|
this.urlUtils.urlFor('admin', true),
|
|
123
123
|
'#',
|
|
124
124
|
`/settings/staff/${user.slug}/email-notifications`,
|
|
@@ -180,7 +180,7 @@ class StaffServiceEmails {
|
|
|
180
180
|
cancellationReason: subscription.cancellationReason || '',
|
|
181
181
|
};
|
|
182
182
|
|
|
183
|
-
|
|
183
|
+
const staffUrl = this.urlUtils.urlJoin(
|
|
184
184
|
this.urlUtils.urlFor('admin', true),
|
|
185
185
|
'#',
|
|
186
186
|
`/settings/staff/${user.slug}/email-notifications`,
|
|
@@ -217,7 +217,7 @@ class StaffServiceEmails {
|
|
|
217
217
|
* @param {string} recipient.slug
|
|
218
218
|
*/
|
|
219
219
|
async getSharedData(recipient) {
|
|
220
|
-
|
|
220
|
+
const staffUrl = this.urlUtils.urlJoin(
|
|
221
221
|
this.urlUtils.urlFor('admin', true),
|
|
222
222
|
'#',
|
|
223
223
|
`/settings/staff/${recipient.slug}/email-notifications`,
|
|
@@ -273,7 +273,7 @@ class StaffServiceEmails {
|
|
|
273
273
|
for (const user of users) {
|
|
274
274
|
const to = user.email;
|
|
275
275
|
|
|
276
|
-
|
|
276
|
+
const staffUrl = this.urlUtils.urlJoin(
|
|
277
277
|
this.urlUtils.urlFor('admin', true),
|
|
278
278
|
'#',
|
|
279
279
|
`/settings/staff/${user.slug}/email-notifications`,
|
|
@@ -442,7 +442,7 @@ class StaffServiceEmails {
|
|
|
442
442
|
for (const user of users) {
|
|
443
443
|
const to = user.email;
|
|
444
444
|
|
|
445
|
-
|
|
445
|
+
const staffUrl = this.urlUtils.urlJoin(
|
|
446
446
|
this.urlUtils.urlFor('admin', true),
|
|
447
447
|
'#',
|
|
448
448
|
`/settings/staff/${user.slug}/email-notifications`,
|
|
@@ -485,7 +485,7 @@ class StaffServiceEmails {
|
|
|
485
485
|
|
|
486
486
|
/** @private */
|
|
487
487
|
getMemberData(member) {
|
|
488
|
-
|
|
488
|
+
const name = member?.name || member?.email;
|
|
489
489
|
return {
|
|
490
490
|
name,
|
|
491
491
|
email: member?.email,
|
|
@@ -607,7 +607,7 @@ class StaffServiceEmails {
|
|
|
607
607
|
this.logging.warn(message.text);
|
|
608
608
|
}
|
|
609
609
|
|
|
610
|
-
|
|
610
|
+
const msg = Object.assign(
|
|
611
611
|
{
|
|
612
612
|
from: this.fromEmailAddress,
|
|
613
613
|
forceTextContent: true,
|
|
@@ -355,7 +355,7 @@ class PostsStatsService {
|
|
|
355
355
|
.groupBy('source');
|
|
356
356
|
|
|
357
357
|
// Now join all the data
|
|
358
|
-
|
|
358
|
+
const query = this.knex
|
|
359
359
|
.with('free_referrers', freeReferrersCTE)
|
|
360
360
|
.with('paid_referrers', paidReferrersCTE)
|
|
361
361
|
.with('mrr_referrers', mrrReferrersCTE)
|
|
@@ -657,7 +657,7 @@ class PostsStatsService {
|
|
|
657
657
|
const { dateFrom, dateTo } = getDateBoundaries(options);
|
|
658
658
|
|
|
659
659
|
// Simpler approach mirroring _buildFreeMembersSubquery
|
|
660
|
-
|
|
660
|
+
const subquery = knex('members_created_events as mce')
|
|
661
661
|
.select('mce.referrer_source as source')
|
|
662
662
|
.countDistinct('mce.member_id as free_members')
|
|
663
663
|
.leftJoin('members_subscription_created_events as msce', function () {
|
|
@@ -686,7 +686,7 @@ class PostsStatsService {
|
|
|
686
686
|
_buildPaidReferrersSubquery(postId, options) {
|
|
687
687
|
const knex = this.knex;
|
|
688
688
|
const { dateFrom, dateTo } = getDateBoundaries(options);
|
|
689
|
-
|
|
689
|
+
const subquery = knex('members_subscription_created_events as msce')
|
|
690
690
|
.select('msce.referrer_source as source')
|
|
691
691
|
.countDistinct('msce.member_id as paid_members')
|
|
692
692
|
.where('msce.attribution_id', postId)
|
|
@@ -708,7 +708,7 @@ class PostsStatsService {
|
|
|
708
708
|
_buildMrrReferrersSubquery(postId, options) {
|
|
709
709
|
const knex = this.knex;
|
|
710
710
|
const { dateFrom, dateTo } = getDateBoundaries(options);
|
|
711
|
-
|
|
711
|
+
const subquery = knex('members_subscription_created_events as msce')
|
|
712
712
|
.select('msce.referrer_source as source')
|
|
713
713
|
.sum('mpse.mrr_delta as mrr')
|
|
714
714
|
.join('members_paid_subscription_events as mpse', function () {
|
|
@@ -744,7 +744,7 @@ class PostsStatsService {
|
|
|
744
744
|
const { dateFrom, dateTo } = getDateBoundaries(options);
|
|
745
745
|
|
|
746
746
|
// Parse order field and direction
|
|
747
|
-
|
|
747
|
+
const [orderField, orderDirection = 'desc'] = order.split(' ');
|
|
748
748
|
|
|
749
749
|
// Map frontend order fields to database fields (simplified for ORDER BY)
|
|
750
750
|
const orderFieldMap = {
|
|
@@ -834,7 +834,7 @@ class PostsStatsService {
|
|
|
834
834
|
const { dateFrom, dateTo } = getDateBoundaries(options);
|
|
835
835
|
|
|
836
836
|
// Parse order field and direction
|
|
837
|
-
|
|
837
|
+
const [orderField, orderDirection = 'desc'] = order.split(' ');
|
|
838
838
|
|
|
839
839
|
// Map frontend order fields to database fields (simplified for ORDER BY)
|
|
840
840
|
const orderFieldMap = {
|
|
@@ -1095,7 +1095,7 @@ class PostsStatsService {
|
|
|
1095
1095
|
const { dateFrom, dateTo } = getDateBoundaries(options);
|
|
1096
1096
|
|
|
1097
1097
|
// Build optimized deltas query - avoid expensive JOIN
|
|
1098
|
-
|
|
1098
|
+
const deltasQuery = this.knex('members_subscribe_events as mse')
|
|
1099
1099
|
.select(
|
|
1100
1100
|
this.knex.raw(`DATE(mse.created_at) as date`),
|
|
1101
1101
|
this.knex.raw(`SUM(CASE WHEN mse.subscribed = 1 THEN 1 ELSE -1 END) as value`),
|
|
@@ -1150,7 +1150,7 @@ class PostsStatsService {
|
|
|
1150
1150
|
// Build complete time series with all dates
|
|
1151
1151
|
const completeValues = [];
|
|
1152
1152
|
let lastValue = startingValue; // Use provided starting value
|
|
1153
|
-
|
|
1153
|
+
const currentDate = rangeStart.clone();
|
|
1154
1154
|
|
|
1155
1155
|
while (currentDate.isSameOrBefore(rangeEnd)) {
|
|
1156
1156
|
const dateKey = currentDate.format('YYYY-MM-DD');
|
|
@@ -1507,7 +1507,7 @@ class PostsStatsService {
|
|
|
1507
1507
|
try {
|
|
1508
1508
|
// Build free members query (modeled after _buildFreeMembersSubquery)
|
|
1509
1509
|
// Members who signed up on post but paid elsewhere/never
|
|
1510
|
-
|
|
1510
|
+
const freeMembersQuery = this.knex('members_created_events as mce')
|
|
1511
1511
|
.select('mce.attribution_id as post_id')
|
|
1512
1512
|
.countDistinct('mce.member_id as free_members')
|
|
1513
1513
|
.leftJoin('members_subscription_created_events as msce', function () {
|
|
@@ -1525,7 +1525,7 @@ class PostsStatsService {
|
|
|
1525
1525
|
|
|
1526
1526
|
// Build paid members query (modeled after _buildPaidMembersSubquery)
|
|
1527
1527
|
// Members whose paid conversion was attributed to this post
|
|
1528
|
-
|
|
1528
|
+
const paidMembersQuery = this.knex('members_subscription_created_events as msce')
|
|
1529
1529
|
.select('msce.attribution_id as post_id')
|
|
1530
1530
|
.countDistinct('msce.member_id as paid_members')
|
|
1531
1531
|
.whereIn('msce.attribution_type', ['post', 'page'])
|
|
@@ -226,7 +226,7 @@ class ReferrersStatsService {
|
|
|
226
226
|
const { dateFrom: startDateTime, dateTo: endDateTime } = getDateBoundaries(options);
|
|
227
227
|
|
|
228
228
|
// Join subscription created events with paid subscription events to get MRR changes
|
|
229
|
-
|
|
229
|
+
const query = knex('members_subscription_created_events as msce')
|
|
230
230
|
.join('members_paid_subscription_events as mpse', function () {
|
|
231
231
|
this.on('msce.member_id', '=', 'mpse.member_id').andOn(
|
|
232
232
|
'msce.subscription_id',
|
|
@@ -25,12 +25,12 @@ class SubscriptionStatsService {
|
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
/** @type {SubscriptionHistoryEntry[]} */
|
|
28
|
-
|
|
28
|
+
const subscriptionHistoryEntries = [];
|
|
29
29
|
|
|
30
30
|
/** @type {string[]} */
|
|
31
|
-
|
|
31
|
+
const cadences = [];
|
|
32
32
|
/** @type {string[]} */
|
|
33
|
-
|
|
33
|
+
const tiers = [];
|
|
34
34
|
|
|
35
35
|
for (let index = subscriptionDeltaEntries.length - 1; index >= 0; index -= 1) {
|
|
36
36
|
const entry = subscriptionDeltaEntries[index];
|
|
@@ -82,6 +82,8 @@ const create = ({ config, request, settingsCache, tinybirdService }) => {
|
|
|
82
82
|
}
|
|
83
83
|
});
|
|
84
84
|
|
|
85
|
+
searchParams.ghost_client = 'server';
|
|
86
|
+
|
|
85
87
|
// Convert searchParams to query string and append to URL
|
|
86
88
|
const queryString = new URLSearchParams(searchParams).toString();
|
|
87
89
|
const fullUrl = `${tinybirdUrl}?${queryString}`;
|
|
@@ -91,7 +93,12 @@ const create = ({ config, request, settingsCache, tinybirdService }) => {
|
|
|
91
93
|
Authorization: `Bearer ${token}`,
|
|
92
94
|
},
|
|
93
95
|
timeout: {
|
|
94
|
-
|
|
96
|
+
// Allow Tinybird's 30-second query deadline to finish before timing out locally.
|
|
97
|
+
request: 35000,
|
|
98
|
+
},
|
|
99
|
+
retry: {
|
|
100
|
+
// A failed request may still be executing; avoid duplicating expensive queries.
|
|
101
|
+
limit: 0,
|
|
95
102
|
},
|
|
96
103
|
};
|
|
97
104
|
|
|
@@ -367,7 +367,7 @@ module.exports = class StripeAPI {
|
|
|
367
367
|
let latestCustomer = customers[0];
|
|
368
368
|
let latestSubscriptionTime = 0;
|
|
369
369
|
|
|
370
|
-
for (
|
|
370
|
+
for (const customer of customers) {
|
|
371
371
|
// skip customers with no subscriptions
|
|
372
372
|
if (
|
|
373
373
|
!customer.subscriptions ||
|
|
@@ -378,7 +378,7 @@ module.exports = class StripeAPI {
|
|
|
378
378
|
}
|
|
379
379
|
|
|
380
380
|
// find the customer with the most recent subscription
|
|
381
|
-
for (
|
|
381
|
+
for (const subscription of customer.subscriptions.data) {
|
|
382
382
|
if (
|
|
383
383
|
subscription.current_period_end &&
|
|
384
384
|
subscription.current_period_end > latestSubscriptionTime
|
|
@@ -606,7 +606,7 @@ module.exports = class StripeAPI {
|
|
|
606
606
|
subscriptionData.trial_period_days = options.trialDays;
|
|
607
607
|
}
|
|
608
608
|
|
|
609
|
-
|
|
609
|
+
const stripeSessionOptions = {
|
|
610
610
|
payment_method_types: this.PAYMENT_METHOD_TYPES,
|
|
611
611
|
managed_payments: MANAGED_PAYMENTS_DISABLED,
|
|
612
612
|
success_url: options.successUrl || this._config.checkoutSessionSuccessUrl,
|
|
@@ -69,7 +69,7 @@ module.exports = class StripeMigrations {
|
|
|
69
69
|
logging.info(`Populating products and prices for existing stripe customers`);
|
|
70
70
|
const uniquePlans = _.uniq(subscriptions.map((d) => _.get(d, 'plan.id')));
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
const stripePrices = [];
|
|
73
73
|
for (const plan of uniquePlans) {
|
|
74
74
|
try {
|
|
75
75
|
const stripePrice = await this.api.getPrice(plan, {
|
|
@@ -356,9 +356,9 @@ module.exports = class StripeMigrations {
|
|
|
356
356
|
|
|
357
357
|
if (!monthlyPrice) {
|
|
358
358
|
logging.info('Could not any active Monthly price - creating a new one');
|
|
359
|
-
|
|
359
|
+
|
|
360
360
|
const stripeProductsPage = await this.models.StripeProduct.findPage({ ...options, limit: 1 });
|
|
361
|
-
defaultStripeProduct = stripeProductsPage.data[0];
|
|
361
|
+
const defaultStripeProduct = stripeProductsPage.data[0];
|
|
362
362
|
const price = await this.api.createPrice({
|
|
363
363
|
currency: 'usd',
|
|
364
364
|
amount: 5000,
|
|
@@ -445,9 +445,9 @@ module.exports = class StripeMigrations {
|
|
|
445
445
|
|
|
446
446
|
if (!yearlyPrice) {
|
|
447
447
|
logging.info('Could not any active yearly price - creating a new one');
|
|
448
|
-
|
|
448
|
+
|
|
449
449
|
const stripeProductsPage = await this.models.StripeProduct.findPage({ ...options, limit: 1 });
|
|
450
|
-
defaultStripeProduct = stripeProductsPage.data[0];
|
|
450
|
+
const defaultStripeProduct = stripeProductsPage.data[0];
|
|
451
451
|
const price = await this.api.createPrice({
|
|
452
452
|
currency: 'usd',
|
|
453
453
|
amount: 500,
|
|
@@ -621,7 +621,7 @@ module.exports = class StripeMigrations {
|
|
|
621
621
|
});
|
|
622
622
|
if (invalidSubscriptions.length > 0) {
|
|
623
623
|
logging.warn(`Deleting ${invalidSubscriptions.length} invalid subscription(s)`);
|
|
624
|
-
for (
|
|
624
|
+
for (const sub of invalidSubscriptions) {
|
|
625
625
|
logging.warn(`Deleting subscription - ${sub.id} - no price found`);
|
|
626
626
|
await sub.destroy(options);
|
|
627
627
|
}
|