ghost 6.63.0 → 6.64.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/lib/duplicate-deps.js +204 -0
- package/bin/validate-adapters.js +50 -6
- package/components/tryghost-adapter-base-scheduling-0.2.3.tgz +0 -0
- package/components/tryghost-adapter-base-sso-0.1.3.tgz +0 -0
- package/components/tryghost-admin-api-schema-0.0.0.tgz +0 -0
- package/components/tryghost-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.5.tgz → tryghost-kg-default-cards-10.3.6.tgz} +0 -0
- package/components/tryghost-kg-default-nodes-2.2.1.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.1.tgz +0 -0
- package/components/tryghost-limit-service-0.0.0.tgz +0 -0
- package/components/tryghost-metafield-types-0.0.0.tgz +0 -0
- package/content/themes/source/assets/built/screen.css +1 -1
- package/content/themes/source/assets/css/screen.css +1 -1
- package/content/themes/source/package.json +7 -7
- package/core/boot.js +10 -4
- package/core/built/admin/assets/Combination-DWfJPcz9.js +41 -0
- package/core/built/admin/assets/{PolarAngleAxis-pkMyqz8g.js → PolarAngleAxis-a81ieQUO.js} +2 -2
- package/core/built/admin/assets/RadialBarChart-CHRBhiBN.js +1 -0
- package/core/built/admin/assets/_baseAssignValue-DcPokYW8.js +1 -0
- package/core/built/admin/assets/about-39CAfroa.js +1 -0
- package/core/built/admin/assets/accordion-CJmRaqK7.js +1 -0
- package/core/built/admin/assets/account-migration-DYf7skbb.js +1 -0
- package/core/built/admin/assets/action-list-Crnh-_UI.js +1 -0
- package/core/built/admin/assets/add-integration-modal-B12oRifD.js +1 -0
- package/core/built/admin/assets/add-newsletter-modal-CTvXiIqY.js +1 -0
- package/core/built/admin/assets/add-recommendation-modal-CJf92edY.js +1 -0
- package/core/built/admin/assets/analytics-PHR1Fggi.js +1 -0
- package/core/built/admin/assets/announcement-bar-modal-Bql0CXdp.js +1 -0
- package/core/built/admin/assets/api-keys-CubH-7_H.js +1 -0
- package/core/built/admin/assets/{api-keys-BGPzLHzA.js → api-keys-omLA6iYn.js} +1 -1
- package/core/built/admin/assets/{audience-ceV3XVHq.js → audience-6GXevic-.js} +1 -1
- package/core/built/admin/assets/automated-emails-DJQ4uNZo.js +1 -0
- package/core/built/admin/assets/automations-DcZSLFDU.js +1 -0
- package/core/built/admin/assets/automations-hDVcRPjh.js +1 -0
- package/core/built/admin/assets/avatar-flipboard-DiAGgshK.js +1 -0
- package/core/built/admin/assets/badge-qP06OT7C.js +1 -0
- package/core/built/admin/assets/bluesky-sharing-CJw4d4Mf.js +1 -0
- package/core/built/admin/assets/box-CZ_LSVSy.js +1 -0
- package/core/built/admin/assets/brand-icon-D3ffDYaC.js +1 -0
- package/core/built/admin/assets/breadcrumb-Chn1Ip_q.js +1 -0
- package/core/built/admin/assets/button-DvIh2Bq-.js +1 -0
- package/core/built/admin/assets/calendar-1QGoStFM.js +1 -0
- package/core/built/admin/assets/card-FHQ4D10L.js +1 -0
- package/core/built/admin/assets/chart-helpers-CNpA7re_.js +1 -0
- package/core/built/admin/assets/{chart-BrhA41Zi.js → chart-jVz9Nf9t.js} +9 -9
- package/core/built/admin/assets/checkbox-DKht9xMl.js +1 -0
- package/core/built/admin/assets/{chunk-KS7C4IRE-DCsL4i4D.js → chunk-KS7C4IRE-DhOcHQOU.js} +1 -1
- package/core/built/admin/assets/{chunk.254.035b85ec456ebbd7336b.js → chunk.368.22ce1b732c0b40abd3f1.js} +159 -120
- package/core/built/admin/assets/chunk.524.cc9be98e44890cedc8c8.js +25 -0
- package/core/built/admin/assets/{chunk.582.98b485f9b2802f540897.js → chunk.582.e6fe742b3217207b11a6.js} +23 -30
- package/core/built/admin/assets/{chunk.901.4ccc639821020230bcca.js → chunk.972.4b8c97f93d66db15e751.js} +10625 -10088
- package/core/built/admin/assets/clean-tracked-url-dkN05vOf.js +1 -0
- package/core/built/admin/assets/code-editor-view-BLQIV85-.js +1 -0
- package/core/built/admin/assets/code-editor-view-Cg5eJxcr.js +1 -0
- package/core/built/admin/assets/color-picker-DQoghc0t.js +3 -0
- package/core/built/admin/assets/color-picker-field-BbeK5RRs.js +1 -0
- package/core/built/admin/assets/combobox-weO4FBbv.js +1 -0
- package/core/built/admin/assets/command-DlLrCm9V.js +1 -0
- package/core/built/admin/assets/comments-BjTitLmP.js +1 -0
- package/core/built/admin/assets/components-CwL6a6As-CCRaoCeP.js +1 -0
- package/core/built/admin/assets/{config-kSHvwdTG.js → config-BPljH6wF.js} +1 -1
- package/core/built/admin/assets/confirmation-context-IyqoXVk-.js +1 -0
- package/core/built/admin/assets/container-DAimjOF_.js +1 -0
- package/core/built/admin/assets/content-api-modal-0ZjuLcQ8.js +1 -0
- package/core/built/admin/assets/context-menu-BtioYFrg.js +1 -0
- package/core/built/admin/assets/copy-field-C6ujqJlP.js +1 -0
- package/core/built/admin/assets/create-ghost-browse-value-source-DAZMWZNq.js +1 -0
- package/core/built/admin/assets/custom-integration-modal-Dm8QI_J4.js +1 -0
- package/core/built/admin/assets/data-list-C0CKkeWW.js +1 -0
- package/core/built/admin/assets/date-range-select-DrjHQdgz.js +1 -0
- package/core/built/admin/assets/design-and-theme-modal-CXVOzBWu.js +2 -0
- package/core/built/admin/assets/detail-page-QpLIL-EO.js +1 -0
- package/core/built/admin/assets/dirty-confirm-dialog-DWwxREGh.js +1 -0
- package/core/built/admin/assets/disabled-sources-indicator-CLZhMv8J.js +1 -0
- package/core/built/admin/assets/dist-BRQkNYN1.js +11 -0
- package/core/built/admin/assets/{dist-B3keLvjj.js → dist-BXHrDV19.js} +2 -2
- package/core/built/admin/assets/dist-Bf-HQtVL.js +1 -0
- package/core/built/admin/assets/dist-Bm-PB47a.js +6 -0
- package/core/built/admin/assets/{dist-B6bJuxL3.js → dist-C2lYC76d.js} +1 -1
- package/core/built/admin/assets/dist-CUwte9v_.js +1 -0
- package/core/built/admin/assets/dist-Cm2qbZKL.js +1 -0
- package/core/built/admin/assets/{dist-BtaTA7Ii.js → dist-D7yMk931.js} +1 -1
- package/core/built/admin/assets/{dist-zwwGt8Yf.js → dist-DNAdeRyr.js} +1 -1
- package/core/built/admin/assets/dist-DS6zpxid.js +1 -0
- package/core/built/admin/assets/dist-DVVKsyPh.js +23 -0
- package/core/built/admin/assets/dist-DxfQlAmn.js +1 -0
- package/core/built/admin/assets/dist-DziNzWI2.js +1 -0
- package/core/built/admin/assets/dist-FEQQAwTe.js +1 -0
- package/core/built/admin/assets/dist-nmRzULcD.js +1 -0
- package/core/built/admin/assets/domain-DBrBic6q.js +1 -0
- package/core/built/admin/assets/dropzone-D61QVcEY.js +5 -0
- package/core/built/admin/assets/edit-profile-jCqJBxqw.js +1 -0
- package/core/built/admin/assets/editor-8Fm4UBEd.js +8 -0
- package/core/built/admin/assets/editor-screen-BSX_uC2B.js +27 -0
- package/core/built/admin/assets/email-previews-Bs-JDhIw.js +1 -0
- package/core/built/admin/assets/email-sending-status-context-C76KYL1V.js +1 -0
- package/core/built/admin/assets/email-sending-status-provider-DnNhlIvt.js +1 -0
- package/core/built/admin/assets/{emails-vFMk4yYl.js → emails-CgvIIz3q.js} +1 -1
- package/core/built/admin/assets/{embed-signup-form-modal-DGqsORxS.js → embed-signup-form-modal-DqtBs1WE.js} +1 -1
- package/core/built/admin/assets/empty-indicator-L4Ql5Db7.js +1 -0
- package/core/built/admin/assets/en-Cx75dJv5.js +1 -0
- package/core/built/admin/assets/esm--rhhUGIG.js +2 -0
- package/core/built/admin/assets/explore-DXhDCtKw.js +1 -0
- package/core/built/admin/assets/feature-flag-overrides-context-CrcQKm9Z.js +1 -0
- package/core/built/admin/assets/feature-image-placeholder-e2q6TcH6.js +1 -0
- package/core/built/admin/assets/feed-mmt4noNL.js +1 -0
- package/core/built/admin/assets/feedback-BTPBQLT5.js +1 -0
- package/core/built/admin/assets/field-p7KnP98B.js +1 -0
- package/core/built/admin/assets/filter-bar-CiIKBg3D.js +1 -0
- package/core/built/admin/assets/filter-sources-I-dRaQxl.js +1 -0
- package/core/built/admin/assets/filters-1injvyxJ.js +1 -0
- package/core/built/admin/assets/filters-DnpO6GWX.js +1 -0
- package/core/built/admin/assets/first-promoter-modal-wr73Dldc.js +1 -0
- package/core/built/admin/assets/focus-koenig-editor-on-bottom-click-CkFA8EkI.js +1 -0
- package/core/built/admin/assets/framework-provider-DB-svAju.js +4 -0
- package/core/built/admin/assets/{ghost-b4e8a403baba61905cd7560e30b9732d.js → ghost-a1e6e172c6917e8ef8fa6b0007756d9b.js} +39 -30
- package/core/built/admin/assets/gift-link-modal-C3H7YFXO.js +1 -0
- package/core/built/admin/assets/{gift-links-CfLSnst2.js → gift-links-D8gl_yJS.js} +1 -1
- package/core/built/admin/assets/global-data-context-3MItMry2.js +1 -0
- package/core/built/admin/assets/grid-5vplBYri.js +1 -0
- package/core/built/admin/assets/growth-B1og1kQp.js +1 -0
- package/core/built/admin/assets/growth-Bf6OHZlK.js +3 -0
- package/core/built/admin/assets/heading-BB21QAbb.js +1 -0
- package/core/built/admin/assets/history-modal-t_qEnxPx.js +1 -0
- package/core/built/admin/assets/hooks-DYfTEQLk.js +2 -0
- package/core/built/admin/assets/html-field-COLQbV4r.js +1 -0
- package/core/built/admin/assets/iframe-buffering-Bq1el-gw.js +1 -0
- package/core/built/admin/assets/images-4mvoc3lB.js +1 -0
- package/core/built/admin/assets/{inbox-gJHG7_xd.js → inbox-DgSZ6w2p.js} +34 -34
- package/core/built/admin/assets/index-B3HZU2i8.css +2 -0
- package/core/built/admin/assets/index-DDd-zhNL.js +4 -0
- package/core/built/admin/assets/index.es-Ct5XQNSj.js +1 -0
- package/core/built/admin/assets/inline-B8H6NzIw.js +1 -0
- package/core/built/admin/assets/input-group-CLIN2ykI.js +1 -0
- package/core/built/admin/assets/{input-surface-BsrIZeSF.js → input-surface-wSO5CRy5.js} +1 -1
- package/core/built/admin/assets/integration-header-CKGrXNVP.js +1 -0
- package/core/built/admin/assets/{integrations-B4kuRBFY.js → integrations-DnJrZnHv.js} +1 -1
- package/core/built/admin/assets/invite-user-modal-BaN2mdhI.js +1 -0
- package/core/built/admin/assets/jsx-runtime-BlNNh7jY.js +1 -0
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +3 -3
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +1 -1
- package/core/built/admin/assets/{koenig-lexical-CGXb0F8o.js → koenig-lexical-CXVgQFUk.js} +1 -1
- package/core/built/admin/assets/koenig-loader-B1XPPY5C.js +2 -0
- package/core/built/admin/assets/kpi-card-CRLPVlFW.js +1 -0
- package/core/built/admin/assets/kpi-card-CRPbW8NZ.js +1 -0
- package/core/built/admin/assets/kpi-helpers-D7zT96bp.js +1 -0
- package/core/built/admin/assets/kpi-tabs-DE_yh9Go.js +1 -0
- package/core/built/admin/assets/label-CgeBxy4o.js +1 -0
- package/core/built/admin/assets/label-picker-DGDp4Vwr.js +1 -0
- package/core/built/admin/assets/labels-KMkFoRG6.js +1 -0
- package/core/built/admin/assets/layout-DWnOMly4.js +1 -0
- package/core/built/admin/assets/lib-_QYaUU89.js +2 -0
- package/core/built/admin/assets/link-helpers-8J7ixADV.js +1 -0
- package/core/built/admin/assets/links-FwNCVyVe.js +1 -0
- package/core/built/admin/assets/list-page-DLMP0PxC.js +1 -0
- package/core/built/admin/assets/luxon-BXCsmep3.js +1 -0
- package/core/built/admin/assets/member-activity-ClMWFyvN.js +1 -0
- package/core/built/admin/assets/member-activity-feed-BQY5Rwaj.js +1 -0
- package/core/built/admin/assets/member-custom-fields-Dd_ie1zG.js +1 -0
- package/core/built/admin/assets/member-detail-DjwkGVne.js +1 -0
- package/core/built/admin/assets/members--N9lhk1N.js +4 -0
- package/core/built/admin/assets/modal-page-Dz-9TP4E.js +1 -0
- package/core/built/admin/assets/moderation-DfYBKq9s.js +1 -0
- package/core/built/admin/assets/multi-select-combobox-BcBEzUW_.js +1 -0
- package/core/built/admin/assets/navigation-modal-Cd-scywg.js +1 -0
- package/core/built/admin/assets/newsletter-detail-modal-CFRY6vg_.js +1 -0
- package/core/built/admin/assets/newsletter-emails-4ntck1AC.js +1 -0
- package/core/built/admin/assets/newsletter-o6eCJtab.js +1 -0
- package/core/built/admin/assets/newsletters-Bmlv0edG.js +1 -0
- package/core/built/admin/assets/{newsletters-Rq1M3GD-.js → newsletters-Dz77m__5.js} +1 -1
- package/core/built/admin/assets/note-CWs3LF-0.js +1 -0
- package/core/built/admin/assets/notifications-BjSvTJqh.js +1 -0
- package/core/built/admin/assets/{nql-BLpCn7qX.js → nql-DnDc7UuU.js} +1 -1
- package/core/built/admin/assets/nql-lang-CeTB_Bhv.js +19 -0
- package/core/built/admin/assets/{offers--e2nGvkW.js → offers-ByWSK0rR.js} +1 -1
- package/core/built/admin/assets/offers-container-modal-Bc9A196w.js +1 -0
- package/core/built/admin/assets/onboarding-B4hfBi9a.js +1 -0
- package/core/built/admin/assets/onboarding-DV_XbHts.js +1 -0
- package/core/built/admin/assets/onboarding-route-Di1LJYEE.js +1 -0
- package/core/built/admin/assets/overview-DE7NHZQN.js +1 -0
- package/core/built/admin/assets/overview-DEF-ZY6x.js +1 -0
- package/core/built/admin/assets/page-header-B-G_g42C.js +1 -0
- package/core/built/admin/assets/pagemenu-CnkTDO71.js +1 -0
- package/core/built/admin/assets/{pages-CjDY2CBI.js → pages-DZ_YGB1D.js} +1 -1
- package/core/built/admin/assets/pages-route-VT7r7YhG.js +1 -0
- package/core/built/admin/assets/papaparse.min-BlhnCUXn.js +10 -0
- package/core/built/admin/assets/pintura-modal-BljM7hf8.js +1 -0
- package/core/built/admin/assets/portal-frame-D9V8iq5x.js +1 -0
- package/core/built/admin/assets/portal-modal-B5OOR9ZD.js +1 -0
- package/core/built/admin/assets/post-analytics-context-bt2YTBAC.js +1 -0
- package/core/built/admin/assets/post-analytics-header-J0WciLx6.js +1 -0
- package/core/built/admin/assets/post-analytics-provider-CgreZDjS.js +1 -0
- package/core/built/admin/assets/post-analytics-rGb-PgD-.js +1 -0
- package/core/built/admin/assets/post-share-modal-D0BbTo4W.js +1 -0
- package/core/built/admin/assets/posts-list-screen-CO5jAWoU.js +2 -0
- package/core/built/admin/assets/posts-route-DV-CXWK9.js +1 -0
- package/core/built/admin/assets/{posts-pCPrhQeR.js → posts-tcoO3iRG.js} +1 -1
- package/core/built/admin/assets/preferences-Tac29oG6.js +5 -0
- package/core/built/admin/assets/preview-chrome-C2lQgZBZ.js +1 -0
- package/core/built/admin/assets/preview-modal-CjRbBr8U.js +1 -0
- package/core/built/admin/assets/profile-yiM1f_Og.js +1 -0
- package/core/built/admin/assets/prop-types-6lTeqvom.js +1 -0
- package/core/built/admin/assets/radio-group-CKROWsw4.js +1 -0
- package/core/built/admin/assets/react-BXwhMTuc.js +1 -0
- package/core/built/admin/assets/{jsx-runtime-DX3WBWVO.js → react-dom-CMOtJ5MH.js} +2 -2
- package/core/built/admin/assets/{referrers-D8oHPmDB.js → referrers-1R8bPpoV.js} +1 -1
- package/core/built/admin/assets/router-provider-CU87qxXw.js +1 -0
- package/core/built/admin/assets/select-CKaC4ggu.js +1 -0
- package/core/built/admin/assets/settings-81kxUa28.js +1 -0
- package/core/built/admin/assets/settings-BVXFqBVK.js +4 -0
- package/core/built/admin/assets/settings-breadcrumbs-czGRx-iu.js +1 -0
- package/core/built/admin/assets/{shade-app-CcS3f8MZ-vwURazk8.js → shade-app-CcS3f8MZ-D5BnfHck.js} +1 -1
- package/core/built/admin/assets/share-modal-BL-16PiB.js +1 -0
- package/core/built/admin/assets/skeleton-DwCva0-b.js +1 -0
- package/core/built/admin/assets/slack-modal-D7W_fNON.js +1 -0
- package/core/built/admin/assets/sort-button-Dquc83jY.js +1 -0
- package/core/built/admin/assets/source-icon-CQboPZQ3.js +1 -0
- package/core/built/admin/assets/stack-BURz77VS.js +1 -0
- package/core/built/admin/assets/{stats-D9PDLS3x.js → stats-Cvp8Ep5m.js} +1 -1
- package/core/built/admin/assets/stats-view-NDja_g96.js +1 -0
- package/core/built/admin/assets/step-1-BKhjy0PV.js +1 -0
- package/core/built/admin/assets/step-2-PxA1OM7R.js +1 -0
- package/core/built/admin/assets/step-3-BJbAiq16.js +2 -0
- package/core/built/admin/assets/stripe-button-C3cfCAou.js +1 -0
- package/core/built/admin/assets/stripe-connect-modal-FyE3Ey2c.js +1 -0
- package/core/built/admin/assets/switch-zfUUy9Jh.js +1 -0
- package/core/built/admin/assets/table-dE4GTIRT.js +1 -0
- package/core/built/admin/assets/tabs-B3XK93sR.js +1 -0
- package/core/built/admin/assets/tag-detail-D4P-tZdM.js +2 -0
- package/core/built/admin/assets/tag-picker-BNSZ6Qxw.js +1 -0
- package/core/built/admin/assets/tags-BsZcaJ6h.js +1 -0
- package/core/built/admin/assets/{tags-ChfdwJyS.js → tags-NwZ7BPK6.js} +1 -1
- package/core/built/admin/assets/testimonials-modal-Dkt6ODLW.js +1 -0
- package/core/built/admin/assets/text-DC-ot6u2.js +1 -0
- package/core/built/admin/assets/textarea-B4FffFmE.js +1 -0
- package/core/built/admin/assets/themes-DtcEFQWm.js +1 -0
- package/core/built/admin/assets/tier-detail-modal-a77Z2VMH.js +1 -0
- package/core/built/admin/assets/{tiers-BCpIOGQr.js → tiers-6mPzCXlM.js} +1 -1
- package/core/built/admin/assets/toggle-group-D2p4okmJ.js +1 -0
- package/core/built/admin/assets/topic-filter-DVOe3D-b.js +1 -0
- package/core/built/admin/assets/transistor-modal-C8RMkhOD.js +1 -0
- package/core/built/admin/assets/trend-badge-B9v7kMF8.js +1 -0
- package/core/built/admin/assets/unsplash-modal-DXt7Brum.js +1 -0
- package/core/built/admin/assets/use-analytics-data-ChHqiZXv.js +1 -0
- package/core/built/admin/assets/use-availability-hPdeG76y.js +1 -0
- package/core/built/admin/assets/{use-check-theme-limit-error-DRUjK4YM.js → use-check-theme-limit-error-JD-J5aaZ.js} +2 -2
- package/core/built/admin/assets/use-email-sending-status-DNMtL5B9.js +1 -0
- package/core/built/admin/assets/use-filter-params-BSFigDIn.js +1 -0
- package/core/built/admin/assets/use-filterable-api-CEMSAYPg.js +1 -0
- package/core/built/admin/assets/use-form-DJKZJhQh.js +1 -0
- package/core/built/admin/assets/use-growth-stats-CqqdnESN.js +1 -0
- package/core/built/admin/assets/use-host-limits-mpTkZIq8.js +1 -0
- package/core/built/admin/assets/use-limiter-DBGjYqu7.js +19 -0
- package/core/built/admin/assets/use-navigate-with-base-path-88EQpw2k.js +1 -0
- package/core/built/admin/assets/use-pintura-config-BmU45Ruy.js +1 -0
- package/core/built/admin/assets/use-pintura-editor-Bz2bZ4iT.js +1 -0
- package/core/built/admin/assets/use-post-referrers-DyPjyBSN.js +1 -0
- package/core/built/admin/assets/use-query-params-DlOHCo-R.js +1 -0
- package/core/built/admin/assets/use-reply-chain-data-DmD2yX5D.js +1 -0
- package/core/built/admin/assets/use-router-history-entry-CKx9LhqD.js +1 -0
- package/core/built/admin/assets/use-sending-eta-CQeG6OP_.js +1 -0
- package/core/built/admin/assets/use-setting-group-Dza6bQ7W.js +1 -0
- package/core/built/admin/assets/use-settings-navigation-BIjI5mL3.js +1 -0
- package/core/built/admin/assets/use-simple-pagination-DwVxe-Lo.js +1 -0
- package/core/built/admin/assets/use-staff-users-i_Mq9OGR.js +1 -0
- package/core/built/admin/assets/{use-tinybird-query-CmdbCS9X.js → use-tinybird-query-DXoF74NM.js} +1 -1
- package/core/built/admin/assets/use-tinybird-token-Lk1RSn0t.js +1 -0
- package/core/built/admin/assets/use-unsaved-changes-guard-CKVPWz_F.js +1 -0
- package/core/built/admin/assets/use-upgrade-route-CVjDlNSs.js +1 -0
- package/core/built/admin/assets/{use-url-input-fvp-TpPx.js → use-url-input-DpmbDppC.js} +1 -1
- package/core/built/admin/assets/user-detail-modal-BU4QCHE7.js +1 -0
- package/core/built/admin/assets/{users-DVNWrqg9.js → users-C60_hpn6.js} +1 -1
- package/core/built/admin/assets/{validator-Cr0sMKuW.js → validator-DlFQP70j.js} +1 -1
- package/core/built/admin/assets/virtual-list-DScLNuU8.js +1 -0
- package/core/built/admin/assets/web-BZS-t4H0.js +1 -0
- package/core/built/admin/assets/web-DxAUxnK3.js +2 -0
- package/core/built/admin/assets/zapier-modal-BafLUO4R.js +1 -0
- package/core/built/admin/index.html +35 -32
- package/core/cli/command.js +17 -2
- package/core/frontend/meta/asset-url.js +1 -16
- package/core/frontend/services/asset-hash/index.js +32 -2
- package/core/frontend/services/routing/controllers/unsubscribe.js +2 -1
- package/core/frontend/services/rss/generate-feed.js +1 -1
- package/core/frontend/services/theme-engine/active.js +2 -4
- package/core/frontend/services/theme-engine/i18n/i18n.js +11 -1
- package/core/frontend/services/theme-engine/i18next/theme-i18n.js +1 -1
- package/core/frontend/web/middleware/llms-discovery.js +34 -43
- package/core/server/adapters/route-settings/S3RouteSettingsStore.js +1 -1
- package/core/server/adapters/storage/LocalFilesStorage.js +12 -2
- package/core/server/adapters/storage/LocalStorageBase.js +13 -0
- package/core/server/api/endpoints/actions.js +2 -1
- package/core/server/api/endpoints/automated-emails.js +3 -2
- package/core/server/api/endpoints/automations.js +77 -49
- package/core/server/api/endpoints/emails.js +8 -3
- package/core/server/api/endpoints/index.js +1 -1
- package/core/server/api/endpoints/invites.js +2 -1
- package/core/server/api/endpoints/labels.js +6 -2
- package/core/server/api/endpoints/member-metafields.js +2 -2
- package/core/server/api/endpoints/members.js +22 -6
- package/core/server/api/endpoints/pages.js +2 -6
- package/core/server/api/endpoints/posts.js +3 -11
- package/core/server/api/endpoints/snippets.js +2 -1
- package/core/server/api/endpoints/tags.js +6 -2
- package/core/server/api/endpoints/users.js +2 -6
- package/core/server/api/endpoints/utils/api-filter-utils.js +62 -3
- package/core/server/api/endpoints/utils/serializers/output/utils/clean.js +2 -0
- package/core/server/api/endpoints/utils/serializers/output/utils/extra-attrs.js +3 -0
- package/core/server/api/endpoints/utils/validators/input/settings.js +15 -1
- package/core/server/data/exporter/exporter.js +2 -1
- package/core/server/data/exporter/table-lists.js +3 -5
- package/core/server/data/importer/importers/data/settings-importer.js +8 -2
- package/core/server/data/migrations/versions/6.64/2026-09-03-15-40-25-add-member-access-to-members-metafields.js +12 -0
- package/core/server/data/migrations/versions/6.64/2026-09-08-11-01-12-add-posts-auto-excerpt-and-reading-time-columns.js +17 -0
- package/core/server/data/migrations/versions/6.64/2026-09-09-13-56-18-add-automation-run-updated-at-indexes.js +6 -0
- package/core/server/data/migrations/versions/6.64/2026-09-09-13-56-18-add-tinybird-syncs-table.js +10 -0
- package/core/server/data/schema/schema.js +28 -2
- package/core/server/data/seeders/importers/automations-importer.js +0 -1
- package/core/server/data/seeders/importers/comments-importer.js +1 -1
- package/core/server/data/seeders/importers/email-recipients-importer.js +1 -1
- package/core/server/data/seeders/importers/emails-importer.js +1 -1
- package/core/server/data/seeders/importers/members-importer.js +1 -1
- package/core/server/data/seeders/importers/members-login-events-importer.js +1 -1
- package/core/server/data/seeders/importers/members-stripe-customers-subscriptions-importer.js +1 -1
- package/core/server/data/seeders/utils/blog-info.js +4 -3
- package/core/server/data/seeders/utils/event-generator.js +72 -46
- package/core/server/data/tinybird/datasources/_mv_automation_run_steps.datasource +10 -0
- package/core/server/data/tinybird/datasources/_mv_automation_runs.datasource +10 -0
- package/core/server/data/tinybird/datasources/_mv_pending_automation_runs.datasource +10 -0
- package/core/server/data/tinybird/datasources/automation_run_events.datasource +12 -0
- package/core/server/data/tinybird/datasources/automation_run_step_events.datasource +12 -0
- package/core/server/data/tinybird/endpoints/api_automation_browse_stats.pipe +43 -0
- package/core/server/data/tinybird/fixtures/automation_run_events.ndjson +7 -0
- package/core/server/data/tinybird/fixtures/automation_run_step_events.ndjson +8 -0
- package/core/server/data/tinybird/pipes/mv_automation_run_steps.pipe +13 -0
- package/core/server/data/tinybird/pipes/mv_automation_runs.pipe +15 -0
- package/core/server/data/tinybird/pipes/mv_pending_automation_runs.pipe +7 -0
- package/core/server/data/tinybird/tests/api_automation_browse_stats.yaml +18 -0
- package/core/server/ghost-server.js +3 -3
- package/core/server/lib/generate-password.js +54 -0
- package/core/server/lib/public-jwk.js +77 -0
- package/core/server/models/user.js +11 -9
- package/core/server/services/adapter-manager/base-classes.js +21 -3
- package/core/server/services/automations/automations-api.js +46 -1
- package/core/server/services/automations/tinybird-automation-stats.js +56 -0
- package/core/server/services/content-import/import/media.js +1 -1
- package/core/server/services/email-analytics/email-analytics-service-wrapper.js +15 -29
- package/core/server/services/email-analytics/email-analytics-service.js +19 -3
- package/core/server/services/email-analytics/index.js +9 -4
- package/core/server/services/email-rendering/finalize.js +7 -2
- package/core/server/services/email-service/README.md +3 -0
- package/core/server/services/email-service/email-renderer.js +7 -2
- package/core/server/services/email-service/email-service-wrapper.js +1 -1
- package/core/server/services/email-service/email-service.js +43 -34
- package/core/server/services/email-service/sending-status.js +10 -4
- package/core/server/services/gifts/gift-email-service.js +10 -3
- package/core/server/services/gifts/index.js +1 -0
- package/core/server/services/i18n.js +1 -1
- package/core/server/services/identity-tokens/identity-token-service-wrapper.js +3 -4
- package/core/server/services/limits.js +17 -1
- package/core/server/services/member-welcome-emails/service.js +1 -1
- package/core/server/services/members/import-export/index.js +5 -4
- package/core/server/services/members/members-api/controllers/router-controller.js +7 -2
- package/core/server/services/members/members-api/controllers/well-known-controller.js +2 -1
- package/core/server/services/members/members-api/repositories/event-repository.js +4 -0
- package/core/server/services/members/members-api/services/member-bread-service.js +15 -12
- package/core/server/services/members/members-api/services/token-service.js +11 -12
- package/core/server/services/members/middleware.js +9 -2
- package/core/server/services/members/request-integrity-token-provider.js +2 -1
- package/core/server/services/members-metafields/access.js +31 -20
- package/core/server/services/members-metafields/actions.js +1 -0
- package/core/server/services/members-metafields/codec.js +9 -2
- package/core/server/services/members-metafields/definitions-service.js +56 -46
- package/core/server/services/members-metafields/index.js +2 -2
- package/core/server/services/members-metafields/models.js +2 -0
- package/core/server/services/members-metafields/queries.js +39 -11
- package/core/server/services/members-metafields/schema.js +2 -0
- package/core/server/services/members-metafields/serializers.js +1 -0
- package/core/server/services/members-metafields/values-service.js +20 -11
- package/core/server/services/mentions/mention-discovery-service.js +1 -1
- package/core/server/services/mentions/mention-sending-service.js +1 -1
- package/core/server/services/mentions/mention.js +1 -1
- package/core/server/services/oembed/oembed-service.js +36 -11
- package/core/server/services/posts/post-scheduling.js +20 -0
- package/core/server/services/staff/staff-service-emails.js +5 -1
- package/core/server/services/stats/stats-service.js +12 -3
- package/core/server/services/tier-checkout-config/service.js +17 -1
- package/core/server/services/tinybird/tinybird-service.js +1 -0
- package/core/server/services/tinybird-sync/get-ingest-config.js +39 -0
- package/core/server/services/tinybird-sync/index.js +28 -0
- package/core/server/services/tinybird-sync/sync-table-to-tinybird.js +149 -0
- package/core/server/services/tinybird-sync/tinybird-sync-service.js +62 -0
- package/core/server/web/api/endpoints/admin/routes.js +33 -34
- package/core/server/web/well-known.js +12 -16
- package/core/shared/config/defaults.json +1 -2
- package/core/shared/{flush-logs.js → flush.js} +7 -3
- package/core/shared/labs.js +2 -0
- package/core/shared/timing-safe-string-equal.js +26 -0
- package/package.json +42 -42
- package/patches/@elastic__elasticsearch@8.19.2.patch +67 -0
- package/patches/juice@11.1.1.patch +46 -0
- package/pnpm-lock.yaml +457 -1391
- package/pnpm-workspace.yaml +34 -21
- package/scripts/prune.mts +70 -3
- package/components/tryghost-kg-lexical-html-renderer-1.5.0.tgz +0 -0
- package/core/built/admin/assets/Combination-B0l4MKVh.js +0 -41
- package/core/built/admin/assets/RadialBarChart-JAKoS4KT.js +0 -1
- package/core/built/admin/assets/_baseAssignValue-C_vooEQc.js +0 -1
- package/core/built/admin/assets/about-C1C3s5-g.js +0 -1
- package/core/built/admin/assets/accordion-CxGsDKwa.js +0 -1
- package/core/built/admin/assets/account-migration-CbUhW6gk.js +0 -1
- package/core/built/admin/assets/action-list-C4v0-du8.js +0 -1
- package/core/built/admin/assets/add-integration-modal-BT_onDJy.js +0 -1
- package/core/built/admin/assets/add-newsletter-modal-Cx1kQpiY.js +0 -1
- package/core/built/admin/assets/add-recommendation-modal-B5nvAhvr.js +0 -1
- package/core/built/admin/assets/analytics-DjoJWPI7.js +0 -1
- package/core/built/admin/assets/announcement-bar-modal-Dwd0EGFP.js +0 -1
- package/core/built/admin/assets/api-keys-BoeacM-s.js +0 -1
- package/core/built/admin/assets/automated-emails-BLesE41L.js +0 -1
- package/core/built/admin/assets/automations-BN4u3GR8.js +0 -1
- package/core/built/admin/assets/automations-C-ZTUwW3.js +0 -1
- package/core/built/admin/assets/avatar-flipboard-C6Kj3Awu.js +0 -1
- package/core/built/admin/assets/bluesky-sharing-vzh-oPXL.js +0 -1
- package/core/built/admin/assets/box-CdfQAP_F.js +0 -1
- package/core/built/admin/assets/brand-icon-CrIGOA3Z.js +0 -1
- package/core/built/admin/assets/breadcrumb-CaLk2b7D.js +0 -1
- package/core/built/admin/assets/build-CsiH26uS.js +0 -1
- package/core/built/admin/assets/button-Dvcv1QSR.js +0 -1
- package/core/built/admin/assets/calendar-Bl9RLcZX.js +0 -1
- package/core/built/admin/assets/card--VNbfgo3.js +0 -1
- package/core/built/admin/assets/chart-helpers-FHywU0pj.js +0 -1
- package/core/built/admin/assets/checkbox-BtayFtjg.js +0 -1
- package/core/built/admin/assets/chunk.524.e6975095fccdf22d90f8.js +0 -32
- package/core/built/admin/assets/code-editor-view-C3ZfoF1X.js +0 -1
- package/core/built/admin/assets/code-editor-view-CAyRWy1s.js +0 -1
- package/core/built/admin/assets/color-picker-G4kGR7rp.js +0 -3
- package/core/built/admin/assets/color-picker-field-DQFVTNnT.js +0 -1
- package/core/built/admin/assets/combobox-BnYzgEB4.js +0 -1
- package/core/built/admin/assets/command-C_vyTikI.js +0 -1
- package/core/built/admin/assets/comments-aBrxfnZf.js +0 -1
- package/core/built/admin/assets/components-CwL6a6As-B0E0-NBJ.js +0 -1
- package/core/built/admin/assets/confirmation-context-DwXX_Y5h.js +0 -1
- package/core/built/admin/assets/container-BuQG1wuP.js +0 -1
- package/core/built/admin/assets/content-api-modal-D2G0nJP6.js +0 -1
- package/core/built/admin/assets/context-menu-DOVB6yaz.js +0 -1
- package/core/built/admin/assets/copy-field-DCJwh9qf.js +0 -1
- package/core/built/admin/assets/create-ghost-browse-value-source-5C53jJaX.js +0 -1
- package/core/built/admin/assets/custom-field-type-option-BAuW0F-E.js +0 -1
- package/core/built/admin/assets/custom-integration-modal-AbJGVyKc.js +0 -1
- package/core/built/admin/assets/data-list-CA2jYGPq.js +0 -1
- package/core/built/admin/assets/date-range-select-BY3K-ukj.js +0 -1
- package/core/built/admin/assets/design-and-theme-modal-BvEy4_pC.js +0 -2
- package/core/built/admin/assets/detail-page-Dnv-CdR1.js +0 -1
- package/core/built/admin/assets/dirty-confirm-dialog-DVPuGz3U.js +0 -1
- package/core/built/admin/assets/disabled-sources-indicator-Cy7Zp4c8.js +0 -1
- package/core/built/admin/assets/dist-4m6pHdc0.js +0 -23
- package/core/built/admin/assets/dist-8YJUlf3B.js +0 -1
- package/core/built/admin/assets/dist-CZgIBXQN.js +0 -1
- package/core/built/admin/assets/dist-CiHx7vA5.js +0 -6
- package/core/built/admin/assets/dist-DIC8yz5C.js +0 -1
- package/core/built/admin/assets/dist-Dcsslyo72.js +0 -1
- package/core/built/admin/assets/dist-Dgt2cr6a.js +0 -1
- package/core/built/admin/assets/dist-ECAUrdGc.js +0 -1
- package/core/built/admin/assets/dist-JLOy8o0Q.js +0 -1
- package/core/built/admin/assets/dist-Ndy-PuGN.js +0 -1
- package/core/built/admin/assets/dist-Z97pCNqS.js +0 -11
- package/core/built/admin/assets/domain-Dl61QGuk.js +0 -1
- package/core/built/admin/assets/dropzone-Dtz5Rmjt.js +0 -5
- package/core/built/admin/assets/edit-profile-DNJSMDwm.js +0 -1
- package/core/built/admin/assets/editor-DbAen9zf.js +0 -8
- package/core/built/admin/assets/editor-screen-BFWThIai.js +0 -26
- package/core/built/admin/assets/email-sending-status-context-CWDOD1FN.js +0 -1
- package/core/built/admin/assets/email-sending-status-provider-DCPkDICt.js +0 -1
- package/core/built/admin/assets/empty-indicator-D9QdpuNX.js +0 -1
- package/core/built/admin/assets/en-B1jX3WMs.js +0 -1
- package/core/built/admin/assets/esm-CXo5SEPy.js +0 -2
- package/core/built/admin/assets/explore-nnRr1Fja.js +0 -1
- package/core/built/admin/assets/feature-flag-overrides-context-DQjdJFAk.js +0 -1
- package/core/built/admin/assets/feature-image-placeholder-BrIHmPs8.js +0 -1
- package/core/built/admin/assets/feed-BNUcNu-W.js +0 -1
- package/core/built/admin/assets/feedback-DJ4Zb9rZ.js +0 -1
- package/core/built/admin/assets/field-C93_Mg6j.js +0 -1
- package/core/built/admin/assets/filter-bar-Da1qxybu.js +0 -1
- package/core/built/admin/assets/filter-sources-CGJb4C5r.js +0 -1
- package/core/built/admin/assets/filters--kKP-EC8.js +0 -1
- package/core/built/admin/assets/filters-DxA_a4FP.js +0 -1
- package/core/built/admin/assets/first-promoter-modal-BYDtrz2S.js +0 -1
- package/core/built/admin/assets/focus-koenig-editor-on-bottom-click-BbSnGOtK.js +0 -1
- package/core/built/admin/assets/framework-provider-DqI25epG.js +0 -4
- package/core/built/admin/assets/gift-link-modal-B7u5bD4e.js +0 -1
- package/core/built/admin/assets/global-data-context-gAMDH9u1.js +0 -1
- package/core/built/admin/assets/grid-Dj29PY05.js +0 -1
- package/core/built/admin/assets/growth-Cd1uO9d2.js +0 -1
- package/core/built/admin/assets/growth-aG32xfdE.js +0 -3
- package/core/built/admin/assets/heading-Dh5SFVjL.js +0 -1
- package/core/built/admin/assets/history-modal-Df8lW8h-.js +0 -1
- package/core/built/admin/assets/hooks-Cy_-oZ4o.js +0 -2
- package/core/built/admin/assets/html-field-DA4eU7eq.js +0 -1
- package/core/built/admin/assets/iframe-buffering-B2OKJzbz.js +0 -1
- package/core/built/admin/assets/images-KXmyO3Ss.js +0 -1
- package/core/built/admin/assets/index-BHHXtR5C.css +0 -2
- package/core/built/admin/assets/index-CgMCwsxN.js +0 -4
- package/core/built/admin/assets/index.es-CY6-yuw9.js +0 -1
- package/core/built/admin/assets/inline-BWSs_VzR.js +0 -1
- package/core/built/admin/assets/input-group-BE8rM2y1.js +0 -1
- package/core/built/admin/assets/integration-header-Bm6IDb1A.js +0 -1
- package/core/built/admin/assets/invite-user-modal-B4CuNcx4.js +0 -1
- package/core/built/admin/assets/koenig-loader-BeM5rFPX.js +0 -2
- package/core/built/admin/assets/kpi-card-B21aToe8.js +0 -1
- package/core/built/admin/assets/kpi-card-pz6Wv4Ae.js +0 -1
- package/core/built/admin/assets/kpi-helpers-Dq5jelmP.js +0 -1
- package/core/built/admin/assets/kpi-tabs-DEZHpKUt.js +0 -1
- package/core/built/admin/assets/label-OLCzze8N.js +0 -1
- package/core/built/admin/assets/label-picker-BigOvMPV.js +0 -1
- package/core/built/admin/assets/labels-Dr0SgUQD.js +0 -1
- package/core/built/admin/assets/layout-DUTL8SH5.js +0 -1
- package/core/built/admin/assets/lib-7QPTI0FS.js +0 -1
- package/core/built/admin/assets/limit-service-BhiEvqcP.js +0 -20
- package/core/built/admin/assets/link-helpers-BRAg9SCj.js +0 -1
- package/core/built/admin/assets/links-BDHPTlyj.js +0 -1
- package/core/built/admin/assets/list-page-BucXJ0hi.js +0 -1
- package/core/built/admin/assets/luxon-D1RVjjpq.js +0 -1
- package/core/built/admin/assets/member-custom-fields-TRTHCAz9.js +0 -1
- package/core/built/admin/assets/member-detail-b6dRwc3C.js +0 -1
- package/core/built/admin/assets/members-Czt5lJSc.js +0 -4
- package/core/built/admin/assets/modal-page-xCivTMvI.js +0 -1
- package/core/built/admin/assets/moderation-ZWefD9uH.js +0 -1
- package/core/built/admin/assets/multi-select-combobox-CT13MTo-.js +0 -1
- package/core/built/admin/assets/navigation-modal-C8FEhBK5.js +0 -1
- package/core/built/admin/assets/newsletter-5VYW4RyJ.js +0 -1
- package/core/built/admin/assets/newsletter-detail-modal-ChjC0ZqH.js +0 -1
- package/core/built/admin/assets/newsletter-emails-DZH6I-PY.js +0 -1
- package/core/built/admin/assets/newsletters-DOC9KBcX.js +0 -1
- package/core/built/admin/assets/note-DIV-Pojr.js +0 -1
- package/core/built/admin/assets/notifications-s20-H49V.js +0 -1
- package/core/built/admin/assets/nql-lang-CaWrLesS.js +0 -19
- package/core/built/admin/assets/offers-container-modal-BmG5M5Tv.js +0 -1
- package/core/built/admin/assets/onboarding-CUuy9unR.js +0 -1
- package/core/built/admin/assets/onboarding-pXyct0Jm.js +0 -1
- package/core/built/admin/assets/onboarding-route-CK4pcXoR.js +0 -1
- package/core/built/admin/assets/overview-CaPsciMs.js +0 -1
- package/core/built/admin/assets/overview-a8GfcsKX.js +0 -1
- package/core/built/admin/assets/page-header-DM_KyoFI.js +0 -1
- package/core/built/admin/assets/pagemenu-vgZVUVKR.js +0 -1
- package/core/built/admin/assets/pages-route-BzKZYdV5.js +0 -1
- package/core/built/admin/assets/papaparse.min-cQwnxGCG.js +0 -10
- package/core/built/admin/assets/pintura-modal-DExCF1ii.js +0 -1
- package/core/built/admin/assets/portal-frame-Cqanidq4.js +0 -1
- package/core/built/admin/assets/portal-modal-oinBgA27.js +0 -1
- package/core/built/admin/assets/post-analytics-C5oJ1dWV.js +0 -1
- package/core/built/admin/assets/post-analytics-context-D0Mw-Pmv.js +0 -1
- package/core/built/admin/assets/post-analytics-header-OATo3X_r.js +0 -1
- package/core/built/admin/assets/post-analytics-provider-tOpIVGT5.js +0 -1
- package/core/built/admin/assets/post-share-modal-DvhC1XgV.js +0 -1
- package/core/built/admin/assets/posts-list-screen-o4ZjbgS3.js +0 -2
- package/core/built/admin/assets/posts-route-9F--xdIb.js +0 -1
- package/core/built/admin/assets/preferences--vNubsqD.js +0 -5
- package/core/built/admin/assets/preview-chrome-BljUBlOk.js +0 -1
- package/core/built/admin/assets/preview-modal-YYbzlYdO.js +0 -1
- package/core/built/admin/assets/profile-BllKV3dR.js +0 -1
- package/core/built/admin/assets/prop-types-DeUPn3oD.js +0 -1
- package/core/built/admin/assets/radio-group-DL8GI8rt.js +0 -1
- package/core/built/admin/assets/react-Bb3IsNbi.js +0 -1
- package/core/built/admin/assets/rolldown-runtime-DAXXjFlN.js +0 -1
- package/core/built/admin/assets/router-provider-BSvTXgZY.js +0 -1
- package/core/built/admin/assets/select-v5YbA3Mw.js +0 -1
- package/core/built/admin/assets/settings-PEsZupw1.js +0 -4
- package/core/built/admin/assets/settings-breadcrumbs-NwPnCTC7.js +0 -1
- package/core/built/admin/assets/settings-u_s1CRkr.js +0 -1
- package/core/built/admin/assets/share-modal-SskCmVGL.js +0 -1
- package/core/built/admin/assets/skeleton-Ce9GgUpf.js +0 -1
- package/core/built/admin/assets/slack-modal-XxSJiYgo.js +0 -1
- package/core/built/admin/assets/sort-button-Cx1KtINE.js +0 -1
- package/core/built/admin/assets/source-icon-Bdp9Im_5.js +0 -1
- package/core/built/admin/assets/stack-B2eszIiq.js +0 -1
- package/core/built/admin/assets/stats-view-W2g6Jsd-.js +0 -1
- package/core/built/admin/assets/step-1-BQYzvBzr.js +0 -1
- package/core/built/admin/assets/step-2-xES32xJV.js +0 -1
- package/core/built/admin/assets/step-3-DA_XK5kW.js +0 -2
- package/core/built/admin/assets/stripe-button-CVsLHelt.js +0 -1
- package/core/built/admin/assets/stripe-connect-modal-ClmLOMGS.js +0 -1
- package/core/built/admin/assets/switch-CI4gLWqb.js +0 -1
- package/core/built/admin/assets/table-BenqVupI.js +0 -1
- package/core/built/admin/assets/tabs-eBBlxPp8.js +0 -1
- package/core/built/admin/assets/tag-detail-Ce8Se2qd.js +0 -2
- package/core/built/admin/assets/tag-picker-C3UR-uJ-.js +0 -1
- package/core/built/admin/assets/tags-B-kJxCs7.js +0 -1
- package/core/built/admin/assets/testimonials-modal-9Q6fT06V.js +0 -1
- package/core/built/admin/assets/text-BQDSDsKs.js +0 -1
- package/core/built/admin/assets/textarea-DJ1Q5V39.js +0 -1
- package/core/built/admin/assets/tier-detail-modal-CDyYdqK7.js +0 -1
- package/core/built/admin/assets/toggle-group-CviIkyok.js +0 -1
- package/core/built/admin/assets/topic-filter-I2jCBGxm.js +0 -1
- package/core/built/admin/assets/transistor-modal-p53u3W8y.js +0 -1
- package/core/built/admin/assets/trend-badge-CideVzQd.js +0 -1
- package/core/built/admin/assets/unsplash-modal-DY8UcKcE.js +0 -1
- package/core/built/admin/assets/use-analytics-data-DAIGcr2f.js +0 -1
- package/core/built/admin/assets/use-filter-params-JkZhIS8L.js +0 -1
- package/core/built/admin/assets/use-filterable-api-BVEVMrhZ.js +0 -1
- package/core/built/admin/assets/use-form-vRjI0Kwk.js +0 -1
- package/core/built/admin/assets/use-growth-stats-937CUj6j.js +0 -1
- package/core/built/admin/assets/use-host-limits-D0Dv3tKA.js +0 -1
- package/core/built/admin/assets/use-limiter-CohWfzvK.js +0 -2
- package/core/built/admin/assets/use-navigate-with-base-path-BkxcPj5l.js +0 -1
- package/core/built/admin/assets/use-pintura-config-xgytjU35.js +0 -1
- package/core/built/admin/assets/use-pintura-editor-CaV1mbfO.js +0 -1
- package/core/built/admin/assets/use-post-referrers-BCQI7fDg.js +0 -1
- package/core/built/admin/assets/use-query-params-BfzuqbcD.js +0 -1
- package/core/built/admin/assets/use-reply-chain-data-CYRhoaxY.js +0 -1
- package/core/built/admin/assets/use-router-history-entry-NOKcd--l.js +0 -1
- package/core/built/admin/assets/use-setting-group-bLKMwoBT.js +0 -1
- package/core/built/admin/assets/use-settings-navigation-B-qrriKD.js +0 -1
- package/core/built/admin/assets/use-simple-pagination-CNPd6Rf6.js +0 -1
- package/core/built/admin/assets/use-staff-users-pRIMIyiW.js +0 -1
- package/core/built/admin/assets/use-tinybird-token-KLne235s.js +0 -1
- package/core/built/admin/assets/use-unsaved-changes-guard-7-ug0JdH.js +0 -1
- package/core/built/admin/assets/use-upgrade-route-Dm_qqKr0.js +0 -1
- package/core/built/admin/assets/user-detail-modal-D3KlGYv-.js +0 -1
- package/core/built/admin/assets/virtual-list-CZ3RK2Yf.js +0 -1
- package/core/built/admin/assets/web-ClEJsCAj.js +0 -2
- package/core/built/admin/assets/web-X9rdnrtq.js +0 -1
- package/core/built/admin/assets/zapier-modal-DfVhV17j.js +0 -1
- /package/core/built/admin/assets/{chunk.901.4ccc639821020230bcca.js.LICENSE.txt → chunk.972.4b8c97f93d66db15e751.js.LICENSE.txt} +0 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.getPublicKeyInfo = getPublicKeyInfo;
|
|
40
|
+
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
41
|
+
const errors = __importStar(require("@tryghost/errors"));
|
|
42
|
+
// Parsing a PEM and thumbprinting it costs real CPU, so results are shared
|
|
43
|
+
// across every consumer of the same key. Keyed by digest so the cache never
|
|
44
|
+
// holds another reference to private key material.
|
|
45
|
+
const cache = new Map();
|
|
46
|
+
async function parse(privateKeyPem) {
|
|
47
|
+
// jose 6 is ESM-only. tsc emits this as `require('jose')` under module: commonjs,
|
|
48
|
+
// which resolves via Node's require(esm) - available on every Node in `engines`.
|
|
49
|
+
const { calculateJwkThumbprint } = await Promise.resolve().then(() => __importStar(require('jose')));
|
|
50
|
+
// Node handles both PKCS#1 and PKCS#8 PEMs, and exports public fields only.
|
|
51
|
+
const publicKey = node_crypto_1.default.createPublicKey(node_crypto_1.default.createPrivateKey(privateKeyPem));
|
|
52
|
+
const { kty, n, e } = publicKey.export({ format: 'jwk' });
|
|
53
|
+
if (kty !== 'RSA' || !n || !e) {
|
|
54
|
+
throw new errors.IncorrectUsageError({
|
|
55
|
+
message: 'Expected an RSA private key',
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const jwk = { kty, n, e };
|
|
59
|
+
return { kid: await calculateJwkThumbprint(jwk, 'sha256'), jwk };
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Public JWK and `kid` for a PEM-encoded RSA private key. Never returns private
|
|
63
|
+
* parameters.
|
|
64
|
+
*/
|
|
65
|
+
function getPublicKeyInfo(privateKeyPem) {
|
|
66
|
+
const digest = node_crypto_1.default.createHash('sha256').update(privateKeyPem).digest('hex');
|
|
67
|
+
let info = cache.get(digest);
|
|
68
|
+
if (!info) {
|
|
69
|
+
info = parse(privateKeyPem).catch((err) => {
|
|
70
|
+
// Don't pin a failure forever - a later caller should retry.
|
|
71
|
+
cache.delete(digest);
|
|
72
|
+
throw err;
|
|
73
|
+
});
|
|
74
|
+
cache.set(digest, info);
|
|
75
|
+
}
|
|
76
|
+
return info;
|
|
77
|
+
}
|
|
@@ -7,6 +7,7 @@ const tpl = require('@tryghost/tpl');
|
|
|
7
7
|
const errors = require('@tryghost/errors');
|
|
8
8
|
const security = require('@tryghost/security');
|
|
9
9
|
const { validatePassword } = require('../lib/validate-password');
|
|
10
|
+
const { generatePassword } = require('../lib/generate-password');
|
|
10
11
|
const permissions = require('../services/permissions');
|
|
11
12
|
const urlUtils = require('../../shared/url-utils').default;
|
|
12
13
|
const { setIsRoles } = require('./role-utils');
|
|
@@ -66,8 +67,7 @@ User = ghostBookshelf.Model.extend(
|
|
|
66
67
|
|
|
67
68
|
defaults: function defaults() {
|
|
68
69
|
return {
|
|
69
|
-
|
|
70
|
-
password: security.identifier.uid(50),
|
|
70
|
+
password: generatePassword(''),
|
|
71
71
|
visibility: 'public',
|
|
72
72
|
status: 'active',
|
|
73
73
|
comment_notifications: true,
|
|
@@ -208,8 +208,7 @@ User = ghostBookshelf.Model.extend(
|
|
|
208
208
|
*/
|
|
209
209
|
lock: function lock(options) {
|
|
210
210
|
const update = {
|
|
211
|
-
|
|
212
|
-
password: security.identifier.uid(50),
|
|
211
|
+
password: generatePassword(this.get('email') || ''),
|
|
213
212
|
};
|
|
214
213
|
if (this.get('status') !== 'inactive') {
|
|
215
214
|
update.status = 'locked';
|
|
@@ -306,8 +305,8 @@ User = ghostBookshelf.Model.extend(
|
|
|
306
305
|
}
|
|
307
306
|
|
|
308
307
|
if (options.importing) {
|
|
309
|
-
//
|
|
310
|
-
this.set('password',
|
|
308
|
+
// generate a random password when importing
|
|
309
|
+
this.set('password', generatePassword(this.get('email') || ''));
|
|
311
310
|
|
|
312
311
|
// lock users so they have to follow the password reset flow
|
|
313
312
|
if (this.get('status') !== 'inactive') {
|
|
@@ -1037,10 +1036,13 @@ User = ghostBookshelf.Model.extend(
|
|
|
1037
1036
|
}),
|
|
1038
1037
|
);
|
|
1039
1038
|
}
|
|
1040
|
-
} else if (roleId !== contextRoleId) {
|
|
1039
|
+
} else if (roleId !== contextRoleId || editedUserId !== context.user) {
|
|
1041
1040
|
// CASE: you are trying to change a role, but you are not owner
|
|
1042
|
-
// @NOTE:
|
|
1043
|
-
//
|
|
1041
|
+
// @NOTE: assigning any role to *another* user must always go through
|
|
1042
|
+
// the assign check, including your own role. Otherwise an Editor could
|
|
1043
|
+
// promote an Author to Editor, which the role hierarchy disallows.
|
|
1044
|
+
// The only case that skips the check is a self-edit that leaves your
|
|
1045
|
+
// own role untouched, e.g. a profile update that echoes back `roles`.
|
|
1044
1046
|
|
|
1045
1047
|
return permissions
|
|
1046
1048
|
.canThis(context)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.baseClasses = void 0;
|
|
3
|
+
exports.baseClassPackages = exports.baseClasses = void 0;
|
|
4
4
|
const ghost_storage_base_1 = require("ghost-storage-base");
|
|
5
5
|
const adapter_base_scheduling_1 = require("@tryghost/adapter-base-scheduling");
|
|
6
6
|
const adapter_base_sso_1 = require("@tryghost/adapter-base-sso");
|
|
@@ -10,8 +10,7 @@ const adapter_base_route_settings_1 = require("@tryghost/adapter-base-route-sett
|
|
|
10
10
|
const adapter_base_jobs_1 = require("@tryghost/adapter-base-jobs");
|
|
11
11
|
/**
|
|
12
12
|
* The base class every adapter of a given type must extend. Also read by
|
|
13
|
-
* bin/validate-adapters.js,
|
|
14
|
-
* keep this the only place the mapping is declared.
|
|
13
|
+
* bin/validate-adapters.js, so keep this the only place the mapping is declared.
|
|
15
14
|
*/
|
|
16
15
|
exports.baseClasses = {
|
|
17
16
|
storage: ghost_storage_base_1.StorageBase,
|
|
@@ -22,3 +21,22 @@ exports.baseClasses = {
|
|
|
22
21
|
'route-settings': adapter_base_route_settings_1.RouteSettingsStoreBase,
|
|
23
22
|
jobs: adapter_base_jobs_1.JobsBackendBase,
|
|
24
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* The package each base class above is imported from. An adapter that installs
|
|
26
|
+
* one of these itself gets a second copy of the base class - a different function
|
|
27
|
+
* object, so `instanceof` fails and Ghost falls back to comparing class names.
|
|
28
|
+
* bin/validate-adapters.js fails a build on such a duplicate, where a duplicate
|
|
29
|
+
* of any other package is only reported.
|
|
30
|
+
*
|
|
31
|
+
* Keyed by adapter type so `satisfies` demands an entry per type in
|
|
32
|
+
* `baseClasses`; a unit test keeps the names matching the imports above.
|
|
33
|
+
*/
|
|
34
|
+
exports.baseClassPackages = {
|
|
35
|
+
storage: 'ghost-storage-base',
|
|
36
|
+
scheduling: '@tryghost/adapter-base-scheduling',
|
|
37
|
+
sso: '@tryghost/adapter-base-sso',
|
|
38
|
+
cache: '@tryghost/adapter-base-cache',
|
|
39
|
+
redirects: '@tryghost/adapter-base-redirects',
|
|
40
|
+
'route-settings': '@tryghost/adapter-base-route-settings',
|
|
41
|
+
jobs: '@tryghost/adapter-base-jobs',
|
|
42
|
+
};
|
|
@@ -18,16 +18,22 @@ exports.getAutomatedEmailRecipientsByMailgunIds = getAutomatedEmailRecipientsByM
|
|
|
18
18
|
exports.trackEmailDeliveredAndOpened = trackEmailDeliveredAndOpened;
|
|
19
19
|
exports.trackEmailClicked = trackEmailClicked;
|
|
20
20
|
const errors_1 = __importDefault(require("@tryghost/errors"));
|
|
21
|
+
const logging_1 = __importDefault(require("@tryghost/logging"));
|
|
21
22
|
const tpl_1 = __importDefault(require("@tryghost/tpl"));
|
|
22
23
|
const bson_objectid_1 = __importDefault(require("bson-objectid"));
|
|
23
24
|
const zod_1 = require("zod");
|
|
24
25
|
const database_automations_repository_1 = require("./database-automations-repository");
|
|
25
26
|
const fake_wait_hours_multiplier_1 = require("./fake-wait-hours-multiplier");
|
|
27
|
+
const tinybird_automation_stats_1 = require("./tinybird-automation-stats");
|
|
26
28
|
const start_automations_poll_event_1 = require("./events/start-automations-poll-event");
|
|
27
29
|
const { knex } = require('../../data/db');
|
|
28
30
|
const domainEvents = require('@tryghost/domain-events');
|
|
29
31
|
const labs = require('../../../shared/labs');
|
|
30
32
|
const config = require('../../../shared/config');
|
|
33
|
+
const settingsCache = require('../../../shared/settings-cache');
|
|
34
|
+
const requestExternal = require('../../lib/request-external');
|
|
35
|
+
const TinybirdServiceWrapper = require('../tinybird');
|
|
36
|
+
const { create: createTinybirdClient } = require('../stats/utils/tinybird');
|
|
31
37
|
const lexicalLib = require('../../lib/lexical');
|
|
32
38
|
const MAX_AUTOMATION_ACTIONS = 20;
|
|
33
39
|
const messages = {
|
|
@@ -77,8 +83,47 @@ const repository = (0, database_automations_repository_1.createDatabaseAutomatio
|
|
|
77
83
|
knex,
|
|
78
84
|
fakeWaitHoursMultiplier: (0, fake_wait_hours_multiplier_1.parseFakeWaitHoursMultiplier)(config.get('automations:fakeWaitHoursMultiplier')),
|
|
79
85
|
});
|
|
86
|
+
function getTinybirdClient() {
|
|
87
|
+
if (!labs.isSet('automationsTinybirdSync') || !config.get('tinybird:stats')) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
const tinybirdService = TinybirdServiceWrapper.instance;
|
|
92
|
+
if (!tinybirdService?.getToken()?.token) {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
return createTinybirdClient({
|
|
96
|
+
config,
|
|
97
|
+
// Fall back to MySQL after the first failed attempt.
|
|
98
|
+
request: requestExternal.extend({ retry: { limit: 0 } }),
|
|
99
|
+
settingsCache,
|
|
100
|
+
tinybirdService,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
logging_1.default.error('Error preparing Tinybird automation stats client:', error);
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
80
108
|
async function browse() {
|
|
81
|
-
|
|
109
|
+
const tinybirdClient = getTinybirdClient();
|
|
110
|
+
if (!tinybirdClient) {
|
|
111
|
+
return await repository.browse({ includeStats: true });
|
|
112
|
+
}
|
|
113
|
+
const [browseResult, stats] = await Promise.all([
|
|
114
|
+
repository.browse({ includeStats: false }),
|
|
115
|
+
(0, tinybird_automation_stats_1.fetchAutomationStats)(tinybirdClient),
|
|
116
|
+
]);
|
|
117
|
+
if (stats === null) {
|
|
118
|
+
return await repository.browse({ includeStats: true });
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
...browseResult,
|
|
122
|
+
data: browseResult.data.map((automation) => ({
|
|
123
|
+
...automation,
|
|
124
|
+
stats: stats.get(automation.id) ?? { ...tinybird_automation_stats_1.EMPTY_AUTOMATION_STATS },
|
|
125
|
+
})),
|
|
126
|
+
};
|
|
82
127
|
}
|
|
83
128
|
async function read(automationId) {
|
|
84
129
|
const automation = await repository.getById(automationId);
|
|
@@ -0,0 +1,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.EMPTY_AUTOMATION_STATS = void 0;
|
|
7
|
+
exports.fetchAutomationStats = fetchAutomationStats;
|
|
8
|
+
const logging_1 = __importDefault(require("@tryghost/logging"));
|
|
9
|
+
const zod_1 = require("zod");
|
|
10
|
+
exports.EMPTY_AUTOMATION_STATS = {
|
|
11
|
+
last_run_created_at: null,
|
|
12
|
+
total_run_count: 0,
|
|
13
|
+
in_progress_run_count: 0,
|
|
14
|
+
};
|
|
15
|
+
const runCountSchema = zod_1.z
|
|
16
|
+
.union([zod_1.z.number(), zod_1.z.string().regex(/^\d+$/)])
|
|
17
|
+
.pipe(zod_1.z.coerce.number().int().nonnegative());
|
|
18
|
+
const statsRowSchema = zod_1.z.object({
|
|
19
|
+
automation_id: zod_1.z.string(),
|
|
20
|
+
last_run_created_at: zod_1.z.iso
|
|
21
|
+
.datetime()
|
|
22
|
+
.transform((value) => new Date(value))
|
|
23
|
+
.nullable(),
|
|
24
|
+
total_run_count: runCountSchema,
|
|
25
|
+
in_progress_run_count: runCountSchema,
|
|
26
|
+
});
|
|
27
|
+
async function fetchAutomationStats(client) {
|
|
28
|
+
let rows;
|
|
29
|
+
try {
|
|
30
|
+
// Override the traffic analytics version: this pipe has no version suffix.
|
|
31
|
+
rows = await client.fetch('api_automation_browse_stats', { version: '' });
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
logging_1.default.error('Error fetching Tinybird automation stats:', error);
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
if (rows === null) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
const parsed = zod_1.z.array(statsRowSchema).safeParse(rows);
|
|
41
|
+
if (!parsed.success) {
|
|
42
|
+
logging_1.default.error({
|
|
43
|
+
system: { event: 'automations.stats.invalid_tinybird_response' },
|
|
44
|
+
issues: parsed.error.issues,
|
|
45
|
+
}, 'Unexpected response from the Tinybird automation stats pipe');
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
return new Map(parsed.data.map((row) => [
|
|
49
|
+
row.automation_id,
|
|
50
|
+
{
|
|
51
|
+
last_run_created_at: row.last_run_created_at,
|
|
52
|
+
total_run_count: row.total_run_count,
|
|
53
|
+
in_progress_run_count: row.in_progress_run_count,
|
|
54
|
+
},
|
|
55
|
+
]));
|
|
56
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PostMediaInliner = exports.MediaInliningFailure = void 0;
|
|
4
4
|
exports.isBlockedMediaUrl = isBlockedMediaUrl;
|
|
5
|
-
const cheerio = require('cheerio');
|
|
5
|
+
const cheerio = require('cheerio/slim');
|
|
6
6
|
class MediaInliningFailure extends Error {
|
|
7
7
|
failures;
|
|
8
8
|
constructor(failures) {
|
|
@@ -75,7 +75,7 @@ class EmailAnalyticsServiceWrapper {
|
|
|
75
75
|
}
|
|
76
76
|
return result;
|
|
77
77
|
}
|
|
78
|
-
_logJobCompletion(jobType, fetchResult, totalDurationMs) {
|
|
78
|
+
_logJobCompletion(jobType, fetchResult, totalDurationMs, lagSeconds = null) {
|
|
79
79
|
const config = this.#getConfig();
|
|
80
80
|
const { eventCount, apiPollingTimeMs, processingTimeMs, aggregationTimeMs, emailAggregationTimeMs, memberAggregationTimeMs, result, } = fetchResult;
|
|
81
81
|
if (eventCount === 0) {
|
|
@@ -89,6 +89,7 @@ class EmailAnalyticsServiceWrapper {
|
|
|
89
89
|
const logMessage = [
|
|
90
90
|
`[Background Job] ${this.#backgroundJobName} processed ${jobType} | ${this.#logPrefix}`,
|
|
91
91
|
`${eventCount} events in ${(totalDurationMs / 1000).toFixed(1)}s (${throughput.toFixed(2)} events/s)`,
|
|
92
|
+
...(lagSeconds === null ? [] : [`Lag: ${(lagSeconds / 60).toFixed(1)}m`]),
|
|
92
93
|
`Mode: ${batchMode}`,
|
|
93
94
|
`Timings: API ${(apiPollingTimeMs / 1000).toFixed(1)}s (${apiPercent}%) / Processing ${(processingTimeMs / 1000).toFixed(1)}s (${processingPercent}%) / Aggregation ${(aggregationTimeMs / 1000).toFixed(1)}s (${aggregationPercent}%) [Email ${(emailAggregationTimeMs / 1000).toFixed(1)}s / Member ${(memberAggregationTimeMs / 1000).toFixed(1)}s]`,
|
|
94
95
|
`Events: opened=${result.opened} delivered=${result.delivered} failed=${result.permanentFailed + result.temporaryFailed} unprocessable=${result.unprocessable}`,
|
|
@@ -100,6 +101,7 @@ class EmailAnalyticsServiceWrapper {
|
|
|
100
101
|
task: jobType,
|
|
101
102
|
event_count: eventCount,
|
|
102
103
|
duration_ms: totalDurationMs,
|
|
104
|
+
...(lagSeconds === null ? {} : { lag_seconds: lagSeconds }),
|
|
103
105
|
},
|
|
104
106
|
}, logMessage);
|
|
105
107
|
// We're only concerned with open throughput as this is displayed to users and is most sensitive to being up to date
|
|
@@ -124,46 +126,30 @@ class EmailAnalyticsServiceWrapper {
|
|
|
124
126
|
}
|
|
125
127
|
}
|
|
126
128
|
}
|
|
127
|
-
async
|
|
128
|
-
const config = this.#getConfig();
|
|
129
|
-
const beginTimestamp = await this.service.getLastOpenedEventTimestamp();
|
|
130
|
-
const lagMinutes = (Date.now() - beginTimestamp.getTime()) / 60000;
|
|
131
|
-
const lagThreshold = config.get('emailAnalytics:openedJobLagWarningMinutes');
|
|
132
|
-
// NOTE: We only update the begin timestamp when we process events, so there's cases where we can have a false positive
|
|
133
|
-
// - Ghost or Mailgun outages
|
|
134
|
-
// - Lack of actual email activity
|
|
135
|
-
if (lagThreshold && lagMinutes > lagThreshold) {
|
|
136
|
-
logging_1.default.warn(`${this.#logPrefix} Opened events processing is ${lagMinutes.toFixed(1)} minutes behind (threshold: ${lagThreshold})`);
|
|
137
|
-
}
|
|
129
|
+
async #fetchAndLog(jobType, fetch, lagPipeline) {
|
|
138
130
|
const fetchStartedAt = Date.now();
|
|
139
|
-
const fetchResult = await
|
|
131
|
+
const fetchResult = await fetch();
|
|
140
132
|
const totalDuration = Date.now() - fetchStartedAt;
|
|
141
|
-
|
|
133
|
+
// Lag is read after the fetch so a clean run counts as caught up
|
|
134
|
+
const lagSeconds = lagPipeline ? this.service.getStatus()[lagPipeline].lagSeconds : null;
|
|
135
|
+
this._logJobCompletion(jobType, fetchResult, totalDuration, lagSeconds);
|
|
142
136
|
return fetchResult.eventCount;
|
|
143
137
|
}
|
|
138
|
+
async fetchLatestOpenedEvents({ maxEvents = Infinity, } = {}) {
|
|
139
|
+
return this.#fetchAndLog('latest-opened', () => this.service.fetchLatestOpenedEvents({ maxEvents }), 'latestOpened');
|
|
140
|
+
}
|
|
144
141
|
async fetchLatestNonOpenedEvents({ maxEvents = Infinity, } = {}) {
|
|
145
|
-
|
|
146
|
-
const fetchResult = await this.service.fetchLatestNonOpenedEvents({ maxEvents });
|
|
147
|
-
const totalDuration = Date.now() - fetchStartedAt;
|
|
148
|
-
this._logJobCompletion('latest', fetchResult, totalDuration);
|
|
149
|
-
return fetchResult.eventCount;
|
|
142
|
+
return this.#fetchAndLog('latest', () => this.service.fetchLatestNonOpenedEvents({ maxEvents }), 'latest');
|
|
150
143
|
}
|
|
151
144
|
async fetchMissing({ maxEvents = Infinity } = {}) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const totalDuration = Date.now() - fetchStartedAt;
|
|
155
|
-
this._logJobCompletion('missing', fetchResult, totalDuration);
|
|
156
|
-
return fetchResult.eventCount;
|
|
145
|
+
// The missing-events sweep trails the delivery pipeline by design, so it has no lag of its own
|
|
146
|
+
return this.#fetchAndLog('missing', () => this.service.fetchMissing({ maxEvents }));
|
|
157
147
|
}
|
|
158
148
|
async fetchScheduled({ maxEvents }) {
|
|
159
149
|
if (maxEvents < 300) {
|
|
160
150
|
return 0;
|
|
161
151
|
}
|
|
162
|
-
|
|
163
|
-
const fetchResult = await this.service.fetchScheduled({ maxEvents });
|
|
164
|
-
const totalDuration = Date.now() - fetchStartedAt;
|
|
165
|
-
this._logJobCompletion('scheduled', fetchResult, totalDuration);
|
|
166
|
-
return fetchResult.eventCount;
|
|
152
|
+
return this.#fetchAndLog('scheduled', () => this.service.fetchScheduled({ maxEvents }));
|
|
167
153
|
}
|
|
168
154
|
async startFetch() {
|
|
169
155
|
const startedAt = Date.now();
|
|
@@ -65,11 +65,18 @@ class EmailAnalyticsService {
|
|
|
65
65
|
this.queries.setJobMetadata(this.#jobNames.scheduled, null);
|
|
66
66
|
}
|
|
67
67
|
getStatus() {
|
|
68
|
+
const now = Date.now();
|
|
69
|
+
const withLag = (data) => Object.assign(data, {
|
|
70
|
+
fetchedThrough: data.fetchedThrough ?? null,
|
|
71
|
+
lagSeconds: data.fetchedThrough
|
|
72
|
+
? Math.max(0, Math.floor((now - data.fetchedThrough.getTime()) / 1000))
|
|
73
|
+
: null,
|
|
74
|
+
});
|
|
68
75
|
return {
|
|
69
|
-
latest: this.#fetchLatestNonOpenedData,
|
|
70
|
-
missing: this.#fetchMissingData,
|
|
76
|
+
latest: withLag(this.#fetchLatestNonOpenedData),
|
|
77
|
+
missing: withLag(this.#fetchMissingData),
|
|
71
78
|
scheduled: this.#fetchScheduledData,
|
|
72
|
-
latestOpened: this.#fetchLatestOpenedData,
|
|
79
|
+
latestOpened: withLag(this.#fetchLatestOpenedData),
|
|
73
80
|
};
|
|
74
81
|
}
|
|
75
82
|
/**
|
|
@@ -363,6 +370,7 @@ class EmailAnalyticsService {
|
|
|
363
370
|
});
|
|
364
371
|
}
|
|
365
372
|
};
|
|
373
|
+
let fetchedThrough;
|
|
366
374
|
try {
|
|
367
375
|
const fetchResult = await this.#fetchEvents({
|
|
368
376
|
batchHandler: processBatch,
|
|
@@ -371,6 +379,11 @@ class EmailAnalyticsService {
|
|
|
371
379
|
maxEvents,
|
|
372
380
|
events: eventTypes,
|
|
373
381
|
});
|
|
382
|
+
// A void result means fetching was skipped (for example, Mailgun is not configured).
|
|
383
|
+
// Empty successful windows still establish progress through their requested end.
|
|
384
|
+
if (fetchResult) {
|
|
385
|
+
fetchedThrough = fetchResult.safeCursor ?? end;
|
|
386
|
+
}
|
|
374
387
|
if (fetchResult?.safeCursor &&
|
|
375
388
|
(!fetchData.lastEventTimestamp || fetchResult.safeCursor < fetchData.lastEventTimestamp)) {
|
|
376
389
|
fetchData.lastEventTimestamp = fetchResult.safeCursor;
|
|
@@ -425,6 +438,9 @@ class EmailAnalyticsService {
|
|
|
425
438
|
if (error) {
|
|
426
439
|
throw error;
|
|
427
440
|
}
|
|
441
|
+
if (fetchedThrough) {
|
|
442
|
+
fetchData.fetchedThrough = fetchedThrough;
|
|
443
|
+
}
|
|
428
444
|
return {
|
|
429
445
|
eventCount,
|
|
430
446
|
apiPollingTimeMs,
|
|
@@ -50,8 +50,13 @@ const init = ({ automationsApi, config, db, domainEvents, emailSuppressionList,
|
|
|
50
50
|
prometheusClient,
|
|
51
51
|
});
|
|
52
52
|
const newsletterMailgunTags = ['bulk-email'];
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
const automationMailgunTags = [constants_1.AUTOMATION_EMAIL_TAG];
|
|
54
|
+
const giftMailgunTags = [constants_2.GIFT_DELIVERY_EMAIL_TAG];
|
|
55
|
+
const mailgunTagFromConfig = config.get('bulkEmail:mailgun:tag');
|
|
56
|
+
if (mailgunTagFromConfig) {
|
|
57
|
+
newsletterMailgunTags.push(mailgunTagFromConfig);
|
|
58
|
+
automationMailgunTags.push(mailgunTagFromConfig);
|
|
59
|
+
giftMailgunTags.push(mailgunTagFromConfig);
|
|
55
60
|
}
|
|
56
61
|
prometheusClient?.registerCounter({
|
|
57
62
|
name: newsletter_email_analytics_batch_processor_1.AGGREGATE_MEMBER_STATS_METRIC_NAME,
|
|
@@ -91,7 +96,7 @@ const init = ({ automationsApi, config, db, domainEvents, emailSuppressionList,
|
|
|
91
96
|
domainEvents,
|
|
92
97
|
event: start_automation_email_analytics_job_event_1.StartAutomationEmailAnalyticsJobEvent,
|
|
93
98
|
queries,
|
|
94
|
-
mailgunTags:
|
|
99
|
+
mailgunTags: automationMailgunTags,
|
|
95
100
|
jobNames: {
|
|
96
101
|
latestNonOpened: 'email-analytics-automation-latest-others',
|
|
97
102
|
missing: 'email-analytics-automation-missing',
|
|
@@ -116,7 +121,7 @@ const init = ({ automationsApi, config, db, domainEvents, emailSuppressionList,
|
|
|
116
121
|
domainEvents,
|
|
117
122
|
event: start_gift_email_analytics_job_event_1.StartGiftEmailAnalyticsJobEvent,
|
|
118
123
|
queries,
|
|
119
|
-
mailgunTags:
|
|
124
|
+
mailgunTags: giftMailgunTags,
|
|
120
125
|
jobNames: {
|
|
121
126
|
latestNonOpened: 'email-analytics-gifts-latest-others',
|
|
122
127
|
missing: 'email-analytics-gifts-missing',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const cheerio = require('cheerio');
|
|
1
|
+
const cheerio = require('cheerio/slim');
|
|
2
2
|
const juice = require('juice');
|
|
3
3
|
const htmlToPlaintext = require('@tryghost/html-to-plaintext');
|
|
4
4
|
|
|
@@ -12,7 +12,12 @@ const finalizeHtml = (html) => {
|
|
|
12
12
|
$('figcaption').addClass('kg-card-figcaption');
|
|
13
13
|
html = $.html();
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
// resolveCSSVariables crashes on nameless declarations in user-authored style attributes
|
|
16
|
+
const juicedHtml = juice(html, {
|
|
17
|
+
inlinePseudoElements: true,
|
|
18
|
+
removeStyleTags: true,
|
|
19
|
+
resolveCSSVariables: false,
|
|
20
|
+
});
|
|
16
21
|
|
|
17
22
|
// Many email clients, like Outlook and Yahoo, [lack support for <figure>
|
|
18
23
|
// and <figcaption>][0]. To work around this, change the tags to <div>s.
|
|
@@ -25,6 +25,9 @@ failed email.
|
|
|
25
25
|
The rough ETA measures recent recipient throughput, including work completed by
|
|
26
26
|
concurrent workers. It stays `null` until enough timing samples are available in
|
|
27
27
|
the current phase and attempt, so short sends may finish without showing an ETA.
|
|
28
|
+
The rate uses the last minute of completions, including the interval crossing
|
|
29
|
+
the window boundary. Early estimates use the available history. Sparse sends
|
|
30
|
+
retain at least two measured intervals.
|
|
28
31
|
Progress counts update independently of the estimate.
|
|
29
32
|
|
|
30
33
|
The ETA is always `null` for failed emails and `0` once no work remains in the
|
|
@@ -192,7 +192,7 @@ function escapeRegExp(string) {
|
|
|
192
192
|
* @return {ReturnType<typeof cheerio.load>}
|
|
193
193
|
*/
|
|
194
194
|
function cheerioLoad(html) {
|
|
195
|
-
const cheerio = require('cheerio');
|
|
195
|
+
const cheerio = require('cheerio/slim');
|
|
196
196
|
return cheerio.load(html);
|
|
197
197
|
}
|
|
198
198
|
|
|
@@ -709,7 +709,12 @@ class EmailRenderer {
|
|
|
709
709
|
|
|
710
710
|
// Juice HTML (inline CSS)
|
|
711
711
|
const juice = require('juice');
|
|
712
|
-
|
|
712
|
+
// resolveCSSVariables crashes on nameless declarations in user-authored style attributes
|
|
713
|
+
html = juice(html, {
|
|
714
|
+
inlinePseudoElements: true,
|
|
715
|
+
removeStyleTags: true,
|
|
716
|
+
resolveCSSVariables: false,
|
|
717
|
+
});
|
|
713
718
|
|
|
714
719
|
// happens after inlining of CSS so we can change element types without worrying about styling
|
|
715
720
|
$ = cheerioLoad(html);
|
|
@@ -44,7 +44,7 @@ class EmailServiceWrapper {
|
|
|
44
44
|
const limitService = require('../limits');
|
|
45
45
|
const labs = require('../../../shared/labs');
|
|
46
46
|
const emailAddressService = require('../email-address');
|
|
47
|
-
const i18nLib = require('@tryghost/i18n');
|
|
47
|
+
const i18nLib = require('@tryghost/i18n').default;
|
|
48
48
|
const lexicalLib = require('../../lib/lexical');
|
|
49
49
|
const urlUtils = require('../../../shared/url-utils').default;
|
|
50
50
|
const memberAttribution = require('../member-attribution');
|