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
|
@@ -82,7 +82,7 @@ interface StripeSubscriptions {
|
|
|
82
82
|
|
|
83
83
|
// Gifts: reassigning a redeemed gift to the imported member.
|
|
84
84
|
export interface GiftService {
|
|
85
|
-
reassignRedeemer(giftId: string, memberId: string, options:
|
|
85
|
+
reassignRedeemer(giftId: string, memberId: string, options: {transacting?: Knex.Transaction}): Promise<void>;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
// The completion email concern: who it goes to, the links it carries, and sending
|
|
@@ -99,7 +99,7 @@ type CustomFieldPlan = unknown;
|
|
|
99
99
|
// The custom fields collaborator as the import needs it. activeFields is the field set a
|
|
100
100
|
// custom_fields.* column is read against, empty when the feature is off; planWrite
|
|
101
101
|
// validates a row's values (throwing so the row fails whole) and applyWrite persists
|
|
102
|
-
// them, both on the row's transaction.
|
|
102
|
+
// them, touching only the parts the row named, both on the row's transaction.
|
|
103
103
|
export interface CustomFieldsImport {
|
|
104
104
|
activeFields(): Promise<CsvField[]>;
|
|
105
105
|
planWrite(values: Record<string, unknown>): Promise<CustomFieldPlan[]>;
|
|
@@ -332,7 +332,7 @@ class MembersCSVImporter {
|
|
|
332
332
|
// before any member write -- so there is no reason to hold a transaction
|
|
333
333
|
// across it, and doing so would deadlock the single-connection SQLite pool.
|
|
334
334
|
const customFieldPlan = activeCustomFields.length > 0
|
|
335
|
-
? await this._customFields.planWrite(fieldValuesFromCsvRow(activeCustomFields, row, stripFormulaGuard))
|
|
335
|
+
? await namingTheColumn(() => this._customFields.planWrite(fieldValuesFromCsvRow(activeCustomFields, row, stripFormulaGuard)))
|
|
336
336
|
: [];
|
|
337
337
|
|
|
338
338
|
trx = await this._knex.transaction(undefined, {doNotRejectOnRollback: false});
|
|
@@ -432,15 +432,16 @@ class MembersCSVImporter {
|
|
|
432
432
|
imported += 1;
|
|
433
433
|
} catch (error) {
|
|
434
434
|
const errorList: unknown[] = Array.isArray(error) ? error : [error];
|
|
435
|
-
const
|
|
435
|
+
const reasons = errorList
|
|
436
436
|
.map(e => (typeof e === 'object' && e !== null && 'message' in e ? e.message : undefined))
|
|
437
|
-
.
|
|
437
|
+
.filter((message): message is string => typeof message === 'string');
|
|
438
|
+
const errorMessage = reasons.join('\n');
|
|
438
439
|
// trx is unset if the row failed before the transaction opened (a bad
|
|
439
440
|
// custom field value or gift combination).
|
|
440
441
|
if (trx) {
|
|
441
442
|
await trx.rollback();
|
|
442
443
|
}
|
|
443
|
-
importErrors.push({...row, error: errorMessage});
|
|
444
|
+
importErrors.push({...row, error: errorMessage, errors: reasons});
|
|
444
445
|
}
|
|
445
446
|
}
|
|
446
447
|
|
|
@@ -457,6 +458,26 @@ class MembersCSVImporter {
|
|
|
457
458
|
}
|
|
458
459
|
}
|
|
459
460
|
|
|
461
|
+
// A row error is read next to a spreadsheet, and a value rejection states only what the
|
|
462
|
+
// value should be — the same sentence Admin shows under a single input, where the field is
|
|
463
|
+
// already on screen. `property` is the dotted path a default export writes as its column
|
|
464
|
+
// header, so prefixing with it names the column a publisher has to go and fix.
|
|
465
|
+
//
|
|
466
|
+
// A rejection about the whole request carries the bare namespace and names no field after
|
|
467
|
+
// it, so it is left alone rather than made to point at a column that does not exist.
|
|
468
|
+
async function namingTheColumn<T>(plan: () => Promise<T>): Promise<T> {
|
|
469
|
+
try {
|
|
470
|
+
return await plan();
|
|
471
|
+
} catch (error) {
|
|
472
|
+
const {property, message} = (error ?? {}) as {property?: unknown; message?: unknown};
|
|
473
|
+
const namesAField = typeof property === 'string' && property.includes('.');
|
|
474
|
+
if (!namesAField || typeof message !== 'string') {
|
|
475
|
+
throw error;
|
|
476
|
+
}
|
|
477
|
+
throw new errors.DataImportError({message: `${property}: ${message}`});
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
460
481
|
function wrapGiftError(error: unknown) {
|
|
461
482
|
const err = error as {message?: unknown};
|
|
462
483
|
const message = (err && typeof err.message === 'string' && err.message) || tpl(messages.giftReassignFailed);
|
|
@@ -42,7 +42,11 @@ export type MemberImportRow = z.infer<typeof memberImportRowSchema>;
|
|
|
42
42
|
|
|
43
43
|
// A row that failed to import, carrying the raw message that stopped it. The message is
|
|
44
44
|
// left raw here; turning it into human copy is a presentation concern.
|
|
45
|
-
|
|
45
|
+
// A row can fail for more than one reason. `errors` is the list; `error` is that list
|
|
46
|
+
// written out for the error report's single cell. Two fields because a reason may quote a
|
|
47
|
+
// cell the publisher wrote, and a CSV cell legally holds commas and newlines, so no
|
|
48
|
+
// separator survives being split back apart.
|
|
49
|
+
export type ImportErrorRow = MemberImportRow & {error: string; errors: string[]};
|
|
46
50
|
|
|
47
51
|
// The persisted import label as plain data -- taken off the Bookshelf model before it
|
|
48
52
|
// leaves the kernel, so the result and the email carry only what they show.
|
|
@@ -40,7 +40,11 @@ function makeImporter(deps) {
|
|
|
40
40
|
// Gifts is initialised at boot and always present at request time; the getter
|
|
41
41
|
// resolves it lazily so the ready service is picked up whenever a row uses it.
|
|
42
42
|
const gifts = {
|
|
43
|
-
reassignRedeemer: (giftId, memberId, options) => deps.getGiftService().reassignRedeemer(
|
|
43
|
+
reassignRedeemer: (giftId, memberId, options) => deps.getGiftService().reassignRedeemer({
|
|
44
|
+
giftId,
|
|
45
|
+
memberId,
|
|
46
|
+
transacting: options.transacting
|
|
47
|
+
})
|
|
44
48
|
};
|
|
45
49
|
// Gated by the same labs flag as the export, so the two halves round-trip or stay
|
|
46
50
|
// silent together: off, activeFields resolves empty and every custom_fields.* column
|
|
@@ -48,7 +52,7 @@ function makeImporter(deps) {
|
|
|
48
52
|
const customFields = {
|
|
49
53
|
activeFields: async () => (labs.isSet('membersCustomFields') ? deps.customFields.definitions.browse() : []),
|
|
50
54
|
planWrite: values => deps.customFields.values.planWrite(values),
|
|
51
|
-
applyWrite: (memberId, plan, executor) => deps.customFields.values.applyWrite(memberId, plan, executor)
|
|
55
|
+
applyWrite: (memberId, plan, executor) => deps.customFields.values.applyWrite(memberId, plan, { executor })
|
|
52
56
|
};
|
|
53
57
|
return new importer_1.default({
|
|
54
58
|
knex: deps.knex,
|
|
@@ -18,7 +18,9 @@ interface ImporterServices {
|
|
|
18
18
|
getMembersRepository(): Promise<Omit<MembersRepository, 'getImportLabel'>>;
|
|
19
19
|
getDefaultTier(): Promise<Tier>;
|
|
20
20
|
getTierByName(name: string): Promise<Tier | null>;
|
|
21
|
-
getGiftService():
|
|
21
|
+
getGiftService(): {
|
|
22
|
+
reassignRedeemer(input: {giftId: string; memberId: string; transacting?: Knex.Transaction}): Promise<void>;
|
|
23
|
+
};
|
|
22
24
|
sendEmail: EmailNotifications['send'];
|
|
23
25
|
urlFor: EmailNotifications['urlFor'];
|
|
24
26
|
addJob(job: {job: () => Promise<void>; offloaded: boolean; name: string}): void;
|
|
@@ -31,7 +33,7 @@ interface ImporterServices {
|
|
|
31
33
|
definitions: {browse(): Promise<CsvField[]>};
|
|
32
34
|
values: {
|
|
33
35
|
planWrite(values: Record<string, unknown>): Promise<unknown[]>;
|
|
34
|
-
applyWrite(memberId: string, plan: unknown[], executor
|
|
36
|
+
applyWrite(memberId: string, plan: unknown[], options?: {executor?: Knex}): Promise<void>;
|
|
35
37
|
};
|
|
36
38
|
};
|
|
37
39
|
}
|
|
@@ -72,7 +74,11 @@ export function makeImporter(deps: ImporterServices) {
|
|
|
72
74
|
// Gifts is initialised at boot and always present at request time; the getter
|
|
73
75
|
// resolves it lazily so the ready service is picked up whenever a row uses it.
|
|
74
76
|
const gifts: GiftService = {
|
|
75
|
-
reassignRedeemer: (giftId, memberId, options) => deps.getGiftService().reassignRedeemer(
|
|
77
|
+
reassignRedeemer: (giftId, memberId, options) => deps.getGiftService().reassignRedeemer({
|
|
78
|
+
giftId,
|
|
79
|
+
memberId,
|
|
80
|
+
transacting: options.transacting
|
|
81
|
+
})
|
|
76
82
|
};
|
|
77
83
|
|
|
78
84
|
// Gated by the same labs flag as the export, so the two halves round-trip or stay
|
|
@@ -81,7 +87,7 @@ export function makeImporter(deps: ImporterServices) {
|
|
|
81
87
|
const customFields: CustomFieldsImport = {
|
|
82
88
|
activeFields: async () => (labs.isSet('membersCustomFields') ? deps.customFields.definitions.browse() : []),
|
|
83
89
|
planWrite: values => deps.customFields.values.planWrite(values),
|
|
84
|
-
applyWrite: (memberId, plan, executor) => deps.customFields.values.applyWrite(memberId, plan, executor)
|
|
90
|
+
applyWrite: (memberId, plan, executor) => deps.customFields.values.applyWrite(memberId, plan, {executor})
|
|
85
91
|
};
|
|
86
92
|
|
|
87
93
|
return new MembersCSVImporter({
|
|
@@ -525,7 +525,7 @@ module.exports = class RouterController {
|
|
|
525
525
|
* @param {string} options.cancelUrl URL to redirect to after cancelled checkout
|
|
526
526
|
* @param {string} [options.email] Email address of the customer
|
|
527
527
|
* @param {object} [options.member] Currently authenticated member OR member associated with the email address
|
|
528
|
-
* @param {
|
|
528
|
+
* @param {number|null} [options.giftTrialDays] Stable continuation decision from gift subscriptions
|
|
529
529
|
* @param {boolean} options.isAuthenticated
|
|
530
530
|
* @param {object} options.metadata Metadata to be passed to Stripe
|
|
531
531
|
* @returns
|
|
@@ -680,9 +680,11 @@ module.exports = class RouterController {
|
|
|
680
680
|
|
|
681
681
|
/**
|
|
682
682
|
* @param {object} options
|
|
683
|
-
* @param {
|
|
684
|
-
* @param {
|
|
685
|
-
* @param {string} options.
|
|
683
|
+
* @param {string} options.tierId
|
|
684
|
+
* @param {string} [options.offerId]
|
|
685
|
+
* @param {string} [options.cadence]
|
|
686
|
+
* @param {number} [options.duration]
|
|
687
|
+
* @param {string} [options.email]
|
|
686
688
|
* @param {string} options.successUrl
|
|
687
689
|
* @param {string} options.cancelUrl
|
|
688
690
|
* @param {object} options.metadata
|
|
@@ -698,10 +700,26 @@ module.exports = class RouterController {
|
|
|
698
700
|
}
|
|
699
701
|
|
|
700
702
|
try {
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
703
|
+
return await this._giftService.service.startCheckout({
|
|
704
|
+
tierId: options.tierId,
|
|
705
|
+
offerId: options.offerId,
|
|
706
|
+
cadence: options.cadence,
|
|
707
|
+
duration: options.duration,
|
|
708
|
+
metadata: options.metadata,
|
|
709
|
+
successUrl: options.successUrl,
|
|
710
|
+
cancelUrl: options.cancelUrl,
|
|
711
|
+
buyer: {
|
|
712
|
+
memberId: options.member?.id ?? null,
|
|
713
|
+
email: options.member?.get('email') ?? options.email ?? null,
|
|
714
|
+
name: options.member?.get('name') ?? null,
|
|
715
|
+
isAuthenticated: options.isAuthenticated
|
|
716
|
+
}
|
|
717
|
+
});
|
|
704
718
|
} catch (err) {
|
|
719
|
+
if (err instanceof BadRequestError || err instanceof NoPermissionError) {
|
|
720
|
+
throw err;
|
|
721
|
+
}
|
|
722
|
+
|
|
705
723
|
logging.error(err);
|
|
706
724
|
this._sentry?.captureException?.(err);
|
|
707
725
|
throw new BadRequestError({
|
|
@@ -788,7 +806,7 @@ module.exports = class RouterController {
|
|
|
788
806
|
let tier;
|
|
789
807
|
let cadence;
|
|
790
808
|
let offer;
|
|
791
|
-
let
|
|
809
|
+
let giftTrialDays;
|
|
792
810
|
|
|
793
811
|
if (req.body.continueFromGift) {
|
|
794
812
|
if (!isAuthenticated || !member) {
|
|
@@ -796,25 +814,16 @@ module.exports = class RouterController {
|
|
|
796
814
|
message: tpl(messages.signInRequired)
|
|
797
815
|
});
|
|
798
816
|
}
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
});
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
gift = await this._giftService.service.getActiveByMember(member.id);
|
|
807
|
-
if (!gift) {
|
|
808
|
-
throw new BadRequestError({
|
|
809
|
-
message: tpl(messages.badRequest),
|
|
810
|
-
context: 'No active gift subscription found for member'
|
|
811
|
-
});
|
|
812
|
-
}
|
|
817
|
+
const continuation = await this._giftService.service.preparePaidContinuation({
|
|
818
|
+
memberId: member.id,
|
|
819
|
+
memberStatus: member.get('status')
|
|
820
|
+
});
|
|
813
821
|
|
|
814
822
|
({tier, cadence} = await this._getSubscriptionCheckoutData({
|
|
815
|
-
tierId:
|
|
816
|
-
cadence:
|
|
823
|
+
tierId: continuation.tierId,
|
|
824
|
+
cadence: continuation.cadence
|
|
817
825
|
}));
|
|
826
|
+
giftTrialDays = continuation.trialDays;
|
|
818
827
|
} else {
|
|
819
828
|
({tier, cadence, offer} = await this._getSubscriptionCheckoutData(req.body));
|
|
820
829
|
}
|
|
@@ -825,7 +834,7 @@ module.exports = class RouterController {
|
|
|
825
834
|
tier,
|
|
826
835
|
cadence,
|
|
827
836
|
offer,
|
|
828
|
-
|
|
837
|
+
giftTrialDays
|
|
829
838
|
});
|
|
830
839
|
|
|
831
840
|
// Add welcome_page_url to the response if available and member is authenticated
|
|
@@ -842,19 +851,12 @@ module.exports = class RouterController {
|
|
|
842
851
|
});
|
|
843
852
|
}
|
|
844
853
|
|
|
845
|
-
if (req.body.offerId) {
|
|
846
|
-
throw new BadRequestError({
|
|
847
|
-
message: tpl(messages.badRequest),
|
|
848
|
-
context: 'Offers cannot be applied to gift subscriptions'
|
|
849
|
-
});
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
const data = await this._getSubscriptionCheckoutData(req.body);
|
|
853
|
-
|
|
854
854
|
response = await this._createGiftCheckoutSession({
|
|
855
855
|
...options,
|
|
856
|
-
|
|
857
|
-
|
|
856
|
+
tierId: req.body.tierId,
|
|
857
|
+
offerId: req.body.offerId,
|
|
858
|
+
cadence: req.body.cadence,
|
|
859
|
+
duration: req.body.duration,
|
|
858
860
|
successUrl: siteUrl,
|
|
859
861
|
cancelUrl: options.cancelUrl || siteUrl
|
|
860
862
|
});
|
|
@@ -67,8 +67,7 @@ module.exports = function MembersAPI({
|
|
|
67
67
|
MemberFeedback,
|
|
68
68
|
Automation,
|
|
69
69
|
WelcomeEmailAutomationRun,
|
|
70
|
-
AutomatedEmailRecipient
|
|
71
|
-
Gift
|
|
70
|
+
AutomatedEmailRecipient
|
|
72
71
|
},
|
|
73
72
|
tiersService,
|
|
74
73
|
stripeAPIService,
|
|
@@ -142,7 +141,7 @@ module.exports = function MembersAPI({
|
|
|
142
141
|
memberAttributionService,
|
|
143
142
|
MemberEmailChangeEvent,
|
|
144
143
|
AutomatedEmailRecipient,
|
|
145
|
-
|
|
144
|
+
giftSubscriptions: giftService
|
|
146
145
|
});
|
|
147
146
|
|
|
148
147
|
const nextPaymentCalculator = new NextPaymentCalculator();
|
|
@@ -192,8 +191,7 @@ module.exports = function MembersAPI({
|
|
|
192
191
|
Offer,
|
|
193
192
|
offersAPI,
|
|
194
193
|
stripeAPIService,
|
|
195
|
-
settingsCache
|
|
196
|
-
giftService
|
|
194
|
+
settingsCache
|
|
197
195
|
});
|
|
198
196
|
|
|
199
197
|
const memberController = new MemberController({
|
|
@@ -283,7 +281,10 @@ module.exports = function MembersAPI({
|
|
|
283
281
|
}
|
|
284
282
|
|
|
285
283
|
if (giftToken) {
|
|
286
|
-
await giftService.service.redeem(
|
|
284
|
+
await giftService.service.redeem({
|
|
285
|
+
token: giftToken,
|
|
286
|
+
memberId: member.id
|
|
287
|
+
});
|
|
287
288
|
}
|
|
288
289
|
|
|
289
290
|
await MemberLoginEvent.add({member_id: member.id});
|
|
@@ -316,7 +317,12 @@ module.exports = function MembersAPI({
|
|
|
316
317
|
{name, email, labels, newsletters, attribution, geolocation, status: 'gift'},
|
|
317
318
|
{transacting}
|
|
318
319
|
);
|
|
319
|
-
await giftService.service.redeem(
|
|
320
|
+
await giftService.service.redeem({
|
|
321
|
+
token: giftToken,
|
|
322
|
+
memberId: created.id,
|
|
323
|
+
transacting,
|
|
324
|
+
newMember: true
|
|
325
|
+
});
|
|
320
326
|
return created;
|
|
321
327
|
});
|
|
322
328
|
} else {
|
|
@@ -37,7 +37,7 @@ module.exports = class EventRepository {
|
|
|
37
37
|
urlService,
|
|
38
38
|
MemberEmailChangeEvent,
|
|
39
39
|
AutomatedEmailRecipient,
|
|
40
|
-
|
|
40
|
+
giftSubscriptions
|
|
41
41
|
}) {
|
|
42
42
|
this._DonationPaymentEvent = DonationPaymentEvent;
|
|
43
43
|
this._MemberSubscribeEvent = MemberSubscribeEvent;
|
|
@@ -57,7 +57,7 @@ module.exports = class EventRepository {
|
|
|
57
57
|
this._memberAttributionService = memberAttributionService;
|
|
58
58
|
this._MemberEmailChangeEvent = MemberEmailChangeEvent;
|
|
59
59
|
this._AutomatedEmailRecipient = AutomatedEmailRecipient;
|
|
60
|
-
this.
|
|
60
|
+
this._giftSubscriptions = giftSubscriptions;
|
|
61
61
|
this._knex = db.knex;
|
|
62
62
|
}
|
|
63
63
|
|
|
@@ -462,101 +462,11 @@ module.exports = class EventRepository {
|
|
|
462
462
|
}
|
|
463
463
|
|
|
464
464
|
async getGiftPurchaseEvents(options = {}, filter) {
|
|
465
|
-
options
|
|
466
|
-
...options,
|
|
467
|
-
withRelated: ['buyer', 'tier'],
|
|
468
|
-
filter: 'buyer_member_id:-null+custom:true',
|
|
469
|
-
useBasicCount: true,
|
|
470
|
-
mongoTransformer: chainTransformers(
|
|
471
|
-
// First set the filter manually
|
|
472
|
-
replaceCustomFilterTransformer(filter),
|
|
473
|
-
|
|
474
|
-
// Map the used keys in that filter
|
|
475
|
-
...mapKeys({
|
|
476
|
-
'data.created_at': 'purchased_at',
|
|
477
|
-
'data.member_id': 'buyer_member_id'
|
|
478
|
-
})
|
|
479
|
-
)
|
|
480
|
-
};
|
|
481
|
-
|
|
482
|
-
if (options.order) {
|
|
483
|
-
options.order = options.order.replace(/created_at/g, 'purchased_at');
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
const {data: models, meta} = await this._Gift.findPage(options);
|
|
487
|
-
|
|
488
|
-
const data = models.map((model) => {
|
|
489
|
-
const json = model.toJSON(options);
|
|
490
|
-
|
|
491
|
-
return {
|
|
492
|
-
type: 'gift_purchase_event',
|
|
493
|
-
data: {
|
|
494
|
-
id: json.id,
|
|
495
|
-
member: json.buyer || null,
|
|
496
|
-
member_id: json.buyer_member_id,
|
|
497
|
-
tier_name: json.tier?.name,
|
|
498
|
-
cadence: json.cadence,
|
|
499
|
-
duration: json.duration,
|
|
500
|
-
amount: json.amount,
|
|
501
|
-
currency: json.currency,
|
|
502
|
-
created_at: json.purchased_at
|
|
503
|
-
}
|
|
504
|
-
};
|
|
505
|
-
});
|
|
506
|
-
|
|
507
|
-
return {
|
|
508
|
-
data,
|
|
509
|
-
meta
|
|
510
|
-
};
|
|
465
|
+
return this._giftSubscriptions.service.browsePurchaseEvents(options, filter);
|
|
511
466
|
}
|
|
512
467
|
|
|
513
468
|
async getGiftRedemptionEvents(options = {}, filter) {
|
|
514
|
-
options
|
|
515
|
-
...options,
|
|
516
|
-
withRelated: ['redeemer', 'tier'],
|
|
517
|
-
filter: 'redeemer_member_id:-null+custom:true',
|
|
518
|
-
useBasicCount: true,
|
|
519
|
-
mongoTransformer: chainTransformers(
|
|
520
|
-
// First set the filter manually
|
|
521
|
-
replaceCustomFilterTransformer(filter),
|
|
522
|
-
|
|
523
|
-
// Map the used keys in that filter
|
|
524
|
-
...mapKeys({
|
|
525
|
-
'data.created_at': 'redeemed_at',
|
|
526
|
-
'data.member_id': 'redeemer_member_id'
|
|
527
|
-
})
|
|
528
|
-
)
|
|
529
|
-
};
|
|
530
|
-
|
|
531
|
-
if (options.order) {
|
|
532
|
-
options.order = options.order.replace(/created_at/g, 'redeemed_at');
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
const {data: models, meta} = await this._Gift.findPage(options);
|
|
536
|
-
|
|
537
|
-
const data = models.map((model) => {
|
|
538
|
-
const json = model.toJSON(options);
|
|
539
|
-
|
|
540
|
-
return {
|
|
541
|
-
type: 'gift_redemption_event',
|
|
542
|
-
data: {
|
|
543
|
-
id: json.id,
|
|
544
|
-
member: json.redeemer || null,
|
|
545
|
-
member_id: json.redeemer_member_id,
|
|
546
|
-
tier_name: json.tier?.name,
|
|
547
|
-
cadence: json.cadence,
|
|
548
|
-
duration: json.duration,
|
|
549
|
-
amount: json.amount,
|
|
550
|
-
currency: json.currency,
|
|
551
|
-
created_at: json.redeemed_at
|
|
552
|
-
}
|
|
553
|
-
};
|
|
554
|
-
});
|
|
555
|
-
|
|
556
|
-
return {
|
|
557
|
-
data,
|
|
558
|
-
meta
|
|
559
|
-
};
|
|
469
|
+
return this._giftSubscriptions.service.browseRedemptionEvents(options, filter);
|
|
560
470
|
}
|
|
561
471
|
|
|
562
472
|
async getGiftEndedEvents(options = {}, filter) {
|
|
@@ -34,7 +34,7 @@ const CUSTOM_FIELDS_EDITED_ACTION = 'custom_fields_edited';
|
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
36
|
* @typedef {object} IGiftServiceWrapper
|
|
37
|
-
* @prop {{
|
|
37
|
+
* @prop {{getMemberPresentations: (memberIds: string[]) => Promise<Map<string, {cadence: 'month' | 'year', currency: string, amount: number}>>}} service
|
|
38
38
|
*/
|
|
39
39
|
|
|
40
40
|
module.exports = class MemberBREADService {
|
|
@@ -347,7 +347,7 @@ module.exports = class MemberBREADService {
|
|
|
347
347
|
* @private
|
|
348
348
|
* Fetches active redeemed gifts for any gift-status members in the input list.
|
|
349
349
|
* @param {import('bookshelf').Model[]} members - Bookshelf member models
|
|
350
|
-
* @returns {Promise<Map<string, {cadence: 'month' | 'year', currency: string, amount: number}>>} keyed by member.id →
|
|
350
|
+
* @returns {Promise<Map<string, {cadence: 'month' | 'year', currency: string, amount: number}>>} keyed by member.id → stable gift presentation
|
|
351
351
|
*/
|
|
352
352
|
async fetchActiveGiftsForMembers(members) {
|
|
353
353
|
const giftMemberIds = members
|
|
@@ -359,7 +359,7 @@ module.exports = class MemberBREADService {
|
|
|
359
359
|
}
|
|
360
360
|
|
|
361
361
|
try {
|
|
362
|
-
return await this.giftService.service.
|
|
362
|
+
return await this.giftService.service.getMemberPresentations(giftMemberIds);
|
|
363
363
|
} catch (e) {
|
|
364
364
|
logging.error(`Failed to load active gifts for members - ${giftMemberIds.join(', ')}.`);
|
|
365
365
|
logging.error(e);
|
|
@@ -14,7 +14,6 @@ class PaymentsService {
|
|
|
14
14
|
* @param {import('../../../offers/application/offers-api')} deps.offersAPI
|
|
15
15
|
* @param {import('../../../stripe/stripe-api')} deps.stripeAPIService
|
|
16
16
|
* @param {{get(key: string): any}} deps.settingsCache
|
|
17
|
-
* @param {{service: import('../../../gifts/gift-service').GiftService}} deps.giftService
|
|
18
17
|
*/
|
|
19
18
|
constructor(deps) {
|
|
20
19
|
/** @private */
|
|
@@ -31,9 +30,6 @@ class PaymentsService {
|
|
|
31
30
|
this.stripeAPIService = deps.stripeAPIService;
|
|
32
31
|
/** @private */
|
|
33
32
|
this.settingsCache = deps.settingsCache;
|
|
34
|
-
/** @private */
|
|
35
|
-
this.giftService = deps.giftService;
|
|
36
|
-
|
|
37
33
|
DomainEvents.subscribe(OfferCreatedEvent, async (event) => {
|
|
38
34
|
await this.getCouponForOffer(event.data.offer.id);
|
|
39
35
|
});
|
|
@@ -65,7 +61,7 @@ class PaymentsService {
|
|
|
65
61
|
* @param {Tier.Cadence} params.cadence
|
|
66
62
|
* @param {Offer} [params.offer]
|
|
67
63
|
* @param {Member} [params.member]
|
|
68
|
-
* @param {
|
|
64
|
+
* @param {number|null} [params.giftTrialDays]
|
|
69
65
|
* @param {Object.<string, any>} [params.metadata]
|
|
70
66
|
* @param {string} params.successUrl
|
|
71
67
|
* @param {string} params.cancelUrl
|
|
@@ -73,7 +69,7 @@ class PaymentsService {
|
|
|
73
69
|
*
|
|
74
70
|
* @returns {Promise<URL>}
|
|
75
71
|
*/
|
|
76
|
-
async getPaymentLink({tier, cadence, offer, member,
|
|
72
|
+
async getPaymentLink({tier, cadence, offer, member, giftTrialDays, metadata, successUrl, cancelUrl, email}) {
|
|
77
73
|
let coupon = null;
|
|
78
74
|
let trialDays = null;
|
|
79
75
|
if (offer) {
|
|
@@ -94,12 +90,10 @@ class PaymentsService {
|
|
|
94
90
|
}
|
|
95
91
|
}
|
|
96
92
|
|
|
97
|
-
//
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
trialDays = Math.min(remainingDays, 730); // Stripe max trial period
|
|
102
|
-
}
|
|
93
|
+
// Gift subscriptions owns the continuation calculation. This adapter only
|
|
94
|
+
// translates the stable decision into the recurring Stripe checkout.
|
|
95
|
+
if (trialDays === null && giftTrialDays !== undefined) {
|
|
96
|
+
trialDays = giftTrialDays;
|
|
103
97
|
}
|
|
104
98
|
|
|
105
99
|
let customer = null;
|
|
@@ -163,62 +157,6 @@ class PaymentsService {
|
|
|
163
157
|
return session.url;
|
|
164
158
|
}
|
|
165
159
|
|
|
166
|
-
/**
|
|
167
|
-
* @param {object} params
|
|
168
|
-
* @param {import('../../../tiers/tier')} params.tier
|
|
169
|
-
* @param {'month'|'year'} params.cadence
|
|
170
|
-
* @param {number} params.duration
|
|
171
|
-
* @param {string} params.successUrl
|
|
172
|
-
* @param {string} params.cancelUrl
|
|
173
|
-
* @param {object} params.metadata
|
|
174
|
-
* @param {object} [params.member]
|
|
175
|
-
* @param {boolean} params.isAuthenticated
|
|
176
|
-
* @param {string} [params.email]
|
|
177
|
-
*
|
|
178
|
-
* @returns {Promise<string>}
|
|
179
|
-
*/
|
|
180
|
-
async getGiftPaymentLink({tier, cadence, duration, metadata, successUrl, cancelUrl, member, isAuthenticated, email}) {
|
|
181
|
-
let customer = null;
|
|
182
|
-
if (member && isAuthenticated) {
|
|
183
|
-
customer = await this.getCustomerForMember(member);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
const amount = tier.getPrice(cadence);
|
|
187
|
-
const currency = tier.currency.toLowerCase();
|
|
188
|
-
|
|
189
|
-
const token = this.giftService.service.generateToken();
|
|
190
|
-
|
|
191
|
-
const successUrlObj = new URL(successUrl);
|
|
192
|
-
successUrlObj.searchParams.set('stripe', 'gift-purchase-success');
|
|
193
|
-
successUrlObj.searchParams.set('gift_token', token);
|
|
194
|
-
successUrlObj.searchParams.set('gift_tier', tier.id.toHexString());
|
|
195
|
-
successUrlObj.searchParams.set('gift_cadence', cadence);
|
|
196
|
-
|
|
197
|
-
const data = {
|
|
198
|
-
amount,
|
|
199
|
-
currency,
|
|
200
|
-
tierName: tier.name,
|
|
201
|
-
cadence,
|
|
202
|
-
duration,
|
|
203
|
-
metadata: {
|
|
204
|
-
...metadata,
|
|
205
|
-
ghost_gift: 'true',
|
|
206
|
-
gift_token: token,
|
|
207
|
-
tier_id: tier.id.toHexString(),
|
|
208
|
-
cadence,
|
|
209
|
-
duration: String(duration)
|
|
210
|
-
},
|
|
211
|
-
successUrl: successUrlObj.toString(),
|
|
212
|
-
cancelUrl,
|
|
213
|
-
customer,
|
|
214
|
-
customerEmail: !customer && email ? email : null
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
const session = await this.stripeAPIService.createGiftCheckoutSession(data);
|
|
218
|
-
|
|
219
|
-
return session.url;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
160
|
async getCustomerForMember(member) {
|
|
223
161
|
const rows = await this.StripeCustomerModel.where({
|
|
224
162
|
member_id: member.id
|
|
@@ -3,19 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.activeFields = activeFields;
|
|
4
4
|
const schema_1 = require("./schema");
|
|
5
5
|
const FIELDS_TABLE = 'members_custom_fields';
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
// fields must stay out of every read and every write, and that's enforced by a
|
|
11
|
-
// filter, not a database constraint — nothing stops a value row referencing an
|
|
12
|
-
// archived field, so a query that forgets the filter is a silent bug. Keeping the
|
|
13
|
-
// filter in one builder means there's one place to get it right.
|
|
14
|
-
/**
|
|
15
|
-
* The active field definitions. Takes the executor — a knex instance or a
|
|
16
|
-
* transaction — so the same query runs standalone or inside a write's
|
|
17
|
-
* transaction; callers chain their own `select`/`orderBy`/`whereIn` onto it.
|
|
18
|
-
*/
|
|
6
|
+
// Archived fields must stay out of every read and write, and nothing in the database
|
|
7
|
+
// enforces that — no constraint stops a value row referencing an archived field. A query
|
|
8
|
+
// that forgets the filter is a silent bug, so the filter lives in one place.
|
|
9
|
+
/** Takes the executor so the same query runs standalone or inside a write's transaction. */
|
|
19
10
|
function activeFields(db) {
|
|
20
11
|
return db(FIELDS_TABLE).where('status', schema_1.FIELD_STATUS.active);
|
|
21
12
|
}
|
|
@@ -3,20 +3,11 @@ import {FIELD_STATUS} from './schema';
|
|
|
3
3
|
|
|
4
4
|
const FIELDS_TABLE = 'members_custom_fields';
|
|
5
5
|
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
// The `status = 'active'` filter is the one invariant worth centralising: archived
|
|
10
|
-
// fields must stay out of every read and every write, and that's enforced by a
|
|
11
|
-
// filter, not a database constraint — nothing stops a value row referencing an
|
|
12
|
-
// archived field, so a query that forgets the filter is a silent bug. Keeping the
|
|
13
|
-
// filter in one builder means there's one place to get it right.
|
|
6
|
+
// Archived fields must stay out of every read and write, and nothing in the database
|
|
7
|
+
// enforces that — no constraint stops a value row referencing an archived field. A query
|
|
8
|
+
// that forgets the filter is a silent bug, so the filter lives in one place.
|
|
14
9
|
|
|
15
|
-
/**
|
|
16
|
-
* The active field definitions. Takes the executor — a knex instance or a
|
|
17
|
-
* transaction — so the same query runs standalone or inside a write's
|
|
18
|
-
* transaction; callers chain their own `select`/`orderBy`/`whereIn` onto it.
|
|
19
|
-
*/
|
|
10
|
+
/** Takes the executor so the same query runs standalone or inside a write's transaction. */
|
|
20
11
|
export function activeFields(db: Knex) {
|
|
21
12
|
return db(FIELDS_TABLE).where('status', FIELD_STATUS.active);
|
|
22
13
|
}
|