ghost 6.62.0 → 6.63.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/components/tryghost-adapter-base-jobs-0.0.0.tgz +0 -0
- package/components/tryghost-adapter-base-scheduling-0.2.3.tgz +0 -0
- package/components/tryghost-adapter-base-sso-0.1.3.tgz +0 -0
- package/components/tryghost-admin-api-schema-0.0.0.tgz +0 -0
- package/components/tryghost-checkout-0.0.0.tgz +0 -0
- package/components/tryghost-i18n-0.0.0.tgz +0 -0
- package/components/tryghost-kg-card-factory-5.2.4.tgz +0 -0
- package/components/tryghost-kg-clean-basic-html-4.3.4.tgz +0 -0
- package/components/tryghost-kg-converters-1.2.5.tgz +0 -0
- package/components/tryghost-kg-default-cards-10.3.5.tgz +0 -0
- package/components/tryghost-kg-default-nodes-2.2.1.tgz +0 -0
- package/components/tryghost-kg-default-transforms-1.3.4.tgz +0 -0
- package/components/tryghost-kg-html-to-lexical-1.4.0.tgz +0 -0
- package/components/tryghost-kg-lexical-html-renderer-1.5.0.tgz +0 -0
- package/components/tryghost-kg-markdown-html-renderer-7.2.4.tgz +0 -0
- package/components/tryghost-kg-utils-1.1.4.tgz +0 -0
- package/components/tryghost-limit-service-0.0.0.tgz +0 -0
- package/components/tryghost-metafield-types-0.0.0.tgz +0 -0
- package/content/themes/source/package.json +2 -2
- package/content/themes/source/partials/post-card.hbs +1 -1
- package/core/boot.js +7 -5
- package/core/built/admin/assets/{about-Dyae_UT6.js → about-C1C3s5-g.js} +1 -1
- package/core/built/admin/assets/accordion-CxGsDKwa.js +1 -0
- package/core/built/admin/assets/{account-migration-CESa0mnX.js → account-migration-CbUhW6gk.js} +1 -1
- package/core/built/admin/assets/activitypub/{account-migration-By69CgCp.js → account-migration-KA6Jjf9L.js} +7 -7
- package/core/built/admin/assets/activitypub/activitypub.js +3 -3
- package/core/built/admin/assets/activitypub/{avatar-DLPL3Abs.js → avatar-DVJF5bxP.js} +2 -2
- package/core/built/admin/assets/activitypub/{avatar-flipboard-C9iDY-QV.js → avatar-flipboard-csQaNeYK.js} +2 -2
- package/core/built/admin/assets/activitypub/{bluesky-sharing-BJcPMrDd.js → bluesky-sharing-C7nTDMvw.js} +9 -9
- package/core/built/admin/assets/activitypub/{content-formatters-3rTHg3mp.js → content-formatters-CLcjaBwV.js} +4 -4
- package/core/built/admin/assets/activitypub/{copy-DIAOQoCZ.js → copy-DcOh8kXw.js} +2 -2
- package/core/built/admin/assets/activitypub/{domain-DUR4xSkV.js → domain-fZ-X8i4-.js} +9 -9
- package/core/built/admin/assets/activitypub/{edit-profile-BqtfzxCp.js → edit-profile-BqMLQV88.js} +6 -6
- package/core/built/admin/assets/activitypub/{explore-BxuJd-J4.js → explore-B4yPoP8E.js} +10 -10
- package/core/built/admin/assets/activitypub/{feed-BM1TcksA.js → feed-BRC_mvAe.js} +9 -9
- package/core/built/admin/assets/activitypub/{field-Dn7HHx2-.js → field-COacNgOt.js} +3 -3
- package/core/built/admin/assets/activitypub/{hash-Bm3WxYN4.js → hash-C7u-irQQ.js} +2 -2
- package/core/built/admin/assets/activitypub/{inbox-CCjkuow2.js → inbox-BW-yvUoN.js} +10 -10
- package/core/built/admin/assets/activitypub/{inbox-d8oJRTf4.js → inbox-CbTTdDQ3.js} +2 -2
- package/core/built/admin/assets/activitypub/{label-1AA_s9Fa.js → label-kPMmYI7l.js} +3 -3
- package/core/built/admin/assets/activitypub/layout-BL4_jtuV.js +1 -0
- package/core/built/admin/assets/activitypub/{moderation-CnmxEB8w.js → moderation-CuidJzc0.js} +10 -10
- package/core/built/admin/assets/activitypub/{note-ZKc_Bnba.js → note-CAMRRSqD.js} +7 -7
- package/core/built/admin/assets/activitypub/{notifications-CB2tJZau.js → notifications-BmNlXGgp.js} +9 -9
- package/core/built/admin/assets/activitypub/{onboarding-BsJ9E5qf.js → onboarding-Bqg7fh_L.js} +2 -2
- package/core/built/admin/assets/activitypub/{onboarding-CSUJJIlh.js → onboarding-Dmun9jr_.js} +2 -2
- package/core/built/admin/assets/activitypub/{preferences-0-JZnUkI.js → preferences--oH19wf9.js} +11 -11
- package/core/built/admin/assets/activitypub/{profile-C35cFIhM.js → profile-DH_tQx2D.js} +14 -14
- package/core/built/admin/assets/activitypub/{reply-DYK5vVqb.js → reply-Cap9PxSH.js} +2 -2
- package/core/built/admin/assets/activitypub/{routes-BD4vscyc.js → routes-DdyY9uFF.js} +30 -30
- package/core/built/admin/assets/activitypub/{separator-BbQqTm-p.js → separator-CAxxu8VV.js} +3 -3
- package/core/built/admin/assets/activitypub/{settings-BsMROdqh.js → settings-B6EEcVkW.js} +6 -6
- package/core/built/admin/assets/activitypub/{site-O0RL9YCN.js → site-BYps63oh.js} +2 -2
- package/core/built/admin/assets/activitypub/{step-1-BMSx7c_X.js → step-1-CKjR2KAm.js} +6 -6
- package/core/built/admin/assets/activitypub/{step-2-DtPQzlTH.js → step-2-B6PKfOUQ.js} +6 -6
- package/core/built/admin/assets/activitypub/{step-3-CLlOZTyt.js → step-3-C-qBbcUo.js} +11 -11
- package/core/built/admin/assets/activitypub/{tabs-Dxk-b9M-.js → tabs-DLhZtVde.js} +6 -6
- package/core/built/admin/assets/activitypub/{topic-filter-5yZH6tId.js → topic-filter-DsUOuu0k.js} +3 -3
- package/core/built/admin/assets/activitypub/{use-activity-pub-queries-CV50qe03.js → use-activity-pub-queries-CX9snsLs.js} +3 -3
- package/core/built/admin/assets/activitypub/{use-navigate-with-base-path-Bmk5h4lW.js → use-navigate-with-base-path-DsJTGDSS.js} +988 -959
- package/core/built/admin/assets/activitypub/{use-reply-chain-data-Cbvzgjzd.js → use-reply-chain-data-AJi9zkzm.js} +5 -5
- package/core/built/admin/assets/activitypub/{users-BjcoP_HC.js → users-inweyKL5.js} +186 -160
- package/core/built/admin/assets/activitypub/{x-DbQZOLiI.js → x-DR8AT3-4.js} +2 -2
- package/core/built/admin/assets/{add-integration-modal-BlF6rs_f.js → add-integration-modal-BT_onDJy.js} +1 -1
- package/core/built/admin/assets/{add-newsletter-modal-CglVQqah.js → add-newsletter-modal-Cx1kQpiY.js} +1 -1
- package/core/built/admin/assets/{add-recommendation-modal-wz7BsuaG.js → add-recommendation-modal-B5nvAhvr.js} +1 -1
- package/core/built/admin/assets/{analytics-C4HE1gBg.js → analytics-DjoJWPI7.js} +1 -1
- package/core/built/admin/assets/{announcement-bar-modal-Ci4zz8jO.js → announcement-bar-modal-Dwd0EGFP.js} +1 -1
- package/core/built/admin/assets/{api-keys-3-0vJC3Y.js → api-keys-BGPzLHzA.js} +1 -1
- package/core/built/admin/assets/{api-keys-Ck-Yteiv.js → api-keys-BoeacM-s.js} +1 -1
- package/core/built/admin/assets/{audience-CtbA54Sn.js → audience-ceV3XVHq.js} +1 -1
- package/core/built/admin/assets/automated-emails-BLesE41L.js +1 -0
- package/core/built/admin/assets/{automations-sAcJ1334.js → automations-BN4u3GR8.js} +1 -1
- package/core/built/admin/assets/automations-C-ZTUwW3.js +1 -0
- package/core/built/admin/assets/{bluesky-sharing-BEtJ_gL_.js → bluesky-sharing-vzh-oPXL.js} +1 -1
- package/core/built/admin/assets/{breadcrumb-zUrZrBtW.js → breadcrumb-CaLk2b7D.js} +1 -1
- package/core/built/admin/assets/{button-eNMKQWXr.js → button-Dvcv1QSR.js} +1 -1
- package/core/built/admin/assets/calendar-Bl9RLcZX.js +1 -0
- package/core/built/admin/assets/{chart-helpers-CfBKt0vT.js → chart-helpers-FHywU0pj.js} +1 -1
- package/core/built/admin/assets/{checkbox-CgOn_tKW.js → checkbox-BtayFtjg.js} +1 -1
- package/core/built/admin/assets/chunk.254.035b85ec456ebbd7336b.js +440 -0
- package/core/built/admin/assets/{chunk.524.a697dee88db67fdf6021.js → chunk.524.e6975095fccdf22d90f8.js} +5 -5
- package/core/built/admin/assets/{chunk.582.5ed5d124cfca9c259b9c.js → chunk.582.98b485f9b2802f540897.js} +6 -6
- package/core/built/admin/assets/{chunk.492.f24d855d7e3f3aad261c.js → chunk.901.4ccc639821020230bcca.js} +9949 -7921
- package/core/built/admin/assets/{code-editor-view-K2wI-I5f.js → code-editor-view-C3ZfoF1X.js} +1 -1
- package/core/built/admin/assets/{code-editor-view-BYNoAoNV.js → code-editor-view-CAyRWy1s.js} +1 -1
- package/core/built/admin/assets/{color-picker-Ddw80xX6.js → color-picker-G4kGR7rp.js} +1 -1
- package/core/built/admin/assets/{color-picker-field-D9nUhvA7.js → color-picker-field-DQFVTNnT.js} +1 -1
- package/core/built/admin/assets/{combobox-w9j8PPQT.js → combobox-BnYzgEB4.js} +1 -1
- package/core/built/admin/assets/{command-BfpHORBv.js → command-C_vyTikI.js} +1 -1
- package/core/built/admin/assets/comments-aBrxfnZf.js +1 -0
- package/core/built/admin/assets/{config-DOMQDZGZ.js → config-kSHvwdTG.js} +1 -1
- package/core/built/admin/assets/{confirmation-context-CBM8G0Vj.js → confirmation-context-DwXX_Y5h.js} +1 -1
- package/core/built/admin/assets/{content-api-modal-TXRz3U7S.js → content-api-modal-D2G0nJP6.js} +1 -1
- package/core/built/admin/assets/{context-menu-_QMdd3kp.js → context-menu-DOVB6yaz.js} +1 -1
- package/core/built/admin/assets/{copy-field-6N01S07E.js → copy-field-DCJwh9qf.js} +1 -1
- package/core/built/admin/assets/{create-ghost-browse-value-source-qIBymvvf.js → create-ghost-browse-value-source-5C53jJaX.js} +1 -1
- package/core/built/admin/assets/custom-field-type-option-BAuW0F-E.js +1 -0
- package/core/built/admin/assets/{custom-integration-modal-DmNquxUV.js → custom-integration-modal-AbJGVyKc.js} +1 -1
- package/core/built/admin/assets/{date-range-select-uvz_DtPh.js → date-range-select-BY3K-ukj.js} +1 -1
- package/core/built/admin/assets/design-and-theme-modal-BvEy4_pC.js +2 -0
- package/core/built/admin/assets/{dirty-confirm-dialog-BZ1iytEd.js → dirty-confirm-dialog-DVPuGz3U.js} +1 -1
- package/core/built/admin/assets/{disabled-sources-indicator-DMRrxsiJ.js → disabled-sources-indicator-Cy7Zp4c8.js} +1 -1
- package/core/built/admin/assets/{domain-BNYrt0aD.js → domain-Dl61QGuk.js} +1 -1
- package/core/built/admin/assets/{dropzone-D7nFdAe5.js → dropzone-Dtz5Rmjt.js} +4 -4
- package/core/built/admin/assets/edit-profile-DNJSMDwm.js +1 -0
- package/core/built/admin/assets/editor-DbAen9zf.js +8 -0
- package/core/built/admin/assets/editor-screen-BFWThIai.js +26 -0
- package/core/built/admin/assets/email-sending-status-context-CWDOD1FN.js +1 -0
- package/core/built/admin/assets/email-sending-status-provider-DCPkDICt.js +1 -0
- package/core/built/admin/assets/emails-vFMk4yYl.js +1 -0
- package/core/built/admin/assets/{embed-signup-form-modal-Ds6mPEi5.js → embed-signup-form-modal-DGqsORxS.js} +1 -1
- package/core/built/admin/assets/{explore-UY10Egsp.js → explore-nnRr1Fja.js} +1 -1
- package/core/built/admin/assets/feature-flag-overrides-context-DQjdJFAk.js +1 -0
- package/core/built/admin/assets/{feature-image-placeholder-D1iF_8bc.js → feature-image-placeholder-BrIHmPs8.js} +1 -1
- package/core/built/admin/assets/{feed-81C8mJWR.js → feed-BNUcNu-W.js} +1 -1
- package/core/built/admin/assets/feedback-DJ4Zb9rZ.js +1 -0
- package/core/built/admin/assets/{field-Dihp5p18.js → field-C93_Mg6j.js} +1 -1
- package/core/built/admin/assets/filter-sources-CGJb4C5r.js +1 -0
- package/core/built/admin/assets/{filters-DirqNXjH.js → filters--kKP-EC8.js} +1 -1
- package/core/built/admin/assets/filters-DxA_a4FP.js +1 -0
- package/core/built/admin/assets/{first-promoter-modal-CT6MxYZb.js → first-promoter-modal-BYDtrz2S.js} +1 -1
- package/core/built/admin/assets/focus-koenig-editor-on-bottom-click-BbSnGOtK.js +1 -0
- package/core/built/admin/assets/{ghost-8eabfc1ece81b03cf7b90780d31487e8.css → ghost-8fd5bb799356bbefb254210ba7e1236d.css} +1 -1
- package/core/built/admin/assets/{ghost-c2848508292937415f20f5a830eea59e.js → ghost-b4e8a403baba61905cd7560e30b9732d.js} +43 -27
- package/core/built/admin/assets/{ghost-dark-a7bebe2c561f55369dcf29f4c820f7ff.css → ghost-dark-cac0cb2d5bb78e9bd14d8d1c2768ed45.css} +1 -1
- package/core/built/admin/assets/{gift-link-modal-CQVAye17.js → gift-link-modal-B7u5bD4e.js} +1 -1
- package/core/built/admin/assets/{gift-links-DLDS7ljO.js → gift-links-CfLSnst2.js} +1 -1
- package/core/built/admin/assets/growth-Cd1uO9d2.js +1 -0
- package/core/built/admin/assets/growth-aG32xfdE.js +3 -0
- package/core/built/admin/assets/{history-modal-CFd1Hvx6.js → history-modal-Df8lW8h-.js} +1 -1
- package/core/built/admin/assets/hooks-Cy_-oZ4o.js +2 -0
- package/core/built/admin/assets/{html-field-CJBCLTvv.js → html-field-DA4eU7eq.js} +1 -1
- package/core/built/admin/assets/{images-scfkWZiK.js → images-KXmyO3Ss.js} +1 -1
- package/core/built/admin/assets/{inbox-Mcp4DXZN.js → inbox-gJHG7_xd.js} +6 -6
- package/core/built/admin/assets/index-BHHXtR5C.css +2 -0
- package/core/built/admin/assets/index-CgMCwsxN.js +4 -0
- package/core/built/admin/assets/index.es-CY6-yuw9.js +1 -0
- package/core/built/admin/assets/{input-group-CMhe2DvY.js → input-group-BE8rM2y1.js} +1 -1
- package/core/built/admin/assets/{integrations-Bjbu86Z0.js → integrations-B4kuRBFY.js} +1 -1
- package/core/built/admin/assets/{invite-user-modal-DfheMXs0.js → invite-user-modal-B4CuNcx4.js} +1 -1
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +2 -2
- package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +2 -2
- package/core/built/admin/assets/{koenig-lexical-DBSqAuiI.js → koenig-lexical-CGXb0F8o.js} +2 -2
- package/core/built/admin/assets/koenig-loader-BeM5rFPX.js +2 -0
- package/core/built/admin/assets/{kpi-card-DBRMfGOW.js → kpi-card-B21aToe8.js} +1 -1
- package/core/built/admin/assets/{kpi-card-DFafD1qq.js → kpi-card-pz6Wv4Ae.js} +1 -1
- package/core/built/admin/assets/{kpi-helpers-Cv8i8hns.js → kpi-helpers-Dq5jelmP.js} +1 -1
- package/core/built/admin/assets/{kpi-tabs-BJItvLYm.js → kpi-tabs-DEZHpKUt.js} +1 -1
- package/core/built/admin/assets/{label-BnSCvffu.js → label-OLCzze8N.js} +1 -1
- package/core/built/admin/assets/label-picker-BigOvMPV.js +1 -0
- package/core/built/admin/assets/{labels-CH3Kn8RV.js → labels-Dr0SgUQD.js} +1 -1
- package/core/built/admin/assets/layout-DUTL8SH5.js +1 -0
- package/core/built/admin/assets/lib-7QPTI0FS.js +1 -0
- package/core/built/admin/assets/link-helpers-BRAg9SCj.js +1 -0
- package/core/built/admin/assets/links-BDHPTlyj.js +1 -0
- package/core/built/admin/assets/{member-custom-fields-DDQV6QeG.js → member-custom-fields-TRTHCAz9.js} +1 -1
- package/core/built/admin/assets/member-detail-b6dRwc3C.js +1 -0
- package/core/built/admin/assets/members-Czt5lJSc.js +4 -0
- package/core/built/admin/assets/{moderation-AgCIEso4.js → moderation-ZWefD9uH.js} +1 -1
- package/core/built/admin/assets/{multi-select-combobox-BcITkUVr.js → multi-select-combobox-CT13MTo-.js} +1 -1
- package/core/built/admin/assets/navigation-modal-C8FEhBK5.js +1 -0
- package/core/built/admin/assets/newsletter-5VYW4RyJ.js +1 -0
- package/core/built/admin/assets/newsletter-detail-modal-ChjC0ZqH.js +1 -0
- package/core/built/admin/assets/{newsletter-emails-DKzwafuh.js → newsletter-emails-DZH6I-PY.js} +1 -1
- package/core/built/admin/assets/{newsletters-BRBb_uQC.js → newsletters-DOC9KBcX.js} +1 -1
- package/core/built/admin/assets/newsletters-Rq1M3GD-.js +1 -0
- package/core/built/admin/assets/{note-DyGHtS9a.js → note-DIV-Pojr.js} +1 -1
- package/core/built/admin/assets/{notifications-ZgWniKna.js → notifications-s20-H49V.js} +1 -1
- package/core/built/admin/assets/{offers-9J1CSiLy.js → offers--e2nGvkW.js} +1 -1
- package/core/built/admin/assets/{offers-container-modal-B-E8TIWr.js → offers-container-modal-BmG5M5Tv.js} +1 -1
- package/core/built/admin/assets/onboarding-CUuy9unR.js +1 -0
- package/core/built/admin/assets/{onboarding-CzIsre-d.js → onboarding-pXyct0Jm.js} +1 -1
- package/core/built/admin/assets/{onboarding-route-CaavZulg.js → onboarding-route-CK4pcXoR.js} +1 -1
- package/core/built/admin/assets/overview-CaPsciMs.js +1 -0
- package/core/built/admin/assets/overview-a8GfcsKX.js +1 -0
- package/core/built/admin/assets/{page-header-De0VzKBi.js → page-header-DM_KyoFI.js} +1 -1
- package/core/built/admin/assets/{pagemenu-B5KKCpbA.js → pagemenu-vgZVUVKR.js} +1 -1
- package/core/built/admin/assets/pages-CjDY2CBI.js +1 -0
- package/core/built/admin/assets/pages-route-BzKZYdV5.js +1 -0
- package/core/built/admin/assets/{pintura-modal-BZ2J9w3n.js → pintura-modal-DExCF1ii.js} +1 -1
- package/core/built/admin/assets/{portal-frame-B6Hr9wHc.js → portal-frame-Cqanidq4.js} +1 -1
- package/core/built/admin/assets/portal-modal-oinBgA27.js +1 -0
- package/core/built/admin/assets/post-analytics-C5oJ1dWV.js +1 -0
- package/core/built/admin/assets/post-analytics-header-OATo3X_r.js +1 -0
- package/core/built/admin/assets/post-analytics-provider-tOpIVGT5.js +1 -0
- package/core/built/admin/assets/post-helpers-C88JBa4D.js +1 -0
- package/core/built/admin/assets/post-share-modal-DvhC1XgV.js +1 -0
- package/core/built/admin/assets/post-utils-DKF4mfuo.js +1 -0
- package/core/built/admin/assets/posts-list-screen-o4ZjbgS3.js +2 -0
- package/core/built/admin/assets/posts-pCPrhQeR.js +1 -0
- package/core/built/admin/assets/posts-route-9F--xdIb.js +1 -0
- package/core/built/admin/assets/{preferences-C5YJLp74.js → preferences--vNubsqD.js} +2 -2
- package/core/built/admin/assets/{preview-modal-BfeFqi5y.js → preview-modal-YYbzlYdO.js} +1 -1
- package/core/built/admin/assets/profile-BllKV3dR.js +1 -0
- package/core/built/admin/assets/radio-group-DL8GI8rt.js +1 -0
- package/core/built/admin/assets/{referrers-CnhCMWCs.js → referrers-D8oHPmDB.js} +1 -1
- package/core/built/admin/assets/router-provider-BSvTXgZY.js +1 -0
- package/core/built/admin/assets/schemas-BoYdB6YU.js +64 -0
- package/core/built/admin/assets/{select-cb0t_TAJ.js → select-v5YbA3Mw.js} +1 -1
- package/core/built/admin/assets/settings-PEsZupw1.js +4 -0
- package/core/built/admin/assets/{settings-breadcrumbs-DLzbRRSt.js → settings-breadcrumbs-NwPnCTC7.js} +1 -1
- package/core/built/admin/assets/{settings-DZqxR0Da.js → settings-u_s1CRkr.js} +1 -1
- package/core/built/admin/assets/{share-modal-D2-Bz1_I.js → share-modal-SskCmVGL.js} +1 -1
- package/core/built/admin/assets/{slack-modal-DYDTUria.js → slack-modal-XxSJiYgo.js} +1 -1
- package/core/built/admin/assets/{sort-button-VVeQjjbu.js → sort-button-Cx1KtINE.js} +1 -1
- package/core/built/admin/assets/{source-icon-Ck5_5Kgq.js → source-icon-Bdp9Im_5.js} +1 -1
- package/core/built/admin/assets/stats-D9PDLS3x.js +1 -0
- package/core/built/admin/assets/stats-view-W2g6Jsd-.js +1 -0
- package/core/built/admin/assets/{step-1-CsaBjeN4.js → step-1-BQYzvBzr.js} +1 -1
- package/core/built/admin/assets/{step-2-D2vnxOOM.js → step-2-xES32xJV.js} +1 -1
- package/core/built/admin/assets/{step-3-wBoLdGEb.js → step-3-DA_XK5kW.js} +2 -2
- package/core/built/admin/assets/{stripe-button-CDgLz0S0.js → stripe-button-CVsLHelt.js} +1 -1
- package/core/built/admin/assets/{stripe-connect-modal-CSjMJetP.js → stripe-connect-modal-ClmLOMGS.js} +1 -1
- package/core/built/admin/assets/style-Wd9nQubI.css +1 -0
- package/core/built/admin/assets/{table-Do6iQ83Q.js → table-BenqVupI.js} +1 -1
- package/core/built/admin/assets/{tabs-D2yWLMp_.js → tabs-eBBlxPp8.js} +1 -1
- package/core/built/admin/assets/tag-detail-Ce8Se2qd.js +2 -0
- package/core/built/admin/assets/tag-picker-C3UR-uJ-.js +1 -0
- package/core/built/admin/assets/tags-B-kJxCs7.js +1 -0
- package/core/built/admin/assets/{tags-zTFiKRpb.js → tags-ChfdwJyS.js} +1 -1
- package/core/built/admin/assets/{testimonials-modal-CtnZBJKl.js → testimonials-modal-9Q6fT06V.js} +1 -1
- package/core/built/admin/assets/tier-detail-modal-CDyYdqK7.js +1 -0
- package/core/built/admin/assets/tiers-BCpIOGQr.js +1 -0
- package/core/built/admin/assets/{toggle-group-ByUJsxwD.js → toggle-group-CviIkyok.js} +1 -1
- package/core/built/admin/assets/{topic-filter-BgC3g5_v.js → topic-filter-I2jCBGxm.js} +1 -1
- package/core/built/admin/assets/{transistor-modal-Drr0SNfo.js → transistor-modal-p53u3W8y.js} +1 -1
- package/core/built/admin/assets/{trend-badge-6ye93YAW.js → trend-badge-CideVzQd.js} +1 -1
- package/core/built/admin/assets/{unsplash-modal-p6AoQoWp.js → unsplash-modal-DY8UcKcE.js} +1 -1
- package/core/built/admin/assets/{use-analytics-data-CWCMAESo.js → use-analytics-data-DAIGcr2f.js} +1 -1
- package/core/built/admin/assets/{use-check-theme-limit-error-Cw3WQHy8.js → use-check-theme-limit-error-DRUjK4YM.js} +1 -1
- package/core/built/admin/assets/use-filter-params-JkZhIS8L.js +1 -0
- package/core/built/admin/assets/{use-filterable-api-CzXcpUh8.js → use-filterable-api-BVEVMrhZ.js} +1 -1
- package/core/built/admin/assets/{use-growth-stats-DCVG3s9w.js → use-growth-stats-937CUj6j.js} +1 -1
- package/core/built/admin/assets/use-host-limits-D0Dv3tKA.js +1 -0
- package/core/built/admin/assets/{use-limiter-D2WRRx0H.js → use-limiter-CohWfzvK.js} +1 -1
- package/core/built/admin/assets/{use-navigate-with-base-path-BHPA228f.js → use-navigate-with-base-path-BkxcPj5l.js} +1 -1
- package/core/built/admin/assets/use-pintura-config-xgytjU35.js +1 -0
- package/core/built/admin/assets/{use-pintura-editor-BfN1UwzH.js → use-pintura-editor-CaV1mbfO.js} +1 -1
- package/core/built/admin/assets/{use-post-referrers-Czg47m8s.js → use-post-referrers-BCQI7fDg.js} +1 -1
- package/core/built/admin/assets/{use-reply-chain-data-ns0caK8k.js → use-reply-chain-data-CYRhoaxY.js} +1 -1
- package/core/built/admin/assets/{use-router-history-entry-uldn7zJO.js → use-router-history-entry-NOKcd--l.js} +1 -1
- package/core/built/admin/assets/{use-setting-group-DpcuCUDg.js → use-setting-group-bLKMwoBT.js} +1 -1
- package/core/built/admin/assets/{use-settings-navigation-CZjGrhsp.js → use-settings-navigation-B-qrriKD.js} +1 -1
- package/core/built/admin/assets/{use-simple-pagination-DzJWobPR.js → use-simple-pagination-CNPd6Rf6.js} +1 -1
- package/core/built/admin/assets/use-staff-users-pRIMIyiW.js +1 -0
- package/core/built/admin/assets/{use-tinybird-query-CSnGXzZh.js → use-tinybird-query-CmdbCS9X.js} +1 -1
- package/core/built/admin/assets/{use-tinybird-token-DTOKRR7e.js → use-tinybird-token-KLne235s.js} +1 -1
- package/core/built/admin/assets/{use-unsaved-changes-guard-CBzs-KPi.js → use-unsaved-changes-guard-7-ug0JdH.js} +1 -1
- package/core/built/admin/assets/use-upgrade-route-Dm_qqKr0.js +1 -0
- package/core/built/admin/assets/{use-url-input-DFr8lCbS.js → use-url-input-fvp-TpPx.js} +1 -1
- package/core/built/admin/assets/user-detail-modal-D3KlGYv-.js +1 -0
- package/core/built/admin/assets/{users-Cg-OeGzC.js → users-DVNWrqg9.js} +1 -1
- package/core/built/admin/assets/{vendor-5753232c7d6ffb3c44e1eb0a02133953.js → vendor-2dd263291938d407802568d3357ec69e.js} +19 -17
- package/core/built/admin/assets/{virtual-list-BW-padMe.js → virtual-list-CZ3RK2Yf.js} +1 -1
- package/core/built/admin/assets/{web-C1v33ehA.js → web-ClEJsCAj.js} +2 -2
- package/core/built/admin/assets/web-X9rdnrtq.js +1 -0
- package/core/built/admin/assets/{zapier-modal-BBFfI6Ml.js → zapier-modal-DfVhV17j.js} +1 -1
- package/core/built/admin/index.html +19 -18
- package/core/server/adapters/jobs/InMemoryJobsBackend.js +74 -29
- package/core/server/api/endpoints/authentication.js +1 -2
- package/core/server/api/endpoints/authors-public.js +15 -5
- package/core/server/api/endpoints/emails.js +13 -0
- package/core/server/api/endpoints/index.js +8 -0
- package/core/server/api/endpoints/member-metafields-members.js +23 -0
- package/core/server/api/endpoints/member-metafields.js +33 -20
- package/core/server/api/endpoints/members-account.js +42 -0
- package/core/server/api/endpoints/newsletters-public.js +10 -1
- package/core/server/api/endpoints/pages-public.js +15 -5
- package/core/server/api/endpoints/posts-public.js +15 -5
- package/core/server/api/endpoints/tags-public.js +22 -3
- package/core/server/api/endpoints/tiers-checkout-config.js +2 -2
- package/core/server/api/endpoints/tiers-public.js +38 -1
- package/core/server/api/endpoints/users.js +2 -2
- package/core/server/api/endpoints/utils/api-filter-utils.js +170 -3
- package/core/server/api/endpoints/utils/public-cache-keys.js +3 -0
- package/core/server/api/endpoints/utils/serializers/input/authors.js +2 -0
- package/core/server/api/endpoints/utils/serializers/input/members.js +16 -2
- package/core/server/api/endpoints/utils/serializers/input/pages.js +2 -0
- package/core/server/api/endpoints/utils/serializers/input/posts.js +2 -0
- package/core/server/api/endpoints/utils/serializers/input/tags.js +2 -0
- package/core/server/api/endpoints/utils/serializers/output/emails.js +7 -0
- package/core/server/api/endpoints/utils/serializers/output/index.js +4 -0
- package/core/server/api/endpoints/utils/serializers/output/member-metafields.js +3 -3
- package/core/server/api/endpoints/utils/serializers/output/members-account.js +19 -0
- package/core/server/api/endpoints/utils/serializers/output/members-csv-transform.js +1 -1
- package/core/server/api/endpoints/utils/serializers/output/tiers.js +10 -2
- package/core/server/api/endpoints/utils/serializers/output/users.js +0 -10
- package/core/server/data/exporter/table-lists.js +3 -3
- package/core/server/data/migrations/versions/6.53/2026-07-15-20-22-53-add-members-custom-field-values.js +1 -1
- package/core/server/data/migrations/versions/6.57/2026-08-04-18-00-00-store-custom-field-values-as-leaf-rows.js +10 -1
- package/core/server/data/migrations/versions/6.63/2026-09-03-10-07-03-rename-custom-field-tables-to-metafields.js +169 -0
- package/core/server/data/migrations/versions/6.63/2026-09-03-11-03-31-remove-member-custom-field-read-permissions.js +30 -0
- package/core/server/data/schema/fixtures/fixtures.json +0 -11
- package/core/server/data/schema/lib/default-index-name.js +8 -11
- package/core/server/data/schema/schema.js +18 -18
- package/core/server/data/seeders/README.md +48 -0
- package/core/server/data/tinybird/pipes/mv_hits.pipe +86 -50
- package/core/server/lib/db-types/count.js +16 -0
- package/core/server/lib/validate-password.js +81 -120
- package/core/server/models/action.js +4 -4
- package/core/server/models/base/plugins/filtered-collection.js +16 -0
- package/core/server/models/member.js +6 -6
- package/core/server/models/user.js +1 -1
- package/core/server/services/automations/automations-api.js +1 -1
- package/core/server/services/automations/database-automations-repository.js +11 -4
- package/core/server/services/email-service/CONTEXT.md +37 -0
- package/core/server/services/email-service/README.md +42 -0
- package/core/server/services/email-service/batch-sending-service.js +2 -0
- package/core/server/services/email-service/email-controller.js +18 -2
- package/core/server/services/email-service/email-service-wrapper.js +3 -0
- package/core/server/services/email-service/sending-status-schema.js +21 -0
- package/core/server/services/email-service/sending-status-serializers.js +33 -0
- package/core/server/services/email-service/sending-status-service.js +47 -0
- package/core/server/services/email-service/sending-status.js +111 -0
- package/core/server/services/email-suppression-list/email-suppression-list.js +0 -33
- package/core/server/services/email-suppression-list/mailgun-email-suppression-list.js +6 -7
- package/core/server/services/gifts/README.md +2 -2
- package/core/server/services/gifts/constants.js +1 -1
- package/core/server/services/gifts/gift-service.js +19 -57
- package/core/server/services/gifts/index.js +0 -2
- package/core/server/services/jobs-service/index.js +8 -0
- package/core/server/services/jobs-service/jobs-service.js +52 -3
- package/core/server/services/jobs-service/register-job-handlers.js +13 -2
- package/core/server/services/members/account-service.js +98 -0
- package/core/server/services/members/api.js +4 -4
- package/core/server/services/members/import-export/export/exporter.js +20 -20
- package/core/server/services/members/import-export/import/completion-email.js +6 -6
- package/core/server/services/members/import-export/import/importer.js +13 -13
- package/core/server/services/members/import-export/index.js +7 -7
- package/core/server/services/members/members-api/members-api.js +26 -6
- package/core/server/services/members/members-api/repositories/member-repository.js +4 -4
- package/core/server/services/members/members-api/services/member-bread-service.js +45 -39
- package/core/server/services/members/members-ssr.js +18 -0
- package/core/server/services/members/middleware.js +95 -81
- package/core/server/services/members/service.js +70 -42
- package/core/server/services/members/utils.js +9 -0
- package/core/server/services/members-metafields/access.js +28 -0
- package/core/server/services/{members-custom-fields → members-metafields}/actions.js +5 -5
- package/core/server/services/members-metafields/bindings-service.js +147 -0
- package/core/server/services/{members-custom-fields → members-metafields}/codec.js +4 -4
- package/core/server/services/{members-custom-fields → members-metafields}/config.js +1 -1
- package/core/server/services/{members-custom-fields → members-metafields}/definitions-service.js +17 -23
- package/core/server/services/{members-custom-fields → members-metafields}/filter.js +9 -9
- package/core/server/services/{members-custom-fields → members-metafields}/index.js +16 -7
- package/core/server/services/{members-custom-fields → members-metafields}/key.js +1 -1
- package/core/server/services/{members-custom-fields → members-metafields}/models.js +4 -4
- package/core/server/services/members-metafields/namespaces.js +34 -0
- package/core/server/services/{members-custom-fields → members-metafields}/queries.js +1 -1
- package/core/server/services/{members-custom-fields → members-metafields}/schema.js +16 -12
- package/core/server/services/{members-custom-fields → members-metafields}/serializers.js +6 -6
- package/core/server/services/{members-custom-fields → members-metafields}/values-service.js +32 -22
- package/core/server/services/mentions/mention-sending-service.js +26 -9
- package/core/server/services/mentions/send-webmentions-job.js +18 -0
- package/core/server/services/mentions/service.js +1 -31
- package/core/server/services/stripe/services/webhook/checkout-session-event-service.js +2 -2
- package/core/server/services/stripe/stripe-service.js +4 -4
- package/core/server/services/tier-checkout-config/codec.js +2 -2
- package/core/server/services/tier-checkout-config/index.js +2 -1
- package/core/server/services/tier-checkout-config/models.js +2 -2
- package/core/server/services/tier-checkout-config/queries.js +8 -8
- package/core/server/services/tier-checkout-config/serializers.js +57 -0
- package/core/server/services/tier-checkout-config/service.js +1 -1
- package/core/server/services/tiers/service.js +3 -3
- package/core/server/services/url/router-filter.js +8 -10
- package/core/server/services/users.js +1 -19
- package/core/server/web/api/endpoints/admin/routes.js +1 -0
- package/core/server/web/members/account/index.js +2 -0
- package/core/server/web/members/account/routes.js +46 -0
- package/core/server/web/members/app.js +4 -18
- package/core/shared/config/defaults.json +1 -1
- package/core/shared/labs.js +4 -2
- package/package.json +22 -22
- package/pnpm-lock.yaml +513 -571
- package/pnpm-workspace.yaml +12 -12
- package/components/tryghost-custom-field-types-0.0.0.tgz +0 -0
- package/core/built/admin/assets/activitypub/layout-2-0bw6HN.js +0 -1
- package/core/built/admin/assets/automated-emails-D5VVMND9.js +0 -1
- package/core/built/admin/assets/automations-CzKt5fb8.js +0 -1
- package/core/built/admin/assets/chunk.598.7e056fabb47ce7dbd73f.js +0 -366
- package/core/built/admin/assets/comments-BLmCmyCs.js +0 -1
- package/core/built/admin/assets/custom-field-type-option-BddFlJFa.js +0 -1
- package/core/built/admin/assets/design-and-theme-modal-BSmo12Op.js +0 -2
- package/core/built/admin/assets/edit-profile-C5Asm4LA.js +0 -1
- package/core/built/admin/assets/editor-REokrzci.js +0 -8
- package/core/built/admin/assets/filter-sources-BO9xUPj7.js +0 -1
- package/core/built/admin/assets/filters-CRUWecfY.js +0 -1
- package/core/built/admin/assets/growth-BWIu-6xj.js +0 -3
- package/core/built/admin/assets/growth-DU29oxeA.js +0 -1
- package/core/built/admin/assets/hooks-CuEZV2-q.js +0 -2
- package/core/built/admin/assets/index-6MkPdCtr.js +0 -4
- package/core/built/admin/assets/index-Bn7QhcZu.css +0 -2
- package/core/built/admin/assets/index.es-CNnuNH0d.js +0 -1
- package/core/built/admin/assets/koenig-loader-aFQNlJlD.js +0 -2
- package/core/built/admin/assets/label-picker-KVoo91sh.js +0 -1
- package/core/built/admin/assets/layout-Bjv2Ll-5.js +0 -1
- package/core/built/admin/assets/link-helpers-MVDdnFCY.js +0 -1
- package/core/built/admin/assets/member-detail-CdJF6Agw.js +0 -1
- package/core/built/admin/assets/members-DjQbq9Z2.js +0 -4
- package/core/built/admin/assets/navigation-modal-BkT7b1M2.js +0 -1
- package/core/built/admin/assets/newsletter-BMMAuvgq.js +0 -1
- package/core/built/admin/assets/newsletter-detail-modal-0SCJ7Zpm.js +0 -1
- package/core/built/admin/assets/newsletters-DhNigJUh.js +0 -1
- package/core/built/admin/assets/onboarding-qg8Akovm.js +0 -1
- package/core/built/admin/assets/overview-BW8GLeYi.js +0 -1
- package/core/built/admin/assets/overview-BkXZNzaZ.js +0 -1
- package/core/built/admin/assets/pages-jgaFm69d.js +0 -1
- package/core/built/admin/assets/pages-route-CIUAQxtY.js +0 -1
- package/core/built/admin/assets/portal-modal-D4ceei3t.js +0 -1
- package/core/built/admin/assets/post-analytics-header-BYCsT0GP.js +0 -1
- package/core/built/admin/assets/post-analytics-ot7f6pih.js +0 -1
- package/core/built/admin/assets/post-analytics-provider-Bo1gmYaP.js +0 -1
- package/core/built/admin/assets/post-helpers-C5OQMBoi.js +0 -1
- package/core/built/admin/assets/post-share-modal-C-PaYZ_e.js +0 -1
- package/core/built/admin/assets/posts-DuGazgTb.js +0 -1
- package/core/built/admin/assets/posts-list-screen-CBGGgjjj.js +0 -2
- package/core/built/admin/assets/posts-route-D6xmS7Vf.js +0 -1
- package/core/built/admin/assets/profile-B8mx2yAu.js +0 -1
- package/core/built/admin/assets/radio-group-DczlLKOn.js +0 -1
- package/core/built/admin/assets/router-provider-B0gZyiGJ.js +0 -1
- package/core/built/admin/assets/schemas-DppqmpeJ.js +0 -64
- package/core/built/admin/assets/settings-DvfTNdHQ.js +0 -4
- package/core/built/admin/assets/stats-Rjmk5owg.js +0 -1
- package/core/built/admin/assets/stats-view-BGGmkmgv.js +0 -1
- package/core/built/admin/assets/tag-detail-BhXlOsCa.js +0 -2
- package/core/built/admin/assets/tags-ldukRApe.js +0 -1
- package/core/built/admin/assets/tier-detail-modal-BOs8e_G8.js +0 -1
- package/core/built/admin/assets/tiers-Nd_z4BZY.js +0 -1
- package/core/built/admin/assets/use-filter-params-BIni9taJ.js +0 -1
- package/core/built/admin/assets/use-host-limits-DZtR08oa.js +0 -1
- package/core/built/admin/assets/use-pintura-config-h-J0Lvta.js +0 -1
- package/core/built/admin/assets/use-staff-users-Csipb-O0.js +0 -1
- package/core/built/admin/assets/use-upgrade-route-DhRSo7at.js +0 -1
- package/core/built/admin/assets/user-detail-modal-B_iUClI6.js +0 -1
- package/core/built/admin/assets/web-C4BKzn2T.js +0 -1
- package/core/server/services/email-suppression-list/in-memory-email-suppression-list.js +0 -39
- package/core/server/services/members-custom-fields/bindings-service.js +0 -120
- /package/core/built/admin/assets/{chunk.492.f24d855d7e3f3aad261c.js.LICENSE.txt → chunk.901.4ccc639821020230bcca.js.LICENSE.txt} +0 -0
- /package/core/server/services/{members-custom-fields → members-metafields}/storage.js +0 -0
|
@@ -4,12 +4,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.actingContext = actingContext;
|
|
7
|
-
exports.
|
|
7
|
+
exports.recordMetafieldAction = recordMetafieldAction;
|
|
8
8
|
const logging_1 = __importDefault(require("@tryghost/logging"));
|
|
9
9
|
/**
|
|
10
10
|
* Who is acting, read off an API frame's context.
|
|
11
11
|
*
|
|
12
|
-
* Here rather than in each endpoint, because two resources now record
|
|
12
|
+
* Here rather than in each endpoint, because two resources now record metafield history
|
|
13
13
|
* and a second reading of the same shape is a second chance to disagree about it. An
|
|
14
14
|
* integration and a user are both actors; a request that is neither — a webhook, a job —
|
|
15
15
|
* has none, and the history says so rather than guessing.
|
|
@@ -36,7 +36,7 @@ const COMMANDS = {
|
|
|
36
36
|
delete: 'deleted',
|
|
37
37
|
};
|
|
38
38
|
// Best-effort action-log write: a failed action must never fail the command that triggered it.
|
|
39
|
-
async function
|
|
39
|
+
async function recordMetafieldAction({ Action, context, verb, subject, details, }) {
|
|
40
40
|
if (!context.actor) {
|
|
41
41
|
return;
|
|
42
42
|
}
|
|
@@ -55,12 +55,12 @@ async function recordCustomFieldAction({ Action, context, verb, subject, details
|
|
|
55
55
|
}
|
|
56
56
|
catch (err) {
|
|
57
57
|
logging_1.default.error({
|
|
58
|
-
event: { name: 'members.
|
|
58
|
+
event: { name: 'members.metafields.action_log_failed' },
|
|
59
59
|
err,
|
|
60
60
|
verb,
|
|
61
61
|
subject,
|
|
62
62
|
actorType: context.actor.type,
|
|
63
63
|
actorId: context.actor.id,
|
|
64
|
-
}, 'Failed to record a member
|
|
64
|
+
}, 'Failed to record a member metafield action');
|
|
65
65
|
}
|
|
66
66
|
}
|
|
@@ -0,0 +1,147 @@
|
|
|
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.MetafieldBindingsService = void 0;
|
|
7
|
+
const bson_objectid_1 = __importDefault(require("bson-objectid"));
|
|
8
|
+
const logging_1 = __importDefault(require("@tryghost/logging"));
|
|
9
|
+
const access_1 = require("./access");
|
|
10
|
+
const schema_1 = require("./schema");
|
|
11
|
+
const FIELDS_TABLE = 'members_metafields';
|
|
12
|
+
const { CUSTOM_NAMESPACE } = require('@tryghost/metafield-types/identity');
|
|
13
|
+
const BINDINGS_TABLE = 'members_metafield_bindings';
|
|
14
|
+
/**
|
|
15
|
+
* Where a source sends what it collected: a `port` is the name that source uses for a
|
|
16
|
+
* thing, and the binding resolves it to one of the publisher's fields.
|
|
17
|
+
*/
|
|
18
|
+
class MetafieldBindingsService {
|
|
19
|
+
knex;
|
|
20
|
+
values;
|
|
21
|
+
constructor({ knex, values }) {
|
|
22
|
+
this.knex = knex;
|
|
23
|
+
this.values = values;
|
|
24
|
+
}
|
|
25
|
+
async bind(db, productId, port, metafieldKey, now) {
|
|
26
|
+
const existing = await db(BINDINGS_TABLE).where({ product_id: productId, port }).first();
|
|
27
|
+
if (existing?.metafield_key === metafieldKey) {
|
|
28
|
+
await db(BINDINGS_TABLE).where('id', existing.id).update({ updated_at: now });
|
|
29
|
+
return existing.id;
|
|
30
|
+
}
|
|
31
|
+
if (existing) {
|
|
32
|
+
await db(BINDINGS_TABLE).where('id', existing.id).del();
|
|
33
|
+
}
|
|
34
|
+
const bindingId = new bson_objectid_1.default().toHexString();
|
|
35
|
+
await db(BINDINGS_TABLE).insert({
|
|
36
|
+
id: bindingId,
|
|
37
|
+
product_id: productId,
|
|
38
|
+
port,
|
|
39
|
+
metafield_key: metafieldKey,
|
|
40
|
+
created_at: now,
|
|
41
|
+
updated_at: now,
|
|
42
|
+
});
|
|
43
|
+
return bindingId;
|
|
44
|
+
}
|
|
45
|
+
/** Stops the writing. Whatever hangs off the binding cascades with it. */
|
|
46
|
+
async remove(db, productId, port) {
|
|
47
|
+
await db(BINDINGS_TABLE).where({ product_id: productId, port }).del();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Values a processor collected on Ghost's behalf and sent back.
|
|
51
|
+
*
|
|
52
|
+
* Nobody supplied these in a sense the site can name — a payment page asked, and a
|
|
53
|
+
* machine reported the answers — so what is recorded against them is the binding that
|
|
54
|
+
* routed each one. That resolves back to the tier that asked, what it was collected
|
|
55
|
+
* as, and the field it landed in, which is everything worth knowing about how the
|
|
56
|
+
* value arrived.
|
|
57
|
+
*/
|
|
58
|
+
async writeCollected(memberId, productId, collected) {
|
|
59
|
+
return this.writeThrough(memberId, productId, collected, (binding) => ({
|
|
60
|
+
type: 'binding',
|
|
61
|
+
id: binding.bindingId,
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Values a member supplied about themselves, through the same ports a checkout uses.
|
|
66
|
+
*
|
|
67
|
+
* A member typing their own address into a form is answerable for it in a way no
|
|
68
|
+
* routing is, and a record saying a binding wrote it would be wrong. The member is the
|
|
69
|
+
* one whose record this is, so there is nobody else it could be.
|
|
70
|
+
*/
|
|
71
|
+
async writeSuppliedByMember(memberId, productId, supplied) {
|
|
72
|
+
return this.writeThrough(memberId, productId, supplied, () => ({
|
|
73
|
+
type: 'member',
|
|
74
|
+
id: memberId,
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Values arrive in the order they are to be applied: where two land in one field, the
|
|
79
|
+
* last of them is what the field holds.
|
|
80
|
+
*
|
|
81
|
+
* Every value is attempted, and then the first failure is raised. Attempting them all
|
|
82
|
+
* is this method's business: one refused answer must not cost a publisher the address
|
|
83
|
+
* a courier needs, and the values have nothing to do with each other beyond arriving
|
|
84
|
+
* together. Whether the failure is worth acting on is the caller's, which is why it
|
|
85
|
+
* leaves here rather than being logged and forgotten — a checkout webhook has already
|
|
86
|
+
* taken the money and must never fail, while a member filling in a form is owed the
|
|
87
|
+
* news.
|
|
88
|
+
*/
|
|
89
|
+
async writeThrough(memberId, productId, values, attribute) {
|
|
90
|
+
let failure;
|
|
91
|
+
for (const { port, value } of values) {
|
|
92
|
+
try {
|
|
93
|
+
// Inside, because working out where a value goes can fail the same way storing
|
|
94
|
+
// it can, and a value nobody could place is no more reason to abandon the rest
|
|
95
|
+
// than one nobody could store.
|
|
96
|
+
const destination = await this.resolve(productId, port);
|
|
97
|
+
if (!destination) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
await this.writeOne(memberId, destination, value, attribute);
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
failure = failure ?? err;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (failure) {
|
|
107
|
+
throw failure;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async writeOne(memberId, into, value, attribute) {
|
|
111
|
+
// Internal: what may be set is bounded by the binding rather than by who is
|
|
112
|
+
// looking. A port exists because a publisher pointed it at a field, and that
|
|
113
|
+
// decision is what admits the value, whoever supplied it.
|
|
114
|
+
const planned = await this.values.planWrite({ [`${CUSTOM_NAMESPACE}.${into.key}`]: value }, access_1.INTERNAL);
|
|
115
|
+
await this.values.applyWrite(memberId, planned, { writtenBy: attribute(into) });
|
|
116
|
+
}
|
|
117
|
+
async resolve(productId, port) {
|
|
118
|
+
const row = await this.knex(BINDINGS_TABLE)
|
|
119
|
+
.join(FIELDS_TABLE, `${BINDINGS_TABLE}.metafield_key`, `${FIELDS_TABLE}.key`)
|
|
120
|
+
.where(`${BINDINGS_TABLE}.product_id`, productId)
|
|
121
|
+
.where(`${BINDINGS_TABLE}.port`, port)
|
|
122
|
+
// An archived destination is still where this goes, and still not somewhere a value
|
|
123
|
+
// can land, so the write drops rather than waiting.
|
|
124
|
+
.where(`${FIELDS_TABLE}.status`, schema_1.FIELD_STATUS.active)
|
|
125
|
+
.select(`${BINDINGS_TABLE}.id as binding_id`, `${FIELDS_TABLE}.key`, `${FIELDS_TABLE}.type`)
|
|
126
|
+
.first();
|
|
127
|
+
if (!row) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
// Decoded rather than trusted: a join is a read boundary, and `type` is what decides
|
|
131
|
+
// how the collected value is read. Unreadable counts as unresolved rather than
|
|
132
|
+
// throwing, so one bad row skips its value the way an unbound port does instead of
|
|
133
|
+
// failing everything else the same checkout collected.
|
|
134
|
+
const bound = schema_1.DbBoundField.safeParse(row);
|
|
135
|
+
if (!bound.success) {
|
|
136
|
+
logging_1.default.warn({
|
|
137
|
+
event: { name: 'members.metafields.binding_unreadable' },
|
|
138
|
+
err: bound.error,
|
|
139
|
+
productId,
|
|
140
|
+
port,
|
|
141
|
+
}, 'A binding could not be read');
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
return { bindingId: bound.data.binding_id, key: bound.data.key, type: bound.data.type };
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
exports.MetafieldBindingsService = MetafieldBindingsService;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.metafieldCodec = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
-
const identity_1 = require("@tryghost/
|
|
5
|
+
const identity_1 = require("@tryghost/metafield-types/identity");
|
|
6
6
|
const case_keys_1 = require("../../lib/case-keys");
|
|
7
7
|
const schema_1 = require("./schema");
|
|
8
8
|
const models_1 = require("./models");
|
|
9
|
-
exports.
|
|
10
|
-
//
|
|
9
|
+
exports.metafieldCodec = zod_1.z.codec(schema_1.DbMetafield, models_1.Metafield, {
|
|
10
|
+
// DbMetafield validates `type` as the field-type enum, so the decoded row
|
|
11
11
|
// already carries a FieldType and camelKeys preserves it — no cast needed.
|
|
12
12
|
decode: (row) => ({ ...(0, case_keys_1.camelKeys)(row), namespace: identity_1.CUSTOM_NAMESPACE }),
|
|
13
13
|
encode: ({ namespace: _namespace, ...field }) => (0, case_keys_1.snakeKeys)(field),
|
|
@@ -22,7 +22,7 @@ const Ceiling = zod_1.z
|
|
|
22
22
|
// rather than restated. Parsed eagerly because a missing or malformed value
|
|
23
23
|
// there is our bug rather than an operator's, and should fail loudly at boot
|
|
24
24
|
// instead of quietly becoming the fallback for everything below.
|
|
25
|
-
const shippedCeiling = Ceiling.parse(require('../../../shared/config/defaults.json').members.
|
|
25
|
+
const shippedCeiling = Ceiling.parse(require('../../../shared/config/defaults.json').members.metafields.maxDefinitions);
|
|
26
26
|
// A higher layer can override the shipped value with anything. Something
|
|
27
27
|
// unreadable falls back to the shipped ceiling rather than throwing, because an
|
|
28
28
|
// operator can correct this live and a bad value must not take the feature down
|
package/core/server/services/{members-custom-fields → members-metafields}/definitions-service.js
RENAMED
|
@@ -3,14 +3,16 @@ 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
|
-
exports.
|
|
6
|
+
exports.MetafieldDefinitionsService = void 0;
|
|
7
7
|
const bson_objectid_1 = __importDefault(require("bson-objectid"));
|
|
8
8
|
const errors_1 = __importDefault(require("@tryghost/errors"));
|
|
9
9
|
const zod_1 = require("zod");
|
|
10
|
-
const
|
|
11
|
-
const identity_1 = require("@tryghost/
|
|
10
|
+
const metafield_types_1 = require("@tryghost/metafield-types");
|
|
11
|
+
const identity_1 = require("@tryghost/metafield-types/identity");
|
|
12
12
|
const codec_1 = require("./codec");
|
|
13
|
+
const namespaces_1 = require("./namespaces");
|
|
13
14
|
const schema_1 = require("./schema");
|
|
15
|
+
const access_1 = require("./access");
|
|
14
16
|
const queries_1 = require("./queries");
|
|
15
17
|
const key_1 = require("./key");
|
|
16
18
|
// The same NQL -> knex bridge Bookshelf's filter plugin uses, applied directly to
|
|
@@ -18,7 +20,7 @@ const key_1 = require("./key");
|
|
|
18
20
|
// turns that into parametrised WHERE clauses. Neither needs a Bookshelf model.
|
|
19
21
|
const nql = require('@tryghost/nql');
|
|
20
22
|
const knexify = require('@tryghost/mongo-knex');
|
|
21
|
-
const TABLE = '
|
|
23
|
+
const TABLE = 'members_metafields';
|
|
22
24
|
// Column limits come from the canonical schema — the same source the migration and
|
|
23
25
|
// Bookshelf models read — so the service can never drift from the database. The
|
|
24
26
|
// name cap turns an over-long input into a clean 422 (not a DB error), and the key
|
|
@@ -48,7 +50,7 @@ const FieldName = zod_1.z
|
|
|
48
50
|
// The backend mints the key from the name, so create takes just a name and type.
|
|
49
51
|
const AddFieldInput = zod_1.z.object({
|
|
50
52
|
name: FieldName,
|
|
51
|
-
type:
|
|
53
|
+
type: metafield_types_1.FieldTypeSchema,
|
|
52
54
|
});
|
|
53
55
|
// A bound on the work one request can ask for, separate from how many definitions
|
|
54
56
|
// a site may hold in total. Every definition in a batch costs several queries
|
|
@@ -77,9 +79,9 @@ const EditFieldInput = zod_1.z.object({
|
|
|
77
79
|
name: FieldName.optional(),
|
|
78
80
|
status: schema_1.FieldStatusSchema.optional(),
|
|
79
81
|
key: zod_1.z.string().optional(),
|
|
80
|
-
type:
|
|
82
|
+
type: metafield_types_1.FieldTypeSchema.optional(),
|
|
81
83
|
});
|
|
82
|
-
class
|
|
84
|
+
class MetafieldDefinitionsService {
|
|
83
85
|
knex;
|
|
84
86
|
recordAction;
|
|
85
87
|
getMaxDefinitions;
|
|
@@ -104,15 +106,7 @@ class CustomFieldDefinitionsService {
|
|
|
104
106
|
isStored(namespace) {
|
|
105
107
|
return namespace === identity_1.CUSTOM_NAMESPACE;
|
|
106
108
|
}
|
|
107
|
-
|
|
108
|
-
if (!this.isStored(namespace)) {
|
|
109
|
-
throw new errors_1.default.ValidationError({
|
|
110
|
-
message: `Fields cannot be defined in the "${namespace}" namespace.`,
|
|
111
|
-
property: 'namespace',
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
async browse(options = {}) {
|
|
109
|
+
async browse(options = {}, audience = access_1.ADMIN) {
|
|
116
110
|
if (options.namespace !== undefined && !this.isStored(options.namespace)) {
|
|
117
111
|
return [];
|
|
118
112
|
}
|
|
@@ -126,7 +120,7 @@ class CustomFieldDefinitionsService {
|
|
|
126
120
|
const query = options.filter
|
|
127
121
|
? applyFilter(this.knex(TABLE), options.filter)
|
|
128
122
|
: (0, queries_1.activeFields)(this.knex);
|
|
129
|
-
return this.list(query);
|
|
123
|
+
return (0, access_1.readableFields)(audience, await this.list(query));
|
|
130
124
|
}
|
|
131
125
|
/**
|
|
132
126
|
* Decode a definition query into the domain, in the publisher's order.
|
|
@@ -136,7 +130,7 @@ class CustomFieldDefinitionsService {
|
|
|
136
130
|
*/
|
|
137
131
|
async list(query) {
|
|
138
132
|
const rows = await (0, queries_1.inFieldOrder)(query).select('*');
|
|
139
|
-
return rows.map((row) => zod_1.z.decode(codec_1.
|
|
133
|
+
return rows.map((row) => zod_1.z.decode(codec_1.metafieldCodec, row));
|
|
140
134
|
}
|
|
141
135
|
async read(namespace, key) {
|
|
142
136
|
const [field] = this.isStored(namespace) ? await this.list((0, queries_1.fieldByKey)(this.knex, key)) : [];
|
|
@@ -156,7 +150,7 @@ class CustomFieldDefinitionsService {
|
|
|
156
150
|
* key get distinct ones, exactly as if they had arrived as separate requests.
|
|
157
151
|
*/
|
|
158
152
|
async add(context, namespace, input) {
|
|
159
|
-
|
|
153
|
+
(0, namespaces_1.assertDefinable)(namespace);
|
|
160
154
|
const requestedCount = Array.isArray(input) ? input.length : 0;
|
|
161
155
|
const parsed = AddFieldsInput.safeParse(input);
|
|
162
156
|
if (!parsed.success) {
|
|
@@ -276,7 +270,7 @@ class CustomFieldDefinitionsService {
|
|
|
276
270
|
/** `read` for a caller that is deciding rather than serving: absent is an answer. */
|
|
277
271
|
async findByKey(key, { executor = this.knex } = {}) {
|
|
278
272
|
const row = await executor(TABLE).where('key', key).first();
|
|
279
|
-
return row ? zod_1.z.decode(codec_1.
|
|
273
|
+
return row ? zod_1.z.decode(codec_1.metafieldCodec, row) : null;
|
|
280
274
|
}
|
|
281
275
|
/** The same entry `add` writes. Only the caller knows its transaction committed. */
|
|
282
276
|
async recordCreated(context, fields) {
|
|
@@ -335,7 +329,7 @@ class CustomFieldDefinitionsService {
|
|
|
335
329
|
* Returns every definition, archived included, matching what the request named.
|
|
336
330
|
*/
|
|
337
331
|
async reorder(context, namespace, input) {
|
|
338
|
-
|
|
332
|
+
(0, namespaces_1.assertDefinable)(namespace);
|
|
339
333
|
const parsed = ReorderInput.safeParse(input);
|
|
340
334
|
if (!parsed.success) {
|
|
341
335
|
const issue = parsed.error.issues[0];
|
|
@@ -399,7 +393,7 @@ class CustomFieldDefinitionsService {
|
|
|
399
393
|
async readMany(db, keys) {
|
|
400
394
|
const rows = await db(TABLE).whereIn('key', keys).select('*');
|
|
401
395
|
const byKey = new Map(rows.map((row) => [row.key, row]));
|
|
402
|
-
return keys.map((key) => zod_1.z.decode(codec_1.
|
|
396
|
+
return keys.map((key) => zod_1.z.decode(codec_1.metafieldCodec, byKey.get(key)));
|
|
403
397
|
}
|
|
404
398
|
/**
|
|
405
399
|
* Pick a free key from the name's base: `base`, then `base_2`, `base_3`, ...
|
|
@@ -551,7 +545,7 @@ class CustomFieldDefinitionsService {
|
|
|
551
545
|
});
|
|
552
546
|
}
|
|
553
547
|
}
|
|
554
|
-
exports.
|
|
548
|
+
exports.MetafieldDefinitionsService = MetafieldDefinitionsService;
|
|
555
549
|
/**
|
|
556
550
|
* The shape a stated key has to have. Minting derives one that is usable by
|
|
557
551
|
* construction, so this is the check that path never needed: a caller stating its own
|
|
@@ -3,8 +3,8 @@ 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
|
-
exports.
|
|
7
|
-
exports.
|
|
6
|
+
exports.METAFIELDS_RELATION = void 0;
|
|
7
|
+
exports.createMetafieldsFilterTransformer = createMetafieldsFilterTransformer;
|
|
8
8
|
// Translates the metafield clauses of a members filter into a query over the
|
|
9
9
|
// values table. A metafield is a publisher-defined field on a member; it is
|
|
10
10
|
// addressed as `namespace.key`, and a composite value such as an address names
|
|
@@ -15,13 +15,13 @@ exports.createCustomFieldsFilterTransformer = createCustomFieldsFilterTransforme
|
|
|
15
15
|
// metafields.key:'custom.company' // has a value
|
|
16
16
|
// metafields.key:-'custom.shipping_address.country' // that part is not set
|
|
17
17
|
//
|
|
18
|
-
// The values table holds one row per stored value: `
|
|
18
|
+
// The values table holds one row per stored value: `metafield_key`, `path`
|
|
19
19
|
// (empty for a plain field, the part's name for one part of a composite) and
|
|
20
20
|
// `value_text`. A filter addresses those columns directly, so each one becomes a
|
|
21
21
|
// single $elemMatch over them — positive asserts a matching row exists, $not
|
|
22
22
|
// asserts none does — with no lookup against the field definitions.
|
|
23
23
|
const errors_1 = __importDefault(require("@tryghost/errors"));
|
|
24
|
-
const identity_1 = require("@tryghost/
|
|
24
|
+
const identity_1 = require("@tryghost/metafield-types/identity");
|
|
25
25
|
const RELATION = 'metafields';
|
|
26
26
|
const PREFIX = `${RELATION}.`;
|
|
27
27
|
const KEY_ATTRIBUTE = `${PREFIX}key`;
|
|
@@ -78,11 +78,11 @@ function parseLeafAddress(raw) {
|
|
|
78
78
|
}
|
|
79
79
|
return { key: identity.key, path: identity.partPath };
|
|
80
80
|
}
|
|
81
|
-
function
|
|
81
|
+
function createMetafieldsFilterTransformer() {
|
|
82
82
|
// One (maybe-negated) $elemMatch over the leaf columns: positive is "a leaf pinned
|
|
83
83
|
// by these matches", `$not` is "no leaf does".
|
|
84
84
|
function buildElemMatch(target, value, negate) {
|
|
85
|
-
const match = {
|
|
85
|
+
const match = { metafield_key: target.key };
|
|
86
86
|
if (value !== undefined) {
|
|
87
87
|
match.path = target.path ?? ROOT_PATH;
|
|
88
88
|
match.value_text = value;
|
|
@@ -167,14 +167,14 @@ function createCustomFieldsFilterTransformer() {
|
|
|
167
167
|
return (query) => transform(query);
|
|
168
168
|
}
|
|
169
169
|
/**
|
|
170
|
-
* The Member filter relation that exposes
|
|
170
|
+
* The Member filter relation that exposes metafield values. A member has many leaf
|
|
171
171
|
* rows (one per field, or per part of a composite field), and a predicate asks whether
|
|
172
172
|
* one of them matches, so this joins the values table on member_id and mongo-knex emits
|
|
173
173
|
* it as a correlated `members.id IN (…)` subquery — composing with every other member
|
|
174
174
|
* filter.
|
|
175
175
|
*/
|
|
176
|
-
exports.
|
|
177
|
-
tableName: '
|
|
176
|
+
exports.METAFIELDS_RELATION = {
|
|
177
|
+
tableName: 'members_metafield_values',
|
|
178
178
|
tableNameAs: RELATION,
|
|
179
179
|
type: 'oneToOne',
|
|
180
180
|
joinFrom: 'member_id',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.bindings = exports.values = exports.definitions = exports.actingContext = void 0;
|
|
3
|
+
exports.bindings = exports.values = exports.definitions = exports.readableFields = exports.canWrite = exports.MEMBERS = exports.INTERNAL = exports.ADMIN = exports.actingContext = void 0;
|
|
4
4
|
exports.init = init;
|
|
5
5
|
const definitions_service_1 = require("./definitions-service");
|
|
6
6
|
const values_service_1 = require("./values-service");
|
|
@@ -9,6 +9,15 @@ const actions_1 = require("./actions");
|
|
|
9
9
|
const config_1 = require("./config");
|
|
10
10
|
var actions_2 = require("./actions");
|
|
11
11
|
Object.defineProperty(exports, "actingContext", { enumerable: true, get: function () { return actions_2.actingContext; } });
|
|
12
|
+
// Which door a request came through, which is what decides how much of a member's
|
|
13
|
+
// answers it may see or change. Required wherever that is asked, so a new caller
|
|
14
|
+
// has to name itself rather than inherit an answer by default.
|
|
15
|
+
var access_1 = require("./access");
|
|
16
|
+
Object.defineProperty(exports, "ADMIN", { enumerable: true, get: function () { return access_1.ADMIN; } });
|
|
17
|
+
Object.defineProperty(exports, "INTERNAL", { enumerable: true, get: function () { return access_1.INTERNAL; } });
|
|
18
|
+
Object.defineProperty(exports, "MEMBERS", { enumerable: true, get: function () { return access_1.MEMBERS; } });
|
|
19
|
+
Object.defineProperty(exports, "canWrite", { enumerable: true, get: function () { return access_1.canWrite; } });
|
|
20
|
+
Object.defineProperty(exports, "readableFields", { enumerable: true, get: function () { return access_1.readableFields; } });
|
|
12
21
|
function init() {
|
|
13
22
|
// The three are constructed together below, so checking all of them keeps the "all or
|
|
14
23
|
// none" invariant explicit rather than trusting one to stand in for the rest.
|
|
@@ -17,25 +26,25 @@ function init() {
|
|
|
17
26
|
}
|
|
18
27
|
const { knex } = require('../../data/db');
|
|
19
28
|
const models = require('../../models');
|
|
20
|
-
const recordAction = ({ context, verb, subject, details }) => (0, actions_1.
|
|
29
|
+
const recordAction = ({ context, verb, subject, details }) => (0, actions_1.recordMetafieldAction)({ Action: models.Action, context, verb, subject, details });
|
|
21
30
|
// Resolved here, not in the service: reading config is this module's job, and
|
|
22
31
|
// the service is handed a number. A getter rather than a value because the
|
|
23
32
|
// ceiling is an operator setting that can change between requests, and a Ghost
|
|
24
33
|
// container holds no state across them.
|
|
25
34
|
const config = require('../../../shared/config');
|
|
26
|
-
exports.definitions = new definitions_service_1.
|
|
35
|
+
exports.definitions = new definitions_service_1.MetafieldDefinitionsService({
|
|
27
36
|
knex,
|
|
28
37
|
recordAction,
|
|
29
|
-
getMaxDefinitions: () => (0, config_1.resolveMaxDefinitions)(config.get('members:
|
|
38
|
+
getMaxDefinitions: () => (0, config_1.resolveMaxDefinitions)(config.get('members:metafields:maxDefinitions')),
|
|
30
39
|
});
|
|
31
40
|
// The values service reads the field definitions straight from the table, so
|
|
32
41
|
// it needs knex and the same ceiling — no handle on the definitions service.
|
|
33
|
-
exports.values = new values_service_1.
|
|
42
|
+
exports.values = new values_service_1.MetafieldValuesService({
|
|
34
43
|
knex,
|
|
35
|
-
getMaxDefinitions: () => (0, config_1.resolveMaxDefinitions)(config.get('members:
|
|
44
|
+
getMaxDefinitions: () => (0, config_1.resolveMaxDefinitions)(config.get('members:metafields:maxDefinitions')),
|
|
36
45
|
});
|
|
37
46
|
// Built after the values, which is what a binding routes into. It has no handle on the
|
|
38
47
|
// definitions: making a field is not part of binding to one, so a caller that needs both
|
|
39
48
|
// asks for both.
|
|
40
|
-
exports.bindings = new bindings_service_1.
|
|
49
|
+
exports.bindings = new bindings_service_1.MetafieldBindingsService({ knex, values: exports.values });
|
|
41
50
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.KEY_CHARACTERS = void 0;
|
|
4
4
|
exports.mintableKey = mintableKey;
|
|
5
|
-
const identity_1 = require("@tryghost/
|
|
5
|
+
const identity_1 = require("@tryghost/metafield-types/identity");
|
|
6
6
|
// Neither package ships types.
|
|
7
7
|
const { stripInvisibleChars } = require('@tryghost/string');
|
|
8
8
|
const unidecode = require('unidecode');
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.Metafield = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
-
const
|
|
5
|
+
const metafield_types_1 = require("@tryghost/metafield-types");
|
|
6
6
|
const schema_1 = require("./schema");
|
|
7
|
-
exports.
|
|
7
|
+
exports.Metafield = zod_1.z.object({
|
|
8
8
|
id: zod_1.z.string(),
|
|
9
9
|
namespace: zod_1.z.string(),
|
|
10
10
|
key: zod_1.z.string(),
|
|
11
11
|
name: zod_1.z.string(),
|
|
12
|
-
type:
|
|
12
|
+
type: metafield_types_1.FieldTypeSchema,
|
|
13
13
|
status: schema_1.FieldStatusSchema,
|
|
14
14
|
createdAt: zod_1.z.date(),
|
|
15
15
|
updatedAt: zod_1.z.date().nullable(),
|
|
@@ -0,0 +1,34 @@
|
|
|
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.definableByPublisher = definableByPublisher;
|
|
7
|
+
exports.assertDefinable = assertDefinable;
|
|
8
|
+
const errors_1 = __importDefault(require("@tryghost/errors"));
|
|
9
|
+
const identity_1 = require("@tryghost/metafield-types/identity");
|
|
10
|
+
/**
|
|
11
|
+
* Who may define fields in a namespace.
|
|
12
|
+
*
|
|
13
|
+
* This is a property of the namespace, not of whoever is asking, so it is settled before
|
|
14
|
+
* any question about the caller. Asking the caller first gets the order wrong in a way
|
|
15
|
+
* that shows: a request to define a field in a namespace nobody owns would be refused for
|
|
16
|
+
* want of a permission, telling the caller to go and get one, when no permission would
|
|
17
|
+
* have helped.
|
|
18
|
+
*
|
|
19
|
+
* The publisher owns `custom` and nothing owns anything else yet. An app owning its own
|
|
20
|
+
* namespace resolves here too, and will not resolve to a permission at all: the caller
|
|
21
|
+
* has to *be* that app rather than hold a role, which is why the staff permission stays
|
|
22
|
+
* named after the publisher's fields rather than after metafields at large.
|
|
23
|
+
*/
|
|
24
|
+
function definableByPublisher(namespace) {
|
|
25
|
+
return namespace === identity_1.CUSTOM_NAMESPACE;
|
|
26
|
+
}
|
|
27
|
+
function assertDefinable(namespace) {
|
|
28
|
+
if (!definableByPublisher(namespace)) {
|
|
29
|
+
throw new errors_1.default.ValidationError({
|
|
30
|
+
message: `Fields cannot be defined in the "${namespace}" namespace.`,
|
|
31
|
+
property: 'namespace',
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -4,7 +4,7 @@ exports.activeFields = activeFields;
|
|
|
4
4
|
exports.fieldByKey = fieldByKey;
|
|
5
5
|
exports.inFieldOrder = inFieldOrder;
|
|
6
6
|
const schema_1 = require("./schema");
|
|
7
|
-
const FIELDS_TABLE = '
|
|
7
|
+
const FIELDS_TABLE = 'members_metafields';
|
|
8
8
|
// Archived fields must stay out of every read and write, and nothing in the database
|
|
9
9
|
// enforces that — no constraint stops a value row referencing an archived field. A query
|
|
10
10
|
// that forgets the filter is a silent bug, so the filter lives in one place.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DbBoundField = exports.
|
|
3
|
+
exports.DbBoundField = exports.DbMetafieldBinding = exports.DbMetafieldLeaf = exports.DbMetafieldValue = exports.WrittenBy = exports.DbMetafield = exports.FieldStatusSchema = exports.FIELD_STATUS = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
-
const
|
|
5
|
+
const metafield_types_1 = require("@tryghost/metafield-types");
|
|
6
6
|
const date_1 = require("../../lib/db-types/date");
|
|
7
7
|
// `archived` is soft: the field drops out of the values path but stays in the definition
|
|
8
8
|
// list so it can be renamed, restored or deleted. Mirrors schema.js's `isIn` on the
|
|
@@ -11,11 +11,11 @@ exports.FIELD_STATUS = { active: 'active', archived: 'archived' };
|
|
|
11
11
|
exports.FieldStatusSchema = zod_1.z.enum([exports.FIELD_STATUS.active, exports.FIELD_STATUS.archived]);
|
|
12
12
|
// The single source for the read projection and the knex table type below. `type` parses
|
|
13
13
|
// as the field-type enum, so the row carries the narrow type and no codec needs a cast.
|
|
14
|
-
exports.
|
|
14
|
+
exports.DbMetafield = zod_1.z.object({
|
|
15
15
|
id: zod_1.z.string(),
|
|
16
16
|
key: zod_1.z.string(),
|
|
17
17
|
name: zod_1.z.string(),
|
|
18
|
-
type:
|
|
18
|
+
type: metafield_types_1.FieldTypeSchema,
|
|
19
19
|
status: exports.FieldStatusSchema,
|
|
20
20
|
created_at: date_1.DbDate,
|
|
21
21
|
updated_at: date_1.DbDate.nullable(),
|
|
@@ -23,7 +23,7 @@ exports.DbCustomField = zod_1.z.object({
|
|
|
23
23
|
/**
|
|
24
24
|
* How a value arrived, not who caused it: who edited a member's fields is already an
|
|
25
25
|
* action, and Stripe is not a person. `type` is the namespace that makes `id` resolvable —
|
|
26
|
-
* `users`, `integrations`, `
|
|
26
|
+
* `users`, `integrations`, `members_metafield_bindings` — so the one writer that
|
|
27
27
|
* resolves in no table is the one with no id to give.
|
|
28
28
|
*/
|
|
29
29
|
exports.WrittenBy = zod_1.z.discriminatedUnion('type', [
|
|
@@ -31,12 +31,16 @@ exports.WrittenBy = zod_1.z.discriminatedUnion('type', [
|
|
|
31
31
|
zod_1.z.object({ type: zod_1.z.literal('integration'), id: zod_1.z.string() }),
|
|
32
32
|
zod_1.z.object({ type: zod_1.z.literal('binding'), id: zod_1.z.string() }),
|
|
33
33
|
zod_1.z.object({ type: zod_1.z.literal('import'), id: zod_1.z.null() }),
|
|
34
|
+
// A member writing their own answers. Resolvable in `members`, like the others,
|
|
35
|
+
// and the only writer whose changes leave nothing in the staff action log: that
|
|
36
|
+
// log records what staff did.
|
|
37
|
+
zod_1.z.object({ type: zod_1.z.literal('member'), id: zod_1.z.string() }),
|
|
34
38
|
]);
|
|
35
39
|
// One part of a member's value. What a `path` means is storage.ts's business, so the row
|
|
36
40
|
// carries it as a plain string.
|
|
37
|
-
exports.
|
|
41
|
+
exports.DbMetafieldValue = zod_1.z.object({
|
|
38
42
|
id: zod_1.z.string(),
|
|
39
|
-
|
|
43
|
+
metafield_key: zod_1.z.string(),
|
|
40
44
|
member_id: zod_1.z.string(),
|
|
41
45
|
path: zod_1.z.string(),
|
|
42
46
|
// Nullable like the column, though nothing here writes a null: a part with no value
|
|
@@ -55,18 +59,18 @@ exports.DbCustomFieldValue = zod_1.z.object({
|
|
|
55
59
|
// `type` takes no part in the assembly and is here as a gate: a value whose type has left
|
|
56
60
|
// the catalog is one the definitions list no longer returns either, so failing to parse
|
|
57
61
|
// is what drops it.
|
|
58
|
-
exports.
|
|
62
|
+
exports.DbMetafieldLeaf = zod_1.z.object({
|
|
59
63
|
member_id: zod_1.z.string(),
|
|
60
64
|
key: zod_1.z.string(),
|
|
61
|
-
type:
|
|
65
|
+
type: metafield_types_1.FieldTypeSchema,
|
|
62
66
|
path: zod_1.z.string(),
|
|
63
67
|
value_text: zod_1.z.string(),
|
|
64
68
|
});
|
|
65
|
-
exports.
|
|
69
|
+
exports.DbMetafieldBinding = zod_1.z.object({
|
|
66
70
|
id: zod_1.z.string(),
|
|
67
71
|
product_id: zod_1.z.string(),
|
|
68
72
|
port: zod_1.z.string(),
|
|
69
|
-
|
|
73
|
+
metafield_key: zod_1.z.string(),
|
|
70
74
|
created_at: date_1.DbDate,
|
|
71
75
|
updated_at: date_1.DbDate.nullable(),
|
|
72
76
|
});
|
|
@@ -74,5 +78,5 @@ exports.DbCustomFieldBinding = zod_1.z.object({
|
|
|
74
78
|
exports.DbBoundField = zod_1.z.object({
|
|
75
79
|
binding_id: zod_1.z.string(),
|
|
76
80
|
key: zod_1.z.string(),
|
|
77
|
-
type:
|
|
81
|
+
type: metafield_types_1.FieldTypeSchema,
|
|
78
82
|
});
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.toMetafieldsResponse = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const case_keys_1 = require("../../lib/case-keys");
|
|
6
6
|
const models_1 = require("./models");
|
|
7
|
-
const
|
|
7
|
+
const MetafieldResource = zod_1.z.object({
|
|
8
8
|
namespace: zod_1.z.string(),
|
|
9
9
|
key: zod_1.z.string(),
|
|
10
10
|
name: zod_1.z.string(),
|
|
@@ -13,10 +13,10 @@ const CustomFieldResource = zod_1.z.object({
|
|
|
13
13
|
created_at: zod_1.z.date(),
|
|
14
14
|
updated_at: zod_1.z.date().nullable(),
|
|
15
15
|
});
|
|
16
|
-
const
|
|
17
|
-
exports.
|
|
18
|
-
.array(models_1.
|
|
16
|
+
const MetafieldsResponse = zod_1.z.object({ members_metafields: zod_1.z.array(MetafieldResource) });
|
|
17
|
+
exports.toMetafieldsResponse = zod_1.z
|
|
18
|
+
.array(models_1.Metafield)
|
|
19
19
|
.transform((fields) => ({
|
|
20
20
|
members_metafields: fields.map((field) => (0, case_keys_1.snakeKeys)(field)),
|
|
21
21
|
}))
|
|
22
|
-
.pipe(
|
|
22
|
+
.pipe(MetafieldsResponse);
|