ghost 6.57.1 → 6.58.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/LICENSE +22 -0
- package/bin/validate-adapters.js +1 -5
- 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.2.tgz +0 -0
- package/components/tryghost-adapter-base-sso-0.1.2.tgz +0 -0
- package/components/tryghost-admin-api-schema-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.0.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/core/boot.js +35 -3
- package/core/built/admin/assets/{about-BNojRaxf.js → about-B_BvSyLF.js} +1 -1
- package/core/built/admin/assets/{account-migration-DMS8JsM-.js → account-migration-oJUGxnzT.js} +1 -1
- package/core/built/admin/assets/activitypub/{account-migration-DHFbePl6.js → account-migration-BpDeIF3G.js} +8 -8
- package/core/built/admin/assets/activitypub/activitypub.js +4 -4
- package/core/built/admin/assets/activitypub/{avatar-CT4tS2_S.js → avatar-B0SpBPVL.js} +3 -3
- package/core/built/admin/assets/activitypub/{avatar-flipboard-ByYWKipo.js → avatar-flipboard-DKt1LGcE.js} +3 -3
- package/core/built/admin/assets/activitypub/{bluesky-sharing-srVnSHDz.js → bluesky-sharing-aPMtrS3L.js} +10 -10
- package/core/built/admin/assets/activitypub/{chunk-KS7C4IRE-D4HEcEwi.js → chunk-KS7C4IRE-CnTrsgmM.js} +26 -15
- package/core/built/admin/assets/activitypub/{content-formatters-C2sos5Ht.js → content-formatters-BORfuA9G.js} +318 -284
- package/core/built/admin/assets/activitypub/{copy-B1UBTOoZ.js → copy-D-YvNi2E.js} +2 -2
- package/core/built/admin/assets/activitypub/{dist-MPsb2WZ1.js → dist-Dqggkccr.js} +5 -5
- package/core/built/admin/assets/activitypub/{domain-DzcM9Dzo.js → domain-CPdiB27_.js} +10 -10
- package/core/built/admin/assets/activitypub/{edit-profile-CsQ_4xAk.js → edit-profile-BY2PawIe.js} +7 -7
- package/core/built/admin/assets/activitypub/{explore-CJe0DZBK.js → explore-Sp9bgAwq.js} +11 -11
- package/core/built/admin/assets/activitypub/{feed-CKV3qWON.js → feed-BjtF4ohL.js} +10 -10
- package/core/built/admin/assets/activitypub/{field-DckHfDJf.js → field-BDOYVTg6.js} +4 -4
- package/core/built/admin/assets/activitypub/{hash-Dlp8RM55.js → hash-DqXYHgzG.js} +2 -2
- package/core/built/admin/assets/activitypub/{inbox-CsPy4R0M.js → inbox-CZ7IOAMn.js} +2 -2
- package/core/built/admin/assets/activitypub/{inbox-DAsjzUUe.js → inbox-z1o2j1Tb.js} +11 -11
- package/core/built/admin/assets/activitypub/{label-DWyo9E5T.js → label-1jhN-qhD.js} +4 -4
- package/core/built/admin/assets/activitypub/layout-BRMezuty.js +1 -0
- package/core/built/admin/assets/activitypub/{moderation-B0Inc03M.js → moderation-CZudJi8N.js} +9 -9
- package/core/built/admin/assets/activitypub/{note-CSE54lER.js → note-nr_m_5yb.js} +8 -8
- package/core/built/admin/assets/activitypub/{notifications-RSwbKqdh.js → notifications-BdcyivbT.js} +10 -10
- package/core/built/admin/assets/activitypub/{onboarding-BFDkzeR2.js → onboarding-B4kwav9u.js} +2 -2
- package/core/built/admin/assets/activitypub/{onboarding-D6rcBdPe.js → onboarding-DZNElJYP.js} +3 -3
- package/core/built/admin/assets/activitypub/{preferences-CE231n2_.js → preferences-CNqy1x9C.js} +13 -13
- package/core/built/admin/assets/activitypub/{profile-aaQ1j1Eo.js → profile-DlY4rhbO.js} +15 -15
- package/core/built/admin/assets/activitypub/{reply-Cjb0Vs3m.js → reply-DASIN0Ec.js} +2 -2
- package/core/built/admin/assets/activitypub/{routes-Djb0mc9k.js → routes-CEHdEZzS.js} +31 -31
- package/core/built/admin/assets/activitypub/{separator-D8pROI5n.js → separator-B3k35sUV.js} +4 -4
- package/core/built/admin/assets/activitypub/{settings-DMc32IQl.js → settings-CrSV1cux.js} +6 -6
- package/core/built/admin/assets/activitypub/{site-DVIcsohX.js → site-CtBUCPBz.js} +6 -6
- package/core/built/admin/assets/activitypub/{step-1-9Yey9usF.js → step-1-D9jGWyAy.js} +7 -7
- package/core/built/admin/assets/activitypub/{step-2-DdYmKRXV.js → step-2-Jz_enuo9.js} +7 -7
- package/core/built/admin/assets/activitypub/{step-3-hdSkcjZU.js → step-3-KpUqpGWi.js} +12 -12
- package/core/built/admin/assets/activitypub/{tabs-CUqseYzQ.js → tabs-DvlsxTCI.js} +7 -7
- package/core/built/admin/assets/activitypub/{topic-filter-Coni6OXM.js → topic-filter-CIN1E2jg.js} +4 -4
- package/core/built/admin/assets/activitypub/{use-activity-pub-queries-MeHTPMQv.js → use-activity-pub-queries-CATFd6YV.js} +4 -4
- package/core/built/admin/assets/activitypub/{use-navigate-with-base-path-B046AM38.js → use-navigate-with-base-path-iCkcbMGk.js} +2 -2
- package/core/built/admin/assets/activitypub/{use-reply-chain-data-1AO-Xob6.js → use-reply-chain-data-DJ0vhA8V.js} +6 -6
- package/core/built/admin/assets/activitypub/{users-BLeiOTHc.js → users-sgJ6GNZX.js} +12 -11
- package/core/built/admin/assets/activitypub/{x-BRfRYd16.js → x-Cy2jUiYM.js} +2 -2
- package/core/built/admin/assets/add-integration-modal-BW23PDYs.js +1 -0
- package/core/built/admin/assets/add-newsletter-modal-M0ls8BKO.js +1 -0
- package/core/built/admin/assets/{add-recommendation-modal-D-3LOrdd.js → add-recommendation-modal-B0NeBMzl.js} +1 -1
- package/core/built/admin/assets/{analytics-DTIMRhWw.js → analytics-BC2oR8ay.js} +1 -1
- package/core/built/admin/assets/announcement-bar-modal-pXBqjQE_.js +1 -0
- package/core/built/admin/assets/{api-keys-_iCT4dxr.js → api-keys-BgKr003d.js} +1 -1
- package/core/built/admin/assets/{api-keys-Dx4NeNpK.js → api-keys-Df6uv1dT.js} +1 -1
- package/core/built/admin/assets/{audience-DkknNqhZ.js → audience-BY8od8If.js} +1 -1
- package/core/built/admin/assets/{automated-emails-PayPCT8L.js → automated-emails-28c2Lbb3.js} +1 -1
- package/core/built/admin/assets/{automations-DvSU7QhW.js → automations-DCs6Wady.js} +1 -1
- package/core/built/admin/assets/{automations-162q5HjL.js → automations-Dzp_QnON.js} +1 -1
- package/core/built/admin/assets/{bluesky-sharing-yZ9A_jL8.js → bluesky-sharing-D0P42Cws.js} +1 -1
- package/core/built/admin/assets/{breadcrumb-CjOH7LCU.js → breadcrumb-MTj_cKLb.js} +1 -1
- package/core/built/admin/assets/card-CiiE7QfM.js +1 -0
- package/core/built/admin/assets/{chart-helpers-DGxvWnBT.js → chart-helpers-DcO3k_vA.js} +1 -1
- package/core/built/admin/assets/{checkbox-BSUcnNq_.js → checkbox-LmClhqcS.js} +1 -1
- package/core/built/admin/assets/{chunk.424.4a27628efdade15c2dab.js → chunk.408.1a258af360eb8d905508.js} +40 -37
- package/core/built/admin/assets/{chunk.571.40f093ed6d883993714e.js → chunk.492.a9da46ca956b10116774.js} +1342 -1342
- package/core/built/admin/assets/{chunk.571.40f093ed6d883993714e.js.LICENSE.txt → chunk.492.a9da46ca956b10116774.js.LICENSE.txt} +1 -1
- package/core/built/admin/assets/chunk.524.4c693c3a00ac91df34fa.js +25 -0
- package/core/built/admin/assets/chunk.582.20b600e329e58d12d7c2.js +27 -0
- package/core/built/admin/assets/code-editor-view-DqTOUnbM.js +1 -0
- package/core/built/admin/assets/code-editor-view-bA0lfxUL.js +1 -0
- package/core/built/admin/assets/{debounce-Cx5B_9OI.js → color-picker-CBlJMv3y.js} +2 -2
- package/core/built/admin/assets/color-picker-field-Cv9GOJQZ.js +1 -0
- package/core/built/admin/assets/{combobox-5rdgDrDV.js → combobox-BbPJzjCp.js} +1 -1
- package/core/built/admin/assets/command-BrhXIlDr.js +1 -0
- package/core/built/admin/assets/comments-Cu4rD1aJ.js +1 -0
- package/core/built/admin/assets/confirmation-provider-BEdrnHns.js +1 -0
- package/core/built/admin/assets/{content-api-modal-BtW4Z1-1.js → content-api-modal-BOFWRUkC.js} +1 -1
- package/core/built/admin/assets/{copy-field-CEp_XieW.js → copy-field-8biQvNMD.js} +1 -1
- package/core/built/admin/assets/custom-field-type-option-CNhAgHbJ.js +1 -0
- package/core/built/admin/assets/custom-integration-modal-CrGOI8IB.js +1 -0
- package/core/built/admin/assets/{date-range-select-B3Ij1Rqg.js → date-range-select-Bsh4gIek.js} +1 -1
- package/core/built/admin/assets/debounce-pscB46sW.js +1 -0
- package/core/built/admin/assets/design-and-theme-modal-DWZguwWX.js +23 -0
- package/core/built/admin/assets/{dirty-confirm-dialog-YE9L21gY.js → dirty-confirm-dialog-DmdMpgyN.js} +1 -1
- package/core/built/admin/assets/{disabled-sources-indicator-uIzbWL7K.js → disabled-sources-indicator-BLnmyWgt.js} +1 -1
- package/core/built/admin/assets/dist-4m6pHdc0.js +23 -0
- package/core/built/admin/assets/{dist-DCk0UkGx.js → dist-B6bJuxL3.js} +1 -1
- package/core/built/admin/assets/{dist-CbHbGtQ-.js → dist-BtaTA7Ii.js} +1 -1
- package/core/built/admin/assets/{dist-Q1p9iXwH.js → dist-CZgIBXQN.js} +1 -1
- package/core/built/admin/assets/dist-CiHx7vA5.js +6 -0
- package/core/built/admin/assets/{dist-ARN6XTcR.js → dist-ECAUrdGc.js} +1 -1
- package/core/built/admin/assets/dist-Z97pCNqS.js +11 -0
- package/core/built/admin/assets/{dist-t6AXpf_4.js → dist-zwwGt8Yf.js} +1 -1
- package/core/built/admin/assets/{domain-DzrOAPY8.js → domain-Dp9TRrFp.js} +1 -1
- package/core/built/admin/assets/{dropzone-CzhP33wa.js → dropzone-B21Entqz.js} +1 -1
- package/core/built/admin/assets/{edit-profile-oufs4R4n.js → edit-profile-DG6lpMsr.js} +1 -1
- package/core/built/admin/assets/editor-CPQOrhrn.js +8 -0
- package/core/built/admin/assets/{editor-DtxX27Jz.css → editor-DLioOiRN.css} +1 -1
- package/core/built/admin/assets/{embed-signup-form-modal-Ch3s6lqA.js → embed-signup-form-modal-CgWniDha.js} +2 -2
- package/core/built/admin/assets/esm-CXo5SEPy.js +2 -0
- package/core/built/admin/assets/{explore-CA-R01Br.js → explore-C3rzONJv.js} +1 -1
- package/core/built/admin/assets/{feed-ClC8_Gld.js → feed-DpUwS1cU.js} +1 -1
- package/core/built/admin/assets/{field-B3OPenbP.js → field-BQqLTgHM.js} +1 -1
- package/core/built/admin/assets/{filter-sources-CiPLnG9A.js → filter-sources-FgqoUIL7.js} +1 -1
- package/core/built/admin/assets/{filters-yFvybRMe.js → filters-D0uIMD8n.js} +1 -1
- package/core/built/admin/assets/filters-DZJT29GW.js +1 -0
- package/core/built/admin/assets/{first-promoter-modal-BC0UpYCD.js → first-promoter-modal-DJhQQheG.js} +1 -1
- package/core/built/admin/assets/framework-provider-CFLwK5uS.js +4 -0
- package/core/built/admin/assets/{ghost-d38c30b866e59f2e06a357b5eb844fe5.css → ghost-68f447a1796b93a1f128b649bac8506d.css} +1 -1
- package/core/built/admin/assets/{ghost-d683fbeb945b13155ea669caa5d8db41.js → ghost-ba408063a5922b458b4a8f216cf23251.js} +124 -342
- package/core/built/admin/assets/{ghost-dark-1bffd5099ba7a749303133efacf8480b.css → ghost-dark-28ae4899c92022857f3584694bcb50ef.css} +1 -1
- package/core/built/admin/assets/{gift-link-modal-BKRuqo-k.js → gift-link-modal-sdFLjND9.js} +1 -1
- package/core/built/admin/assets/{gift-links-CVuqLhsZ.js → gift-links-D7BJ9qfe.js} +1 -1
- package/core/built/admin/assets/{global-data-provider-RzW6Bnlf.js → global-data-provider-CixmTX00.js} +1 -1
- package/core/built/admin/assets/{growth-ClNAldfL.js → growth-0YYkBEeS.js} +1 -1
- package/core/built/admin/assets/{growth-Dz8OSG06.js → growth-DpjAPeQT.js} +2 -2
- package/core/built/admin/assets/{history-modal-DIVuQ5Ct.js → history-modal-BWJ4-cJ0.js} +1 -1
- package/core/built/admin/assets/{hooks-D6EE7BIt.js → hooks-CJepWnbB.js} +1 -1
- package/core/built/admin/assets/{html-field-CVZ2sMxw.js → html-field-C-oa5DEl.js} +1 -1
- package/core/built/admin/assets/{iframe-buffering-e8vH4-Qn.js → iframe-buffering-Ba9sDpi2.js} +1 -1
- package/core/built/admin/assets/{images-Ok8FFJ3A.js → images-3cQgwfTD.js} +1 -1
- package/core/built/admin/assets/{inbox-CMUVI6qb.js → inbox-Dz_JblyJ.js} +6 -6
- package/core/built/admin/assets/index-BOJzlYiz.js +67 -0
- package/core/built/admin/assets/index-Bid6LAyc.css +1 -0
- package/core/built/admin/assets/{input-group-2XU-iuh_.js → input-group-DpogNUIt.js} +1 -1
- package/core/built/admin/assets/{integrations-BT6_iJvu.js → integrations-B9yYgci5.js} +1 -1
- package/core/built/admin/assets/{invite-user-modal-DrZ7xxrZ.js → invite-user-modal-DCiQSiuD.js} +1 -1
- package/core/built/admin/assets/{koenig-editor-base-BPj4S760.js → koenig-editor-base-BApy8Q7C.js} +1 -1
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +8328 -8294
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +84 -84
- package/core/built/admin/assets/{koenig-lexical-Cdjv-m3_.js → koenig-lexical-2KuqRwZI.js} +33 -33
- package/core/built/admin/assets/{kpi-card-J8Mj1sDX.js → kpi-card-Ck3tT2Wg.js} +1 -1
- package/core/built/admin/assets/{kpi-card-awos0BMH.js → kpi-card-DDIxptaS.js} +1 -1
- package/core/built/admin/assets/{kpi-helpers-SEhvH-8E.js → kpi-helpers-ssbuy-hD.js} +1 -1
- package/core/built/admin/assets/{kpi-tabs-R6BjsKhd.js → kpi-tabs-BqoIM6bI.js} +1 -1
- package/core/built/admin/assets/{label-BMC3dzLI.js → label-DodDsMzn.js} +1 -1
- package/core/built/admin/assets/label-picker-Cvvbmzb5.js +1 -0
- package/core/built/admin/assets/{labels-DAPjKPy2.js → labels-DqvSR6JF.js} +1 -1
- package/core/built/admin/assets/layout-DkkGyev2.js +1 -0
- package/core/built/admin/assets/limit-service-BhiEvqcP.js +20 -0
- package/core/built/admin/assets/{link-helpers-Bzkk68GD.js → link-helpers-kpbU8TWh.js} +1 -1
- package/core/built/admin/assets/luxon-D1RVjjpq.js +1 -0
- package/core/built/admin/assets/member-custom-fields-CvGcpaiW.js +1 -0
- package/core/built/admin/assets/member-detail-CMCMZ47_.js +1 -0
- package/core/built/admin/assets/members-sRl6fNfq.js +11 -0
- package/core/built/admin/assets/{moderation-mPjYHgZW.js → moderation-KhKwGqI1.js} +1 -1
- package/core/built/admin/assets/{multi-select-combobox-CsoyHAiX.js → multi-select-combobox-nhCff0_K.js} +1 -1
- package/core/built/admin/assets/{navigation-modal-D_c0badj.js → navigation-modal-MDJExWDJ.js} +1 -1
- package/core/built/admin/assets/newsletter-BIBHumfV.js +1 -0
- package/core/built/admin/assets/newsletter-detail-modal-CfjBMH3v.js +1 -0
- package/core/built/admin/assets/{newsletter-emails-B-OLfrvr.js → newsletter-emails-ClDL-7dA.js} +1 -1
- package/core/built/admin/assets/newsletters-CBe-IPzK.js +1 -0
- package/core/built/admin/assets/{newsletters-Du0lzskS.js → newsletters-ILsexy-5.js} +1 -1
- package/core/built/admin/assets/{note-CSVsUKBm.js → note-HnNUOt4d.js} +1 -1
- package/core/built/admin/assets/{notifications-DV9FRtDw.js → notifications-Cj5e-258.js} +1 -1
- package/core/built/admin/assets/nql-lang-CaWrLesS.js +19 -0
- package/core/built/admin/assets/{offers-Um6ab71O.js → offers-DMxebaoK.js} +1 -1
- package/core/built/admin/assets/offers-container-modal-BHwHtixC.js +1 -0
- package/core/built/admin/assets/{onboarding-route--jL5KLPD.js → onboarding-route-D_4jp7Nq.js} +1 -1
- package/core/built/admin/assets/overview-CezDdg-F.js +1 -0
- package/core/built/admin/assets/overview-D5mM51Lj.js +1 -0
- package/core/built/admin/assets/{page-header-DAvDYKO9.js → page-header-VLPJfj_d.js} +1 -1
- package/core/built/admin/assets/{pages-BVMnpI2O.js → pages-Gchxp5c7.js} +1 -1
- package/core/built/admin/assets/{pintura-modal-jiUCxX0Q.js → pintura-modal-BXXJ8Iaa.js} +1 -1
- package/core/built/admin/assets/{portal-frame-D4D4nEO6.js → portal-frame-BLCvF8f-.js} +1 -1
- package/core/built/admin/assets/portal-modal-DN80tAcy.js +1 -0
- package/core/built/admin/assets/{post-analytics-BhAtiFJp.js → post-analytics-Gv81eN_g.js} +1 -1
- package/core/built/admin/assets/post-analytics-header-_ydSY8qO.js +1 -0
- package/core/built/admin/assets/{post-analytics-provider-DGg0FUqs.js → post-analytics-provider-O2YjZMhN.js} +1 -1
- package/core/built/admin/assets/{post-share-modal-DtFAC132.js → post-share-modal-CzYak_a5.js} +1 -1
- package/core/built/admin/assets/{posts-CxG7v0-M.js → posts-DgcUi2rc.js} +1 -1
- package/core/built/admin/assets/preferences-gneLb6LV.js +5 -0
- package/core/built/admin/assets/{preview-modal-DctYx20m.js → preview-modal-Bkq-tgVm.js} +1 -1
- package/core/built/admin/assets/profile-CzXmCNTC.js +1 -0
- package/core/built/admin/assets/{radio-group-CI5_Kf_d.js → radio-group-Dsq5ZEbV.js} +1 -1
- package/core/built/admin/assets/{referrers-B9QDAfYm.js → referrers-C3a2K8qB.js} +1 -1
- package/core/built/admin/assets/{router-provider-DSQfprxH.js → router-provider-CkB_ArLF.js} +1 -1
- package/core/built/admin/assets/{select-CkXqNJDJ.js → select-xuZAuDyS.js} +1 -1
- package/core/built/admin/assets/{settings-ZCj-W56o.js → settings-Ct8pabhr.js} +1 -1
- package/core/built/admin/assets/settings-KSWWQanQ.js +4 -0
- package/core/built/admin/assets/{settings-breadcrumbs-DIq31FwA.js → settings-breadcrumbs-DbPGu-Tu.js} +1 -1
- package/core/built/admin/assets/{share-modal-BNj14g79.js → share-modal-CdiUx9WM.js} +1 -1
- package/core/built/admin/assets/{slack-modal-C6SpMQ-q.js → slack-modal-BP--Z3jE.js} +1 -1
- package/core/built/admin/assets/{sort-button-B-k54ow2.js → sort-button-CjfKdlsL.js} +1 -1
- package/core/built/admin/assets/{source-icon-Cej3sZM6.js → source-icon-DHj1h6Ts.js} +1 -1
- package/core/built/admin/assets/{stats-B2KW8E2y.js → stats-C615kulJ.js} +1 -1
- package/core/built/admin/assets/{stats-view-CVzU2-p5.js → stats-view-BSMRdYiN.js} +1 -1
- package/core/built/admin/assets/{step-1-Dbn1iIMU.js → step-1-pSdGYtIF.js} +1 -1
- package/core/built/admin/assets/{step-2-BahnSuN6.js → step-2-T9Uy4eBD.js} +1 -1
- package/core/built/admin/assets/{step-3-CW04e2ZJ.js → step-3-D4uXe_XG.js} +2 -2
- package/core/built/admin/assets/{stripe-button-BkBZqaGG.js → stripe-button-Bh4p6Wud.js} +1 -1
- package/core/built/admin/assets/stripe-connect-modal-C2vTvepi.js +1 -0
- package/core/built/admin/assets/{table-BtLcEi1M.js → table-DghJxZMH.js} +1 -1
- package/core/built/admin/assets/{tabs-BaWRfg8j.js → tabs-l9c7FjzI.js} +1 -1
- package/core/built/admin/assets/tag-detail-DBw_M2-p.js +2 -0
- package/core/built/admin/assets/{tags-BbygUvNB.js → tags-DoWsAG6l.js} +1 -1
- package/core/built/admin/assets/{tags-BwCgmr5v.js → tags-EmEvJN75.js} +1 -1
- package/core/built/admin/assets/{testimonials-modal--bdzppyh.js → testimonials-modal-BZKePE2T.js} +1 -1
- package/core/built/admin/assets/tier-detail-modal-D65pVWsN.js +1 -0
- package/core/built/admin/assets/{tiers-Da6kxHQP.js → tiers-8iTFjJWg.js} +1 -1
- package/core/built/admin/assets/{toggle-group-CVl-Xigr.js → toggle-group-uJnl42w3.js} +1 -1
- package/core/built/admin/assets/{topic-filter-BoRHRbL1.js → topic-filter-BM7hz0kW.js} +1 -1
- package/core/built/admin/assets/transistor-modal-VZOGN3od.js +1 -0
- package/core/built/admin/assets/{unsplash-modal-CixoRAO2.js → unsplash-modal-CKGfACxF.js} +1 -1
- package/core/built/admin/assets/{use-analytics-data-BiWvcf1u.js → use-analytics-data-IxJcSjc9.js} +1 -1
- package/core/built/admin/assets/use-check-theme-limit-error-CGp3CGT5.js +1 -0
- package/core/built/admin/assets/use-feature-flag-CSq2Lwzt.js +1 -0
- package/core/built/admin/assets/use-filter-params-0hcJJuEJ.js +1 -0
- package/core/built/admin/assets/{use-filterable-api-iMpDZBxD.js → use-filterable-api-CQBtVG-l.js} +1 -1
- package/core/built/admin/assets/{use-growth-stats-Dom8xVzo.js → use-growth-stats-1NW-8eEZ.js} +1 -1
- package/core/built/admin/assets/use-limiter-ffwpsZPp.js +2 -0
- package/core/built/admin/assets/{use-pintura-config-Bj4QmiVk.js → use-pintura-config-BjFChXV1.js} +1 -1
- package/core/built/admin/assets/{use-pintura-editor-DvrslmPE.js → use-pintura-editor-Cb41oJyL.js} +1 -1
- package/core/built/admin/assets/{use-post-referrers-pxIHTXFs.js → use-post-referrers-Dp1BnTAK.js} +1 -1
- package/core/built/admin/assets/{use-reply-chain-data-CmFe0N6F.js → use-reply-chain-data-C0ZUTkfk.js} +1 -1
- package/core/built/admin/assets/{use-setting-group-Cmp_sy-d.js → use-setting-group-Bx8M6FL2.js} +1 -1
- package/core/built/admin/assets/{use-settings-navigation-BmROPrls.js → use-settings-navigation-BOZcat_V.js} +1 -1
- package/core/built/admin/assets/{use-simple-pagination-D5rL3YwO.js → use-simple-pagination-DsEGSJhe.js} +1 -1
- package/core/built/admin/assets/{use-tinybird-query-DP2dMaq7.js → use-tinybird-query-Ci_DiPkX.js} +1 -1
- package/core/built/admin/assets/{use-tinybird-token-DrK_skPQ.js → use-tinybird-token-CsUwc722.js} +1 -1
- package/core/built/admin/assets/use-upgrade-route-B3_DUiuT.js +1 -0
- package/core/built/admin/assets/{use-url-input-ChrUZBFf.js → use-url-input-BEZJpVgN.js} +2 -2
- package/core/built/admin/assets/user-detail-modal-595z1N5r.js +1 -0
- package/core/built/admin/assets/{users-B6hIds6n.js → users-DmGMPfw7.js} +1 -1
- package/core/built/admin/assets/virtual-list-D5ugXyZY.js +1 -0
- package/core/built/admin/assets/{web-D71mjB2r.js → web-CAta3lRE.js} +1 -1
- package/core/built/admin/assets/web-Ds9_wWJK.js +2 -0
- package/core/built/admin/assets/zapier-modal-CcfDZY53.js +1 -0
- package/core/built/admin/index.html +12 -12
- package/core/frontend/apps/private-blogging/lib/middleware.js +5 -58
- package/core/frontend/helpers/ghost_head.js +52 -0
- package/core/frontend/meta/asset-url.js +20 -9
- package/core/frontend/public/cards.manifest.json +1 -0
- package/core/frontend/public/ghost-stats.min.js +1 -1
- package/core/frontend/services/assets-minification/card-assets.js +121 -46
- package/core/frontend/services/assets-minification/index.js +13 -4
- package/core/frontend/services/data/fetch-data.js +7 -14
- package/core/frontend/services/llms/service.js +27 -6
- package/core/frontend/services/proxy.js +1 -0
- package/core/frontend/services/routing/api-adapter.js +11 -5
- package/core/frontend/services/routing/collection-router.js +1 -2
- package/core/frontend/services/routing/controllers/entry/markdown.js +63 -5
- package/core/frontend/services/routing/controllers/entry.js +1 -1
- package/core/frontend/services/routing/controllers/previews.js +0 -3
- package/core/frontend/services/routing/events.js +2 -1
- package/core/frontend/services/routing/parent-router.js +0 -22
- package/core/frontend/services/routing/router-manager.js +2 -2
- package/core/frontend/services/routing/static-pages-router.js +0 -1
- package/core/frontend/services/sitemap/handler.js +3 -4
- package/core/frontend/services/sitemap/site-map-manager.js +1 -2
- package/core/frontend/services/theme-engine/i18n/i18n.js +0 -33
- package/core/frontend/web/middleware/llms-discovery.js +2 -2
- package/core/frontend/web/routers/serve-public-file.js +33 -3
- package/core/frontend/web/site.js +5 -4
- package/core/server/adapters/jobs/InMemoryJobsBackend.js +113 -0
- package/core/server/adapters/redirects/S3RedirectsStore.js +33 -13
- package/core/server/adapters/route-settings/S3RouteSettingsStore.js +33 -13
- package/core/server/adapters/scheduling/scheduling-default.js +6 -7
- package/core/server/adapters/storage/LocalStorageBase.js +1 -3
- package/core/server/api/endpoints/index.js +0 -4
- package/core/server/api/endpoints/member-custom-fields.js +15 -4
- package/core/server/api/endpoints/pages.js +3 -11
- package/core/server/api/endpoints/posts.js +3 -11
- package/core/server/api/endpoints/utils/api-filter-utils.js +15 -1
- package/core/server/api/endpoints/utils/serializers/input/settings.js +4 -0
- package/core/server/api/endpoints/utils/serializers/output/index.js +0 -4
- package/core/server/api/endpoints/utils/serializers/output/mappers/email-batches.js +1 -1
- package/core/server/api/endpoints/utils/serializers/output/mappers/snippets.js +0 -1
- package/core/server/api/endpoints/utils/serializers/output/member-custom-fields.js +1 -0
- package/core/server/data/exporter/table-lists.js +4 -1
- package/core/server/data/migrations/utils/schema.js +5 -3
- package/core/server/data/migrations/versions/6.57/2026-08-04-18-00-00-store-custom-field-values-as-leaf-rows.js +19 -7
- package/core/server/data/migrations/versions/6.58/2026-08-10-08-20-50-add-machine-payments-settings.js +41 -0
- package/core/server/data/migrations/versions/6.58/2026-08-10-08-21-00-add-machine-payment-events-table.js +18 -0
- package/core/server/data/migrations/versions/6.58/2026-08-10-15-24-09-reset-custom-field-definitions-for-underscored-keys.js +66 -0
- package/core/server/data/migrations/versions/6.58/2026-08-11-10-00-00-swap-custom-field-values-to-key-fk.js +65 -0
- package/core/server/data/migrations/versions/6.58/2026-08-11-10-34-25-remove-legacy-explore-integration.js +131 -0
- package/core/server/data/migrations/versions/6.58/2026-08-11-16-00-00-add-sort-order-to-members-custom-fields.js +13 -0
- package/core/server/data/migrations/versions/6.58/2026-08-11-21-22-48-rename-email-batches-provider-id.js +8 -0
- package/core/server/data/migrations/versions/6.58/2026-08-13-16-07-33-add-automation-runs-automation-id-created-at-index.js +28 -0
- package/core/server/data/schema/README.md +87 -0
- package/core/server/data/schema/commands.js +5 -2
- package/core/server/data/schema/default-settings/default-settings.json +27 -0
- package/core/server/data/schema/fixtures/fixtures.json +0 -21
- package/core/server/data/schema/schema.js +37 -9
- package/core/server/data/seeders/data-generator.js +3 -1
- package/core/server/data/seeders/importers/automation-action-edges-importer.js +38 -0
- package/core/server/data/seeders/importers/automation-action-revisions-importer.js +139 -0
- package/core/server/data/seeders/importers/automation-actions-importer.js +84 -0
- package/core/server/data/seeders/importers/automation-run-steps-importer.js +134 -0
- package/core/server/data/seeders/importers/automation-runs-importer.js +97 -0
- package/core/server/data/seeders/importers/automations-importer.js +78 -0
- package/core/server/data/seeders/importers/benefits-importer.js +1 -1
- package/core/server/data/seeders/importers/comment-reports-importer.js +5 -5
- package/core/server/data/seeders/importers/comments-importer.js +6 -6
- package/core/server/data/seeders/importers/email-batches-importer.js +9 -8
- package/core/server/data/seeders/importers/email-recipient-failures-importer.js +1 -1
- package/core/server/data/seeders/importers/email-recipients-importer.js +12 -12
- package/core/server/data/seeders/importers/emails-importer.js +7 -7
- package/core/server/data/seeders/importers/index.js +6 -0
- package/core/server/data/seeders/importers/labels-importer.js +4 -4
- package/core/server/data/seeders/importers/members-click-events-importer.js +4 -4
- package/core/server/data/seeders/importers/members-created-events-importer.js +5 -5
- package/core/server/data/seeders/importers/members-feedback-importer.js +7 -7
- package/core/server/data/seeders/importers/members-importer.js +5 -5
- package/core/server/data/seeders/importers/members-labels-importer.js +1 -1
- package/core/server/data/seeders/importers/members-login-events-importer.js +4 -4
- 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-products-importer.js +3 -3
- package/core/server/data/seeders/importers/members-status-events-importer.js +4 -4
- package/core/server/data/seeders/importers/members-stripe-customers-importer.js +3 -3
- package/core/server/data/seeders/importers/members-stripe-customers-subscriptions-importer.js +8 -8
- package/core/server/data/seeders/importers/members-subscribe-events-importer.js +3 -3
- package/core/server/data/seeders/importers/members-subscription-created-events-importer.js +4 -4
- package/core/server/data/seeders/importers/newsletters-importer.js +1 -1
- package/core/server/data/seeders/importers/offer-redemptions-importer.js +6 -6
- package/core/server/data/seeders/importers/offers-importer.js +4 -4
- package/core/server/data/seeders/importers/posts-authors-importer.js +1 -1
- package/core/server/data/seeders/importers/posts-importer.js +5 -5
- package/core/server/data/seeders/importers/posts-products-importer.js +1 -1
- package/core/server/data/seeders/importers/posts-tags-importer.js +1 -1
- package/core/server/data/seeders/importers/products-benefits-importer.js +1 -1
- package/core/server/data/seeders/importers/products-importer.js +1 -1
- package/core/server/data/seeders/importers/recommendation-click-events-importer.js +1 -1
- package/core/server/data/seeders/importers/recommendation-subscribe-events-importer.js +1 -1
- package/core/server/data/seeders/importers/recommendations-importer.js +1 -1
- package/core/server/data/seeders/importers/redirects-importer.js +1 -1
- package/core/server/data/seeders/importers/roles-users-importer.js +1 -1
- package/core/server/data/seeders/importers/stripe-prices-importer.js +1 -1
- package/core/server/data/seeders/importers/stripe-products-importer.js +1 -1
- package/core/server/data/seeders/importers/table-importer.js +92 -91
- package/core/server/data/seeders/importers/tags-importer.js +3 -3
- package/core/server/data/seeders/importers/users-importer.js +3 -3
- package/core/server/data/seeders/importers/web-mentions-importer.js +3 -3
- package/core/server/data/seeders/utils/database-date.js +14 -18
- package/core/server/data/seeders/utils/json-importer.js +1 -1
- package/core/server/data/seeders/utils/random.js +8 -7
- package/core/server/data/seeders/utils/topological-sort.js +5 -3
- package/core/server/data/tinybird/ARCHITECTURE.md +1 -2
- package/core/server/models/base/plugins/crud.js +0 -5
- package/core/server/models/index.js +2 -0
- package/core/server/models/machine-payment-event.js +18 -0
- package/core/server/models/member.js +24 -0
- package/core/server/models/settings.js +32 -3
- package/core/server/models/user.js +1 -1
- package/core/server/services/README.md +30 -0
- package/core/server/services/activitypub/activity-pub-service.js +2 -3
- package/core/server/services/adapter-manager/base-classes.js +3 -1
- package/core/server/services/auth/passwordreset.js +47 -51
- package/core/server/services/automations/database-automations-repository.js +19 -3
- package/core/server/services/automations/poll.js +2 -8
- package/core/server/services/comments/comments-service.js +4 -16
- package/core/server/services/comments/index.js +1 -3
- package/core/server/services/email-analytics/email-analytics-service-wrapper.js +68 -119
- package/core/server/services/email-analytics/email-analytics-service.js +73 -229
- package/core/server/services/email-analytics/event-processing-result.js +0 -10
- package/core/server/services/email-analytics/fetch-mailgun-events.js +25 -0
- package/core/server/services/email-analytics/index.js +35 -67
- package/core/server/services/email-analytics/lib/queries.js +88 -51
- package/core/server/services/email-analytics/newsletter-email-analytics-batch-processor.js +4 -1
- package/core/server/services/email-service/batch-sending-service.js +1 -1
- package/core/server/services/email-service/email-event-processor.js +12 -12
- package/core/server/services/email-service/events/email-bounced-event.js +8 -46
- package/core/server/services/email-service/events/email-delivered-event.js +8 -36
- package/core/server/services/email-service/events/email-opened-event.js +8 -36
- package/core/server/services/email-service/events/email-temporary-bounced-event.js +8 -46
- package/core/server/services/email-service/events/email-unsubscribed-event.js +8 -31
- package/core/server/services/email-service/events/spam-complaint-event.js +8 -31
- package/core/server/services/email-service/newsletter-email-event-storage.js +8 -7
- package/core/server/services/email-service/sending-service.js +1 -1
- package/core/server/services/email-suppression-list/mailgun-email-suppression-list.js +2 -2
- package/core/server/services/email-suppression-list/service.js +1 -3
- package/core/server/services/explore-ping/explore-ping-service.js +1 -6
- package/core/server/services/explore-ping/index.js +0 -2
- package/core/server/services/gifts/index.js +109 -3
- package/core/server/services/gifts/jobs/clean-gifts-job.js +1 -1
- package/core/server/services/gifts/jobs/send-gift-reminders-job.js +1 -1
- package/core/server/services/jobs-service/index.js +36 -0
- package/core/server/services/jobs-service/job.js +6 -0
- package/core/server/services/jobs-service/jobs-service.js +91 -0
- package/core/server/services/jobs-service/register-job-handlers.js +6 -0
- package/core/server/services/lib/mailgun-client.js +1 -1
- package/core/server/services/machine-payments/README.md +23 -0
- package/core/server/services/machine-payments/adapters/mpp-adapter.js +195 -0
- package/core/server/services/machine-payments/content-loader.js +89 -0
- package/core/server/services/machine-payments/eligibility.js +6 -0
- package/core/server/services/machine-payments/events/machine-payment-event-repository.js +58 -0
- package/core/server/services/machine-payments/events/machine-payment-event.js +46 -0
- package/core/server/services/machine-payments/index.js +87 -0
- package/core/server/services/machine-payments/pricing.js +54 -0
- package/core/server/services/machine-payments/service.js +275 -0
- package/core/server/services/machine-payments/stripe/deposit-address-store.js +157 -0
- package/core/server/services/machine-payments/stripe/payment-recorder.js +85 -0
- package/core/server/services/machine-payments/stripe/stripe-client-options.js +25 -0
- package/core/server/services/machine-payments/types.js +2 -0
- package/core/server/services/members/import-export/csv/parse.js +9 -1
- package/core/server/services/members/import-export/import/completion-email.js +61 -27
- package/core/server/services/members/import-export/import/email-template.js +28 -15
- package/core/server/services/members/import-export/import/importer.js +99 -51
- package/core/server/services/members/import-export/import/spool.js +1 -1
- package/core/server/services/members/import-export/index.js +24 -1
- package/core/server/services/members/members-api/services/member-bread-service.js +2 -2
- package/core/server/services/members/members-config-provider.js +12 -2
- package/core/server/services/members-custom-fields/actions.js +2 -1
- package/core/server/services/members-custom-fields/definitions-service.js +109 -27
- package/core/server/services/members-custom-fields/filter.js +199 -0
- package/core/server/services/members-custom-fields/key.js +37 -0
- package/core/server/services/members-custom-fields/queries.js +15 -0
- package/core/server/services/members-custom-fields/schema.js +1 -1
- package/core/server/services/members-custom-fields/values-service.js +18 -14
- package/core/server/services/members-events/last-seen-at-updater.js +1 -1
- package/core/server/services/oembed/oembed-service.js +8 -2
- package/core/server/services/permissions/can-this.js +4 -1
- package/core/server/services/posts/posts-service.js +18 -16
- package/core/server/services/public-config/config.js +1 -1
- package/core/server/services/route-settings/dynamic-routing-service.js +2 -0
- package/core/server/services/settings-helpers/settings-helpers.js +0 -1
- package/core/server/services/stats/posts-stats-service.js +0 -2
- package/core/server/services/stripe/stripe-api.js +2 -9
- package/core/server/web/api/endpoints/admin/middleware.js +0 -1
- package/core/server/web/api/endpoints/admin/routes.js +2 -3
- package/core/server/web/comments/routes.js +31 -8
- package/core/shared/config/defaults.json +17 -2
- package/core/shared/config/loader.js +11 -2
- package/core/shared/config/overrides.json +2 -0
- package/core/shared/config/secrets.js +71 -0
- package/core/shared/labs.js +4 -13
- package/core/shared/machine-payments.js +30 -0
- package/core/shared/private-site-access/index.js +68 -0
- package/package.json +48 -43
- package/pnpm-lock.yaml +1412 -1583
- package/pnpm-workspace.yaml +85 -48
- package/bin/validate-adapters.ts +0 -87
- package/components/tryghost-adapter-base-scheduling-0.2.1.tgz +0 -0
- package/components/tryghost-adapter-base-sso-0.1.1.tgz +0 -0
- package/components/tryghost-kg-card-factory-5.2.3.tgz +0 -0
- package/components/tryghost-kg-clean-basic-html-4.3.3.tgz +0 -0
- package/components/tryghost-kg-converters-1.2.4.tgz +0 -0
- package/components/tryghost-kg-default-cards-10.3.4.tgz +0 -0
- package/components/tryghost-kg-default-nodes-2.1.5.tgz +0 -0
- package/components/tryghost-kg-default-transforms-1.3.3.tgz +0 -0
- package/components/tryghost-kg-html-to-lexical-1.3.3.tgz +0 -0
- package/components/tryghost-kg-lexical-html-renderer-1.4.3.tgz +0 -0
- package/components/tryghost-kg-markdown-html-renderer-7.2.3.tgz +0 -0
- package/components/tryghost-kg-utils-1.1.3.tgz +0 -0
- package/content/themes/casper/assets/built/casper.js.map +0 -1
- package/content/themes/casper/assets/built/global.css.map +0 -1
- package/content/themes/casper/assets/built/screen.css.map +0 -1
- package/content/themes/source/assets/built/screen.css.map +0 -1
- package/content/themes/source/assets/built/source.js.map +0 -1
- package/core/built/admin/assets/activitypub/layout-DM_3pqsU.js +0 -1
- package/core/built/admin/assets/add-integration-modal-DU9ghGLS.js +0 -1
- package/core/built/admin/assets/add-newsletter-modal-DFxuQrYu.js +0 -1
- package/core/built/admin/assets/announcement-bar-modal-DGCcezB6.js +0 -1
- package/core/built/admin/assets/card-aUHX0hyR.js +0 -1
- package/core/built/admin/assets/chunk.524.dce1c51e0bc30fb2718e.js +0 -25
- package/core/built/admin/assets/chunk.582.3a430d5c6a744fd475b6.js +0 -27
- package/core/built/admin/assets/code-editor-view-BcyKABrG.js +0 -1
- package/core/built/admin/assets/color-picker-field-8NoSnhNI.js +0 -1
- package/core/built/admin/assets/command-BOYMbZa_.js +0 -1
- package/core/built/admin/assets/comments-BhNM5CYl.js +0 -1
- package/core/built/admin/assets/confirmation-modal-CYD7x3UQ.js +0 -1
- package/core/built/admin/assets/custom-integration-modal-bk3lNEuQ.js +0 -1
- package/core/built/admin/assets/design-and-theme-modal-B2xYKS1I.js +0 -23
- package/core/built/admin/assets/dist-Bg8bSvLA.js +0 -6
- package/core/built/admin/assets/dist-BnFdlebk.js +0 -11
- package/core/built/admin/assets/dist-CsvXCJSe.js +0 -23
- package/core/built/admin/assets/editor-BBKrunMK.js +0 -8
- package/core/built/admin/assets/filters-Bz0HsRie.js +0 -1
- package/core/built/admin/assets/framework-provider-CmtnPXIT.js +0 -4
- package/core/built/admin/assets/index-DUXM0NlS.js +0 -67
- package/core/built/admin/assets/index-Ds2iUoF6.css +0 -1
- package/core/built/admin/assets/label-picker-Bnlru5tO.js +0 -1
- package/core/built/admin/assets/layout-yR9rlvEw.js +0 -1
- package/core/built/admin/assets/limit-modal-COmLevuY.js +0 -1
- package/core/built/admin/assets/limit-service-9fwD33lU.js +0 -20
- package/core/built/admin/assets/member-custom-fields-BvFKEpxJ.js +0 -1
- package/core/built/admin/assets/member-detail-CWdPAe3p.js +0 -1
- package/core/built/admin/assets/members-Bnt0ih2R.js +0 -11
- package/core/built/admin/assets/newsletter-DR49NyGS.js +0 -1
- package/core/built/admin/assets/newsletter-detail-modal-B45pL1pb.js +0 -1
- package/core/built/admin/assets/newsletters-DGs5BaKH.js +0 -1
- package/core/built/admin/assets/nql-lang-B7faUf8D.js +0 -19
- package/core/built/admin/assets/offers-container-modal-B0hFS8nk.js +0 -1
- package/core/built/admin/assets/overview-B-ZPNqMo.js +0 -1
- package/core/built/admin/assets/overview-D96iwoJi.js +0 -1
- package/core/built/admin/assets/portal-modal-BLFdYeDH.js +0 -1
- package/core/built/admin/assets/post-analytics-header-DK27VjJm.js +0 -1
- package/core/built/admin/assets/preferences-CuWLISHa.js +0 -5
- package/core/built/admin/assets/profile-BsKYYtuL.js +0 -1
- package/core/built/admin/assets/settings-B4vM-rgV.js +0 -4
- package/core/built/admin/assets/stripe-connect-modal-CYDDrSJm.js +0 -1
- package/core/built/admin/assets/tag-detail-CmqiC32L.js +0 -1
- package/core/built/admin/assets/tier-detail-modal-BZmAsIy4.js +0 -1
- package/core/built/admin/assets/transistor-modal-CBPDqEGy.js +0 -1
- package/core/built/admin/assets/use-check-theme-limit-error-B14lZukR.js +0 -2
- package/core/built/admin/assets/use-feature-flag-BmJoc5WN.js +0 -1
- package/core/built/admin/assets/use-filter-params-ChoV72Hw.js +0 -1
- package/core/built/admin/assets/use-limiter-Dwg8ivgQ.js +0 -2
- package/core/built/admin/assets/user-detail-modal-XODpOqNC.js +0 -1
- package/core/built/admin/assets/virtual-list-Dnoafqbk.js +0 -1
- package/core/built/admin/assets/web-z71lA1Y3.js +0 -2
- package/core/built/admin/assets/zapier-modal-Bp507Um7.js +0 -1
- package/core/frontend/meta/og-type.ts +0 -13
- package/core/frontend/services/routing/api-adapter.ts +0 -157
- package/core/frontend/services/routing/config.ts +0 -59
- package/core/frontend/services/routing/controllers/entry/canonical-url.ts +0 -14
- package/core/frontend/services/routing/controllers/entry/gift-links.ts +0 -56
- package/core/frontend/services/routing/controllers/entry/markdown.ts +0 -72
- package/core/frontend/services/routing/controllers/entry.ts +0 -120
- package/core/frontend/services/routing/controllers/rss.ts +0 -66
- package/core/frontend/services/routing/permalink-adapter.ts +0 -10
- package/core/frontend/src/utils/privacy.ts +0 -66
- package/core/server/adapters/redirects/FileStore.ts +0 -113
- package/core/server/adapters/redirects/S3RedirectsStore.ts +0 -185
- package/core/server/adapters/route-settings/FileStore.ts +0 -144
- package/core/server/adapters/route-settings/S3RouteSettingsStore.ts +0 -199
- package/core/server/adapters/route-settings/utils.ts +0 -17
- package/core/server/adapters/scheduling/deps.d.ts +0 -1
- package/core/server/adapters/scheduling/error-capture.ts +0 -91
- package/core/server/adapters/scheduling/scheduling-default.ts +0 -248
- package/core/server/adapters/scheduling/utils.ts +0 -36
- package/core/server/adapters/sso/DefaultSSOAdapter.ts +0 -15
- package/core/server/adapters/storage/LocalFilesStorage.ts +0 -24
- package/core/server/adapters/storage/LocalImagesStorage.ts +0 -24
- package/core/server/adapters/storage/LocalMediaStorage.ts +0 -24
- package/core/server/adapters/storage/LocalStorageBase.ts +0 -342
- package/core/server/adapters/storage/S3Storage.ts +0 -506
- package/core/server/adapters/storage/utils.ts +0 -60
- package/core/server/api/endpoints/automation-action-links.ts +0 -46
- package/core/server/api/endpoints/explore.js +0 -18
- package/core/server/api/endpoints/gift-links.ts +0 -87
- package/core/server/api/endpoints/libraries.d.ts +0 -2
- package/core/server/api/endpoints/member-commenting.ts +0 -92
- package/core/server/api/endpoints/member-custom-fields.ts +0 -106
- package/core/server/api/endpoints/utils/api-filter-utils.ts +0 -22
- package/core/server/api/endpoints/utils/gift-link-access.ts +0 -82
- package/core/server/api/endpoints/utils/public-cache-keys.ts +0 -47
- package/core/server/api/endpoints/utils/serializers/input/member-commenting.ts +0 -29
- package/core/server/api/endpoints/utils/serializers/output/explore.js +0 -11
- package/core/server/api/endpoints/utils/serializers/output/gift-links.ts +0 -21
- package/core/server/api/endpoints/utils/serializers/output/member-commenting.ts +0 -8
- package/core/server/api/endpoints/utils/serializers/output/member-custom-fields.ts +0 -25
- package/core/server/api/endpoints/utils/serializers/output/members.d.ts +0 -20
- package/core/server/api/endpoints/utils/serializers/output/posts-csv-transform.ts +0 -46
- package/core/server/api/endpoints/utils/serializers/output/stream-csv-response.ts +0 -47
- package/core/server/api/endpoints/utils/validate-email-sender-fields.ts +0 -42
- package/core/server/data/importer/email-template.ts +0 -213
- package/core/server/data/seeders/utils/topological-sort.ts +0 -48
- package/core/server/lib/auto-filling-map.ts +0 -23
- package/core/server/lib/bootstrap-socket.ts +0 -114
- package/core/server/lib/case-keys.ts +0 -30
- package/core/server/lib/common/to-plain.ts +0 -25
- package/core/server/lib/db-date.ts +0 -8
- package/core/server/lib/get-inbox-links.ts +0 -276
- package/core/server/lib/post-revisions.ts +0 -152
- package/core/server/lib/soonest-timer.ts +0 -57
- package/core/server/models/base/plugins/bulk-filters.ts +0 -35
- package/core/server/models/role-utils.ts +0 -56
- package/core/server/services/activitypub/activity-pub-service.ts +0 -216
- package/core/server/services/adapter-manager/adapter-manager.ts +0 -253
- package/core/server/services/adapter-manager/adapter-paths.ts +0 -26
- package/core/server/services/adapter-manager/base-classes.ts +0 -22
- package/core/server/services/adapter-manager/index.ts +0 -16
- package/core/server/services/adapter-manager/types.ts +0 -45
- package/core/server/services/adapter-manager/utils.ts +0 -308
- package/core/server/services/auth/reset-authentication.ts +0 -72
- package/core/server/services/automations/automations-api.ts +0 -396
- package/core/server/services/automations/automations-repository.ts +0 -218
- package/core/server/services/automations/constants.ts +0 -4
- package/core/server/services/automations/database-automations-repository.ts +0 -1513
- package/core/server/services/automations/database-date.ts +0 -26
- package/core/server/services/automations/fake-wait-hours-multiplier.ts +0 -12
- package/core/server/services/automations/get-scheduler-idempotency-key.ts +0 -8
- package/core/server/services/automations/mailgun-message-id.ts +0 -27
- package/core/server/services/automations/poll.ts +0 -325
- package/core/server/services/automations/scheduler-poll-time.ts +0 -38
- package/core/server/services/automations/service.ts +0 -131
- package/core/server/services/automations/stale-lock-cutoff.ts +0 -5
- package/core/server/services/comments/email-templates/new-comment-reply.txt.ts +0 -25
- package/core/server/services/comments/email-templates/new-comment.txt.ts +0 -25
- package/core/server/services/comments/email-templates/report.txt.ts +0 -34
- package/core/server/services/custom-redirects/redirect-config-parser.ts +0 -148
- package/core/server/services/custom-redirects/redirects-service.ts +0 -181
- package/core/server/services/custom-redirects/utils.ts +0 -7
- package/core/server/services/donations/donation-bookshelf-repository.ts +0 -63
- package/core/server/services/donations/donation-payment-event.ts +0 -51
- package/core/server/services/email-address/email-address-parser.d.ts +0 -12
- package/core/server/services/email-address/email-address-service.ts +0 -241
- package/core/server/services/email-analytics/automation-email-analytics-batch-processor.ts +0 -130
- package/core/server/services/email-analytics/batch-event-processor.ts +0 -18
- package/core/server/services/email-analytics/email-analytics-provider-mailgun.js +0 -57
- package/core/server/services/email-analytics/event-processing-result.ts +0 -66
- package/core/server/services/email-analytics/events/start-automation-email-analytics-job-event.ts +0 -14
- package/core/server/services/email-analytics/events/start-email-analytics-job-event.ts +0 -15
- package/core/server/services/email-analytics/index.ts +0 -109
- package/core/server/services/email-analytics/jobs/email-analytics-job-scheduler.ts +0 -126
- package/core/server/services/email-analytics/lib/queries.ts +0 -341
- package/core/server/services/email-service/domain-warming-service.ts +0 -91
- package/core/server/services/explore/explore-service.js +0 -59
- package/core/server/services/explore/index.js +0 -18
- package/core/server/services/explore-ping/explore-ping-service.ts +0 -198
- package/core/server/services/explore-ping/index.ts +0 -42
- package/core/server/services/files/file-type-utils.ts +0 -56
- package/core/server/services/gift-links/actions.ts +0 -51
- package/core/server/services/gift-links/codec.ts +0 -16
- package/core/server/services/gift-links/index.ts +0 -20
- package/core/server/services/gift-links/models.ts +0 -22
- package/core/server/services/gift-links/schema.ts +0 -33
- package/core/server/services/gift-links/serializers.ts +0 -20
- package/core/server/services/gift-links/service.ts +0 -95
- package/core/server/services/gifts/constants.ts +0 -3
- package/core/server/services/gifts/email-templates/gift-purchase-confirmation.ts +0 -43
- package/core/server/services/gifts/email-templates/gift-reminder.ts +0 -50
- package/core/server/services/gifts/gift-bookshelf-repository.ts +0 -366
- package/core/server/services/gifts/gift-checkout-offer.ts +0 -127
- package/core/server/services/gifts/gift-codec.ts +0 -62
- package/core/server/services/gifts/gift-controller.ts +0 -51
- package/core/server/services/gifts/gift-email-renderer.ts +0 -97
- package/core/server/services/gifts/gift-email-service.ts +0 -158
- package/core/server/services/gifts/gift-reminder-scheduler.ts +0 -107
- package/core/server/services/gifts/gift-schema.ts +0 -39
- package/core/server/services/gifts/gift-service-wrapper.js +0 -142
- package/core/server/services/gifts/gift-service.ts +0 -1034
- package/core/server/services/gifts/gift.ts +0 -234
- package/core/server/services/identity-tokens/identity-token-service.ts +0 -36
- package/core/server/services/indexnow-ping/constants.ts +0 -32
- package/core/server/services/indexnow-ping/index.ts +0 -35
- package/core/server/services/indexnow-ping/indexnow-ping-service.ts +0 -311
- package/core/server/services/internal-keys/index.ts +0 -53
- package/core/server/services/lib/dynamic-redirect-manager.d.ts +0 -20
- package/core/server/services/lib/in-memory-repository.ts +0 -78
- package/core/server/services/lib/member-signup-contexts.ts +0 -22
- package/core/server/services/link-redirection/link-redirect.ts +0 -24
- package/core/server/services/member-welcome-emails/constants.ts +0 -35
- package/core/server/services/members/commenting/index.ts +0 -2
- package/core/server/services/members/commenting/member-commenting-codec.ts +0 -73
- package/core/server/services/members/commenting/member-commenting.ts +0 -69
- package/core/server/services/members/create-paid-member-shim.ts +0 -40
- package/core/server/services/members/import-export/config.ts +0 -34
- package/core/server/services/members/import-export/csv/formula.ts +0 -14
- package/core/server/services/members/import-export/csv/index.ts +0 -3
- package/core/server/services/members/import-export/csv/parse.ts +0 -69
- package/core/server/services/members/import-export/csv/serialize.ts +0 -18
- package/core/server/services/members/import-export/export/exporter.ts +0 -325
- package/core/server/services/members/import-export/import/completion-email.ts +0 -146
- package/core/server/services/members/import-export/import/importer.ts +0 -489
- package/core/server/services/members/import-export/import/reader.ts +0 -33
- package/core/server/services/members/import-export/import/row.ts +0 -56
- package/core/server/services/members/import-export/import/spool.ts +0 -38
- package/core/server/services/members/import-export/index.ts +0 -143
- package/core/server/services/members/index.d.ts +0 -32
- package/core/server/services/members-custom-fields/actions.ts +0 -62
- package/core/server/services/members-custom-fields/codec.ts +0 -13
- package/core/server/services/members-custom-fields/config.ts +0 -38
- package/core/server/services/members-custom-fields/definitions-service.ts +0 -413
- package/core/server/services/members-custom-fields/index.ts +0 -50
- package/core/server/services/members-custom-fields/models.ts +0 -15
- package/core/server/services/members-custom-fields/queries.ts +0 -13
- package/core/server/services/members-custom-fields/schema.ts +0 -71
- package/core/server/services/members-custom-fields/serializers.ts +0 -22
- package/core/server/services/members-custom-fields/storage.ts +0 -122
- package/core/server/services/members-custom-fields/values-service.ts +0 -269
- package/core/server/services/notifications/notification-email.ts +0 -66
- package/core/server/services/notifications/sanitize-email-html.ts +0 -35
- package/core/server/services/post-scheduling/index.ts +0 -13
- package/core/server/services/post-scheduling/post-scheduling.ts +0 -133
- package/core/server/services/recommendations/service/bookshelf-click-event-repository.ts +0 -49
- package/core/server/services/recommendations/service/bookshelf-recommendation-repository.ts +0 -117
- package/core/server/services/recommendations/service/bookshelf-repository.ts +0 -192
- package/core/server/services/recommendations/service/bookshelf-subscribe-event-repository.ts +0 -49
- package/core/server/services/recommendations/service/click-event.ts +0 -32
- package/core/server/services/recommendations/service/in-memory-recommendation-repository.ts +0 -20
- package/core/server/services/recommendations/service/incoming-recommendation-controller.ts +0 -51
- package/core/server/services/recommendations/service/incoming-recommendation-email-renderer.ts +0 -37
- package/core/server/services/recommendations/service/incoming-recommendation-service.ts +0 -159
- package/core/server/services/recommendations/service/index.ts +0 -15
- package/core/server/services/recommendations/service/libraries.d.ts +0 -2
- package/core/server/services/recommendations/service/recommendation-controller.ts +0 -257
- package/core/server/services/recommendations/service/recommendation-metadata-service.ts +0 -132
- package/core/server/services/recommendations/service/recommendation-repository.ts +0 -13
- package/core/server/services/recommendations/service/recommendation-service.ts +0 -285
- package/core/server/services/recommendations/service/recommendation.ts +0 -200
- package/core/server/services/recommendations/service/subscribe-event.ts +0 -32
- package/core/server/services/recommendations/service/unsafe-data.ts +0 -217
- package/core/server/services/recommendations/service/well-known-service.ts +0 -47
- package/core/server/services/remote-flags/index.ts +0 -101
- package/core/server/services/remote-flags/remote-flags-service.ts +0 -236
- package/core/server/services/remote-flags/resolve.ts +0 -108
- package/core/server/services/route-settings/route-settings-parser.ts +0 -455
- package/core/server/services/route-settings/validation-errors.ts +0 -271
- package/core/server/services/route-settings/yaml-parser.d.ts +0 -4
- package/core/server/services/slack-ping/constants.ts +0 -15
- package/core/server/services/slack-ping/index.ts +0 -35
- package/core/server/services/slack-ping/slack-ping-service.ts +0 -295
- package/core/server/services/staff/email-templates/donation.txt.ts +0 -26
- package/core/server/services/staff/email-templates/gift.txt.ts +0 -27
- package/core/server/services/staff/email-templates/new-free-signup.txt.ts +0 -15
- package/core/server/services/staff/email-templates/new-gift-subscription.txt.ts +0 -26
- package/core/server/services/staff/email-templates/new-milestone-received.txt.ts +0 -20
- package/core/server/services/staff/email-templates/new-paid-cancellation.txt.ts +0 -15
- package/core/server/services/staff/email-templates/new-paid-started.txt.ts +0 -15
- package/core/server/services/staff/email-templates/recommendation-received.txt.ts +0 -23
- package/core/server/services/staff/email-templates/types.ts +0 -13
- package/core/server/services/url/lazy-find-resource.ts +0 -104
- package/core/server/services/url/lazy-url-service.ts +0 -647
- package/core/server/services/url/permalink-matcher.ts +0 -119
- package/core/server/services/url/router-filter.ts +0 -80
- package/core/server/services/verification/verification-webhook-service.ts +0 -137
- package/core/shared/config/helpers.ts +0 -133
- package/core/shared/config/index.ts +0 -12
- package/core/shared/config/loader.ts +0 -87
- package/core/shared/config/utils.ts +0 -104
- package/core/shared/errify.ts +0 -31
- package/core/shared/events-ts/index.ts +0 -8
- package/core/shared/events-ts/post-deleted-event.ts +0 -15
- package/core/shared/events-ts/posts-bulk-add-tags-event.ts +0 -13
- package/core/shared/events-ts/posts-bulk-destroyed-event.ts +0 -13
- package/core/shared/events-ts/posts-bulk-featured-event.ts +0 -13
- package/core/shared/events-ts/posts-bulk-unfeatured-event.ts +0 -13
- package/core/shared/events-ts/posts-bulk-unpublished-event.ts +0 -13
- package/core/shared/events-ts/posts-bulk-unscheduled-event.ts +0 -13
- package/core/shared/labs-flag-overrides.ts +0 -35
- package/core/shared/one-at-a-time.ts +0 -47
- package/core/shared/url-utils.ts +0 -20
|
@@ -1,63 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
* @property {boolean} running
|
|
11
|
-
* @property {string} jobName Name of the job that is running
|
|
12
|
-
* @property {Date} [lastStarted] Date the last fetch started on
|
|
13
|
-
* @property {Date} [lastBegin] The begin time used during the last fetch
|
|
14
|
-
* @property {Date} [lastEventTimestamp]
|
|
15
|
-
* @property {boolean} [canceled] Set to quit the job early
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @typedef {FetchData & {schedule?: {begin: Date, end: Date}}} FetchDataScheduled
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* @typedef {'delivered' | 'opened' | 'failed' | 'unsubscribed' | 'complained'} EmailAnalyticsEvent
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Names of the jobs this service runs. Each pipeline needs its own set so their
|
|
28
|
-
* cursors don't overwrite each other in the jobs table.
|
|
29
|
-
*
|
|
30
|
-
* @typedef {object} JobNames
|
|
31
|
-
* @property {string} latestNonOpened
|
|
32
|
-
* @property {string} missing
|
|
33
|
-
* @property {string} latestOpened
|
|
34
|
-
* @property {string} scheduled
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Recipient table and timestamp columns used to seed a job's cursor the first
|
|
39
|
-
* time it runs, before there's any job data to resume from.
|
|
40
|
-
*
|
|
41
|
-
* @typedef {object} CursorSeed
|
|
42
|
-
* @prop {string} tableName
|
|
43
|
-
* @prop {Partial<Record<EmailAnalyticsEvent, string>>} eventColumns
|
|
44
|
-
*/
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* @typedef {object} EmailAnalyticsFetchResult
|
|
48
|
-
* @property {number} eventCount - The number of events fetched
|
|
49
|
-
* @property {number} apiPollingTimeMs - Time spent polling the API in milliseconds
|
|
50
|
-
* @property {number} processingTimeMs - Time spent processing events in milliseconds
|
|
51
|
-
* @property {number} aggregationTimeMs - Time spent aggregating stats in milliseconds
|
|
52
|
-
* @property {number} emailAggregationTimeMs - Time spent aggregating email stats in milliseconds
|
|
53
|
-
* @property {number} memberAggregationTimeMs - Time spent aggregating member stats in milliseconds
|
|
54
|
-
* @property {EventProcessingResult} result - The processing result with event breakdown
|
|
55
|
-
*/
|
|
56
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.EmailAnalyticsService = void 0;
|
|
7
|
+
const event_processing_result_1 = require("./event-processing-result");
|
|
8
|
+
const logging_1 = __importDefault(require("@tryghost/logging"));
|
|
9
|
+
const errors_1 = __importDefault(require("@tryghost/errors"));
|
|
57
10
|
const TRUST_THRESHOLD_MS = 30 * 60 * 1000; // 30 minutes
|
|
58
11
|
const FETCH_LATEST_END_MARGIN_MS = 1 * 60 * 1000; // Do not fetch events newer than 1 minute (yet). Reduces the chance of having missed events in fetchLatest.
|
|
59
|
-
const AGGREGATE_MEMBER_STATS_METRIC_NAME = 'email_analytics_aggregate_member_stats_count';
|
|
60
|
-
|
|
61
12
|
/**
|
|
62
13
|
* Helper function to create an empty fetch result
|
|
63
14
|
* @returns {EmailAnalyticsFetchResult}
|
|
@@ -70,55 +21,25 @@ function createEmptyResult() {
|
|
|
70
21
|
aggregationTimeMs: 0,
|
|
71
22
|
emailAggregationTimeMs: 0,
|
|
72
23
|
memberAggregationTimeMs: 0,
|
|
73
|
-
result: new EventProcessingResult()
|
|
24
|
+
result: new event_processing_result_1.EventProcessingResult()
|
|
74
25
|
};
|
|
75
26
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
provider;
|
|
27
|
+
class EmailAnalyticsService {
|
|
28
|
+
queries;
|
|
29
|
+
#fetchEvents;
|
|
80
30
|
#createEventProcessor;
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
/** @type {CursorSeed} */ #cursorSeed;
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* @type {FetchData}
|
|
87
|
-
*/
|
|
31
|
+
#jobNames;
|
|
32
|
+
#cursorSeed;
|
|
88
33
|
#fetchLatestNonOpenedData;
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* @type {FetchData}
|
|
92
|
-
*/
|
|
93
34
|
#fetchMissingData;
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* @type {FetchData}
|
|
97
|
-
*/
|
|
98
35
|
#fetchLatestOpenedData;
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* @type {FetchDataScheduled}
|
|
102
|
-
*/
|
|
103
36
|
#fetchScheduledData;
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* @param {object} dependencies
|
|
107
|
-
* @param {Queries} dependencies.queries
|
|
108
|
-
* @param {object} dependencies.provider
|
|
109
|
-
* @param {PrometheusClient} [dependencies.prometheusClient]
|
|
110
|
-
* @param {() => BatchEventProcessor} dependencies.createEventProcessor
|
|
111
|
-
* @param {JobNames} dependencies.jobNames
|
|
112
|
-
* @param {CursorSeed} dependencies.cursorSeed
|
|
113
|
-
*/
|
|
114
|
-
constructor({queries, provider, prometheusClient, createEventProcessor, jobNames, cursorSeed}) {
|
|
37
|
+
constructor({ queries, fetchEvents, createEventProcessor, jobNames, cursorSeed }) {
|
|
115
38
|
this.queries = queries;
|
|
116
|
-
this
|
|
117
|
-
this.prometheusClient = prometheusClient;
|
|
39
|
+
this.#fetchEvents = fetchEvents;
|
|
118
40
|
this.#createEventProcessor = createEventProcessor;
|
|
119
41
|
this.#jobNames = jobNames;
|
|
120
42
|
this.#cursorSeed = cursorSeed;
|
|
121
|
-
|
|
122
43
|
this.#fetchLatestNonOpenedData = {
|
|
123
44
|
running: false,
|
|
124
45
|
jobName: jobNames.latestNonOpened
|
|
@@ -135,12 +56,7 @@ module.exports = class EmailAnalyticsService {
|
|
|
135
56
|
running: false,
|
|
136
57
|
jobName: jobNames.scheduled
|
|
137
58
|
};
|
|
138
|
-
|
|
139
|
-
if (prometheusClient) {
|
|
140
|
-
prometheusClient.registerCounter({name: AGGREGATE_MEMBER_STATS_METRIC_NAME, help: 'Count of member stats aggregations'});
|
|
141
|
-
}
|
|
142
59
|
}
|
|
143
|
-
|
|
144
60
|
#clearScheduledData() {
|
|
145
61
|
this.#fetchScheduledData = {
|
|
146
62
|
running: false,
|
|
@@ -148,7 +64,6 @@ module.exports = class EmailAnalyticsService {
|
|
|
148
64
|
};
|
|
149
65
|
this.queries.setJobMetadata(this.#jobNames.scheduled, null);
|
|
150
66
|
}
|
|
151
|
-
|
|
152
67
|
getStatus() {
|
|
153
68
|
return {
|
|
154
69
|
latest: this.#fetchLatestNonOpenedData,
|
|
@@ -157,106 +72,77 @@ module.exports = class EmailAnalyticsService {
|
|
|
157
72
|
latestOpened: this.#fetchLatestOpenedData
|
|
158
73
|
};
|
|
159
74
|
}
|
|
160
|
-
|
|
161
75
|
/**
|
|
162
76
|
* Returns the timestamp of the last non-opened event we processed. Defaults to now minus 30 minutes if we have no data yet.
|
|
163
77
|
*/
|
|
164
78
|
async getLastNonOpenedEventTimestamp() {
|
|
165
79
|
return this.#fetchLatestNonOpenedData?.lastEventTimestamp ?? (await this.queries.getLastEventTimestamp(this.#fetchLatestNonOpenedData.jobName, ['delivered', 'failed'], this.#cursorSeed)) ?? new Date(Date.now() - TRUST_THRESHOLD_MS);
|
|
166
80
|
}
|
|
167
|
-
|
|
168
81
|
/**
|
|
169
82
|
* Returns the timestamp of the last opened event we processed. Defaults to now minus 30 minutes if we have no data yet.
|
|
170
83
|
*/
|
|
171
84
|
async getLastOpenedEventTimestamp() {
|
|
172
85
|
return this.#fetchLatestOpenedData?.lastEventTimestamp ?? (await this.queries.getLastEventTimestamp(this.#fetchLatestOpenedData.jobName, ['opened'], this.#cursorSeed)) ?? new Date(Date.now() - TRUST_THRESHOLD_MS);
|
|
173
86
|
}
|
|
174
|
-
|
|
175
87
|
/**
|
|
176
88
|
* Returns the timestamp of the last missing event we processed. Defaults to now minus 2h if we have no data yet.
|
|
177
89
|
*/
|
|
178
90
|
async getLastMissingEventTimestamp() {
|
|
179
91
|
return this.#fetchMissingData?.lastEventTimestamp ?? (await this.queries.getLastJobRunTimestamp(this.#fetchMissingData.jobName)) ?? new Date(Date.now() - TRUST_THRESHOLD_MS * 4);
|
|
180
92
|
}
|
|
181
|
-
|
|
182
93
|
/**
|
|
183
94
|
* Fetches the latest opened events.
|
|
184
|
-
* @param {Object} options - The options for fetching events.
|
|
185
|
-
* @param {number} [options.maxEvents=Infinity] - The maximum number of events to fetch.
|
|
186
|
-
* @returns {Promise<EmailAnalyticsFetchResult>} Fetch results with timing metrics
|
|
187
95
|
*/
|
|
188
|
-
async fetchLatestOpenedEvents({maxEvents = Infinity} = {}) {
|
|
96
|
+
async fetchLatestOpenedEvents({ maxEvents = Infinity } = {}) {
|
|
189
97
|
const begin = await this.getLastOpenedEventTimestamp();
|
|
190
98
|
const end = new Date(Date.now() - FETCH_LATEST_END_MARGIN_MS); // Always stop at x minutes ago to give Mailgun a bit more time to stabilize storage
|
|
191
|
-
|
|
192
99
|
if (end <= begin) {
|
|
193
100
|
// Skip for now
|
|
194
|
-
|
|
101
|
+
logging_1.default.info('[EmailAnalytics] Skipping fetchLatestOpenedEvents because end (' + end + ') is before begin (' + begin + ')');
|
|
195
102
|
return createEmptyResult();
|
|
196
103
|
}
|
|
197
|
-
|
|
198
|
-
return await this.#fetchEvents(this.#fetchLatestOpenedData, {begin, end, maxEvents, eventTypes: ['opened']});
|
|
104
|
+
return await this.#fetchEventsForJob(this.#fetchLatestOpenedData, { begin, end, maxEvents, eventTypes: ['opened'] });
|
|
199
105
|
}
|
|
200
|
-
|
|
201
106
|
/**
|
|
202
107
|
* Fetches the latest non-opened events.
|
|
203
|
-
* @param {Object} options - The options for fetching events.
|
|
204
|
-
* @param {number} [options.maxEvents=Infinity] - The maximum number of events to fetch.
|
|
205
|
-
* @returns {Promise<EmailAnalyticsFetchResult>} Fetch results with timing metrics
|
|
206
108
|
*/
|
|
207
|
-
async fetchLatestNonOpenedEvents({maxEvents = Infinity} = {}) {
|
|
109
|
+
async fetchLatestNonOpenedEvents({ maxEvents = Infinity } = {}) {
|
|
208
110
|
const begin = await this.getLastNonOpenedEventTimestamp();
|
|
209
111
|
const end = new Date(Date.now() - FETCH_LATEST_END_MARGIN_MS); // Always stop at x minutes ago to give Mailgun a bit more time to stabilize storage
|
|
210
|
-
|
|
211
112
|
if (end <= begin) {
|
|
212
113
|
// Skip for now
|
|
213
|
-
|
|
114
|
+
logging_1.default.info('[EmailAnalytics] Skipping fetchLatestNonOpenedEvents because end (' + end + ') is before begin (' + begin + ')');
|
|
214
115
|
return createEmptyResult();
|
|
215
116
|
}
|
|
216
|
-
|
|
217
|
-
return await this.#fetchEvents(this.#fetchLatestNonOpenedData, {begin, end, maxEvents, eventTypes: ['delivered', 'failed', 'unsubscribed', 'complained']});
|
|
117
|
+
return await this.#fetchEventsForJob(this.#fetchLatestNonOpenedData, { begin, end, maxEvents, eventTypes: ['delivered', 'failed', 'unsubscribed', 'complained'] });
|
|
218
118
|
}
|
|
219
|
-
|
|
220
119
|
/**
|
|
221
120
|
* Fetches events that are older than 30 minutes, because then the 'storage' of the Mailgun API is stable. And we are sure we don't miss any events.
|
|
222
|
-
* @param
|
|
223
|
-
* @param {number} [options.maxEvents] Not a strict maximum. We stop fetching after we reached the maximum AND received at least one event after begin (not equal) to prevent deadlocks.
|
|
224
|
-
* @returns {Promise<EmailAnalyticsFetchResult>} Fetch results with timing metrics
|
|
121
|
+
* @param [options.maxEvents] Not a strict maximum. We stop fetching after we reached the maximum AND received at least one event after begin (not equal) to prevent deadlocks.
|
|
225
122
|
*/
|
|
226
|
-
async fetchMissing({maxEvents = Infinity} = {}) {
|
|
123
|
+
async fetchMissing({ maxEvents = Infinity } = {}) {
|
|
227
124
|
const begin = await this.getLastMissingEventTimestamp();
|
|
228
|
-
|
|
229
125
|
// Always stop at the earlier of the time the fetchLatest started fetching on or 30 minutes ago
|
|
230
|
-
const end = new Date(
|
|
231
|
-
|
|
232
|
-
Date.now() - TRUST_THRESHOLD_MS,
|
|
233
|
-
this.#fetchLatestNonOpenedData?.lastBegin?.getTime() || Date.now() // Fallback to now if the previous job didn't run, for whatever reason, prevents catastrophic error
|
|
234
|
-
)
|
|
235
|
-
);
|
|
236
|
-
|
|
126
|
+
const end = new Date(Math.min(Date.now() - TRUST_THRESHOLD_MS, this.#fetchLatestNonOpenedData?.lastBegin?.getTime() || Date.now() // Fallback to now if the previous job didn't run, for whatever reason, prevents catastrophic error
|
|
127
|
+
));
|
|
237
128
|
if (end <= begin) {
|
|
238
129
|
// Skip for now
|
|
239
|
-
|
|
130
|
+
logging_1.default.info('[EmailAnalytics] Skipping fetchMissing because end (' + end + ') is before begin (' + begin + ')');
|
|
240
131
|
return createEmptyResult();
|
|
241
132
|
}
|
|
242
|
-
|
|
243
|
-
return await this.#fetchEvents(this.#fetchMissingData, {begin, end, maxEvents});
|
|
133
|
+
return await this.#fetchEventsForJob(this.#fetchMissingData, { begin, end, maxEvents });
|
|
244
134
|
}
|
|
245
|
-
|
|
246
135
|
/**
|
|
247
136
|
* Schedule a new fetch for email analytics events.
|
|
248
|
-
* @param {Object} options - The options for scheduling the fetch.
|
|
249
|
-
* @param {Date} options.begin - The start date for the scheduled fetch.
|
|
250
|
-
* @param {Date} options.end - The end date for the scheduled fetch.
|
|
251
137
|
* @throws {errors.ValidationError} Throws an error if a fetch is already in progress.
|
|
252
138
|
*/
|
|
253
|
-
async schedule({begin, end}) {
|
|
139
|
+
async schedule({ begin, end }) {
|
|
254
140
|
if (this.#fetchScheduledData && this.#fetchScheduledData.running) {
|
|
255
|
-
throw new
|
|
141
|
+
throw new errors_1.default.ValidationError({
|
|
256
142
|
message: 'Already fetching scheduled events. Wait for it to finish before scheduling a new one.'
|
|
257
143
|
});
|
|
258
144
|
}
|
|
259
|
-
|
|
145
|
+
logging_1.default.info('[EmailAnalytics] Scheduling fetch from ' + begin.toISOString() + ' until ' + end.toISOString());
|
|
260
146
|
this.#fetchScheduledData = {
|
|
261
147
|
running: false,
|
|
262
148
|
jobName: this.#jobNames.scheduled,
|
|
@@ -270,12 +156,10 @@ module.exports = class EmailAnalyticsService {
|
|
|
270
156
|
end: end.toISOString()
|
|
271
157
|
});
|
|
272
158
|
}
|
|
273
|
-
|
|
274
159
|
/**
|
|
275
160
|
* Cancels the scheduled fetch of email analytics events.
|
|
276
161
|
* If a fetch is currently running, it marks it for cancellation.
|
|
277
162
|
* If no fetch is running, it clears the scheduled fetch data.
|
|
278
|
-
* @method cancelScheduled
|
|
279
163
|
*/
|
|
280
164
|
cancelScheduled() {
|
|
281
165
|
if (this.#fetchScheduledData) {
|
|
@@ -283,12 +167,12 @@ module.exports = class EmailAnalyticsService {
|
|
|
283
167
|
this.#fetchScheduledData.canceled = true;
|
|
284
168
|
// Clear metadata eagerly; fetchScheduled() will clear in-memory state next cycle
|
|
285
169
|
this.queries.setJobMetadata(this.#jobNames.scheduled, null);
|
|
286
|
-
}
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
287
172
|
this.#clearScheduledData();
|
|
288
173
|
}
|
|
289
174
|
}
|
|
290
175
|
}
|
|
291
|
-
|
|
292
176
|
/**
|
|
293
177
|
* Restores a previously persisted scheduled fetch from the database.
|
|
294
178
|
* Must only be called once on startup (caller guards against repeated calls).
|
|
@@ -296,119 +180,91 @@ module.exports = class EmailAnalyticsService {
|
|
|
296
180
|
async restoreScheduled() {
|
|
297
181
|
try {
|
|
298
182
|
const jobData = await this.queries.getJobData(this.#jobNames.scheduled);
|
|
299
|
-
if (!jobData
|
|
183
|
+
if (!jobData) {
|
|
300
184
|
return;
|
|
301
185
|
}
|
|
302
|
-
|
|
303
|
-
const metadata = JSON.parse(jobData.metadata);
|
|
186
|
+
const { metadata } = jobData;
|
|
304
187
|
if (metadata.begin && metadata.end) {
|
|
305
188
|
const begin = new Date(metadata.begin);
|
|
306
189
|
const end = new Date(metadata.end);
|
|
307
|
-
|
|
308
190
|
this.#fetchScheduledData = {
|
|
309
191
|
running: false,
|
|
310
192
|
jobName: this.#jobNames.scheduled,
|
|
311
|
-
schedule: {begin, end}
|
|
193
|
+
schedule: { begin, end }
|
|
312
194
|
};
|
|
313
|
-
|
|
314
195
|
// Use finished_at as the resume cursor if available
|
|
315
196
|
if (jobData.finished_at) {
|
|
316
197
|
this.#fetchScheduledData.lastEventTimestamp = new Date(jobData.finished_at);
|
|
317
198
|
}
|
|
318
|
-
|
|
319
|
-
logging.info('[EmailAnalytics] Restored scheduled fetch: ' + begin.toISOString() + ' to ' + end.toISOString());
|
|
199
|
+
logging_1.default.info('[EmailAnalytics] Restored scheduled fetch: ' + begin.toISOString() + ' to ' + end.toISOString());
|
|
320
200
|
}
|
|
321
|
-
}
|
|
322
|
-
|
|
201
|
+
}
|
|
202
|
+
catch (e) {
|
|
203
|
+
logging_1.default.error('[EmailAnalytics] Failed to restore scheduled fetch', e);
|
|
323
204
|
}
|
|
324
205
|
}
|
|
325
|
-
|
|
326
206
|
/**
|
|
327
207
|
* Continues fetching the scheduled events (does not start one). Resets the scheduled event when received 0 events.
|
|
328
|
-
* @method fetchScheduled
|
|
329
|
-
* @param {Object} [options] - The options for fetching scheduled events.
|
|
330
|
-
* @param {number} [options.maxEvents=Infinity] - The maximum number of events to fetch.
|
|
331
|
-
* @returns {Promise<EmailAnalyticsFetchResult>} Fetch results with timing metrics
|
|
332
208
|
*/
|
|
333
|
-
async fetchScheduled({maxEvents = Infinity} = {}) {
|
|
209
|
+
async fetchScheduled({ maxEvents = Infinity } = {}) {
|
|
334
210
|
if (!this.#fetchScheduledData || !this.#fetchScheduledData.schedule) {
|
|
335
211
|
// Nothing scheduled
|
|
336
212
|
return createEmptyResult();
|
|
337
213
|
}
|
|
338
|
-
|
|
339
214
|
if (this.#fetchScheduledData.canceled) {
|
|
340
215
|
this.#clearScheduledData();
|
|
341
216
|
return createEmptyResult();
|
|
342
217
|
}
|
|
343
|
-
|
|
344
218
|
let begin = this.#fetchScheduledData.schedule.begin;
|
|
345
219
|
const end = this.#fetchScheduledData.schedule.end;
|
|
346
|
-
|
|
347
220
|
if (this.#fetchScheduledData.lastEventTimestamp && this.#fetchScheduledData.lastEventTimestamp > begin) {
|
|
348
221
|
// Continue where we left of
|
|
349
222
|
begin = this.#fetchScheduledData.lastEventTimestamp;
|
|
350
223
|
}
|
|
351
|
-
|
|
352
224
|
if (end <= begin) {
|
|
353
|
-
|
|
225
|
+
logging_1.default.info('[EmailAnalytics] Ending fetchScheduled because end is before begin');
|
|
354
226
|
this.#clearScheduledData();
|
|
355
227
|
return createEmptyResult();
|
|
356
228
|
}
|
|
357
|
-
|
|
358
|
-
const fetchResult = await this.#fetchEvents(this.#fetchScheduledData, {begin, end, maxEvents});
|
|
229
|
+
const fetchResult = await this.#fetchEventsForJob(this.#fetchScheduledData, { begin, end, maxEvents });
|
|
359
230
|
if (fetchResult.eventCount === 0 || this.#fetchScheduledData.canceled) {
|
|
360
231
|
this.#clearScheduledData();
|
|
361
232
|
}
|
|
362
|
-
|
|
363
233
|
this.queries.setJobTimestamp(this.#fetchScheduledData.jobName, 'finished', this.#fetchScheduledData.lastEventTimestamp);
|
|
364
234
|
return fetchResult;
|
|
365
235
|
}
|
|
366
236
|
/**
|
|
367
237
|
* Start fetching analytics and store the data of the progress inside fetchData
|
|
368
|
-
* @param
|
|
369
|
-
* @param
|
|
370
|
-
* @param {Date} options.begin - Start date for fetching events
|
|
371
|
-
* @param {Date} options.end - End date for fetching events
|
|
372
|
-
* @param {number} [options.maxEvents=Infinity] - Maximum number of events to fetch. Not a strict maximum. We stop fetching after we reached the maximum AND received at least one event after begin (not equal) to prevent deadlocks.
|
|
373
|
-
* @param {EmailAnalyticsEvent[]} [options.eventTypes] - Array of event types to fetch. If not provided, Mailgun will return all event types.
|
|
374
|
-
* @returns {Promise<EmailAnalyticsFetchResult>} Fetch results with timing metrics
|
|
238
|
+
* @param [options.maxEvents=Infinity] - Maximum number of events to fetch. Not a strict maximum. We stop fetching after we reached the maximum AND received at least one event after begin (not equal) to prevent deadlocks.
|
|
239
|
+
* @param [options.eventTypes] - Array of event types to fetch. If not provided, Mailgun will return all event types.
|
|
375
240
|
*/
|
|
376
|
-
async #
|
|
241
|
+
async #fetchEventsForJob(fetchData, { begin, end, maxEvents = Infinity, eventTypes }) {
|
|
377
242
|
// Start where we left of, or the last stored event in the database, or start 30 minutes ago if we have nothing available
|
|
378
243
|
// Store that we started fetching
|
|
379
244
|
fetchData.running = true;
|
|
380
245
|
fetchData.lastStarted = new Date();
|
|
381
246
|
fetchData.lastBegin = begin;
|
|
382
247
|
await this.queries.setJobTimestamp(fetchData.jobName, 'started', begin);
|
|
383
|
-
|
|
384
248
|
// Timing metrics
|
|
385
249
|
const fetchStartMs = Date.now();
|
|
386
250
|
let processingTimeMs = 0;
|
|
387
251
|
let aggregationTimeMs = 0;
|
|
388
252
|
let emailAggregationTimeMs = 0;
|
|
389
253
|
let memberAggregationTimeMs = 0;
|
|
390
|
-
|
|
391
254
|
let eventCount = 0;
|
|
392
255
|
const includeOpenedEvents = eventTypes?.includes('opened') ?? false;
|
|
393
|
-
|
|
394
256
|
const eventProcessor = this.#createEventProcessor();
|
|
395
|
-
|
|
396
257
|
// We keep the processing result here, so we also have a result in case of failures
|
|
397
|
-
|
|
258
|
+
const processingResult = new event_processing_result_1.EventProcessingResult();
|
|
398
259
|
// Track cumulative event counts separately since processingResult gets reset during intermediate aggregations
|
|
399
|
-
const cumulativeResult = new EventProcessingResult();
|
|
260
|
+
const cumulativeResult = new event_processing_result_1.EventProcessingResult();
|
|
400
261
|
let error = null;
|
|
401
|
-
|
|
402
|
-
/**
|
|
403
|
-
* @param {boolean} isFinal
|
|
404
|
-
* @returns {Promise<void>}
|
|
405
|
-
*/
|
|
406
262
|
const aggregate = async (isFinal) => {
|
|
407
263
|
if (!eventProcessor.aggregate) {
|
|
408
264
|
return;
|
|
409
265
|
}
|
|
410
266
|
const start = Date.now();
|
|
411
|
-
const timings = await eventProcessor.aggregate({includeOpenedEvents, processingResult, isFinal});
|
|
267
|
+
const timings = await eventProcessor.aggregate({ includeOpenedEvents, processingResult, isFinal });
|
|
412
268
|
if (!timings) {
|
|
413
269
|
return;
|
|
414
270
|
}
|
|
@@ -416,12 +272,6 @@ module.exports = class EmailAnalyticsService {
|
|
|
416
272
|
emailAggregationTimeMs += timings.emailAggregationTimeMs;
|
|
417
273
|
memberAggregationTimeMs += timings.memberAggregationTimeMs;
|
|
418
274
|
};
|
|
419
|
-
|
|
420
|
-
/**
|
|
421
|
-
* Process a batch of events
|
|
422
|
-
* @param {Array<Object>} events - Array of event objects to process
|
|
423
|
-
* @returns {Promise<void>}
|
|
424
|
-
*/
|
|
425
275
|
const processBatch = async (events) => {
|
|
426
276
|
// Even if the fetching is interrupted because of an error, we still store the last event timestamp
|
|
427
277
|
const processingStart = Date.now();
|
|
@@ -438,13 +288,11 @@ module.exports = class EmailAnalyticsService {
|
|
|
438
288
|
};
|
|
439
289
|
const beforeEmailIds = new Set(processingResult.emailIds);
|
|
440
290
|
const beforeMemberIds = new Set(processingResult.memberIds);
|
|
441
|
-
|
|
442
291
|
await eventProcessor.processBatch(events, processingResult, fetchData);
|
|
443
292
|
processingTimeMs += (Date.now() - processingStart);
|
|
444
293
|
eventCount += events.length;
|
|
445
|
-
|
|
446
294
|
// Calculate delta (only new counts from this batch) and accumulate for final reporting
|
|
447
|
-
const batchDelta = new EventProcessingResult({
|
|
295
|
+
const batchDelta = new event_processing_result_1.EventProcessingResult({
|
|
448
296
|
opened: processingResult.opened - beforeCounts.opened,
|
|
449
297
|
delivered: processingResult.delivered - beforeCounts.delivered,
|
|
450
298
|
temporaryFailed: processingResult.temporaryFailed - beforeCounts.temporaryFailed,
|
|
@@ -457,48 +305,46 @@ module.exports = class EmailAnalyticsService {
|
|
|
457
305
|
memberIds: processingResult.memberIds.filter(id => !beforeMemberIds.has(id))
|
|
458
306
|
});
|
|
459
307
|
cumulativeResult.merge(batchDelta);
|
|
460
|
-
|
|
461
308
|
// Offer the event processor a chance to aggregate mid-fetch.
|
|
462
309
|
try {
|
|
463
310
|
if (eventCount) {
|
|
464
311
|
await aggregate(false);
|
|
465
312
|
}
|
|
466
|
-
} catch (err) {
|
|
467
|
-
logging.error('[EmailAnalytics] Error while aggregating stats');
|
|
468
|
-
logging.error(err);
|
|
469
313
|
}
|
|
470
|
-
|
|
314
|
+
catch (err) {
|
|
315
|
+
logging_1.default.error('[EmailAnalytics] Error while aggregating stats');
|
|
316
|
+
logging_1.default.error(err);
|
|
317
|
+
}
|
|
471
318
|
if (fetchData.canceled) {
|
|
472
|
-
throw new
|
|
319
|
+
throw new errors_1.default.InternalServerError({
|
|
473
320
|
message: 'Fetching canceled'
|
|
474
321
|
});
|
|
475
322
|
}
|
|
476
323
|
};
|
|
477
|
-
|
|
478
324
|
try {
|
|
479
|
-
await this
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
325
|
+
await this.#fetchEvents({ batchHandler: processBatch, begin, end, maxEvents, events: eventTypes });
|
|
326
|
+
}
|
|
327
|
+
catch (err) {
|
|
328
|
+
if (!(err instanceof Error) || err.message !== 'Fetching canceled') {
|
|
329
|
+
logging_1.default.error('[EmailAnalytics] Error while fetching');
|
|
330
|
+
logging_1.default.error(err);
|
|
484
331
|
error = err;
|
|
485
|
-
}
|
|
486
|
-
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
logging_1.default.error('[EmailAnalytics] Canceled fetching');
|
|
487
335
|
}
|
|
488
336
|
}
|
|
489
|
-
|
|
490
337
|
// Final aggregation.
|
|
491
338
|
try {
|
|
492
339
|
await aggregate(true);
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
340
|
+
}
|
|
341
|
+
catch (err) {
|
|
342
|
+
logging_1.default.error('[EmailAnalytics] Error while aggregating stats');
|
|
343
|
+
logging_1.default.error(err);
|
|
497
344
|
if (!error) {
|
|
498
345
|
error = err;
|
|
499
346
|
}
|
|
500
347
|
}
|
|
501
|
-
|
|
502
348
|
// When we've consumed all available events (eventCount < maxEvents), advance the cursor by 1 second
|
|
503
349
|
// to avoid re-fetching the same batch on the next cycle. When we hit the maxEvents budget mid-second,
|
|
504
350
|
// do NOT advance — the next pass needs to re-cover that second to pick up any remaining events.
|
|
@@ -509,21 +355,18 @@ module.exports = class EmailAnalyticsService {
|
|
|
509
355
|
// Consumed everything in the window — advance to avoid re-fetching same batch
|
|
510
356
|
fetchData.lastEventTimestamp = new Date(fetchData.lastEventTimestamp.getTime() + 1000);
|
|
511
357
|
}
|
|
512
|
-
}
|
|
358
|
+
}
|
|
359
|
+
else {
|
|
513
360
|
await this.queries.setJobStatus(fetchData.jobName, 'finished');
|
|
514
361
|
}
|
|
515
|
-
|
|
516
362
|
fetchData.running = false;
|
|
517
|
-
|
|
518
363
|
const totalTimeMs = Date.now() - fetchStartMs;
|
|
519
364
|
// Derived by subtraction because fetchLatest() invokes processBatch internally,
|
|
520
365
|
// so directly timing fetchLatest() would double-count processing and aggregation time.
|
|
521
366
|
const apiPollingTimeMs = totalTimeMs - processingTimeMs - aggregationTimeMs;
|
|
522
|
-
|
|
523
367
|
if (error) {
|
|
524
368
|
throw error;
|
|
525
369
|
}
|
|
526
|
-
|
|
527
370
|
return {
|
|
528
371
|
eventCount,
|
|
529
372
|
apiPollingTimeMs,
|
|
@@ -534,4 +377,5 @@ module.exports = class EmailAnalyticsService {
|
|
|
534
377
|
result: cumulativeResult
|
|
535
378
|
};
|
|
536
379
|
}
|
|
537
|
-
}
|
|
380
|
+
}
|
|
381
|
+
exports.EmailAnalyticsService = EmailAnalyticsService;
|
|
@@ -32,16 +32,6 @@ class EventProcessingResult {
|
|
|
32
32
|
this.emailIds = [];
|
|
33
33
|
this.memberIds = [];
|
|
34
34
|
}
|
|
35
|
-
get totalEvents() {
|
|
36
|
-
return this.delivered
|
|
37
|
-
+ this.opened
|
|
38
|
-
+ this.temporaryFailed
|
|
39
|
-
+ this.permanentFailed
|
|
40
|
-
+ this.unsubscribed
|
|
41
|
-
+ this.complained
|
|
42
|
-
+ this.unhandled
|
|
43
|
-
+ this.unprocessable;
|
|
44
|
-
}
|
|
45
35
|
merge(other = {}) {
|
|
46
36
|
this.delivered += other.delivered || 0;
|
|
47
37
|
this.opened += other.opened || 0;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.fetchMailgunEvents = fetchMailgunEvents;
|
|
7
|
+
// @ts-expect-error This module lacks type definitions.
|
|
8
|
+
const mailgun_client_1 = __importDefault(require("../lib/mailgun-client"));
|
|
9
|
+
const DEFAULT_EVENT_FILTER = 'delivered OR opened OR failed OR unsubscribed OR complained';
|
|
10
|
+
const PAGE_LIMIT = 300;
|
|
11
|
+
/**
|
|
12
|
+
* Fetch Mailgun email analytics events.
|
|
13
|
+
*/
|
|
14
|
+
async function fetchMailgunEvents({ config, settings, tags, batchHandler, maxEvents, begin, end, events }) {
|
|
15
|
+
const mailgunClient = new mailgun_client_1.default({ config, settings });
|
|
16
|
+
const mailgunOptions = {
|
|
17
|
+
limit: PAGE_LIMIT,
|
|
18
|
+
event: events ? events.join(' OR ') : DEFAULT_EVENT_FILTER,
|
|
19
|
+
tags: tags.join(' AND '),
|
|
20
|
+
begin: begin ? begin.getTime() / 1000 : undefined,
|
|
21
|
+
end: end ? end.getTime() / 1000 : undefined,
|
|
22
|
+
ascending: 'yes'
|
|
23
|
+
};
|
|
24
|
+
return await mailgunClient.fetchEvents(mailgunOptions, batchHandler, { maxEvents });
|
|
25
|
+
}
|