ghost 6.55.0 → 6.57.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/validate-adapters.js +74 -0
- package/bin/validate-adapters.ts +87 -0
- package/bin/warm-compile-cache.sh +60 -0
- package/components/tryghost-custom-field-types-0.0.0.tgz +0 -0
- package/components/tryghost-kg-default-cards-10.3.3.tgz +0 -0
- package/components/tryghost-kg-default-nodes-2.1.4.tgz +0 -0
- package/components/tryghost-kg-default-transforms-1.3.3.tgz +0 -0
- package/components/tryghost-kg-html-to-lexical-1.3.3.tgz +0 -0
- package/components/tryghost-kg-lexical-html-renderer-1.4.3.tgz +0 -0
- package/components/tryghost-nql-string-0.0.0.tgz +0 -0
- package/components/tryghost-parse-email-address-0.0.0.tgz +0 -0
- package/core/app.js +1 -1
- package/core/boot.js +21 -25
- package/core/bridge.js +10 -12
- package/core/built/admin/assets/Combination-BDvCdg1t.js +41 -0
- package/core/built/admin/assets/{PolarAngleAxis-BGjf7sBu.js → PolarAngleAxis-C4qtHy1B.js} +1 -1
- package/core/built/admin/assets/{RadialBarChart-zeFf9mBz.js → RadialBarChart-Bh09Stsj.js} +1 -1
- package/core/built/admin/assets/about-C7O-AgRZ.js +1 -0
- package/core/built/admin/assets/{account-migration-sjHLx5dy.js → account-migration-Cv_ol1ko.js} +1 -1
- package/core/built/admin/assets/action-list-lGzZLHc8.js +1 -0
- package/core/built/admin/assets/activitypub/{account-migration-DoYXtnZ8.js → account-migration-DHFbePl6.js} +7 -7
- package/core/built/admin/assets/activitypub/activitypub.js +6 -6
- package/core/built/admin/assets/activitypub/{avatar-B3DEDB1l.js → avatar-CT4tS2_S.js} +2 -2
- package/core/built/admin/assets/activitypub/{avatar-flipboard-Cqrg0XMx.js → avatar-flipboard-ByYWKipo.js} +2 -2
- package/core/built/admin/assets/activitypub/{bluesky-sharing-Bxeh6MKW.js → bluesky-sharing-srVnSHDz.js} +16 -16
- package/core/built/admin/assets/activitypub/{content-formatters-BpQARh28.js → content-formatters-C2sos5Ht.js} +3 -3
- package/core/built/admin/assets/activitypub/{copy-D9UWIAan.js → copy-B1UBTOoZ.js} +2 -2
- package/core/built/admin/assets/activitypub/{dist-D8sFfdpC.js → dist-MPsb2WZ1.js} +12 -12
- package/core/built/admin/assets/activitypub/{domain-CWueFW6q.js → domain-DzcM9Dzo.js} +9 -9
- package/core/built/admin/assets/activitypub/{edit-profile-BGxPU7N5.js → edit-profile-CsQ_4xAk.js} +945 -945
- package/core/built/admin/assets/activitypub/{explore-DBK-u0Ch.js → explore-CJe0DZBK.js} +8 -8
- package/core/built/admin/assets/activitypub/{feed-Bcir5RQZ.js → feed-CKV3qWON.js} +33 -33
- package/core/built/admin/assets/activitypub/{field-BV-CIT3d.js → field-DckHfDJf.js} +3 -3
- package/core/built/admin/assets/activitypub/{hash-BC9Q0N4c.js → hash-Dlp8RM55.js} +2 -2
- package/core/built/admin/assets/activitypub/{inbox-DQ4ZnC1m.js → inbox-CsPy4R0M.js} +2 -2
- package/core/built/admin/assets/activitypub/{inbox-yC0nfvzl.js → inbox-DAsjzUUe.js} +85 -85
- package/core/built/admin/assets/activitypub/{label-DTRS9TDk.js → label-DWyo9E5T.js} +3 -3
- package/core/built/admin/assets/activitypub/layout-DM_3pqsU.js +1 -0
- package/core/built/admin/assets/activitypub/{moderation-Dwl9t0pb.js → moderation-B0Inc03M.js} +11 -11
- package/core/built/admin/assets/activitypub/{note-B-zKsZ7r.js → note-CSE54lER.js} +7 -7
- package/core/built/admin/assets/activitypub/{notifications-DjJZD54t.js → notifications-RSwbKqdh.js} +9 -9
- package/core/built/admin/assets/activitypub/{preferences-CoU8vs6d.js → preferences-CE231n2_.js} +20 -20
- package/core/built/admin/assets/activitypub/{profile-BAsaJekx.js → profile-aaQ1j1Eo.js} +237 -237
- package/core/built/admin/assets/activitypub/{reply-CpdMeAO5.js → reply-Cjb0Vs3m.js} +2 -2
- package/core/built/admin/assets/activitypub/{routes-CLH3OVTP.js → routes-Djb0mc9k.js} +1139 -1150
- package/core/built/admin/assets/activitypub/{separator-BI1FLsYM.js → separator-D8pROI5n.js} +3 -3
- package/core/built/admin/assets/activitypub/{settings-DA6pNJ-Q.js → settings-DMc32IQl.js} +13 -13
- package/core/built/admin/assets/activitypub/{site-CQD42Pw5.js → site-DVIcsohX.js} +81 -81
- package/core/built/admin/assets/activitypub/{step-1-DIDg4aHb.js → step-1-9Yey9usF.js} +5 -5
- package/core/built/admin/assets/activitypub/{step-2-BfGe8BYt.js → step-2-DdYmKRXV.js} +6 -6
- package/core/built/admin/assets/activitypub/{step-3-mE9spAqw.js → step-3-hdSkcjZU.js} +10 -10
- package/core/built/admin/assets/activitypub/{tabs-Cg0saow1.js → tabs-CUqseYzQ.js} +317 -315
- package/core/built/admin/assets/activitypub/{topic-filter-DLHBZT93.js → topic-filter-Coni6OXM.js} +3 -3
- package/core/built/admin/assets/activitypub/{use-activity-pub-queries-VzbN99u_.js → use-activity-pub-queries-MeHTPMQv.js} +2 -2
- package/core/built/admin/assets/activitypub/{use-navigate-with-base-path-CAwXTmqH.js → use-navigate-with-base-path-B046AM38.js} +115 -96
- package/core/built/admin/assets/activitypub/{use-reply-chain-data-Br4aOWOh.js → use-reply-chain-data-1AO-Xob6.js} +5 -5
- package/core/built/admin/assets/activitypub/{x-C8tAnXly.js → x-BRfRYd16.js} +2 -2
- package/core/built/admin/assets/add-integration-modal-m9Dv6f77.js +1 -0
- package/core/built/admin/assets/add-newsletter-modal-CPSVZL2H.js +1 -0
- package/core/built/admin/assets/add-recommendation-modal-Ci9Z5yat.js +1 -0
- package/core/built/admin/assets/analytics-DqSCVV8U.js +1 -0
- package/core/built/admin/assets/announcement-bar-modal-DU3avV7d.js +1 -0
- package/core/built/admin/assets/api-keys-BK0LylyK.js +1 -0
- package/core/built/admin/assets/api-keys-_iCT4dxr.js +1 -0
- package/core/built/admin/assets/{audience-DjEWNhp3.js → audience-DTJtXXWY.js} +1 -1
- package/core/built/admin/assets/automated-emails-PayPCT8L.js +1 -0
- package/core/built/admin/assets/{automations-DhKeS_U5.js → automations-162q5HjL.js} +1 -1
- package/core/built/admin/assets/{automations-Bx3VcFIL.js → automations-dtQ_MRZ7.js} +1 -1
- package/core/built/admin/assets/{bluesky-sharing-ClMd0-Ft.js → bluesky-sharing-B8Es3AuV.js} +1 -1
- package/core/built/admin/assets/{box-BWbhXh21.js → box-By_EgGtm.js} +1 -1
- package/core/built/admin/assets/brand-icon-09YqFZjV.js +1 -0
- package/core/built/admin/assets/{breadcrumb-BD0U2ygg.js → breadcrumb-tg5zL--z.js} +1 -1
- package/core/built/admin/assets/build-CsiH26uS.js +1 -0
- package/core/built/admin/assets/{card-DGoDJzrn.js → card-aUHX0hyR.js} +1 -1
- package/core/built/admin/assets/{chart-BuRT2Y6p.js → chart-BnXyfH11.js} +1 -1
- package/core/built/admin/assets/{chart-helpers-fjQKRVyY.js → chart-helpers-CZElTGYL.js} +1 -1
- package/core/built/admin/assets/checkbox-Cyo-x7mC.js +1 -0
- package/core/built/admin/assets/chunk.524.cd5498dd4e195f679266.js +25 -0
- package/core/built/admin/assets/chunk.582.6f92ec1f03734bf2ea3f.js +27 -0
- package/core/built/admin/assets/{chunk.481.6c7395a49484bb4583aa.js → chunk.873.b8fc05a8ab877fb819ed.js} +62 -60
- package/core/built/admin/assets/code-editor-view-Dq1rQ4tS.js +1 -0
- package/core/built/admin/assets/color-picker-field-BonBgxhU.js +1 -0
- package/core/built/admin/assets/color-utils-BsrwXuDz.js +1 -0
- package/core/built/admin/assets/combobox-uX5r_paI.js +1 -0
- package/core/built/admin/assets/command-DxwBO2pF.js +1 -0
- package/core/built/admin/assets/comments-Dn-RO-nU.js +1 -0
- package/core/built/admin/assets/components-CwL6a6As-B0E0-NBJ.js +1 -0
- package/core/built/admin/assets/confirmation-modal-B6D6mk6R.js +1 -0
- package/core/built/admin/assets/{container-BYz2Ed39.js → container-LiZf3XdY.js} +1 -1
- package/core/built/admin/assets/content-api-modal-BxQ-7T6u.js +1 -0
- package/core/built/admin/assets/copy-field-BAxL4Zqn.js +1 -0
- package/core/built/admin/assets/currency-Dy4Tc2R2.js +1 -0
- package/core/built/admin/assets/custom-integration-modal---d_l7lc.js +1 -0
- package/core/built/admin/assets/{data-list-16rkJYYi.js → data-list-CupF7bjM.js} +1 -1
- package/core/built/admin/assets/{date-range-select-BFp58EMk.js → date-range-select-PB2n1HZf.js} +1 -1
- package/core/built/admin/assets/debounce-Dg2fW5Rg.js +3 -0
- package/core/built/admin/assets/design-and-theme-modal-DYRT207a.js +23 -0
- package/core/built/admin/assets/dirty-confirm-dialog-BnDJ39ao.js +1 -0
- package/core/built/admin/assets/disabled-sources-indicator-iMHrkyV3.js +1 -0
- package/core/built/admin/assets/dist-B2PvRwLn.js +1 -0
- package/core/built/admin/assets/{dist-DGzPJ_bO.js → dist-Cb5RSHSg.js} +1 -1
- package/core/built/admin/assets/{dist-P_ohUlTi.js → dist-CqO2lWS02.js} +1 -1
- package/core/built/admin/assets/{dist-pHiOxyxa.js → dist-D5vhMdXf.js} +1 -1
- package/core/built/admin/assets/dist-DlCyLrOC.js +1 -0
- package/core/built/admin/assets/dist-WeOIvSYM.js +23 -0
- package/core/built/admin/assets/{dist-DyViJwIy.js → dist-cFzKLG7y.js} +3 -3
- package/core/built/admin/assets/dist-j1xxxnY8.js +1 -0
- package/core/built/admin/assets/dist-myQaY0ka.js +1 -0
- package/core/built/admin/assets/domain-BR8FIdjD.js +1 -0
- package/core/built/admin/assets/{dropzone-DlK-K2DQ.js → dropzone-hNxmUvwD.js} +1 -1
- package/core/built/admin/assets/{edit-profile-BKT-REJw.js → edit-profile-CENrkY0l.js} +1 -1
- package/core/built/admin/assets/editor-B18D0lm8.js +8 -0
- package/core/built/admin/assets/embed-signup-form-modal-BsCYUMvQ.js +9 -0
- package/core/built/admin/assets/{empty-indicator-oX1u1Pkn.js → empty-indicator-WB1WgT9h.js} +1 -1
- package/core/built/admin/assets/{explore-ClUpJZOp.js → explore-BmrnljWw.js} +1 -1
- package/core/built/admin/assets/{feed-DF92dUMP.js → feed-Dy4li6i8.js} +1 -1
- package/core/built/admin/assets/{field-Do7lieBA.js → field-Dh_lwk13.js} +1 -1
- package/core/built/admin/assets/filter-sources-D2zDuJH5.js +1 -0
- package/core/built/admin/assets/filters-3JBQcNtJ.js +1 -0
- package/core/built/admin/assets/filters-CFt_BDe4.js +1 -0
- package/core/built/admin/assets/first-promoter-modal-D6Rjxugw.js +1 -0
- package/core/built/admin/assets/format-url-C-t8G6Qd.js +1 -0
- package/core/built/admin/assets/{ghost-a9c788f6f0b1ea6cf0f14ca4b13f4496.css → ghost-d38c30b866e59f2e06a357b5eb844fe5.css} +1 -1
- package/core/built/admin/assets/{ghost-c4057474943effc568c5659ccc4909d7.js → ghost-d683fbeb945b13155ea669caa5d8db41.js} +420 -398
- package/core/built/admin/assets/{ghost-dark-db36d795d21c61426837df40af270966.css → ghost-dark-1bffd5099ba7a749303133efacf8480b.css} +1 -1
- package/core/built/admin/assets/{gift-link-modal-f9VIMNDv.js → gift-link-modal-zMtlJhLQ.js} +1 -1
- package/core/built/admin/assets/{gift-links-CsUhefWG.js → gift-links-CVuqLhsZ.js} +1 -1
- package/core/built/admin/assets/global-data-provider-B949LDXJ.js +1 -0
- package/core/built/admin/assets/grid-CUciBfjf.js +1 -0
- package/core/built/admin/assets/{growth-CVw1My4S.js → growth-C38Xtp8D.js} +2 -2
- package/core/built/admin/assets/{growth-B3I6gNLm.js → growth-CFws67_i.js} +1 -1
- package/core/built/admin/assets/history-modal-ILAOkbxH.js +1 -0
- package/core/built/admin/assets/{hooks-CixO01lL.js → hooks-D6EE7BIt.js} +2 -2
- package/core/built/admin/assets/html-field-9a9Id_2q.js +1 -0
- package/core/built/admin/assets/iframe-buffering-e8vH4-Qn.js +1 -0
- package/core/built/admin/assets/images-CrQKVc9Q.js +1 -0
- package/core/built/admin/assets/{inbox-CFBSu4Ed.js → inbox-BrSRzyvz.js} +6 -6
- package/core/built/admin/assets/index-BHy2DZX-.js +67 -0
- package/core/built/admin/assets/index-Ds2iUoF6.css +1 -0
- package/core/built/admin/assets/index.es-B9tvf-t4.js +1 -0
- package/core/built/admin/assets/{inline-EMAm3okk.js → inline-Cw-gigDW.js} +1 -1
- package/core/built/admin/assets/input-group-6vEPvX9S.js +1 -0
- package/core/built/admin/assets/{input-surface-BpAjZXY5.js → input-surface-BdOe4KzO.js} +1 -1
- package/core/built/admin/assets/integration-header-B4DyXV06.js +1 -0
- package/core/built/admin/assets/integrations-BT6_iJvu.js +1 -0
- package/core/built/admin/assets/invite-user-modal-5xDCEw90.js +1 -0
- package/core/built/admin/assets/isEmail-BOfC647y.js +1 -0
- package/core/built/admin/assets/koenig-editor-base-BWLEB9Vf.js +1 -0
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +9535 -9527
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +124 -124
- package/core/built/admin/assets/{koenig-lexical-f8vHRYvz.js → koenig-lexical-Cj62r_y9.js} +86 -86
- package/core/built/admin/assets/{kpi-card-DSap9rAy.js → kpi-card-DOUnkZcN.js} +1 -1
- package/core/built/admin/assets/{kpi-card-DU0rn9Cj.js → kpi-card-IHDo8Q56.js} +1 -1
- package/core/built/admin/assets/{kpi-helpers-Dz33AV6h.js → kpi-helpers-CjUdECAK.js} +1 -1
- package/core/built/admin/assets/{kpi-tabs-BtTTrKvJ.js → kpi-tabs-X3DkOYbI.js} +1 -1
- package/core/built/admin/assets/{label-DS8Mi6G5.js → label-Dq6QaOuS.js} +1 -1
- package/core/built/admin/assets/label-picker-8YlhS2U3.js +1 -0
- package/core/built/admin/assets/labels-DAPjKPy2.js +1 -0
- package/core/built/admin/assets/layout-TMj4P-vv.js +1 -0
- package/core/built/admin/assets/limit-modal-BRPsit_B.js +1 -0
- package/core/built/admin/assets/link-helpers-Bzkk68GD.js +1 -0
- package/core/built/admin/assets/{list-page-B6ANtzkd.js → list-page-CdsnQR9N.js} +1 -1
- package/core/built/admin/assets/member-custom-fields-CmvsuuV_.js +1 -0
- package/core/built/admin/assets/member-detail-DCvRrkmJ.js +1 -0
- package/core/built/admin/assets/members-DxbSKngD.js +11 -0
- package/core/built/admin/assets/modal-page-BMTzFHVO.js +1 -0
- package/core/built/admin/assets/{moderation-DySbgyUS.js → moderation-Da5lhhWh.js} +1 -1
- package/core/built/admin/assets/multi-select-combobox-CYdkH7KQ.js +1 -0
- package/core/built/admin/assets/navigation-modal-BIoTwtMy.js +1 -0
- package/core/built/admin/assets/newsletter-BptlVoJm.js +1 -0
- package/core/built/admin/assets/newsletter-detail-modal-BIvxqE0N.js +1 -0
- package/core/built/admin/assets/newsletter-emails-Bf8IZLsP.js +1 -0
- package/core/built/admin/assets/newsletters-BgrIZk0V.js +1 -0
- package/core/built/admin/assets/{newsletters-BXJbJgA-.js → newsletters-Du0lzskS.js} +1 -1
- package/core/built/admin/assets/{note-C8kxrz6w.js → note-DYcLOmDb.js} +1 -1
- package/core/built/admin/assets/{notifications-CgtSfX7t.js → notifications-B2SPFIV9.js} +1 -1
- package/core/built/admin/assets/{offers-DEniVRD5.js → offers-Um6ab71O.js} +1 -1
- package/core/built/admin/assets/offers-container-modal-BZnZITMw.js +1 -0
- package/core/built/admin/assets/{onboarding-route-4qtziA9d.js → onboarding-route-DgdfxkQh.js} +1 -1
- package/core/built/admin/assets/overview-BYQJXSog.js +1 -0
- package/core/built/admin/assets/overview-Dt2_mR6U.js +1 -0
- package/core/built/admin/assets/{page-header-B3Wb9Jqv.js → page-header-CpmxJj5B.js} +1 -1
- package/core/built/admin/assets/{pages-B4goRPUn.js → pages-BVMnpI2O.js} +1 -1
- package/core/built/admin/assets/pintura-modal-B4MuBuuO.js +1 -0
- package/core/built/admin/assets/portal-frame-BF0NBIji.js +1 -0
- package/core/built/admin/assets/portal-modal-DMVbm0oy.js +1 -0
- package/core/built/admin/assets/{post-analytics-We-ko5Cb.js → post-analytics-CXWBOGyP.js} +1 -1
- package/core/built/admin/assets/post-analytics-header-ChzjXVPt.js +1 -0
- package/core/built/admin/assets/{post-analytics-provider-B6UynTGb.js → post-analytics-provider-Cgw4U_fw.js} +1 -1
- package/core/built/admin/assets/{post-share-modal-DFfO93_0.js → post-share-modal-B9Vmk_XM.js} +1 -1
- package/core/built/admin/assets/{posts-DhXE7b6r.js → posts-CxG7v0-M.js} +1 -1
- package/core/built/admin/assets/preferences-BfzJmnsd.js +5 -0
- package/core/built/admin/assets/preview-chrome-BOVO6_PE.js +1 -0
- package/core/built/admin/assets/preview-modal-Dw_HtD6S.js +1 -0
- package/core/built/admin/assets/profile-BT5vtv9b.js +1 -0
- package/core/built/admin/assets/radio-group-I7ou7PoJ.js +1 -0
- package/core/built/admin/assets/{referrers-pmJT4k3-.js → referrers-B9QDAfYm.js} +1 -1
- package/core/built/admin/assets/{router-provider-C1R4AZ2o.js → router-provider-DSQfprxH.js} +1 -1
- package/core/built/admin/assets/select-D9oU1IoM.js +1 -0
- package/core/built/admin/assets/settings-CfZFbyu_.js +4 -0
- package/core/built/admin/assets/{settings-WXNeWyU1.js → settings-CpvHWix7.js} +1 -1
- package/core/built/admin/assets/settings-breadcrumbs-K0USP2nw.js +1 -0
- package/core/built/admin/assets/{shade-app-B3heOAfz-CGXQwWeO.js → shade-app-B3heOAfz-BhQXxNkT.js} +1 -1
- package/core/built/admin/assets/{share-modal-DsgW3wbg.js → share-modal-ClIyPzc5.js} +1 -1
- package/core/built/admin/assets/slack-modal-1XXqOfiw.js +1 -0
- package/core/built/admin/assets/social-urls-CHQ9cTAK.js +1 -0
- package/core/built/admin/assets/{sort-button-Bb_FCl7e.js → sort-button-CdBsm40v.js} +1 -1
- package/core/built/admin/assets/{source-icon-BeaRxUn9.js → source-icon-CEYmVLXR.js} +1 -1
- package/core/built/admin/assets/{stack-xiN0eQ6Z.js → stack-CIfOAAVf.js} +1 -1
- package/core/built/admin/assets/{stats-Bjj_kmJ1.js → stats-D8nZCTy5.js} +1 -1
- package/core/built/admin/assets/{stats-view-BxPbW6K1.js → stats-view-CugFVf0g.js} +1 -1
- package/core/built/admin/assets/{step-1-B1e3-1F8.js → step-1-DOYjrORn.js} +1 -1
- package/core/built/admin/assets/{step-2-C5WaeBJo.js → step-2-vA6RsarH.js} +1 -1
- package/core/built/admin/assets/{step-3-B46iVPwu.js → step-3-BtIBxMId.js} +2 -2
- package/core/built/admin/assets/stripe-button-UFP4QRXd.js +1 -0
- package/core/built/admin/assets/stripe-connect-modal-C_L3uM6n.js +1 -0
- package/core/built/admin/assets/switch-CE2NuMn-.js +1 -0
- package/core/built/admin/assets/{table-CB-4_HBJ.js → table-TMCgCQK7.js} +1 -1
- package/core/built/admin/assets/tabs-Dd6oOKbv.js +1 -0
- package/core/built/admin/assets/tag-detail-D3l-UJPR.js +1 -0
- package/core/built/admin/assets/tags-BwCgmr5v.js +1 -0
- package/core/built/admin/assets/tags-WdKQGWR8.js +1 -0
- package/core/built/admin/assets/testimonials-modal-CqWp-xXJ.js +1 -0
- package/core/built/admin/assets/{text-DwtjwGkh.js → text-DU9Hv33_.js} +1 -1
- package/core/built/admin/assets/textarea-d9qEkMOP.js +1 -0
- package/core/built/admin/assets/tier-detail-modal-BkcR2u0A.js +1 -0
- package/core/built/admin/assets/{tiers-DYsa4DCo.js → tiers-Da6kxHQP.js} +1 -1
- package/core/built/admin/assets/toggle-group-Guorw93z.js +1 -0
- package/core/built/admin/assets/{topic-filter-DAFT87tQ.js → topic-filter-CbgoWIHn.js} +1 -1
- package/core/built/admin/assets/transistor-modal-DuNnnpal.js +1 -0
- package/core/built/admin/assets/unsplash-modal-y2bVwTHH.js +1 -0
- package/core/built/admin/assets/{use-analytics-data-S0FTd43s.js → use-analytics-data-B-b4wNSC.js} +1 -1
- package/core/built/admin/assets/use-check-theme-limit-error-m09J38Mq.js +2 -0
- package/core/built/admin/assets/use-feature-flag-ud0Qz8vt.js +1 -0
- package/core/built/admin/assets/{use-filter-params-Gpoq2E1L.js → use-filter-params-BnbBDc7T.js} +1 -1
- package/core/built/admin/assets/use-filterable-api-iMpDZBxD.js +1 -0
- package/core/built/admin/assets/use-form-vRjI0Kwk.js +1 -0
- package/core/built/admin/assets/{use-growth-stats-CIaiHOVb.js → use-growth-stats-DPU5rt3W.js} +1 -1
- package/core/built/admin/assets/use-hash-link-navigation-guard-B9j6HIrV.js +1 -0
- package/core/built/admin/assets/use-limiter-BkN3E4gw.js +2 -0
- package/core/built/admin/assets/use-pintura-config-C_z8HTG2.js +1 -0
- package/core/built/admin/assets/use-pintura-editor-DNgbkhGp.js +1 -0
- package/core/built/admin/assets/{use-post-referrers-Cq2vBPrA.js → use-post-referrers-C2mXyrp-.js} +1 -1
- package/core/built/admin/assets/use-query-params-DHhhu8wi.js +1 -0
- package/core/built/admin/assets/{use-reply-chain-data-DBDRtGu-.js → use-reply-chain-data-DaK8q2qQ.js} +1 -1
- package/core/built/admin/assets/use-setting-group-YlYcoNyP.js +1 -0
- package/core/built/admin/assets/use-settings-navigation-Bf1g1rEh.js +1 -0
- package/core/built/admin/assets/{use-simple-pagination-CjYNxdwe.js → use-simple-pagination-D9ckKo5-.js} +1 -1
- package/core/built/admin/assets/{use-tinybird-query-falHAtuK.js → use-tinybird-query-GSa32hVw.js} +1 -1
- package/core/built/admin/assets/{use-tinybird-token-D7-8ND1y.js → use-tinybird-token-CKLOZFsw.js} +1 -1
- package/core/built/admin/assets/use-url-input-z-p0Kewm.js +5 -0
- package/core/built/admin/assets/user-detail-modal-BMxOA4Sv.js +1 -0
- package/core/built/admin/assets/{users-Dkv8NQZe.js → users-B6hIds6n.js} +1 -1
- package/core/built/admin/assets/validator-Cr0sMKuW.js +7 -0
- package/core/built/admin/assets/{virtual-list-CvnC9zF2.js → virtual-list-RHeEL05L.js} +1 -1
- package/core/built/admin/assets/{web-jFYWCKDn.js → web-Bw2QMO5u.js} +2 -2
- package/core/built/admin/assets/web-xJtcwMy4.js +1 -0
- package/core/built/admin/assets/zapier-modal-BP2f4-vY.js +1 -0
- package/core/built/admin/index.html +20 -18
- package/core/frontend/helpers/authors.js +1 -1
- package/core/frontend/helpers/link.js +3 -8
- package/core/frontend/helpers/tags.js +1 -1
- package/core/frontend/meta/author-url.js +2 -2
- package/core/frontend/meta/url.js +4 -4
- package/core/frontend/services/data/fetch-data.js +10 -5
- package/core/frontend/services/proxy.js +1 -1
- package/core/frontend/services/routing/api-adapter.js +115 -0
- package/core/frontend/services/routing/api-adapter.ts +157 -0
- package/core/frontend/services/routing/collection-router.js +5 -3
- package/core/frontend/services/routing/controllers/index.js +1 -1
- package/core/frontend/services/routing/controllers/rss.js +26 -31
- package/core/frontend/services/routing/controllers/rss.ts +66 -0
- package/core/frontend/services/routing/controllers/static.js +8 -7
- package/core/frontend/services/routing/events.js +20 -6
- package/core/frontend/services/routing/parent-router.js +17 -4
- package/core/frontend/services/routing/permalink-adapter.js +13 -0
- package/core/frontend/services/routing/permalink-adapter.ts +10 -0
- package/core/frontend/services/routing/registry.js +59 -33
- package/core/frontend/services/routing/router-manager.js +24 -22
- package/core/frontend/services/routing/static-routes-router.js +4 -4
- package/core/frontend/services/routing/taxonomy-router.js +6 -2
- package/core/frontend/services/sitemap/base-site-map-generator.js +1 -28
- package/core/frontend/services/sitemap/site-map-manager.js +22 -57
- package/core/server/adapters/route-settings/utils.js +10 -2
- package/core/server/adapters/route-settings/utils.ts +12 -2
- package/core/server/api/endpoints/email-post.js +1 -1
- package/core/server/api/endpoints/previews.js +1 -1
- package/core/server/api/endpoints/search-index-public.js +3 -3
- package/core/server/api/endpoints/search-index.js +4 -4
- package/core/server/api/endpoints/utils/serializers/input/authors.js +2 -2
- package/core/server/api/endpoints/utils/serializers/input/comments.js +1 -1
- package/core/server/api/endpoints/utils/serializers/input/pages.js +3 -3
- package/core/server/api/endpoints/utils/serializers/input/posts.js +3 -3
- package/core/server/api/endpoints/utils/serializers/input/tags.js +1 -1
- package/core/server/api/endpoints/utils/serializers/input/users.js +2 -2
- package/core/server/api/endpoints/utils/serializers/input/utils/url.js +31 -13
- package/core/server/api/endpoints/utils/serializers/output/mappers/posts.js +2 -2
- package/core/server/api/endpoints/utils/serializers/output/mappers/tags.js +2 -2
- package/core/server/api/endpoints/utils/serializers/output/mappers/users.js +8 -0
- package/core/server/api/endpoints/utils/serializers/output/utils/url.js +18 -11
- package/core/server/data/migrations/versions/6.56/2026-08-03-19-27-51-add-automation-run-step-id-to-automated-email-recipients.js +8 -0
- package/core/server/data/migrations/versions/6.56/2026-08-04-14-42-39-restrict-notification-add-permission-to-administrators.js +12 -0
- package/core/server/data/migrations/versions/6.57/2026-08-04-18-00-00-store-custom-field-values-as-leaf-rows.js +74 -0
- package/core/server/data/migrations/versions/6.57/2026-08-04-18-54-14-reset-automation-email-analytics.js +25 -0
- package/core/server/data/schema/commands.js +21 -5
- package/core/server/data/schema/fixtures/fixtures.json +2 -2
- package/core/server/data/schema/schema.js +25 -5
- package/core/server/lib/common/to-plain.ts +1 -1
- package/core/server/models/post.js +12 -3
- package/core/server/services/adapter-manager/adapter-manager.js +1 -45
- package/core/server/services/adapter-manager/adapter-manager.ts +2 -48
- package/core/server/services/adapter-manager/adapter-paths.js +24 -0
- package/core/server/services/adapter-manager/adapter-paths.ts +21 -0
- package/core/server/services/adapter-manager/base-classes.js +22 -0
- package/core/server/services/adapter-manager/base-classes.ts +22 -0
- package/core/server/services/adapter-manager/index.js +4 -27
- package/core/server/services/adapter-manager/index.ts +4 -31
- package/core/server/services/adapter-manager/utils.js +50 -0
- package/core/server/services/adapter-manager/utils.ts +57 -0
- package/core/server/services/audience-feedback/audience-feedback-controller.js +1 -1
- package/core/server/services/audience-feedback/audience-feedback-service.js +2 -2
- package/core/server/services/automations/automations-repository.ts +3 -1
- package/core/server/services/automations/database-automations-repository.js +33 -14
- package/core/server/services/automations/database-automations-repository.ts +41 -15
- package/core/server/services/automations/get-scheduler-idempotency-key.js +13 -0
- package/core/server/services/automations/get-scheduler-idempotency-key.ts +8 -0
- package/core/server/services/automations/poll.js +3 -1
- package/core/server/services/automations/poll.ts +4 -1
- package/core/server/services/automations/service.js +7 -3
- package/core/server/services/automations/service.ts +7 -3
- package/core/server/services/comments/comments-service-emails.js +1 -1
- package/core/server/services/comments/comments-service.js +1 -1
- package/core/server/services/email-analytics/email-analytics-service-wrapper.js +11 -2
- package/core/server/services/email-analytics/email-analytics-service.js +1 -1
- package/core/server/services/email-service/email-service-wrapper.js +2 -1
- package/core/server/services/email-service/mailgun-email-provider.js +15 -0
- package/core/server/services/gift-links/CONTEXT.md +9 -0
- package/core/server/services/gifts/CONTEXT.md +55 -0
- package/core/server/services/gifts/README.md +28 -0
- package/core/server/services/gifts/gift-bookshelf-repository.js +65 -45
- package/core/server/services/gifts/gift-bookshelf-repository.ts +203 -74
- package/core/server/services/gifts/gift-checkout-adapter.js +59 -0
- package/core/server/services/gifts/gift-checkout-offer.js +74 -0
- package/core/server/services/gifts/gift-checkout-offer.ts +127 -0
- package/core/server/services/gifts/gift-codec.js +63 -0
- package/core/server/services/gifts/gift-codec.ts +62 -0
- package/core/server/services/gifts/gift-controller.js +6 -31
- package/core/server/services/gifts/gift-controller.ts +6 -69
- package/core/server/services/gifts/gift-email-service.ts +3 -2
- package/core/server/services/gifts/gift-schema.js +34 -0
- package/core/server/services/gifts/gift-schema.ts +39 -0
- package/core/server/services/gifts/gift-service-wrapper.js +13 -11
- package/core/server/services/gifts/gift-service.js +265 -52
- package/core/server/services/gifts/gift-service.ts +431 -97
- package/core/server/services/gifts/gift.ts +16 -39
- package/core/server/services/indexnow-ping/indexnow-ping-service.js +1 -1
- package/core/server/services/indexnow-ping/indexnow-ping-service.ts +2 -4
- package/core/server/services/lib/mailgun-client.js +3 -3
- package/core/server/services/link-tracking/link-click-repository.js +6 -1
- package/core/server/services/link-tracking/link-click-tracking-service.js +12 -3
- package/core/server/services/media-inliner/external-media-inliner.js +12 -8
- package/core/server/services/member-attribution/url-translator.js +5 -7
- package/core/server/services/member-welcome-emails/member-welcome-email-renderer.js +4 -3
- package/core/server/services/member-welcome-emails/service.js +79 -15
- package/core/server/services/members/api.js +2 -3
- package/core/server/services/members/import-export/import/completion-email.js +8 -4
- package/core/server/services/members/import-export/import/completion-email.ts +9 -4
- package/core/server/services/members/import-export/import/importer.js +25 -4
- package/core/server/services/members/import-export/import/importer.ts +27 -6
- package/core/server/services/members/import-export/import/row.ts +5 -1
- package/core/server/services/members/import-export/index.js +6 -2
- package/core/server/services/members/import-export/index.ts +10 -4
- package/core/server/services/members/members-api/controllers/router-controller.js +38 -36
- package/core/server/services/members/members-api/members-api.js +13 -7
- package/core/server/services/members/members-api/repositories/event-repository.js +4 -94
- package/core/server/services/members/members-api/services/member-bread-service.js +3 -3
- package/core/server/services/members/members-api/services/payments-service.js +6 -68
- package/core/server/services/members-custom-fields/queries.js +4 -13
- package/core/server/services/members-custom-fields/queries.ts +4 -13
- package/core/server/services/members-custom-fields/schema.js +19 -21
- package/core/server/services/members-custom-fields/schema.ts +18 -20
- package/core/server/services/members-custom-fields/storage.js +94 -27
- package/core/server/services/members-custom-fields/storage.ts +114 -39
- package/core/server/services/members-custom-fields/values-service.js +98 -103
- package/core/server/services/members-custom-fields/values-service.ts +116 -114
- package/core/server/services/mentions/resource-service.js +1 -1
- package/core/server/services/mentions/service.js +2 -2
- package/core/server/services/oembed/oembed-service.js +44 -3
- package/core/server/services/posts/posts-service.js +11 -0
- package/core/server/services/route-settings/dynamic-routing-service.js +10 -62
- package/core/server/services/route-settings/route-settings-parser.js +25 -25
- package/core/server/services/route-settings/route-settings-parser.ts +27 -27
- package/core/server/services/route-settings/validation-errors.js +68 -4
- package/core/server/services/route-settings/validation-errors.ts +79 -4
- package/core/server/services/slack-ping/slack-ping-service.js +2 -2
- package/core/server/services/slack-ping/slack-ping-service.ts +3 -5
- package/core/server/services/stats/content-stats-service.js +3 -3
- package/core/server/services/stats/posts-stats-service.js +29 -25
- package/core/server/services/stripe/services/webhook/charge-refunded-event-service.js +1 -1
- package/core/server/services/stripe/services/webhook/checkout-session-event-service.js +16 -4
- package/core/server/services/stripe/stripe-api.js +10 -0
- package/core/server/services/url/config.js +90 -135
- package/core/server/services/url/index.js +6 -49
- package/core/server/services/url/lazy-find-resource.js +14 -11
- package/core/server/services/url/lazy-find-resource.ts +14 -11
- package/core/server/services/url/lazy-url-service.js +174 -94
- package/core/server/services/url/lazy-url-service.ts +233 -97
- package/core/server/services/url/routable-resources.js +62 -71
- package/core/server/services/url/router-filter.js +12 -4
- package/core/server/services/url/router-filter.ts +12 -4
- package/core/server/services/webhooks/index.js +1 -1
- package/core/server/services/webhooks/serialize.js +2 -1
- package/core/server/web/gift-preview/controller.js +10 -25
- package/core/shared/config/env/config.testing-mysql.json +1 -2
- package/core/shared/config/env/config.testing.json +1 -2
- package/core/shared/events/index.js +1 -2
- package/core/shared/labs.js +4 -4
- package/package.json +10 -10
- package/pnpm-lock.yaml +27 -20
- package/pnpm-workspace.yaml +3 -2
- package/tsconfig.json +1 -0
- package/components/tryghost-kg-default-nodes-2.1.3.tgz +0 -0
- package/core/built/admin/assets/Combination-CJG7Flp-.js +0 -41
- package/core/built/admin/assets/activitypub/layout-qx-bUL1k.js +0 -1
- package/core/built/admin/assets/automated-emails-DRy7qY-J.js +0 -7
- package/core/built/admin/assets/checkbox-CWa28lgO.js +0 -1
- package/core/built/admin/assets/chunk.524.cffd399783a519e404a9.js +0 -25
- package/core/built/admin/assets/chunk.582.eebf0d0b2d202bb746a5.js +0 -27
- package/core/built/admin/assets/code-editor-view-CCr0rBWS.js +0 -1
- package/core/built/admin/assets/comments-DyUSMUdj.js +0 -1
- package/core/built/admin/assets/disabled-sources-indicator-CUxMfiPa.js +0 -1
- package/core/built/admin/assets/dist-2Tnz2Yfq.js +0 -1
- package/core/built/admin/assets/dist-CjY-f5Z1.js +0 -1
- package/core/built/admin/assets/dist-DDY6GRVz.js +0 -1
- package/core/built/admin/assets/dist-DG78yroX.js +0 -23
- package/core/built/admin/assets/domain-C0bV2UV8.js +0 -1
- package/core/built/admin/assets/editor-Dp865O-4.js +0 -8
- package/core/built/admin/assets/esm-CFX93H5M.js +0 -2
- package/core/built/admin/assets/filter-sources-BV2rnpfA.js +0 -1
- package/core/built/admin/assets/filters-CUXJ2Nm9.js +0 -1
- package/core/built/admin/assets/filters-DfbIWc_l.js +0 -1
- package/core/built/admin/assets/index-9Cw8z3rA.css +0 -1
- package/core/built/admin/assets/index-BGG7NckO.js +0 -67
- package/core/built/admin/assets/input-group-BSgG_lVw.js +0 -1
- package/core/built/admin/assets/label-picker-1DvSuLA1.js +0 -1
- package/core/built/admin/assets/labels-CDSUt4J_.js +0 -1
- package/core/built/admin/assets/layout-yQEi2qDM.js +0 -1
- package/core/built/admin/assets/link-helpers-7EYqvvHs.js +0 -1
- package/core/built/admin/assets/member-custom-fields-yOMHyAg9.js +0 -1
- package/core/built/admin/assets/member-detail-BAq7gDaa.js +0 -1
- package/core/built/admin/assets/members-CQpVFJu4.js +0 -10
- package/core/built/admin/assets/modals-ReORvWnu.js +0 -31
- package/core/built/admin/assets/newsletter-CJQvtHqN.js +0 -1
- package/core/built/admin/assets/newsletters-B3QQXfGT.js +0 -1
- package/core/built/admin/assets/nql-BsgFMd93.js +0 -1
- package/core/built/admin/assets/overview-Bf2sbznq.js +0 -1
- package/core/built/admin/assets/overview-CBfePxcr.js +0 -1
- package/core/built/admin/assets/post-analytics-header-Bmc9su6q.js +0 -1
- package/core/built/admin/assets/preferences-DJPfHEGu.js +0 -5
- package/core/built/admin/assets/profile-DqBQp-gT.js +0 -1
- package/core/built/admin/assets/select-C5_xEt5b.js +0 -1
- package/core/built/admin/assets/settings-BwiVIXau.js +0 -4
- package/core/built/admin/assets/social-urls-BQPFEk1_.js +0 -8
- package/core/built/admin/assets/switch-z5Y6Uzt6.js +0 -1
- package/core/built/admin/assets/tabs-CCEgKYzq.js +0 -1
- package/core/built/admin/assets/tags-Cg2VJGmG.js +0 -1
- package/core/built/admin/assets/textarea-Bjccvh_E.js +0 -1
- package/core/built/admin/assets/toggle-group-b3IlxvhV.js +0 -1
- package/core/built/admin/assets/web-B_5GZRvH.js +0 -1
- package/core/server/services/gifts/gift-repository.js +0 -2
- package/core/server/services/gifts/gift-repository.ts +0 -29
- package/core/server/services/route-settings/activation-bridge.js +0 -174
- package/core/server/services/route-settings/activation-bridge.ts +0 -250
- package/core/server/services/url/local-file-cache.js +0 -75
- package/core/server/services/url/queue.js +0 -260
- package/core/server/services/url/resource.js +0 -102
- package/core/server/services/url/resources.js +0 -480
- package/core/server/services/url/url-generator.js +0 -276
- package/core/server/services/url/url-service-facade.js +0 -366
- package/core/server/services/url/url-service-facade.ts +0 -519
- package/core/server/services/url/url-service.js +0 -387
- package/core/server/services/url/urls.js +0 -140
- package/core/shared/events/url-resource-updated-event.js +0 -33
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const logging = require('@tryghost/logging');
|
|
2
|
+
const {createNonTransactionalMigration} = require('../../utils');
|
|
3
|
+
const {addColumn, dropColumn, addUnique, dropUnique, addIndex, dropIndex} = require('../../../schema/commands');
|
|
4
|
+
|
|
5
|
+
const TABLE = 'members_custom_field_values';
|
|
6
|
+
|
|
7
|
+
// Named explicitly; the derived name would overrun MySQL's identifier limit, which
|
|
8
|
+
// schema.test.js checks for every table.
|
|
9
|
+
const LEAF_UNIQUE = 'members_custom_field_values_leaf_unique';
|
|
10
|
+
|
|
11
|
+
// Values are discarded rather than converted: custom fields sit behind a private flag and
|
|
12
|
+
// have never been released, so only a site deliberately opted in can hold one.
|
|
13
|
+
async function discardStoredValues(knex) {
|
|
14
|
+
const discarded = await knex(TABLE).del();
|
|
15
|
+
if (discarded > 0) {
|
|
16
|
+
logging.warn(`Discarded ${discarded} custom field value(s): the storage format changed before the feature was released`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Column changes ask for `auto` so MySQL picks an in-place algorithm where it can; the
|
|
21
|
+
// helpers otherwise default to a full table copy, which blocks writes.
|
|
22
|
+
//
|
|
23
|
+
// Two constraints shape the order of everything below.
|
|
24
|
+
//
|
|
25
|
+
// MySQL refuses to drop the last index serving a foreign key, counting any index whose
|
|
26
|
+
// leftmost column is the referencing one, so each replacement is added before the thing
|
|
27
|
+
// it replaces is dropped.
|
|
28
|
+
//
|
|
29
|
+
// This migration is not transactional, so a crash leaves the table half-changed with
|
|
30
|
+
// nothing recorded as done and knex-migrator runs it again on the next boot. Every step
|
|
31
|
+
// therefore tolerates having already happened: the constraint and index helpers swallow
|
|
32
|
+
// that themselves, the column steps ask first.
|
|
33
|
+
module.exports = createNonTransactionalMigration(
|
|
34
|
+
async function up(knex) {
|
|
35
|
+
// First, so nothing can collide with the new constraint.
|
|
36
|
+
await discardStoredValues(knex);
|
|
37
|
+
|
|
38
|
+
if (!await knex.schema.hasColumn(TABLE, 'path')) {
|
|
39
|
+
await addColumn(TABLE, 'path', knex, undefined, {algorithm: 'auto'});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// `member_id` stays leftmost, covering that foreign key the moment this exists.
|
|
43
|
+
await addUnique(TABLE, ['member_id', 'custom_field_id', 'path'], knex, LEAF_UNIQUE);
|
|
44
|
+
await dropUnique(TABLE, ['member_id', 'custom_field_id'], knex);
|
|
45
|
+
|
|
46
|
+
if (await knex.schema.hasColumn(TABLE, 'value_json')) {
|
|
47
|
+
await dropColumn(TABLE, 'value_json', knex, {}, {algorithm: 'auto'});
|
|
48
|
+
}
|
|
49
|
+
await addIndex(TABLE, ['custom_field_id', 'path'], knex);
|
|
50
|
+
|
|
51
|
+
// Only present after a rollback, where `down` adds it to keep a foreign key
|
|
52
|
+
// covered. Leaving it would be drift against a fresh install.
|
|
53
|
+
await dropIndex(TABLE, ['custom_field_id'], knex);
|
|
54
|
+
},
|
|
55
|
+
async function down(knex) {
|
|
56
|
+
// Rebuilding a composite would need the field-type catalog, which a migration must
|
|
57
|
+
// not read: it has to keep working when the catalog moves on.
|
|
58
|
+
await discardStoredValues(knex);
|
|
59
|
+
|
|
60
|
+
await addUnique(TABLE, ['member_id', 'custom_field_id'], knex);
|
|
61
|
+
await dropUnique(TABLE, ['member_id', 'custom_field_id', 'path'], knex, LEAF_UNIQUE);
|
|
62
|
+
|
|
63
|
+
// Back before the composite one goes, or MySQL has nothing covering that key.
|
|
64
|
+
await addIndex(TABLE, ['custom_field_id'], knex);
|
|
65
|
+
await dropIndex(TABLE, ['custom_field_id', 'path'], knex);
|
|
66
|
+
|
|
67
|
+
if (!await knex.schema.hasColumn(TABLE, 'value_json')) {
|
|
68
|
+
await addColumn(TABLE, 'value_json', knex, {type: 'text', maxlength: 65535, nullable: true}, {algorithm: 'auto'});
|
|
69
|
+
}
|
|
70
|
+
if (await knex.schema.hasColumn(TABLE, 'path')) {
|
|
71
|
+
await dropColumn(TABLE, 'path', knex, {}, {algorithm: 'auto'});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const logging = require('@tryghost/logging');
|
|
2
|
+
const {createTransactionalMigration} = require('../../utils');
|
|
3
|
+
|
|
4
|
+
module.exports = createTransactionalMigration(
|
|
5
|
+
async function up(knex) {
|
|
6
|
+
logging.info('Resetting automation email analytics counts');
|
|
7
|
+
|
|
8
|
+
const updatedRevisions = await knex('automation_action_revisions').update({
|
|
9
|
+
email_sent_count: null,
|
|
10
|
+
email_opened_count: null,
|
|
11
|
+
email_clicked_count: null
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
logging.info(`Reset automation email analytics counts for ${updatedRevisions} action revisions`);
|
|
15
|
+
|
|
16
|
+
const deletedRecipients = await knex('automated_email_recipients')
|
|
17
|
+
.whereNotNull('automation_action_revision_id')
|
|
18
|
+
.del();
|
|
19
|
+
|
|
20
|
+
logging.info(`Deleted ${deletedRecipients} automation email recipient rows`);
|
|
21
|
+
},
|
|
22
|
+
async function down() {
|
|
23
|
+
logging.info('Skipping rollback for automation email analytics reset');
|
|
24
|
+
}
|
|
25
|
+
);
|
|
@@ -276,13 +276,18 @@ async function dropIndex(tableName, columns, transaction = db.knex) {
|
|
|
276
276
|
* @param {string} tableName - name of the table to add unique constraint to
|
|
277
277
|
* @param {string|string[]} columns - column(s) to form unique constraint with
|
|
278
278
|
* @param {import('knex').Knex} [transaction] - connection object containing knex reference
|
|
279
|
+
* @param {string} [indexName] - name for the constraint; knex derives one from the table
|
|
280
|
+
* and every column when omitted, which can overrun MySQL's 64-character limit
|
|
279
281
|
*/
|
|
280
|
-
async function addUnique(tableName, columns, transaction = db.knex) {
|
|
282
|
+
async function addUnique(tableName, columns, transaction = db.knex, indexName) {
|
|
281
283
|
try {
|
|
282
284
|
logging.info(`Adding unique constraint for '${columns}' in table '${tableName}'`);
|
|
283
285
|
|
|
284
286
|
return await transaction.schema.table(tableName, function (table) {
|
|
285
|
-
table
|
|
287
|
+
// Knex derives a name from the table and every column when it is not given
|
|
288
|
+
// one, and that can overrun MySQL's 64-character identifier limit on a wide
|
|
289
|
+
// table or a constraint over several columns.
|
|
290
|
+
table.unique(columns, indexName ? {indexName} : undefined);
|
|
286
291
|
});
|
|
287
292
|
} catch (err) {
|
|
288
293
|
if (err.code === 'SQLITE_ERROR') {
|
|
@@ -304,12 +309,14 @@ async function addUnique(tableName, columns, transaction = db.knex) {
|
|
|
304
309
|
* @param {string|string[]} columns - column(s) unique constraint was formed
|
|
305
310
|
* @param {import('knex').Knex} transaction - connection object containing knex reference
|
|
306
311
|
*/
|
|
307
|
-
async function dropUnique(tableName, columns, transaction = db.knex) {
|
|
312
|
+
async function dropUnique(tableName, columns, transaction = db.knex, indexName) {
|
|
308
313
|
try {
|
|
309
314
|
logging.info(`Dropping unique constraint for '${columns}' in table '${tableName}'`);
|
|
310
315
|
|
|
311
316
|
return await transaction.schema.table(tableName, function (table) {
|
|
312
|
-
|
|
317
|
+
// Named constraints have to be dropped by that name: the one knex would
|
|
318
|
+
// derive from the columns is not what is on the table.
|
|
319
|
+
table.dropUnique(columns, indexName);
|
|
313
320
|
});
|
|
314
321
|
} catch (err) {
|
|
315
322
|
if (err.code === 'SQLITE_ERROR') {
|
|
@@ -542,7 +549,16 @@ function createTable(table, transaction = db.knex, tableSpec = schema[table]) {
|
|
|
542
549
|
});
|
|
543
550
|
}
|
|
544
551
|
if (tableSpec['@@UNIQUE_CONSTRAINTS@@']) {
|
|
545
|
-
tableSpec['@@UNIQUE_CONSTRAINTS@@'].forEach(unique =>
|
|
552
|
+
tableSpec['@@UNIQUE_CONSTRAINTS@@'].forEach((unique) => {
|
|
553
|
+
// An entry is normally the columns alone, and knex names the constraint
|
|
554
|
+
// after the table and every one of them. The object form is for when
|
|
555
|
+
// that derived name would overrun MySQL's 64-character limit.
|
|
556
|
+
if (unique && typeof unique === 'object' && !Array.isArray(unique)) {
|
|
557
|
+
t.unique(unique.columns, {indexName: unique.indexName});
|
|
558
|
+
} else {
|
|
559
|
+
t.unique(unique);
|
|
560
|
+
}
|
|
561
|
+
});
|
|
546
562
|
}
|
|
547
563
|
if (tableSpec['@@PRIMARY_KEY@@']) {
|
|
548
564
|
t.primary(tableSpec['@@PRIMARY_KEY@@']);
|
|
@@ -1066,7 +1066,7 @@
|
|
|
1066
1066
|
"gift_link": "manage"
|
|
1067
1067
|
},
|
|
1068
1068
|
"Super Editor": {
|
|
1069
|
-
"notification": "
|
|
1069
|
+
"notification": ["browse", "destroy"],
|
|
1070
1070
|
"post": "all",
|
|
1071
1071
|
"setting": ["browse", "read"],
|
|
1072
1072
|
"slug": "all",
|
|
@@ -1091,7 +1091,7 @@
|
|
|
1091
1091
|
"gift_link": "manage"
|
|
1092
1092
|
},
|
|
1093
1093
|
"Editor": {
|
|
1094
|
-
"notification": "
|
|
1094
|
+
"notification": ["browse", "destroy"],
|
|
1095
1095
|
"post": "all",
|
|
1096
1096
|
"setting": ["browse", "read"],
|
|
1097
1097
|
"slug": "all",
|
|
@@ -682,15 +682,34 @@ module.exports = {
|
|
|
682
682
|
id: {type: 'string', maxlength: 24, nullable: false, primary: true},
|
|
683
683
|
custom_field_id: {type: 'string', maxlength: 24, nullable: false, references: 'members_custom_fields.id', cascadeDelete: true},
|
|
684
684
|
member_id: {type: 'string', maxlength: 24, nullable: false, references: 'members.id', cascadeDelete: true},
|
|
685
|
-
//
|
|
686
|
-
//
|
|
687
|
-
//
|
|
685
|
+
// Which part of the field's value this row carries. A scalar has one part and
|
|
686
|
+
// stores it under the empty path; a composite stores one row per sub-field it
|
|
687
|
+
// fills, under that sub-field's key. Not nullable, because MySQL counts NULLs
|
|
688
|
+
// as distinct in a unique index and the constraint below would stop holding.
|
|
689
|
+
path: {type: 'string', maxlength: 191, nullable: false, defaultTo: ''},
|
|
690
|
+
// One row, one value: a part a member has not filled in has no row at all. The
|
|
691
|
+
// column stays nullable even so, because making it NOT NULL is only reachable
|
|
692
|
+
// through knex's dropNullable, which rewrites the column on MySQL and widens
|
|
693
|
+
// TEXT to MEDIUMTEXT — a migrated site would then accept sixteen megabytes in a
|
|
694
|
+
// column a fresh install bounds at 65,535 bytes. The bound matching long_text's
|
|
695
|
+
// exactly is worth more than the schema restating what the write path enforces.
|
|
688
696
|
value_text: {type: 'text', maxlength: 65535, nullable: true},
|
|
689
|
-
value_json: {type: 'text', maxlength: 65535, nullable: true},
|
|
690
697
|
created_at: {type: 'dateTime', nullable: false},
|
|
691
698
|
updated_at: {type: 'dateTime', nullable: true},
|
|
699
|
+
// Named, because the name knex derives from the table and all three columns is
|
|
700
|
+
// 65 characters and MySQL stops at 64. The migration that first created this
|
|
701
|
+
// table already shortened a column for the same reason; a third column spends
|
|
702
|
+
// what headroom that bought.
|
|
692
703
|
'@@UNIQUE_CONSTRAINTS@@': [
|
|
693
|
-
['member_id', 'custom_field_id']
|
|
704
|
+
{columns: ['member_id', 'custom_field_id', 'path'], indexName: 'members_custom_field_values_leaf_unique'}
|
|
705
|
+
],
|
|
706
|
+
// What a segment filter looks up: every member holding a given value for a
|
|
707
|
+
// given part of a given field. The value itself is not in the index — it is
|
|
708
|
+
// TEXT, so MySQL would need a prefix length, and the schema's index builder
|
|
709
|
+
// applies one length to every column in a composite index rather than to a
|
|
710
|
+
// single chosen one.
|
|
711
|
+
'@@INDEXES@@': [
|
|
712
|
+
['custom_field_id', 'path']
|
|
694
713
|
]
|
|
695
714
|
},
|
|
696
715
|
members_stripe_customers: {
|
|
@@ -1339,6 +1358,7 @@ module.exports = {
|
|
|
1339
1358
|
id: {type: 'string', maxlength: 24, nullable: false, primary: true},
|
|
1340
1359
|
automated_email_id: {type: 'string', maxlength: 24, nullable: true, references: 'welcome_email_automated_emails.id'},
|
|
1341
1360
|
automation_action_revision_id: {type: 'string', maxlength: 24, nullable: true, references: 'automation_action_revisions.id'},
|
|
1361
|
+
automation_run_step_id: {type: 'string', maxlength: 24, nullable: true, references: 'automation_run_steps.id'},
|
|
1342
1362
|
member_id: {type: 'string', maxlength: 24, nullable: false, index: true},
|
|
1343
1363
|
member_uuid: {type: 'string', maxlength: 36, nullable: false},
|
|
1344
1364
|
member_email: {type: 'string', maxlength: 191, nullable: false},
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* callers accept either shape uniformly:
|
|
8
8
|
*
|
|
9
9
|
* const data = toPlain(post);
|
|
10
|
-
* urlService.
|
|
10
|
+
* urlService.getUrlForResource({...data, type: 'posts'}, ...)
|
|
11
11
|
*/
|
|
12
12
|
type JsonSerializable<T> = {
|
|
13
13
|
toJSON(): T;
|
|
@@ -1006,8 +1006,8 @@ Post = ghostBookshelf.Model.extend({
|
|
|
1006
1006
|
* - `slug`: /:slug/
|
|
1007
1007
|
* - `published_at`: /:year/:slug
|
|
1008
1008
|
* - `author_id`: /:author/:slug, /:primary_author/:slug
|
|
1009
|
-
* - now, the UrlService
|
|
1010
|
-
* - you can ask `urlService.
|
|
1009
|
+
* - now, the UrlService computes urls from the routing config
|
|
1010
|
+
* - you can ask `urlService.getUrlForResource(post)`
|
|
1011
1011
|
*
|
|
1012
1012
|
* ### events
|
|
1013
1013
|
* - you call `findAll` with `columns: id`
|
|
@@ -1346,7 +1346,16 @@ Post = ghostBookshelf.Model.extend({
|
|
|
1346
1346
|
destroy: function destroy(unfilteredOptions) {
|
|
1347
1347
|
let options = this.filterOptions(unfilteredOptions, 'destroy', {extraAllowedProperties: ['id']});
|
|
1348
1348
|
|
|
1349
|
-
const destroyPost = () => {
|
|
1349
|
+
const destroyPost = async () => {
|
|
1350
|
+
// The `comments.in_reply_to_id` references form chains between a post's
|
|
1351
|
+
// comments, which MySQL cannot resolve while cascade-deleting them
|
|
1352
|
+
// alongside `comments.parent_id`. Clear the references first so the
|
|
1353
|
+
// `comments.post_id` cascade delete can do its job
|
|
1354
|
+
await ghostBookshelf.knex('comments')
|
|
1355
|
+
.where('post_id', options.id)
|
|
1356
|
+
.update('in_reply_to_id', null)
|
|
1357
|
+
.transacting(options.transacting);
|
|
1358
|
+
|
|
1350
1359
|
return ghostBookshelf.Model.destroy.call(this, options);
|
|
1351
1360
|
};
|
|
1352
1361
|
|
|
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.AdapterManager = void 0;
|
|
7
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
8
7
|
const errors_1 = __importDefault(require("@tryghost/errors"));
|
|
9
8
|
const utils_1 = require("./utils");
|
|
10
9
|
/**
|
|
@@ -121,50 +120,7 @@ class AdapterManager {
|
|
|
121
120
|
message: `Unable to find ${adapterType} adapter in ${this.pathsToAdapters}.`
|
|
122
121
|
});
|
|
123
122
|
}
|
|
124
|
-
|
|
125
|
-
for (const pathToAdapters of this.pathsToAdapters) {
|
|
126
|
-
let pathToAdapter = node_path_1.default.join(pathToAdapters, adapterType, adapterClassName);
|
|
127
|
-
if (pathToAdapters === '') {
|
|
128
|
-
// We are loading from node_modules, we can remove the `adapterType` prefix
|
|
129
|
-
pathToAdapter = node_path_1.default.join(pathToAdapters, adapterClassName);
|
|
130
|
-
}
|
|
131
|
-
// An adapter directory may be a full module with its own
|
|
132
|
-
// package.json, in which case this resolves the `exports` entry
|
|
133
|
-
// point; otherwise the path passes through unchanged.
|
|
134
|
-
const moduleToLoad = (0, utils_1.resolveAdapterEntryPoint)(pathToAdapter);
|
|
135
|
-
try {
|
|
136
|
-
const adapterModule = this.loadAdapterFromPath(moduleToLoad);
|
|
137
|
-
Adapter = (0, utils_1.resolveAdapterExport)(adapterModule);
|
|
138
|
-
if (Adapter) {
|
|
139
|
-
break;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
catch (err) {
|
|
143
|
-
// Catch runtime errors
|
|
144
|
-
if (!(err instanceof Error) || err.code !== 'MODULE_NOT_FOUND') {
|
|
145
|
-
throw new errors_1.default.IncorrectUsageError({ err: err });
|
|
146
|
-
}
|
|
147
|
-
// Catch missing dependencies BUT NOT missing adapter.
|
|
148
|
-
// Only check the first line — Node appends a "Require stack"
|
|
149
|
-
// that includes the adapter's own path, which would false-positive.
|
|
150
|
-
const firstLine = err.message.split('\n')[0];
|
|
151
|
-
if (!firstLine.includes(pathToAdapter)) {
|
|
152
|
-
// Name the unresolved module so the error is actionable, e.g.
|
|
153
|
-
// "Cannot find module 'superagent'" -> 'superagent'.
|
|
154
|
-
const missingMatch = /Cannot find module '([^']+)'/.exec(firstLine);
|
|
155
|
-
const missingModule = missingMatch ? ` '${missingMatch[1]}'` : '';
|
|
156
|
-
throw new errors_1.default.IncorrectUsageError({
|
|
157
|
-
message: `You are missing a dependency${missingModule} in your adapter ${pathToAdapter}`,
|
|
158
|
-
err: err
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
if (!Adapter) {
|
|
164
|
-
throw new errors_1.default.IncorrectUsageError({
|
|
165
|
-
message: `Unable to find ${adapterType} adapter ${adapterClassName} in ${this.pathsToAdapters}.`
|
|
166
|
-
});
|
|
167
|
-
}
|
|
123
|
+
const Adapter = (0, utils_1.loadAdapterClass)(adapterType, adapterClassName, this.pathsToAdapters, this.loadAdapterFromPath);
|
|
168
124
|
return { Adapter, adapterConfig: adapterConfig ?? {}, adapterType, adapterClassName };
|
|
169
125
|
}
|
|
170
126
|
/**
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import errors from '@tryghost/errors';
|
|
3
|
-
import {
|
|
2
|
+
import {loadAdapterClass, resolveAdapterOptions, normalizeAdapterConfig, getConfiguredFeatures} from './utils';
|
|
4
3
|
import type {ConfigInstance} from '../../../shared/config/loader';
|
|
5
4
|
import type {
|
|
6
5
|
Adapter,
|
|
@@ -186,52 +185,7 @@ export class AdapterManager<BaseClasses extends BaseClassMap = BaseClassMap> {
|
|
|
186
185
|
});
|
|
187
186
|
}
|
|
188
187
|
|
|
189
|
-
|
|
190
|
-
for (const pathToAdapters of this.pathsToAdapters) {
|
|
191
|
-
let pathToAdapter = path.join(pathToAdapters, adapterType, adapterClassName);
|
|
192
|
-
if (pathToAdapters === '') {
|
|
193
|
-
// We are loading from node_modules, we can remove the `adapterType` prefix
|
|
194
|
-
pathToAdapter = path.join(pathToAdapters, adapterClassName);
|
|
195
|
-
}
|
|
196
|
-
// An adapter directory may be a full module with its own
|
|
197
|
-
// package.json, in which case this resolves the `exports` entry
|
|
198
|
-
// point; otherwise the path passes through unchanged.
|
|
199
|
-
const moduleToLoad = resolveAdapterEntryPoint(pathToAdapter);
|
|
200
|
-
|
|
201
|
-
try {
|
|
202
|
-
const adapterModule = this.loadAdapterFromPath(moduleToLoad);
|
|
203
|
-
Adapter = resolveAdapterExport(adapterModule);
|
|
204
|
-
if (Adapter) {
|
|
205
|
-
break;
|
|
206
|
-
}
|
|
207
|
-
} catch (err) {
|
|
208
|
-
// Catch runtime errors
|
|
209
|
-
if (!(err instanceof Error) || (err as NodeJS.ErrnoException).code !== 'MODULE_NOT_FOUND') {
|
|
210
|
-
throw new errors.IncorrectUsageError({err: err as Error});
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// Catch missing dependencies BUT NOT missing adapter.
|
|
214
|
-
// Only check the first line — Node appends a "Require stack"
|
|
215
|
-
// that includes the adapter's own path, which would false-positive.
|
|
216
|
-
const firstLine = err.message.split('\n')[0];
|
|
217
|
-
if (!firstLine.includes(pathToAdapter)) {
|
|
218
|
-
// Name the unresolved module so the error is actionable, e.g.
|
|
219
|
-
// "Cannot find module 'superagent'" -> 'superagent'.
|
|
220
|
-
const missingMatch = /Cannot find module '([^']+)'/.exec(firstLine);
|
|
221
|
-
const missingModule = missingMatch ? ` '${missingMatch[1]}'` : '';
|
|
222
|
-
throw new errors.IncorrectUsageError({
|
|
223
|
-
message: `You are missing a dependency${missingModule} in your adapter ${pathToAdapter}`,
|
|
224
|
-
err: err as Error
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
if (!Adapter) {
|
|
231
|
-
throw new errors.IncorrectUsageError({
|
|
232
|
-
message: `Unable to find ${adapterType} adapter ${adapterClassName} in ${this.pathsToAdapters}.`
|
|
233
|
-
});
|
|
234
|
-
}
|
|
188
|
+
const Adapter = loadAdapterClass(adapterType, adapterClassName, this.pathsToAdapters, this.loadAdapterFromPath);
|
|
235
189
|
|
|
236
190
|
return {Adapter, adapterConfig: adapterConfig ?? {}, adapterType, adapterClassName};
|
|
237
191
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
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.adapterPaths = void 0;
|
|
7
|
+
const config_1 = __importDefault(require("../../../shared/config"));
|
|
8
|
+
/**
|
|
9
|
+
* Where adapters are looked up, in order. Also read by bin/validate-adapters.ts,
|
|
10
|
+
* which checks adapter implementations at build time - keep this the only place
|
|
11
|
+
* the lookup order is declared, so a name resolves there exactly as it does here.
|
|
12
|
+
*/
|
|
13
|
+
exports.adapterPaths = Array.from(new Set([
|
|
14
|
+
'', // A blank path will cause us to check node_modules for the adapter
|
|
15
|
+
config_1.default.get('paths').internalAdaptersPath,
|
|
16
|
+
// custom docker builds may install adapters in a separate path from content,
|
|
17
|
+
// since the content dir is often bind-mounted into the container. Offering
|
|
18
|
+
// an escape hatch here to allow for this
|
|
19
|
+
config_1.default.get('paths').installedAdaptersPath ?? '',
|
|
20
|
+
// load adapters from content last, so that they don't override any other
|
|
21
|
+
// internal or platform-installed adapters
|
|
22
|
+
// TODO: potentially deprecate/remove as part of Ghost 7.0
|
|
23
|
+
config_1.default.getContentPath('adapters')
|
|
24
|
+
]));
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import config from '../../../shared/config';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Where adapters are looked up, in order. Also read by bin/validate-adapters.ts,
|
|
5
|
+
* which checks adapter implementations at build time - keep this the only place
|
|
6
|
+
* the lookup order is declared, so a name resolves there exactly as it does here.
|
|
7
|
+
*/
|
|
8
|
+
export const adapterPaths: string[] = Array.from(new Set<string>([
|
|
9
|
+
'', // A blank path will cause us to check node_modules for the adapter
|
|
10
|
+
config.get('paths').internalAdaptersPath,
|
|
11
|
+
|
|
12
|
+
// custom docker builds may install adapters in a separate path from content,
|
|
13
|
+
// since the content dir is often bind-mounted into the container. Offering
|
|
14
|
+
// an escape hatch here to allow for this
|
|
15
|
+
config.get('paths').installedAdaptersPath ?? '',
|
|
16
|
+
|
|
17
|
+
// load adapters from content last, so that they don't override any other
|
|
18
|
+
// internal or platform-installed adapters
|
|
19
|
+
// TODO: potentially deprecate/remove as part of Ghost 7.0
|
|
20
|
+
config.getContentPath('adapters')
|
|
21
|
+
]));
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.baseClasses = void 0;
|
|
4
|
+
const ghost_storage_base_1 = require("ghost-storage-base");
|
|
5
|
+
const adapter_base_scheduling_1 = require("@tryghost/adapter-base-scheduling");
|
|
6
|
+
const adapter_base_sso_1 = require("@tryghost/adapter-base-sso");
|
|
7
|
+
const adapter_base_cache_1 = require("@tryghost/adapter-base-cache");
|
|
8
|
+
const adapter_base_redirects_1 = require("@tryghost/adapter-base-redirects");
|
|
9
|
+
const adapter_base_route_settings_1 = require("@tryghost/adapter-base-route-settings");
|
|
10
|
+
/**
|
|
11
|
+
* The base class every adapter of a given type must extend. Also read by
|
|
12
|
+
* bin/validate-adapters.js, which checks adapter implementations at build time -
|
|
13
|
+
* keep this the only place the mapping is declared.
|
|
14
|
+
*/
|
|
15
|
+
exports.baseClasses = {
|
|
16
|
+
storage: ghost_storage_base_1.StorageBase,
|
|
17
|
+
scheduling: adapter_base_scheduling_1.SchedulingBase,
|
|
18
|
+
sso: adapter_base_sso_1.SSOBase,
|
|
19
|
+
cache: adapter_base_cache_1.CacheBase,
|
|
20
|
+
redirects: adapter_base_redirects_1.RedirectsStoreBase,
|
|
21
|
+
'route-settings': adapter_base_route_settings_1.RouteSettingsStoreBase
|
|
22
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {StorageBase} from 'ghost-storage-base';
|
|
2
|
+
import {SchedulingBase} from '@tryghost/adapter-base-scheduling';
|
|
3
|
+
import {SSOBase} from '@tryghost/adapter-base-sso';
|
|
4
|
+
import {CacheBase} from '@tryghost/adapter-base-cache';
|
|
5
|
+
import {RedirectsStoreBase} from '@tryghost/adapter-base-redirects';
|
|
6
|
+
import {RouteSettingsStoreBase} from '@tryghost/adapter-base-route-settings';
|
|
7
|
+
|
|
8
|
+
import type {BaseClassMap} from './adapter-manager';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The base class every adapter of a given type must extend. Also read by
|
|
12
|
+
* bin/validate-adapters.js, which checks adapter implementations at build time -
|
|
13
|
+
* keep this the only place the mapping is declared.
|
|
14
|
+
*/
|
|
15
|
+
export const baseClasses = {
|
|
16
|
+
storage: StorageBase,
|
|
17
|
+
scheduling: SchedulingBase,
|
|
18
|
+
sso: SSOBase,
|
|
19
|
+
cache: CacheBase,
|
|
20
|
+
redirects: RedirectsStoreBase,
|
|
21
|
+
'route-settings': RouteSettingsStoreBase
|
|
22
|
+
} satisfies BaseClassMap;
|
|
@@ -3,40 +3,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const ghost_storage_base_1 = require("ghost-storage-base");
|
|
7
|
-
const adapter_base_scheduling_1 = require("@tryghost/adapter-base-scheduling");
|
|
8
|
-
const adapter_base_sso_1 = require("@tryghost/adapter-base-sso");
|
|
9
|
-
const adapter_base_cache_1 = require("@tryghost/adapter-base-cache");
|
|
10
|
-
const adapter_base_redirects_1 = require("@tryghost/adapter-base-redirects");
|
|
11
|
-
const adapter_base_route_settings_1 = require("@tryghost/adapter-base-route-settings");
|
|
12
6
|
const adapter_manager_1 = require("./adapter-manager");
|
|
7
|
+
const adapter_paths_1 = require("./adapter-paths");
|
|
8
|
+
const base_classes_1 = require("./base-classes");
|
|
13
9
|
const config_1 = __importDefault(require("../../../shared/config"));
|
|
14
|
-
const adapterPaths = new Set([
|
|
15
|
-
'', // A blank path will cause us to check node_modules for the adapter
|
|
16
|
-
config_1.default.get('paths').internalAdaptersPath,
|
|
17
|
-
// custom docker builds may install adapters in a separate path from content,
|
|
18
|
-
// since the content dir is often bind-mounted into the container. Offering
|
|
19
|
-
// an escape hatch here to allow for this
|
|
20
|
-
config_1.default.get('paths').installedAdaptersPath ?? '',
|
|
21
|
-
// load adapters from content last, so that they don't override any other
|
|
22
|
-
// internal or platform-installed adapters
|
|
23
|
-
// TODO: potentially deprecate/remove as part of Ghost 7.0
|
|
24
|
-
config_1.default.getContentPath('adapters'),
|
|
25
|
-
]);
|
|
26
10
|
// A singleton adapter manager, preconfigured with the base classes for every
|
|
27
11
|
// known adapter type. `getAdapter` resolves the active adapter and its options
|
|
28
12
|
// from config on each call, so runtime config changes are always reflected.
|
|
29
13
|
const adapterManager = new adapter_manager_1.AdapterManager({
|
|
30
14
|
loadAdapterFromPath: require,
|
|
31
15
|
config: config_1.default,
|
|
32
|
-
pathsToAdapters:
|
|
33
|
-
baseClasses:
|
|
34
|
-
storage: ghost_storage_base_1.StorageBase,
|
|
35
|
-
scheduling: adapter_base_scheduling_1.SchedulingBase,
|
|
36
|
-
sso: adapter_base_sso_1.SSOBase,
|
|
37
|
-
cache: adapter_base_cache_1.CacheBase,
|
|
38
|
-
redirects: adapter_base_redirects_1.RedirectsStoreBase,
|
|
39
|
-
'route-settings': adapter_base_route_settings_1.RouteSettingsStoreBase
|
|
40
|
-
}
|
|
16
|
+
pathsToAdapters: adapter_paths_1.adapterPaths,
|
|
17
|
+
baseClasses: base_classes_1.baseClasses
|
|
41
18
|
});
|
|
42
19
|
exports.default = adapterManager;
|
|
@@ -1,43 +1,16 @@
|
|
|
1
|
-
import {StorageBase} from 'ghost-storage-base';
|
|
2
|
-
import {SchedulingBase} from '@tryghost/adapter-base-scheduling';
|
|
3
|
-
import {SSOBase} from '@tryghost/adapter-base-sso';
|
|
4
|
-
import {CacheBase} from '@tryghost/adapter-base-cache';
|
|
5
|
-
import {RedirectsStoreBase} from '@tryghost/adapter-base-redirects';
|
|
6
|
-
import {RouteSettingsStoreBase} from '@tryghost/adapter-base-route-settings';
|
|
7
|
-
|
|
8
1
|
import {AdapterManager} from './adapter-manager';
|
|
2
|
+
import {adapterPaths} from './adapter-paths';
|
|
3
|
+
import {baseClasses} from './base-classes';
|
|
9
4
|
import config from '../../../shared/config';
|
|
10
5
|
|
|
11
|
-
const adapterPaths = new Set<string>([
|
|
12
|
-
'', // A blank path will cause us to check node_modules for the adapter
|
|
13
|
-
config.get('paths').internalAdaptersPath,
|
|
14
|
-
|
|
15
|
-
// custom docker builds may install adapters in a separate path from content,
|
|
16
|
-
// since the content dir is often bind-mounted into the container. Offering
|
|
17
|
-
// an escape hatch here to allow for this
|
|
18
|
-
config.get('paths').installedAdaptersPath ?? '',
|
|
19
|
-
|
|
20
|
-
// load adapters from content last, so that they don't override any other
|
|
21
|
-
// internal or platform-installed adapters
|
|
22
|
-
// TODO: potentially deprecate/remove as part of Ghost 7.0
|
|
23
|
-
config.getContentPath('adapters'),
|
|
24
|
-
]);
|
|
25
|
-
|
|
26
6
|
// A singleton adapter manager, preconfigured with the base classes for every
|
|
27
7
|
// known adapter type. `getAdapter` resolves the active adapter and its options
|
|
28
8
|
// from config on each call, so runtime config changes are always reflected.
|
|
29
9
|
const adapterManager = new AdapterManager({
|
|
30
10
|
loadAdapterFromPath: require,
|
|
31
11
|
config,
|
|
32
|
-
pathsToAdapters:
|
|
33
|
-
baseClasses
|
|
34
|
-
storage: StorageBase,
|
|
35
|
-
scheduling: SchedulingBase,
|
|
36
|
-
sso: SSOBase,
|
|
37
|
-
cache: CacheBase,
|
|
38
|
-
redirects: RedirectsStoreBase,
|
|
39
|
-
'route-settings': RouteSettingsStoreBase
|
|
40
|
-
}
|
|
12
|
+
pathsToAdapters: adapterPaths,
|
|
13
|
+
baseClasses
|
|
41
14
|
});
|
|
42
15
|
|
|
43
16
|
export default adapterManager;
|
|
@@ -5,12 +5,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.resolveAdapterEntryPoint = resolveAdapterEntryPoint;
|
|
7
7
|
exports.resolveAdapterExport = resolveAdapterExport;
|
|
8
|
+
exports.loadAdapterClass = loadAdapterClass;
|
|
8
9
|
exports.normalizeAdapterConfig = normalizeAdapterConfig;
|
|
9
10
|
exports.getConfiguredFeatures = getConfiguredFeatures;
|
|
10
11
|
exports.resolveAdapterOptions = resolveAdapterOptions;
|
|
11
12
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
12
13
|
const node_path_1 = __importDefault(require("node:path"));
|
|
13
14
|
const node_module_1 = require("node:module");
|
|
15
|
+
const errors_1 = __importDefault(require("@tryghost/errors"));
|
|
14
16
|
/**
|
|
15
17
|
* Whether `filePath` resolves to a location inside `directory`.
|
|
16
18
|
*
|
|
@@ -116,6 +118,54 @@ function resolveAdapterExport(moduleExport) {
|
|
|
116
118
|
}
|
|
117
119
|
return null;
|
|
118
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* Locate and load an adapter constructor by type and class name, trying each of
|
|
123
|
+
* `pathsToAdapters` in order. Shared by the adapter manager and by
|
|
124
|
+
* bin/validate-adapters.ts, so a name resolves — and fails — identically at build
|
|
125
|
+
* time and at runtime.
|
|
126
|
+
*/
|
|
127
|
+
function loadAdapterClass(adapterType, adapterClassName, pathsToAdapters, loadAdapterFromPath) {
|
|
128
|
+
for (const pathToAdapters of pathsToAdapters) {
|
|
129
|
+
let pathToAdapter = node_path_1.default.join(pathToAdapters, adapterType, adapterClassName);
|
|
130
|
+
if (pathToAdapters === '') {
|
|
131
|
+
// We are loading from node_modules, we can remove the `adapterType` prefix
|
|
132
|
+
pathToAdapter = node_path_1.default.join(pathToAdapters, adapterClassName);
|
|
133
|
+
}
|
|
134
|
+
// An adapter directory may be a full module with its own
|
|
135
|
+
// package.json, in which case this resolves the `exports` entry
|
|
136
|
+
// point; otherwise the path passes through unchanged.
|
|
137
|
+
const moduleToLoad = resolveAdapterEntryPoint(pathToAdapter);
|
|
138
|
+
try {
|
|
139
|
+
const Adapter = resolveAdapterExport(loadAdapterFromPath(moduleToLoad));
|
|
140
|
+
if (Adapter) {
|
|
141
|
+
return Adapter;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
// Catch runtime errors
|
|
146
|
+
if (!(err instanceof Error) || err.code !== 'MODULE_NOT_FOUND') {
|
|
147
|
+
throw new errors_1.default.IncorrectUsageError({ err: err });
|
|
148
|
+
}
|
|
149
|
+
// Catch missing dependencies BUT NOT missing adapter.
|
|
150
|
+
// Only check the first line — Node appends a "Require stack"
|
|
151
|
+
// that includes the adapter's own path, which would false-positive.
|
|
152
|
+
const firstLine = err.message.split('\n')[0];
|
|
153
|
+
if (!firstLine.includes(pathToAdapter)) {
|
|
154
|
+
// Name the unresolved module so the error is actionable, e.g.
|
|
155
|
+
// "Cannot find module 'superagent'" -> 'superagent'.
|
|
156
|
+
const missingMatch = /Cannot find module '([^']+)'/.exec(firstLine);
|
|
157
|
+
const missingModule = missingMatch ? ` '${missingMatch[1]}'` : '';
|
|
158
|
+
throw new errors_1.default.IncorrectUsageError({
|
|
159
|
+
message: `You are missing a dependency${missingModule} in your adapter ${pathToAdapter}`,
|
|
160
|
+
err: err
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
throw new errors_1.default.IncorrectUsageError({
|
|
166
|
+
message: `Unable to find ${adapterType} adapter ${adapterClassName} in ${pathsToAdapters}.`
|
|
167
|
+
});
|
|
168
|
+
}
|
|
119
169
|
function getSchedulingConfig(config) {
|
|
120
170
|
const adapterConfig = config.get('adapters:scheduling');
|
|
121
171
|
if (!adapterConfig) {
|