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
|
@@ -1,28 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.INTERNAL = exports.MEMBERS = exports.ADMIN = void 0;
|
|
4
|
-
exports.
|
|
3
|
+
exports.INTERNAL = exports.MEMBERS = exports.ADMIN = exports.MemberAccessSchema = exports.MEMBER_ACCESS = void 0;
|
|
4
|
+
exports.readableLevels = readableLevels;
|
|
5
5
|
exports.canWrite = canWrite;
|
|
6
|
+
const metafield_types_1 = require("@tryghost/metafield-types");
|
|
7
|
+
Object.defineProperty(exports, "MEMBER_ACCESS", { enumerable: true, get: function () { return metafield_types_1.MEMBER_ACCESS; } });
|
|
8
|
+
Object.defineProperty(exports, "MemberAccessSchema", { enumerable: true, get: function () { return metafield_types_1.MemberAccessSchema; } });
|
|
9
|
+
const EVERY_LEVEL = [...metafield_types_1.MEMBER_ACCESS_LEVELS];
|
|
6
10
|
exports.ADMIN = { entry: 'admin' };
|
|
7
11
|
exports.MEMBERS = { entry: 'members' };
|
|
8
12
|
exports.INTERNAL = { entry: 'internal' };
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
// Every audience is spelled out with the levels it may read, staff included, because
|
|
14
|
+
// reads narrow on whatever this returns and an audience with no entry gets an empty
|
|
15
|
+
// list, which matches no field. Giving staff a way to skip the check instead would
|
|
16
|
+
// invert that: an unrecognised audience would then match everything.
|
|
17
|
+
const READABLE = {
|
|
18
|
+
admin: EVERY_LEVEL,
|
|
19
|
+
internal: EVERY_LEVEL,
|
|
20
|
+
members: [metafield_types_1.MEMBER_ACCESS.read, metafield_types_1.MEMBER_ACCESS.write],
|
|
21
|
+
};
|
|
22
|
+
const WRITABLE = {
|
|
23
|
+
admin: EVERY_LEVEL,
|
|
24
|
+
internal: EVERY_LEVEL,
|
|
25
|
+
members: [metafield_types_1.MEMBER_ACCESS.write],
|
|
26
|
+
};
|
|
27
|
+
// `Object.hasOwn` rather than a plain lookup: an entry naming a property every object
|
|
28
|
+
// inherits (`__proto__`, `constructor`, `toString`) would otherwise return that
|
|
29
|
+
// inherited value instead of falling through to the empty list.
|
|
30
|
+
function levelsFor(table, audience) {
|
|
31
|
+
const entry = audience?.entry;
|
|
32
|
+
return entry !== undefined && Object.hasOwn(table, entry) ? table[entry] : [];
|
|
18
33
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
* permission could not express.
|
|
25
|
-
*/
|
|
26
|
-
function canWrite(_audience, _field) {
|
|
27
|
-
return true;
|
|
34
|
+
function readableLevels(audience) {
|
|
35
|
+
return levelsFor(READABLE, audience);
|
|
36
|
+
}
|
|
37
|
+
function canWrite(audience, field) {
|
|
38
|
+
return levelsFor(WRITABLE, audience).includes(field.memberAccess);
|
|
28
39
|
}
|
|
@@ -9,6 +9,13 @@ const models_1 = require("./models");
|
|
|
9
9
|
exports.metafieldCodec = zod_1.z.codec(schema_1.DbMetafield, models_1.Metafield, {
|
|
10
10
|
// DbMetafield validates `type` as the field-type enum, so the decoded row
|
|
11
11
|
// already carries a FieldType and camelKeys preserves it — no cast needed.
|
|
12
|
-
decode: (
|
|
13
|
-
|
|
12
|
+
decode: ({ member_access: memberAccess, ...row }) => ({
|
|
13
|
+
...(0, case_keys_1.camelKeys)(row),
|
|
14
|
+
namespace: identity_1.CUSTOM_NAMESPACE,
|
|
15
|
+
access: { member: memberAccess },
|
|
16
|
+
}),
|
|
17
|
+
encode: ({ namespace: _namespace, access, ...field }) => ({
|
|
18
|
+
...(0, case_keys_1.snakeKeys)(field),
|
|
19
|
+
member_access: access.member,
|
|
20
|
+
}),
|
|
14
21
|
});
|
|
@@ -47,10 +47,12 @@ const FieldName = zod_1.z
|
|
|
47
47
|
.trim()
|
|
48
48
|
.min(1, { message: 'Custom field name is required.' })
|
|
49
49
|
.max(MAX_NAME_LENGTH, { message: 'Custom field name is too long.' });
|
|
50
|
-
|
|
50
|
+
const FieldAccess = zod_1.z.object({ member: access_1.MemberAccessSchema });
|
|
51
|
+
// No key: the backend mints it from the name.
|
|
51
52
|
const AddFieldInput = zod_1.z.object({
|
|
52
53
|
name: FieldName,
|
|
53
54
|
type: metafield_types_1.FieldTypeSchema,
|
|
55
|
+
access: FieldAccess.optional(),
|
|
54
56
|
});
|
|
55
57
|
// A bound on the work one request can ask for, separate from how many definitions
|
|
56
58
|
// a site may hold in total. Every definition in a batch costs several queries
|
|
@@ -73,11 +75,12 @@ const ReorderInput = zod_1.z
|
|
|
73
75
|
key: zod_1.z.string().min(1, { message: 'Every custom field in the order needs a key.' }),
|
|
74
76
|
}))
|
|
75
77
|
.min(1, { message: 'The order must name every custom field.' });
|
|
76
|
-
// Name and
|
|
77
|
-
// rules can reject a change loudly; they are never persisted.
|
|
78
|
+
// Name, status and access are mutable. `key` and `type` are accepted so the
|
|
79
|
+
// immutability rules can reject a change loudly; they are never persisted.
|
|
78
80
|
const EditFieldInput = zod_1.z.object({
|
|
79
81
|
name: FieldName.optional(),
|
|
80
82
|
status: schema_1.FieldStatusSchema.optional(),
|
|
83
|
+
access: FieldAccess.optional(),
|
|
81
84
|
key: zod_1.z.string().optional(),
|
|
82
85
|
type: metafield_types_1.FieldTypeSchema.optional(),
|
|
83
86
|
});
|
|
@@ -95,8 +98,8 @@ class MetafieldDefinitionsService {
|
|
|
95
98
|
// restart. Where the number comes from is the caller's business.
|
|
96
99
|
this.getMaxDefinitions = getMaxDefinitions;
|
|
97
100
|
}
|
|
98
|
-
async
|
|
99
|
-
const [field] = await this.list((0, queries_1.
|
|
101
|
+
async hasAnyReadable(audience) {
|
|
102
|
+
const [field] = await this.list((0, queries_1.definitions)(this.knex, { audience, status: queries_1.ACTIVE_ONLY, limit: 1 }));
|
|
100
103
|
return Boolean(field);
|
|
101
104
|
}
|
|
102
105
|
/**
|
|
@@ -106,34 +109,35 @@ class MetafieldDefinitionsService {
|
|
|
106
109
|
isStored(namespace) {
|
|
107
110
|
return namespace === identity_1.CUSTOM_NAMESPACE;
|
|
108
111
|
}
|
|
109
|
-
async browse(options
|
|
112
|
+
async browse(options, audience) {
|
|
110
113
|
if (options.namespace !== undefined && !this.isStored(options.namespace)) {
|
|
111
114
|
return [];
|
|
112
115
|
}
|
|
113
|
-
// Archived fields are hidden by default: most surfaces (member details, the
|
|
114
|
-
// filter picker, the importer) only ever want active fields. A caller-
|
|
115
|
-
// supplied `filter` can widen that — Settings pulls active and archived
|
|
116
|
-
// together in one request (`filter=status:[active,archived]`).
|
|
117
|
-
//
|
|
118
116
|
// Whichever set comes back, it comes back in the publisher's order: filtering
|
|
119
117
|
// narrows the list, it never reorders it.
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
118
|
+
const { filter } = options;
|
|
119
|
+
if (filter) {
|
|
120
|
+
// A filter naming `status` decides the statuses itself, which is how Settings
|
|
121
|
+
// pulls active and archived together in one request
|
|
122
|
+
// (`filter=status:[active,archived]`). One that does not gets the same active-only
|
|
123
|
+
// scope as an unfiltered read.
|
|
124
|
+
const parsed = parseFilter(filter);
|
|
125
|
+
return this.list((0, queries_1.definitions)(this.knex, {
|
|
126
|
+
audience,
|
|
127
|
+
status: filterReferencesStatus(parsed) ? queries_1.ANY_STATUS : queries_1.ACTIVE_ONLY,
|
|
128
|
+
filter: (query) => knexify(query, parsed, { tableName: TABLE }),
|
|
129
|
+
}));
|
|
130
|
+
}
|
|
131
|
+
return this.list((0, queries_1.definitions)(this.knex, { audience, status: queries_1.ACTIVE_ONLY }));
|
|
124
132
|
}
|
|
125
|
-
/**
|
|
126
|
-
* Decode a definition query into the domain, in the publisher's order.
|
|
127
|
-
*
|
|
128
|
-
* Typed off `activeFields` so the builder keeps the table's row type: every caller
|
|
129
|
-
* hands over a query against the definitions table, whatever it has narrowed.
|
|
130
|
-
*/
|
|
131
133
|
async list(query) {
|
|
132
134
|
const rows = await (0, queries_1.inFieldOrder)(query).select('*');
|
|
133
135
|
return rows.map((row) => zod_1.z.decode(codec_1.metafieldCodec, row));
|
|
134
136
|
}
|
|
135
|
-
async read(namespace, key) {
|
|
136
|
-
const [field] = this.isStored(namespace)
|
|
137
|
+
async read(namespace, key, audience) {
|
|
138
|
+
const [field] = this.isStored(namespace)
|
|
139
|
+
? await this.list((0, queries_1.definitions)(this.knex, { audience, status: queries_1.ANY_STATUS, key }))
|
|
140
|
+
: [];
|
|
137
141
|
if (!field) {
|
|
138
142
|
throw new errors_1.default.NotFoundError({ message: 'Custom field not found.' });
|
|
139
143
|
}
|
|
@@ -191,6 +195,7 @@ class MetafieldDefinitionsService {
|
|
|
191
195
|
key,
|
|
192
196
|
name: field.name,
|
|
193
197
|
type: field.type,
|
|
198
|
+
memberAccess: field.access?.member ?? access_1.MEMBER_ACCESS.none,
|
|
194
199
|
sortOrder: firstSortOrder + index,
|
|
195
200
|
});
|
|
196
201
|
keys.push(key);
|
|
@@ -236,6 +241,7 @@ class MetafieldDefinitionsService {
|
|
|
236
241
|
key: wanted.key,
|
|
237
242
|
name: wanted.name,
|
|
238
243
|
type: wanted.type,
|
|
244
|
+
memberAccess: wanted.access.member,
|
|
239
245
|
sortOrder: await this.nextSortOrder(db),
|
|
240
246
|
});
|
|
241
247
|
const [created] = await this.readMany(db, [wanted.key]);
|
|
@@ -263,6 +269,7 @@ class MetafieldDefinitionsService {
|
|
|
263
269
|
key: field.key,
|
|
264
270
|
name: field.name,
|
|
265
271
|
type: field.type,
|
|
272
|
+
member_access: field.memberAccess,
|
|
266
273
|
sort_order: field.sortOrder,
|
|
267
274
|
created_at: new Date(),
|
|
268
275
|
});
|
|
@@ -351,7 +358,8 @@ class MetafieldDefinitionsService {
|
|
|
351
358
|
.where('key', key)
|
|
352
359
|
.update({ sort_order: ranks.get(key) });
|
|
353
360
|
}
|
|
354
|
-
|
|
361
|
+
// An order covers the whole list, archived definitions included.
|
|
362
|
+
return this.list((0, queries_1.definitions)(trx, { audience: access_1.ADMIN, status: queries_1.ANY_STATUS }));
|
|
355
363
|
});
|
|
356
364
|
await this.recordAction({
|
|
357
365
|
context,
|
|
@@ -460,7 +468,7 @@ class MetafieldDefinitionsService {
|
|
|
460
468
|
});
|
|
461
469
|
}
|
|
462
470
|
const patch = parsed.data;
|
|
463
|
-
const existing = await this.read(identity_1.CUSTOM_NAMESPACE, key);
|
|
471
|
+
const existing = await this.read(identity_1.CUSTOM_NAMESPACE, key, access_1.ADMIN);
|
|
464
472
|
// Key and type are immutable after creation: values are addressed by key
|
|
465
473
|
// and interpreted by type, so changing either would silently orphan or
|
|
466
474
|
// corrupt stored values. Reject a differing value rather than ignore it.
|
|
@@ -500,6 +508,22 @@ class MetafieldDefinitionsService {
|
|
|
500
508
|
details: { primary_name: patch.name, key, previous_name: existing.name },
|
|
501
509
|
});
|
|
502
510
|
}
|
|
511
|
+
if (patch.access !== undefined && patch.access.member !== existing.access.member) {
|
|
512
|
+
await this.knex(TABLE)
|
|
513
|
+
.where('key', key)
|
|
514
|
+
.update({ member_access: patch.access.member, updated_at: new Date() });
|
|
515
|
+
await this.recordAction({
|
|
516
|
+
context,
|
|
517
|
+
verb: 'changeAccess',
|
|
518
|
+
subject: existing.id,
|
|
519
|
+
details: {
|
|
520
|
+
primary_name: patch.name ?? existing.name,
|
|
521
|
+
key,
|
|
522
|
+
member_access: patch.access.member,
|
|
523
|
+
previous_member_access: existing.access.member,
|
|
524
|
+
},
|
|
525
|
+
});
|
|
526
|
+
}
|
|
503
527
|
// A status change is the archive/restore transition. Only write (and log)
|
|
504
528
|
// when it actually flips, so re-sending the current status is a no-op.
|
|
505
529
|
if (patch.status !== undefined && patch.status !== existing.status) {
|
|
@@ -514,7 +538,7 @@ class MetafieldDefinitionsService {
|
|
|
514
538
|
details: { primary_name: patch.name ?? existing.name, key },
|
|
515
539
|
});
|
|
516
540
|
}
|
|
517
|
-
return this.read(identity_1.CUSTOM_NAMESPACE, key);
|
|
541
|
+
return this.read(identity_1.CUSTOM_NAMESPACE, key, access_1.ADMIN);
|
|
518
542
|
}
|
|
519
543
|
/**
|
|
520
544
|
* Permanently delete a field and every member value attached to it (the FK
|
|
@@ -597,12 +621,11 @@ function isUniqueConstraintViolation(error) {
|
|
|
597
621
|
const code = error?.code;
|
|
598
622
|
return code === 'ER_DUP_ENTRY' || code === 'SQLITE_CONSTRAINT';
|
|
599
623
|
}
|
|
600
|
-
//
|
|
601
|
-
//
|
|
602
|
-
// the
|
|
603
|
-
//
|
|
604
|
-
|
|
605
|
-
function applyFilter(query, filter) {
|
|
624
|
+
// Parse a caller-supplied NQL filter, without applying it. A malformed filter is a
|
|
625
|
+
// client error (400), not a 500. Whether the result widens the statuses is decided by
|
|
626
|
+
// the caller, which reads it with `filterReferencesStatus` and says so when building
|
|
627
|
+
// the query; nothing here narrows anything.
|
|
628
|
+
function parseFilter(filter) {
|
|
606
629
|
let mongoQuery;
|
|
607
630
|
try {
|
|
608
631
|
mongoQuery = nql(filter).toJSON();
|
|
@@ -623,20 +646,7 @@ function applyFilter(query, filter) {
|
|
|
623
646
|
property: 'filter',
|
|
624
647
|
});
|
|
625
648
|
}
|
|
626
|
-
|
|
627
|
-
knexify(query, mongoQuery, { tableName: TABLE });
|
|
628
|
-
}
|
|
629
|
-
catch (err) {
|
|
630
|
-
throw new errors_1.default.BadRequestError({
|
|
631
|
-
message: 'Could not parse the filter parameter.',
|
|
632
|
-
property: 'filter',
|
|
633
|
-
err: err,
|
|
634
|
-
});
|
|
635
|
-
}
|
|
636
|
-
if (!filterReferencesStatus(mongoQuery)) {
|
|
637
|
-
query.where('status', schema_1.FIELD_STATUS.active);
|
|
638
|
-
}
|
|
639
|
-
return query;
|
|
649
|
+
return mongoQuery;
|
|
640
650
|
}
|
|
641
651
|
// Whether an NQL-parsed filter constrains `status` anywhere, including inside the
|
|
642
652
|
// $and/$or/$nor combinators — so a status filter at any nesting counts as the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.bindings = exports.values = exports.definitions = exports.
|
|
3
|
+
exports.bindings = exports.values = exports.definitions = exports.canWrite = exports.MEMBER_ACCESS = exports.MEMBERS = exports.INTERNAL = exports.ADMIN = exports.actingContext = void 0;
|
|
4
4
|
exports.init = init;
|
|
5
5
|
const definitions_service_1 = require("./definitions-service");
|
|
6
6
|
const values_service_1 = require("./values-service");
|
|
@@ -16,8 +16,8 @@ var access_1 = require("./access");
|
|
|
16
16
|
Object.defineProperty(exports, "ADMIN", { enumerable: true, get: function () { return access_1.ADMIN; } });
|
|
17
17
|
Object.defineProperty(exports, "INTERNAL", { enumerable: true, get: function () { return access_1.INTERNAL; } });
|
|
18
18
|
Object.defineProperty(exports, "MEMBERS", { enumerable: true, get: function () { return access_1.MEMBERS; } });
|
|
19
|
+
Object.defineProperty(exports, "MEMBER_ACCESS", { enumerable: true, get: function () { return access_1.MEMBER_ACCESS; } });
|
|
19
20
|
Object.defineProperty(exports, "canWrite", { enumerable: true, get: function () { return access_1.canWrite; } });
|
|
20
|
-
Object.defineProperty(exports, "readableFields", { enumerable: true, get: function () { return access_1.readableFields; } });
|
|
21
21
|
function init() {
|
|
22
22
|
// The three are constructed together below, so checking all of them keeps the "all or
|
|
23
23
|
// none" invariant explicit rather than trusting one to stand in for the rest.
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Metafield = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const metafield_types_1 = require("@tryghost/metafield-types");
|
|
6
|
+
const access_1 = require("./access");
|
|
6
7
|
const schema_1 = require("./schema");
|
|
7
8
|
exports.Metafield = zod_1.z.object({
|
|
8
9
|
id: zod_1.z.string(),
|
|
@@ -11,6 +12,7 @@ exports.Metafield = zod_1.z.object({
|
|
|
11
12
|
name: zod_1.z.string(),
|
|
12
13
|
type: metafield_types_1.FieldTypeSchema,
|
|
13
14
|
status: schema_1.FieldStatusSchema,
|
|
15
|
+
access: zod_1.z.object({ member: access_1.MemberAccessSchema }),
|
|
14
16
|
createdAt: zod_1.z.date(),
|
|
15
17
|
updatedAt: zod_1.z.date().nullable(),
|
|
16
18
|
});
|
|
@@ -1,20 +1,48 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.
|
|
3
|
+
exports.ANY_STATUS = exports.ACTIVE_ONLY = void 0;
|
|
4
|
+
exports.readableBy = readableBy;
|
|
5
|
+
exports.definitions = definitions;
|
|
5
6
|
exports.inFieldOrder = inFieldOrder;
|
|
7
|
+
const access_1 = require("./access");
|
|
6
8
|
const schema_1 = require("./schema");
|
|
7
9
|
const FIELDS_TABLE = 'members_metafields';
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// that forgets
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return
|
|
10
|
+
// Nothing in the database keeps an archived or hidden field out of a read: no
|
|
11
|
+
// constraint stops a value row referencing one. Both filters are therefore applied in
|
|
12
|
+
// code, and a query that forgets either is a silent bug.
|
|
13
|
+
function readableBy(query, audience) {
|
|
14
|
+
query.whereIn(`${FIELDS_TABLE}.member_access`, (0, access_1.readableLevels)(audience));
|
|
15
|
+
return query;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Whether a read includes definitions the publisher has archived.
|
|
19
|
+
*
|
|
20
|
+
* A member is never offered an archived field. Staff managing the list are always
|
|
21
|
+
* shown one, since an archived field is still theirs to rename, restore or delete.
|
|
22
|
+
*/
|
|
23
|
+
exports.ACTIVE_ONLY = 'active-only';
|
|
24
|
+
exports.ANY_STATUS = 'any-status';
|
|
25
|
+
// Unannotated so the builder keeps the row type knex derives from the table
|
|
26
|
+
// registration; naming a type here would both lose that and make the alias below
|
|
27
|
+
// refer to itself.
|
|
28
|
+
function metafieldsTable(db) {
|
|
29
|
+
return db(FIELDS_TABLE);
|
|
14
30
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
31
|
+
function definitions(db, scope) {
|
|
32
|
+
let query = metafieldsTable(db);
|
|
33
|
+
if (scope.filter) {
|
|
34
|
+
query = scope.filter(query);
|
|
35
|
+
}
|
|
36
|
+
if (scope.key !== undefined) {
|
|
37
|
+
query = query.where(`${FIELDS_TABLE}.key`, scope.key);
|
|
38
|
+
}
|
|
39
|
+
if (scope.status === exports.ACTIVE_ONLY) {
|
|
40
|
+
query = query.where(`${FIELDS_TABLE}.status`, schema_1.FIELD_STATUS.active);
|
|
41
|
+
}
|
|
42
|
+
if (scope.limit !== undefined) {
|
|
43
|
+
query = query.limit(scope.limit);
|
|
44
|
+
}
|
|
45
|
+
return readableBy(query, scope.audience);
|
|
18
46
|
}
|
|
19
47
|
/**
|
|
20
48
|
* The publisher's order, applied to every read of the list. Here for the same reason the
|
|
@@ -4,6 +4,7 @@ exports.DbBoundField = exports.DbMetafieldBinding = exports.DbMetafieldLeaf = ex
|
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const metafield_types_1 = require("@tryghost/metafield-types");
|
|
6
6
|
const date_1 = require("../../lib/db-types/date");
|
|
7
|
+
const access_1 = require("./access");
|
|
7
8
|
// `archived` is soft: the field drops out of the values path but stays in the definition
|
|
8
9
|
// list so it can be renamed, restored or deleted. Mirrors schema.js's `isIn` on the
|
|
9
10
|
// column, which is static config and cannot import this.
|
|
@@ -17,6 +18,7 @@ exports.DbMetafield = zod_1.z.object({
|
|
|
17
18
|
name: zod_1.z.string(),
|
|
18
19
|
type: metafield_types_1.FieldTypeSchema,
|
|
19
20
|
status: exports.FieldStatusSchema,
|
|
21
|
+
member_access: access_1.MemberAccessSchema,
|
|
20
22
|
created_at: date_1.DbDate,
|
|
21
23
|
updated_at: date_1.DbDate.nullable(),
|
|
22
24
|
});
|
|
@@ -10,6 +10,7 @@ const MetafieldResource = zod_1.z.object({
|
|
|
10
10
|
name: zod_1.z.string(),
|
|
11
11
|
type: zod_1.z.string(),
|
|
12
12
|
status: zod_1.z.string(),
|
|
13
|
+
access: zod_1.z.object({ member: zod_1.z.string() }),
|
|
13
14
|
created_at: zod_1.z.date(),
|
|
14
15
|
updated_at: zod_1.z.date().nullable(),
|
|
15
16
|
});
|
|
@@ -47,7 +47,11 @@ class MetafieldValuesService {
|
|
|
47
47
|
this.knex = knex;
|
|
48
48
|
this.getMaxDefinitions = getMaxDefinitions;
|
|
49
49
|
}
|
|
50
|
-
|
|
50
|
+
// The query is scoped to the audience, so a field they may not see is absent from
|
|
51
|
+
// the map and the caller reports it as unknown. Looking up unscoped and rejecting
|
|
52
|
+
// afterwards would let a member tell a hidden field from an undefined one by the
|
|
53
|
+
// reply they got.
|
|
54
|
+
async allowedFieldsByIdentity(identities, audience) {
|
|
51
55
|
const keys = identities
|
|
52
56
|
.map((identity) => (0, identity_1.parseIdentity)(identity))
|
|
53
57
|
.filter((parsed) => parsed !== null && parsed.namespace === identity_1.CUSTOM_NAMESPACE)
|
|
@@ -55,12 +59,19 @@ class MetafieldValuesService {
|
|
|
55
59
|
if (keys.length === 0) {
|
|
56
60
|
return new Map();
|
|
57
61
|
}
|
|
58
|
-
const fields = await (0, queries_1.
|
|
62
|
+
const fields = await (0, queries_1.definitions)(this.knex, { audience, status: queries_1.ACTIVE_ONLY })
|
|
59
63
|
.whereIn('key', keys)
|
|
60
|
-
.select('id', 'key', 'name', 'type');
|
|
64
|
+
.select('id', 'key', 'name', 'type', 'member_access');
|
|
61
65
|
return new Map(fields.map((field) => [
|
|
62
66
|
(0, identity_1.formatIdentity)({ namespace: identity_1.CUSTOM_NAMESPACE, key: field.key, partPath: null }),
|
|
63
|
-
{
|
|
67
|
+
{
|
|
68
|
+
id: field.id,
|
|
69
|
+
key: field.key,
|
|
70
|
+
name: field.name,
|
|
71
|
+
type: field.type,
|
|
72
|
+
namespace: identity_1.CUSTOM_NAMESPACE,
|
|
73
|
+
memberAccess: field.member_access,
|
|
74
|
+
},
|
|
64
75
|
]));
|
|
65
76
|
}
|
|
66
77
|
async getValuesForMembers(memberIds, audience) {
|
|
@@ -70,8 +81,7 @@ class MetafieldValuesService {
|
|
|
70
81
|
// Not ordered by field: these rows become an object keyed by field, and an object
|
|
71
82
|
// cannot carry an order. `path` is ordered so composite parts assemble the same
|
|
72
83
|
// way every time.
|
|
73
|
-
const rows = await this.knex(VALUES_TABLE)
|
|
74
|
-
.join(FIELDS_TABLE, `${VALUES_TABLE}.metafield_key`, `${FIELDS_TABLE}.key`)
|
|
84
|
+
const rows = await (0, queries_1.readableBy)(this.knex(VALUES_TABLE).join(FIELDS_TABLE, `${VALUES_TABLE}.metafield_key`, `${FIELDS_TABLE}.key`), audience)
|
|
75
85
|
.whereIn(`${VALUES_TABLE}.member_id`, memberIds)
|
|
76
86
|
.where(`${FIELDS_TABLE}.status`, schema_1.FIELD_STATUS.active)
|
|
77
87
|
.orderBy(`${VALUES_TABLE}.path`, 'asc')
|
|
@@ -90,10 +100,7 @@ class MetafieldValuesService {
|
|
|
90
100
|
}, 'Skipping an unreadable metafield value');
|
|
91
101
|
}
|
|
92
102
|
}
|
|
93
|
-
|
|
94
|
-
// several rows, and dropping some of its parts later would hand back half an
|
|
95
|
-
// address rather than no address.
|
|
96
|
-
const flat = (0, storage_1.valuesFromLeaves)((0, access_1.readableFields)(audience, leaves));
|
|
103
|
+
const flat = (0, storage_1.valuesFromLeaves)(leaves);
|
|
97
104
|
return new Map(memberIds.map((memberId) => [memberId, { [identity_1.CUSTOM_NAMESPACE]: flat.get(memberId) ?? {} }]));
|
|
98
105
|
}
|
|
99
106
|
parseValues(input) {
|
|
@@ -157,7 +164,7 @@ class MetafieldValuesService {
|
|
|
157
164
|
property: identity_1.QUALIFIER,
|
|
158
165
|
});
|
|
159
166
|
}
|
|
160
|
-
const byIdentity = await this.
|
|
167
|
+
const byIdentity = await this.allowedFieldsByIdentity(identities, audience);
|
|
161
168
|
const writes = [];
|
|
162
169
|
for (const [identity, raw] of Object.entries(values)) {
|
|
163
170
|
const field = byIdentity.get(identity);
|
|
@@ -167,6 +174,8 @@ class MetafieldValuesService {
|
|
|
167
174
|
property: wireProperty(identity),
|
|
168
175
|
});
|
|
169
176
|
}
|
|
177
|
+
// A different refusal from the unknown-field one above: this audience can
|
|
178
|
+
// already see the field, so naming it discloses nothing.
|
|
170
179
|
if (!(0, access_1.canWrite)(audience, field)) {
|
|
171
180
|
throw new errors_1.default.ValidationError({
|
|
172
181
|
message: `Cannot set custom field: ${identity}`,
|
|
@@ -63,7 +63,7 @@ module.exports = class MentionDiscoveryService {
|
|
|
63
63
|
return null;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
const cheerio = require('cheerio');
|
|
66
|
+
const cheerio = require('cheerio/slim');
|
|
67
67
|
const $ = cheerio.load(response.body);
|
|
68
68
|
|
|
69
69
|
// must be first <link> OR <a> element with rel=webmention
|
|
@@ -242,7 +242,7 @@ module.exports = class MentionSendingService {
|
|
|
242
242
|
* @returns {URL[]}
|
|
243
243
|
*/
|
|
244
244
|
getLinks(html) {
|
|
245
|
-
const cheerio = require('cheerio');
|
|
245
|
+
const cheerio = require('cheerio/slim');
|
|
246
246
|
const $ = cheerio.load(html);
|
|
247
247
|
const urls = [];
|
|
248
248
|
const siteUrl = this.siteUrl;
|
|
@@ -42,6 +42,7 @@ const messages = {
|
|
|
42
42
|
unableToFetchOembed: 'Unable to fetch requested embed.',
|
|
43
43
|
unauthorized: 'URL contains a private resource.',
|
|
44
44
|
unconvertibleSvg: 'SVG image is too large or compressed to convert.',
|
|
45
|
+
unsupportedImage: 'Image is not a supported file type.',
|
|
45
46
|
};
|
|
46
47
|
|
|
47
48
|
const SVG_RASTER_SIZE = 256;
|
|
@@ -68,6 +69,16 @@ const shouldRasterize = (buffer, ext) => {
|
|
|
68
69
|
return head.startsWith('<') && /<svg[\s:>]/i.test(head);
|
|
69
70
|
};
|
|
70
71
|
|
|
72
|
+
let fileTypeFromBuffer;
|
|
73
|
+
|
|
74
|
+
const detectFileType = async (buffer) => {
|
|
75
|
+
if (!fileTypeFromBuffer) {
|
|
76
|
+
({ fileTypeFromBuffer } = await import('file-type'));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return fileTypeFromBuffer(buffer);
|
|
80
|
+
};
|
|
81
|
+
|
|
71
82
|
/**
|
|
72
83
|
* @param {string} url
|
|
73
84
|
* @returns {{url: string, provider: boolean}}
|
|
@@ -234,6 +245,20 @@ class OEmbedService {
|
|
|
234
245
|
});
|
|
235
246
|
|
|
236
247
|
ext = '.png';
|
|
248
|
+
} else {
|
|
249
|
+
// The URL's extension is attacker-controlled and decides the
|
|
250
|
+
// Content-Type the stored file is later served with, so name the
|
|
251
|
+
// file after its contents and hold it to the same allowlist as image
|
|
252
|
+
// uploads. `file-type` never reports SVG, which is handled above.
|
|
253
|
+
const fileType = await detectFileType(imageBuffer);
|
|
254
|
+
ext = fileType ? `.${fileType.ext}` : '';
|
|
255
|
+
|
|
256
|
+
if (!this.config.get('uploads').images.extensions.includes(ext)) {
|
|
257
|
+
throw new errors.ValidationError({
|
|
258
|
+
message: tpl(messages.unsupportedImage),
|
|
259
|
+
context: imageUrl,
|
|
260
|
+
});
|
|
261
|
+
}
|
|
237
262
|
}
|
|
238
263
|
|
|
239
264
|
const uniqueFileName = `${name}-${crypto.randomUUID()}${ext}`;
|
|
@@ -561,12 +586,12 @@ class OEmbedService {
|
|
|
561
586
|
*/
|
|
562
587
|
async fetchOembedData(url, html, cardType) {
|
|
563
588
|
// Lazy require the library to keep boot quick
|
|
564
|
-
const cheerio = require('cheerio');
|
|
589
|
+
const cheerio = require('cheerio/slim');
|
|
565
590
|
|
|
566
591
|
// check for <link rel="alternate" type="application/json+oembed"> element
|
|
567
592
|
let oembedUrl;
|
|
568
593
|
try {
|
|
569
|
-
oembedUrl = cheerio('link[type="application/json+oembed"]'
|
|
594
|
+
oembedUrl = cheerio.load(html)('link[type="application/json+oembed"]').attr('href');
|
|
570
595
|
} catch (e) {
|
|
571
596
|
return this.unknownProvider(url);
|
|
572
597
|
}
|
|
@@ -622,15 +647,15 @@ class OEmbedService {
|
|
|
622
647
|
return;
|
|
623
648
|
}
|
|
624
649
|
|
|
625
|
-
// `rich` and `
|
|
626
|
-
// stored in the post's Lexical payload and rendered
|
|
627
|
-
// editor preview (via srcdoc) and into public themes
|
|
628
|
-
// Known providers (YouTube, Twitter, etc.)
|
|
629
|
-
// with @extractus/oembed-extractor's
|
|
630
|
-
// here is an arbitrary site's
|
|
631
|
-
// must not trust. Drop the
|
|
632
|
-
// a bookmark card.
|
|
633
|
-
if (oembed.type === 'video' || oembed.type === 'rich') {
|
|
650
|
+
// `rich`, `video` and `photo` responses can all ship provider-supplied
|
|
651
|
+
// HTML that gets stored in the post's Lexical payload and rendered
|
|
652
|
+
// into the admin editor preview (via srcdoc) and into public themes
|
|
653
|
+
// and emails (via innerHTML). Known providers (YouTube, Twitter, etc.)
|
|
654
|
+
// go through `knownProvider` with @extractus/oembed-extractor's
|
|
655
|
+
// allowlist — anything reaching here is an arbitrary site's
|
|
656
|
+
// self-declared oEmbed endpoint, which we must not trust. Drop the
|
|
657
|
+
// response and let the caller fall back to a bookmark card.
|
|
658
|
+
if (oembed.type === 'video' || oembed.type === 'rich' || oembed.type === 'photo') {
|
|
634
659
|
return;
|
|
635
660
|
}
|
|
636
661
|
|
|
@@ -16,6 +16,10 @@ const messages = {
|
|
|
16
16
|
// retrying a publish that will never happen.
|
|
17
17
|
const NO_OP = { scheduledResource: null, preScheduledResource: null };
|
|
18
18
|
|
|
19
|
+
// Ignore overlapping deliveries for the same resource. The scheduler owns
|
|
20
|
+
// retries if the active publish fails; always release the guard when it settles.
|
|
21
|
+
const inFlight = new Set();
|
|
22
|
+
|
|
19
23
|
/**
|
|
20
24
|
* Publishes scheduled resource (a post or a page at the moment of writing)
|
|
21
25
|
*
|
|
@@ -27,6 +31,22 @@ const NO_OP = { scheduledResource: null, preScheduledResource: null };
|
|
|
27
31
|
* `scheduledResource: null` when there was nothing to publish yet
|
|
28
32
|
*/
|
|
29
33
|
exports.publish = async (resourceType, id, force, options) => {
|
|
34
|
+
const key = `${resourceType}:${id}`;
|
|
35
|
+
|
|
36
|
+
if (inFlight.has(key)) {
|
|
37
|
+
return NO_OP;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
inFlight.add(key);
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
return await publishNow(resourceType, id, force, options);
|
|
44
|
+
} finally {
|
|
45
|
+
inFlight.delete(key);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const publishNow = async (resourceType, id, force, options) => {
|
|
30
50
|
const publishAPostBySchedulerToleranceInMinutes =
|
|
31
51
|
config.get('times').publishAPostBySchedulerToleranceInMinutes;
|
|
32
52
|
|