ghost 6.56.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.
Files changed (385) hide show
  1. package/bin/validate-adapters.js +74 -0
  2. package/bin/validate-adapters.ts +87 -0
  3. package/bin/warm-compile-cache.sh +60 -0
  4. package/components/tryghost-custom-field-types-0.0.0.tgz +0 -0
  5. package/components/tryghost-kg-html-to-lexical-1.3.3.tgz +0 -0
  6. package/components/tryghost-kg-lexical-html-renderer-1.4.3.tgz +0 -0
  7. package/components/tryghost-parse-email-address-0.0.0.tgz +0 -0
  8. package/core/app.js +1 -1
  9. package/core/boot.js +21 -25
  10. package/core/bridge.js +10 -12
  11. package/core/built/admin/assets/Combination-BDvCdg1t.js +41 -0
  12. package/core/built/admin/assets/about-C7O-AgRZ.js +1 -0
  13. package/core/built/admin/assets/{account-migration-D3O_yVck.js → account-migration-Cv_ol1ko.js} +1 -1
  14. package/core/built/admin/assets/action-list-lGzZLHc8.js +1 -0
  15. package/core/built/admin/assets/activitypub/{account-migration-D8FbP-Z-.js → account-migration-DHFbePl6.js} +7 -7
  16. package/core/built/admin/assets/activitypub/activitypub.js +3 -3
  17. package/core/built/admin/assets/activitypub/{avatar-11EA1VSs.js → avatar-CT4tS2_S.js} +2 -2
  18. package/core/built/admin/assets/activitypub/{avatar-flipboard-jfbLG-xe.js → avatar-flipboard-ByYWKipo.js} +2 -2
  19. package/core/built/admin/assets/activitypub/{bluesky-sharing-f1jTQe2P.js → bluesky-sharing-srVnSHDz.js} +8 -8
  20. package/core/built/admin/assets/activitypub/{content-formatters-nmTOPY9M.js → content-formatters-C2sos5Ht.js} +3 -3
  21. package/core/built/admin/assets/activitypub/{copy-BCwo9ep3.js → copy-B1UBTOoZ.js} +2 -2
  22. package/core/built/admin/assets/activitypub/{dist-BEfX-0aW.js → dist-MPsb2WZ1.js} +4 -4
  23. package/core/built/admin/assets/activitypub/{domain-AaDlZlrA.js → domain-DzcM9Dzo.js} +9 -9
  24. package/core/built/admin/assets/activitypub/{edit-profile-DPi8Tl5M.js → edit-profile-CsQ_4xAk.js} +5 -5
  25. package/core/built/admin/assets/activitypub/{explore-CxTzjILQ.js → explore-CJe0DZBK.js} +8 -8
  26. package/core/built/admin/assets/activitypub/{feed-DPv5x2MX.js → feed-CKV3qWON.js} +9 -9
  27. package/core/built/admin/assets/activitypub/{field-DbgA8lat.js → field-DckHfDJf.js} +3 -3
  28. package/core/built/admin/assets/activitypub/{hash-BWuZoYkA.js → hash-Dlp8RM55.js} +2 -2
  29. package/core/built/admin/assets/activitypub/{inbox-35VDQ2K2.js → inbox-CsPy4R0M.js} +2 -2
  30. package/core/built/admin/assets/activitypub/{inbox-DSrF_i1O.js → inbox-DAsjzUUe.js} +10 -10
  31. package/core/built/admin/assets/activitypub/{label-CPjFBbo7.js → label-DWyo9E5T.js} +3 -3
  32. package/core/built/admin/assets/activitypub/layout-DM_3pqsU.js +1 -0
  33. package/core/built/admin/assets/activitypub/{moderation-BkDC1XVZ.js → moderation-B0Inc03M.js} +7 -7
  34. package/core/built/admin/assets/activitypub/{note-xEyH4xT-.js → note-CSE54lER.js} +7 -7
  35. package/core/built/admin/assets/activitypub/{notifications-DClaL3ui.js → notifications-RSwbKqdh.js} +9 -9
  36. package/core/built/admin/assets/activitypub/{preferences-DpnOa-4Z.js → preferences-CE231n2_.js} +11 -11
  37. package/core/built/admin/assets/activitypub/{profile-Dvi9mz-6.js → profile-aaQ1j1Eo.js} +13 -13
  38. package/core/built/admin/assets/activitypub/{reply-Cs9ySd6Z.js → reply-Cjb0Vs3m.js} +2 -2
  39. package/core/built/admin/assets/activitypub/{routes-DFBeTnfn.js → routes-Djb0mc9k.js} +26 -26
  40. package/core/built/admin/assets/activitypub/{separator-C5u_VjzY.js → separator-D8pROI5n.js} +3 -3
  41. package/core/built/admin/assets/activitypub/{settings-CV2fFu6D.js → settings-DMc32IQl.js} +5 -5
  42. package/core/built/admin/assets/activitypub/{site-_TgDd_EM.js → site-DVIcsohX.js} +4 -4
  43. package/core/built/admin/assets/activitypub/{step-1-BfnNL2oF.js → step-1-9Yey9usF.js} +5 -5
  44. package/core/built/admin/assets/activitypub/{step-2-DLndZkO-.js → step-2-DdYmKRXV.js} +6 -6
  45. package/core/built/admin/assets/activitypub/{step-3-A-PZTtRE.js → step-3-hdSkcjZU.js} +10 -10
  46. package/core/built/admin/assets/activitypub/{tabs-BUbz7tea.js → tabs-CUqseYzQ.js} +6 -6
  47. package/core/built/admin/assets/activitypub/{topic-filter-BdX_xYYT.js → topic-filter-Coni6OXM.js} +3 -3
  48. package/core/built/admin/assets/activitypub/{use-activity-pub-queries-EwuRemHh.js → use-activity-pub-queries-MeHTPMQv.js} +2 -2
  49. package/core/built/admin/assets/activitypub/{use-navigate-with-base-path-cy4ACBc4.js → use-navigate-with-base-path-B046AM38.js} +24 -7
  50. package/core/built/admin/assets/activitypub/{use-reply-chain-data-CyFcGfan.js → use-reply-chain-data-1AO-Xob6.js} +5 -5
  51. package/core/built/admin/assets/activitypub/{x-7zk8mV2p.js → x-BRfRYd16.js} +2 -2
  52. package/core/built/admin/assets/add-integration-modal-m9Dv6f77.js +1 -0
  53. package/core/built/admin/assets/add-newsletter-modal-CPSVZL2H.js +1 -0
  54. package/core/built/admin/assets/add-recommendation-modal-Ci9Z5yat.js +1 -0
  55. package/core/built/admin/assets/analytics-DqSCVV8U.js +1 -0
  56. package/core/built/admin/assets/announcement-bar-modal-DU3avV7d.js +1 -0
  57. package/core/built/admin/assets/api-keys-BK0LylyK.js +1 -0
  58. package/core/built/admin/assets/api-keys-_iCT4dxr.js +1 -0
  59. package/core/built/admin/assets/{audience-CkBb2LlO.js → audience-DTJtXXWY.js} +1 -1
  60. package/core/built/admin/assets/automated-emails-PayPCT8L.js +1 -0
  61. package/core/built/admin/assets/{automations-DhKeS_U5.js → automations-162q5HjL.js} +1 -1
  62. package/core/built/admin/assets/{automations-cMllU545.js → automations-dtQ_MRZ7.js} +1 -1
  63. package/core/built/admin/assets/{bluesky-sharing-DPGpyD-G.js → bluesky-sharing-B8Es3AuV.js} +1 -1
  64. package/core/built/admin/assets/brand-icon-09YqFZjV.js +1 -0
  65. package/core/built/admin/assets/{breadcrumb-DIfcF5ow.js → breadcrumb-tg5zL--z.js} +1 -1
  66. package/core/built/admin/assets/{chart-helpers-DV0FkdcD.js → chart-helpers-CZElTGYL.js} +1 -1
  67. package/core/built/admin/assets/checkbox-Cyo-x7mC.js +1 -0
  68. package/core/built/admin/assets/{chunk.524.87b52f4fada529df2c4c.js → chunk.524.cd5498dd4e195f679266.js} +4 -4
  69. package/core/built/admin/assets/{chunk.582.340bcca873e806cbd4bb.js → chunk.582.6f92ec1f03734bf2ea3f.js} +6 -6
  70. package/core/built/admin/assets/{chunk.332.05991a101d67f732dec3.js → chunk.873.b8fc05a8ab877fb819ed.js} +28 -27
  71. package/core/built/admin/assets/code-editor-view-Dq1rQ4tS.js +1 -0
  72. package/core/built/admin/assets/color-picker-field-BonBgxhU.js +1 -0
  73. package/core/built/admin/assets/color-utils-BsrwXuDz.js +1 -0
  74. package/core/built/admin/assets/combobox-uX5r_paI.js +1 -0
  75. package/core/built/admin/assets/command-DxwBO2pF.js +1 -0
  76. package/core/built/admin/assets/comments-Dn-RO-nU.js +1 -0
  77. package/core/built/admin/assets/components-CwL6a6As-B0E0-NBJ.js +1 -0
  78. package/core/built/admin/assets/confirmation-modal-B6D6mk6R.js +1 -0
  79. package/core/built/admin/assets/content-api-modal-BxQ-7T6u.js +1 -0
  80. package/core/built/admin/assets/copy-field-BAxL4Zqn.js +1 -0
  81. package/core/built/admin/assets/currency-Dy4Tc2R2.js +1 -0
  82. package/core/built/admin/assets/custom-integration-modal---d_l7lc.js +1 -0
  83. package/core/built/admin/assets/{date-range-select-dXc-GsVe.js → date-range-select-PB2n1HZf.js} +1 -1
  84. package/core/built/admin/assets/debounce-Dg2fW5Rg.js +3 -0
  85. package/core/built/admin/assets/design-and-theme-modal-DYRT207a.js +23 -0
  86. package/core/built/admin/assets/dirty-confirm-dialog-BnDJ39ao.js +1 -0
  87. package/core/built/admin/assets/disabled-sources-indicator-iMHrkyV3.js +1 -0
  88. package/core/built/admin/assets/dist-B2PvRwLn.js +1 -0
  89. package/core/built/admin/assets/{dist-pHiOxyxa.js → dist-D5vhMdXf.js} +1 -1
  90. package/core/built/admin/assets/dist-DlCyLrOC.js +1 -0
  91. package/core/built/admin/assets/dist-WeOIvSYM.js +23 -0
  92. package/core/built/admin/assets/{dist-DyViJwIy.js → dist-cFzKLG7y.js} +3 -3
  93. package/core/built/admin/assets/dist-j1xxxnY8.js +1 -0
  94. package/core/built/admin/assets/dist-myQaY0ka.js +1 -0
  95. package/core/built/admin/assets/{domain-B5ogXUBa.js → domain-BR8FIdjD.js} +1 -1
  96. package/core/built/admin/assets/{dropzone-BnFG7dDP.js → dropzone-hNxmUvwD.js} +1 -1
  97. package/core/built/admin/assets/{edit-profile-B07jCZy9.js → edit-profile-CENrkY0l.js} +1 -1
  98. package/core/built/admin/assets/editor-B18D0lm8.js +8 -0
  99. package/core/built/admin/assets/embed-signup-form-modal-BsCYUMvQ.js +9 -0
  100. package/core/built/admin/assets/{explore-Ca1y8HW_.js → explore-BmrnljWw.js} +1 -1
  101. package/core/built/admin/assets/{feed-x4iFMBP4.js → feed-Dy4li6i8.js} +1 -1
  102. package/core/built/admin/assets/{field-ChCAabZg.js → field-Dh_lwk13.js} +1 -1
  103. package/core/built/admin/assets/{filter-sources-LdtH1e-T.js → filter-sources-D2zDuJH5.js} +1 -1
  104. package/core/built/admin/assets/filters-3JBQcNtJ.js +1 -0
  105. package/core/built/admin/assets/{filters-CjVKRP8U.js → filters-CFt_BDe4.js} +1 -1
  106. package/core/built/admin/assets/first-promoter-modal-D6Rjxugw.js +1 -0
  107. package/core/built/admin/assets/format-url-C-t8G6Qd.js +1 -0
  108. package/core/built/admin/assets/{ghost-7f01131115186d1af84ead76e79646dd.js → ghost-d683fbeb945b13155ea669caa5d8db41.js} +300 -298
  109. package/core/built/admin/assets/{gift-link-modal-Buqh2vXh.js → gift-link-modal-zMtlJhLQ.js} +1 -1
  110. package/core/built/admin/assets/{gift-links-CsUhefWG.js → gift-links-CVuqLhsZ.js} +1 -1
  111. package/core/built/admin/assets/global-data-provider-B949LDXJ.js +1 -0
  112. package/core/built/admin/assets/grid-CUciBfjf.js +1 -0
  113. package/core/built/admin/assets/{growth-Dy2UOSay.js → growth-C38Xtp8D.js} +2 -2
  114. package/core/built/admin/assets/{growth-DajOBdN0.js → growth-CFws67_i.js} +1 -1
  115. package/core/built/admin/assets/history-modal-ILAOkbxH.js +1 -0
  116. package/core/built/admin/assets/{hooks-CixO01lL.js → hooks-D6EE7BIt.js} +2 -2
  117. package/core/built/admin/assets/html-field-9a9Id_2q.js +1 -0
  118. package/core/built/admin/assets/iframe-buffering-e8vH4-Qn.js +1 -0
  119. package/core/built/admin/assets/images-CrQKVc9Q.js +1 -0
  120. package/core/built/admin/assets/{inbox-BUOLDoji.js → inbox-BrSRzyvz.js} +13 -13
  121. package/core/built/admin/assets/index-BHy2DZX-.js +67 -0
  122. package/core/built/admin/assets/index-Ds2iUoF6.css +1 -0
  123. package/core/built/admin/assets/index.es-B9tvf-t4.js +1 -0
  124. package/core/built/admin/assets/{input-group-uSK3XT7b.js → input-group-6vEPvX9S.js} +1 -1
  125. package/core/built/admin/assets/integration-header-B4DyXV06.js +1 -0
  126. package/core/built/admin/assets/integrations-BT6_iJvu.js +1 -0
  127. package/core/built/admin/assets/invite-user-modal-5xDCEw90.js +1 -0
  128. package/core/built/admin/assets/isEmail-BOfC647y.js +1 -0
  129. package/core/built/admin/assets/koenig-editor-base-BWLEB9Vf.js +1 -0
  130. package/core/built/admin/assets/{koenig-lexical-BFc4yFed.js → koenig-lexical-Cj62r_y9.js} +1 -1
  131. package/core/built/admin/assets/{kpi-card-BN-E6WYX.js → kpi-card-DOUnkZcN.js} +1 -1
  132. package/core/built/admin/assets/{kpi-card-CCt-qeWD.js → kpi-card-IHDo8Q56.js} +1 -1
  133. package/core/built/admin/assets/{kpi-helpers-DlxTbTs4.js → kpi-helpers-CjUdECAK.js} +1 -1
  134. package/core/built/admin/assets/{kpi-tabs-BlcUttpn.js → kpi-tabs-X3DkOYbI.js} +1 -1
  135. package/core/built/admin/assets/{label-AVrxwmsz.js → label-Dq6QaOuS.js} +1 -1
  136. package/core/built/admin/assets/label-picker-8YlhS2U3.js +1 -0
  137. package/core/built/admin/assets/{labels-DAIqKed7.js → labels-DAPjKPy2.js} +1 -1
  138. package/core/built/admin/assets/layout-TMj4P-vv.js +1 -0
  139. package/core/built/admin/assets/limit-modal-BRPsit_B.js +1 -0
  140. package/core/built/admin/assets/{link-helpers-D9LsDOkG.js → link-helpers-Bzkk68GD.js} +1 -1
  141. package/core/built/admin/assets/member-custom-fields-CmvsuuV_.js +1 -0
  142. package/core/built/admin/assets/member-detail-DCvRrkmJ.js +1 -0
  143. package/core/built/admin/assets/members-DxbSKngD.js +11 -0
  144. package/core/built/admin/assets/modal-page-BMTzFHVO.js +1 -0
  145. package/core/built/admin/assets/{moderation-CQ3urTFE.js → moderation-Da5lhhWh.js} +1 -1
  146. package/core/built/admin/assets/multi-select-combobox-CYdkH7KQ.js +1 -0
  147. package/core/built/admin/assets/navigation-modal-BIoTwtMy.js +1 -0
  148. package/core/built/admin/assets/newsletter-BptlVoJm.js +1 -0
  149. package/core/built/admin/assets/newsletter-detail-modal-BIvxqE0N.js +1 -0
  150. package/core/built/admin/assets/newsletter-emails-Bf8IZLsP.js +1 -0
  151. package/core/built/admin/assets/{newsletters-vt3Ni1Ov.js → newsletters-BgrIZk0V.js} +1 -1
  152. package/core/built/admin/assets/{newsletters-BXJbJgA-.js → newsletters-Du0lzskS.js} +1 -1
  153. package/core/built/admin/assets/{note-Dk877BTv.js → note-DYcLOmDb.js} +1 -1
  154. package/core/built/admin/assets/{notifications-CPlLjPxO.js → notifications-B2SPFIV9.js} +1 -1
  155. package/core/built/admin/assets/{offers-DEniVRD5.js → offers-Um6ab71O.js} +1 -1
  156. package/core/built/admin/assets/offers-container-modal-BZnZITMw.js +1 -0
  157. package/core/built/admin/assets/{onboarding-route-DdStOtjy.js → onboarding-route-DgdfxkQh.js} +1 -1
  158. package/core/built/admin/assets/overview-BYQJXSog.js +1 -0
  159. package/core/built/admin/assets/overview-Dt2_mR6U.js +1 -0
  160. package/core/built/admin/assets/{page-header-pp4dWmOS.js → page-header-CpmxJj5B.js} +1 -1
  161. package/core/built/admin/assets/{pages-B4goRPUn.js → pages-BVMnpI2O.js} +1 -1
  162. package/core/built/admin/assets/pintura-modal-B4MuBuuO.js +1 -0
  163. package/core/built/admin/assets/portal-frame-BF0NBIji.js +1 -0
  164. package/core/built/admin/assets/portal-modal-DMVbm0oy.js +1 -0
  165. package/core/built/admin/assets/{post-analytics-BMJrI81R.js → post-analytics-CXWBOGyP.js} +1 -1
  166. package/core/built/admin/assets/post-analytics-header-ChzjXVPt.js +1 -0
  167. package/core/built/admin/assets/{post-analytics-provider-Btml5vJI.js → post-analytics-provider-Cgw4U_fw.js} +1 -1
  168. package/core/built/admin/assets/{post-share-modal-AcUZkbfL.js → post-share-modal-B9Vmk_XM.js} +1 -1
  169. package/core/built/admin/assets/{posts-DhXE7b6r.js → posts-CxG7v0-M.js} +1 -1
  170. package/core/built/admin/assets/preferences-BfzJmnsd.js +5 -0
  171. package/core/built/admin/assets/preview-chrome-BOVO6_PE.js +1 -0
  172. package/core/built/admin/assets/preview-modal-Dw_HtD6S.js +1 -0
  173. package/core/built/admin/assets/profile-BT5vtv9b.js +1 -0
  174. package/core/built/admin/assets/radio-group-I7ou7PoJ.js +1 -0
  175. package/core/built/admin/assets/{referrers-pmJT4k3-.js → referrers-B9QDAfYm.js} +1 -1
  176. package/core/built/admin/assets/{router-provider-BmEZf6c6.js → router-provider-DSQfprxH.js} +1 -1
  177. package/core/built/admin/assets/select-D9oU1IoM.js +1 -0
  178. package/core/built/admin/assets/settings-CfZFbyu_.js +4 -0
  179. package/core/built/admin/assets/{settings-BGgk7oCI.js → settings-CpvHWix7.js} +1 -1
  180. package/core/built/admin/assets/settings-breadcrumbs-K0USP2nw.js +1 -0
  181. package/core/built/admin/assets/{share-modal-BeuydaBf.js → share-modal-ClIyPzc5.js} +1 -1
  182. package/core/built/admin/assets/slack-modal-1XXqOfiw.js +1 -0
  183. package/core/built/admin/assets/social-urls-CHQ9cTAK.js +1 -0
  184. package/core/built/admin/assets/{sort-button-Df4t2AL8.js → sort-button-CdBsm40v.js} +1 -1
  185. package/core/built/admin/assets/{source-icon-ajoaKb41.js → source-icon-CEYmVLXR.js} +1 -1
  186. package/core/built/admin/assets/{stats-C_lfxZAw.js → stats-D8nZCTy5.js} +1 -1
  187. package/core/built/admin/assets/{stats-view-Cxot1iD8.js → stats-view-CugFVf0g.js} +1 -1
  188. package/core/built/admin/assets/{step-1-ogAA4lDr.js → step-1-DOYjrORn.js} +1 -1
  189. package/core/built/admin/assets/{step-2-C5Xini-7.js → step-2-vA6RsarH.js} +1 -1
  190. package/core/built/admin/assets/{step-3-CZv1FV81.js → step-3-BtIBxMId.js} +2 -2
  191. package/core/built/admin/assets/stripe-button-UFP4QRXd.js +1 -0
  192. package/core/built/admin/assets/stripe-connect-modal-C_L3uM6n.js +1 -0
  193. package/core/built/admin/assets/switch-CE2NuMn-.js +1 -0
  194. package/core/built/admin/assets/{table-DFj1wiYv.js → table-TMCgCQK7.js} +1 -1
  195. package/core/built/admin/assets/tabs-Dd6oOKbv.js +1 -0
  196. package/core/built/admin/assets/tag-detail-D3l-UJPR.js +1 -0
  197. package/core/built/admin/assets/tags-BwCgmr5v.js +1 -0
  198. package/core/built/admin/assets/tags-WdKQGWR8.js +1 -0
  199. package/core/built/admin/assets/testimonials-modal-CqWp-xXJ.js +1 -0
  200. package/core/built/admin/assets/tier-detail-modal-BkcR2u0A.js +1 -0
  201. package/core/built/admin/assets/{tiers-DYsa4DCo.js → tiers-Da6kxHQP.js} +1 -1
  202. package/core/built/admin/assets/toggle-group-Guorw93z.js +1 -0
  203. package/core/built/admin/assets/{topic-filter-DGDxDalo.js → topic-filter-CbgoWIHn.js} +1 -1
  204. package/core/built/admin/assets/transistor-modal-DuNnnpal.js +1 -0
  205. package/core/built/admin/assets/unsplash-modal-y2bVwTHH.js +1 -0
  206. package/core/built/admin/assets/{use-analytics-data-C76v4LIp.js → use-analytics-data-B-b4wNSC.js} +1 -1
  207. package/core/built/admin/assets/use-check-theme-limit-error-m09J38Mq.js +2 -0
  208. package/core/built/admin/assets/use-feature-flag-ud0Qz8vt.js +1 -0
  209. package/core/built/admin/assets/use-filter-params-BnbBDc7T.js +1 -0
  210. package/core/built/admin/assets/use-filterable-api-iMpDZBxD.js +1 -0
  211. package/core/built/admin/assets/use-form-vRjI0Kwk.js +1 -0
  212. package/core/built/admin/assets/{use-growth-stats-aNXJOmQr.js → use-growth-stats-DPU5rt3W.js} +1 -1
  213. package/core/built/admin/assets/use-hash-link-navigation-guard-B9j6HIrV.js +1 -0
  214. package/core/built/admin/assets/use-limiter-BkN3E4gw.js +2 -0
  215. package/core/built/admin/assets/use-pintura-config-C_z8HTG2.js +1 -0
  216. package/core/built/admin/assets/use-pintura-editor-DNgbkhGp.js +1 -0
  217. package/core/built/admin/assets/{use-post-referrers-CG0SZioj.js → use-post-referrers-C2mXyrp-.js} +1 -1
  218. package/core/built/admin/assets/use-query-params-DHhhu8wi.js +1 -0
  219. package/core/built/admin/assets/{use-reply-chain-data-RLdPKRmS.js → use-reply-chain-data-DaK8q2qQ.js} +1 -1
  220. package/core/built/admin/assets/use-setting-group-YlYcoNyP.js +1 -0
  221. package/core/built/admin/assets/use-settings-navigation-Bf1g1rEh.js +1 -0
  222. package/core/built/admin/assets/{use-simple-pagination-DgcF69KI.js → use-simple-pagination-D9ckKo5-.js} +1 -1
  223. package/core/built/admin/assets/{use-tinybird-query-C1R_Kbmy.js → use-tinybird-query-GSa32hVw.js} +1 -1
  224. package/core/built/admin/assets/{use-tinybird-token-C9fPjVM_.js → use-tinybird-token-CKLOZFsw.js} +1 -1
  225. package/core/built/admin/assets/use-url-input-z-p0Kewm.js +5 -0
  226. package/core/built/admin/assets/user-detail-modal-BMxOA4Sv.js +1 -0
  227. package/core/built/admin/assets/{users-Dkv8NQZe.js → users-B6hIds6n.js} +1 -1
  228. package/core/built/admin/assets/validator-Cr0sMKuW.js +7 -0
  229. package/core/built/admin/assets/{virtual-list-BmTUzeoF.js → virtual-list-RHeEL05L.js} +1 -1
  230. package/core/built/admin/assets/web-Bw2QMO5u.js +2 -0
  231. package/core/built/admin/assets/web-xJtcwMy4.js +1 -0
  232. package/core/built/admin/assets/zapier-modal-BP2f4-vY.js +1 -0
  233. package/core/built/admin/index.html +15 -13
  234. package/core/frontend/helpers/authors.js +1 -1
  235. package/core/frontend/helpers/link.js +3 -8
  236. package/core/frontend/helpers/tags.js +1 -1
  237. package/core/frontend/meta/author-url.js +2 -2
  238. package/core/frontend/meta/url.js +4 -4
  239. package/core/frontend/services/proxy.js +1 -1
  240. package/core/frontend/services/routing/events.js +20 -6
  241. package/core/frontend/services/routing/permalink-adapter.js +0 -13
  242. package/core/frontend/services/routing/permalink-adapter.ts +0 -13
  243. package/core/frontend/services/routing/router-manager.js +15 -9
  244. package/core/frontend/services/sitemap/base-site-map-generator.js +1 -28
  245. package/core/frontend/services/sitemap/site-map-manager.js +22 -57
  246. package/core/server/adapters/route-settings/utils.js +10 -2
  247. package/core/server/adapters/route-settings/utils.ts +12 -2
  248. package/core/server/api/endpoints/email-post.js +1 -1
  249. package/core/server/api/endpoints/previews.js +1 -1
  250. package/core/server/api/endpoints/search-index-public.js +3 -3
  251. package/core/server/api/endpoints/search-index.js +4 -4
  252. package/core/server/api/endpoints/utils/serializers/input/authors.js +2 -2
  253. package/core/server/api/endpoints/utils/serializers/input/comments.js +1 -1
  254. package/core/server/api/endpoints/utils/serializers/input/pages.js +3 -3
  255. package/core/server/api/endpoints/utils/serializers/input/posts.js +3 -3
  256. package/core/server/api/endpoints/utils/serializers/input/tags.js +1 -1
  257. package/core/server/api/endpoints/utils/serializers/input/users.js +2 -2
  258. package/core/server/api/endpoints/utils/serializers/input/utils/url.js +31 -13
  259. package/core/server/api/endpoints/utils/serializers/output/mappers/posts.js +2 -2
  260. package/core/server/api/endpoints/utils/serializers/output/mappers/tags.js +2 -2
  261. package/core/server/api/endpoints/utils/serializers/output/mappers/users.js +8 -0
  262. package/core/server/api/endpoints/utils/serializers/output/utils/url.js +18 -11
  263. package/core/server/data/migrations/versions/6.57/2026-08-04-18-00-00-store-custom-field-values-as-leaf-rows.js +74 -0
  264. package/core/server/data/migrations/versions/6.57/2026-08-04-18-54-14-reset-automation-email-analytics.js +25 -0
  265. package/core/server/data/schema/commands.js +21 -5
  266. package/core/server/data/schema/schema.js +24 -5
  267. package/core/server/lib/common/to-plain.ts +1 -1
  268. package/core/server/models/post.js +2 -2
  269. package/core/server/services/adapter-manager/adapter-manager.js +1 -45
  270. package/core/server/services/adapter-manager/adapter-manager.ts +2 -48
  271. package/core/server/services/adapter-manager/adapter-paths.js +24 -0
  272. package/core/server/services/adapter-manager/adapter-paths.ts +21 -0
  273. package/core/server/services/adapter-manager/base-classes.js +22 -0
  274. package/core/server/services/adapter-manager/base-classes.ts +22 -0
  275. package/core/server/services/adapter-manager/index.js +4 -27
  276. package/core/server/services/adapter-manager/index.ts +4 -31
  277. package/core/server/services/adapter-manager/utils.js +50 -0
  278. package/core/server/services/adapter-manager/utils.ts +57 -0
  279. package/core/server/services/audience-feedback/audience-feedback-controller.js +1 -1
  280. package/core/server/services/audience-feedback/audience-feedback-service.js +2 -2
  281. package/core/server/services/automations/service.js +2 -2
  282. package/core/server/services/automations/service.ts +2 -2
  283. package/core/server/services/comments/comments-service-emails.js +1 -1
  284. package/core/server/services/comments/comments-service.js +1 -1
  285. package/core/server/services/email-analytics/email-analytics-service-wrapper.js +11 -2
  286. package/core/server/services/email-analytics/email-analytics-service.js +1 -1
  287. package/core/server/services/email-service/email-service-wrapper.js +2 -1
  288. package/core/server/services/email-service/mailgun-email-provider.js +15 -0
  289. package/core/server/services/indexnow-ping/indexnow-ping-service.js +1 -1
  290. package/core/server/services/indexnow-ping/indexnow-ping-service.ts +2 -4
  291. package/core/server/services/lib/mailgun-client.js +3 -3
  292. package/core/server/services/media-inliner/external-media-inliner.js +12 -8
  293. package/core/server/services/member-attribution/url-translator.js +5 -7
  294. package/core/server/services/member-welcome-emails/service.js +72 -12
  295. package/core/server/services/members/api.js +1 -1
  296. package/core/server/services/members/import-export/import/completion-email.js +8 -4
  297. package/core/server/services/members/import-export/import/completion-email.ts +9 -4
  298. package/core/server/services/members/import-export/import/importer.js +25 -4
  299. package/core/server/services/members/import-export/import/importer.ts +26 -6
  300. package/core/server/services/members/import-export/import/row.ts +5 -1
  301. package/core/server/services/members/import-export/index.js +1 -5
  302. package/core/server/services/members/import-export/index.ts +2 -6
  303. package/core/server/services/members-custom-fields/queries.js +4 -13
  304. package/core/server/services/members-custom-fields/queries.ts +4 -13
  305. package/core/server/services/members-custom-fields/schema.js +18 -27
  306. package/core/server/services/members-custom-fields/schema.ts +17 -27
  307. package/core/server/services/members-custom-fields/storage.js +94 -27
  308. package/core/server/services/members-custom-fields/storage.ts +114 -39
  309. package/core/server/services/members-custom-fields/values-service.js +98 -219
  310. package/core/server/services/members-custom-fields/values-service.ts +110 -238
  311. package/core/server/services/mentions/resource-service.js +1 -1
  312. package/core/server/services/mentions/service.js +2 -2
  313. package/core/server/services/route-settings/dynamic-routing-service.js +9 -59
  314. package/core/server/services/slack-ping/slack-ping-service.js +2 -2
  315. package/core/server/services/slack-ping/slack-ping-service.ts +3 -5
  316. package/core/server/services/stats/content-stats-service.js +3 -3
  317. package/core/server/services/stats/posts-stats-service.js +2 -2
  318. package/core/server/services/url/config.js +90 -135
  319. package/core/server/services/url/index.js +6 -49
  320. package/core/server/services/url/lazy-find-resource.js +14 -11
  321. package/core/server/services/url/lazy-find-resource.ts +14 -11
  322. package/core/server/services/url/lazy-url-service.js +174 -94
  323. package/core/server/services/url/lazy-url-service.ts +233 -97
  324. package/core/server/services/url/routable-resources.js +62 -71
  325. package/core/server/services/url/router-filter.js +12 -4
  326. package/core/server/services/url/router-filter.ts +12 -4
  327. package/core/server/services/webhooks/index.js +1 -1
  328. package/core/server/services/webhooks/serialize.js +2 -1
  329. package/core/shared/config/env/config.testing-mysql.json +1 -2
  330. package/core/shared/config/env/config.testing.json +1 -2
  331. package/core/shared/events/index.js +1 -2
  332. package/core/shared/labs.js +3 -3
  333. package/package.json +5 -6
  334. package/pnpm-lock.yaml +6 -9
  335. package/pnpm-workspace.yaml +2 -2
  336. package/tsconfig.json +1 -0
  337. package/core/built/admin/assets/Combination-BCm9FL4o.js +0 -41
  338. package/core/built/admin/assets/activitypub/layout-CTgrezN7.js +0 -1
  339. package/core/built/admin/assets/automated-emails-6t2bIRWf.js +0 -7
  340. package/core/built/admin/assets/checkbox-BIl077a0.js +0 -1
  341. package/core/built/admin/assets/code-editor-view-C0aWNwdl.js +0 -1
  342. package/core/built/admin/assets/comments-qwhIjH3c.js +0 -1
  343. package/core/built/admin/assets/disabled-sources-indicator-DYAXW-6V.js +0 -1
  344. package/core/built/admin/assets/dist-BUKmD51u.js +0 -1
  345. package/core/built/admin/assets/dist-CNlMj7ML.js +0 -1
  346. package/core/built/admin/assets/dist-DDY6GRVz.js +0 -1
  347. package/core/built/admin/assets/dist-DG78yroX.js +0 -23
  348. package/core/built/admin/assets/editor-DDYSOXGN.js +0 -8
  349. package/core/built/admin/assets/esm-CFX93H5M.js +0 -2
  350. package/core/built/admin/assets/filters-CLehPo_D.js +0 -1
  351. package/core/built/admin/assets/index-08n05-rc.js +0 -67
  352. package/core/built/admin/assets/index-DgUzgFvS.css +0 -1
  353. package/core/built/admin/assets/label-picker-DVnpu_IF.js +0 -1
  354. package/core/built/admin/assets/layout-B0YLh7R9.js +0 -1
  355. package/core/built/admin/assets/member-custom-fields-C8NpZYza.js +0 -1
  356. package/core/built/admin/assets/member-detail-CIVAdKXf.js +0 -1
  357. package/core/built/admin/assets/members-oLPiSkXD.js +0 -10
  358. package/core/built/admin/assets/modals-CB7v-k3T.js +0 -31
  359. package/core/built/admin/assets/newsletter-rbeDX9Wk.js +0 -1
  360. package/core/built/admin/assets/overview--4V-kx9c.js +0 -1
  361. package/core/built/admin/assets/overview-DSLv30oz.js +0 -1
  362. package/core/built/admin/assets/post-analytics-header-pU2m9ZuV.js +0 -1
  363. package/core/built/admin/assets/preferences-Ru4CRPHC.js +0 -5
  364. package/core/built/admin/assets/profile-BNb1oj7D.js +0 -1
  365. package/core/built/admin/assets/select-B0HteHrp.js +0 -1
  366. package/core/built/admin/assets/settings-B1C9Q3wo.js +0 -4
  367. package/core/built/admin/assets/social-urls-DA2lXrhW.js +0 -8
  368. package/core/built/admin/assets/switch-CyQcwMAv.js +0 -1
  369. package/core/built/admin/assets/tabs-D4y1gqUd.js +0 -1
  370. package/core/built/admin/assets/tags-Dmft-Y4O.js +0 -1
  371. package/core/built/admin/assets/toggle-group-R2QMFvXW.js +0 -1
  372. package/core/built/admin/assets/use-filter-params-WrdhAISv.js +0 -1
  373. package/core/built/admin/assets/web-BqW0b0_C.js +0 -1
  374. package/core/built/admin/assets/web-Cy5GKMWM.js +0 -2
  375. package/core/server/services/url/local-file-cache.js +0 -75
  376. package/core/server/services/url/queue.js +0 -260
  377. package/core/server/services/url/resource.js +0 -102
  378. package/core/server/services/url/resources.js +0 -480
  379. package/core/server/services/url/url-generator.js +0 -276
  380. package/core/server/services/url/url-service-facade.js +0 -366
  381. package/core/server/services/url/url-service-facade.ts +0 -519
  382. package/core/server/services/url/url-service.js +0 -387
  383. package/core/server/services/url/urls.js +0 -140
  384. package/core/shared/events/url-resource-updated-event.js +0 -33
  385. /package/core/built/admin/assets/{dist-CqO2lWS0.js → dist-CqO2lWS02.js} +0 -0
@@ -9,9 +9,7 @@ type SettingsCache = {
9
9
  };
10
10
 
11
11
  type UrlService = {
12
- facade: {
13
- getUrlForResource(resource: Record<string, unknown>, options: {absolute: boolean}): string | null;
14
- };
12
+ getUrlForResource(resource: Record<string, unknown>, options: {absolute: boolean}): string | null;
15
13
  };
16
14
 
17
15
  type UrlUtils = {
@@ -126,7 +124,7 @@ export class SlackPingService {
126
124
 
127
125
  // If this is a post, we want to send the link of the post
128
126
  if (hasPostProperties(post)) {
129
- message = this.urlService.facade.getUrlForResource({...post, type: 'posts'}, {absolute: true});
127
+ message = this.urlService.getUrlForResource({...post, type: 'posts'}, {absolute: true});
130
128
  title = post.title ? post.title : null;
131
129
  author = post.authors ? post.authors[0] : null;
132
130
 
@@ -214,7 +212,7 @@ export class SlackPingService {
214
212
  fields: [
215
213
  {
216
214
  title: 'Author',
217
- value: author ? `<${this.urlService.facade.getUrlForResource({...author, type: 'authors'}, {absolute: true})} | ${author.name}>` : null,
215
+ value: author ? `<${this.urlService.getUrlForResource({...author, type: 'authors'}, {absolute: true})} | ${author.name}>` : null,
218
216
  short: true
219
217
  }
220
218
  ],
@@ -199,7 +199,7 @@ class ContentStatsService {
199
199
  }
200
200
 
201
201
  try {
202
- const resource = await this.urlService.facade.resolveUrl(pathname);
202
+ const resource = await this.urlService.resolveUrl(pathname);
203
203
 
204
204
  if (resource) {
205
205
  // resource.type is the routing-level plural form (posts/pages/tags/authors).
@@ -251,8 +251,8 @@ class ContentStatsService {
251
251
  if (this.urlService && item.pathname) {
252
252
  try {
253
253
  // Check if URL service is ready
254
- if (this.urlService.facade.hasFinished && this.urlService.facade.hasFinished()) {
255
- const resource = await this.urlService.facade.resolveUrl(item.pathname);
254
+ if (this.urlService.hasFinished && this.urlService.hasFinished()) {
255
+ const resource = await this.urlService.resolveUrl(item.pathname);
256
256
  urlExists = !!resource; // Convert to boolean
257
257
  }
258
258
  // If URL service isn't ready, we default to true (clickable)
@@ -222,8 +222,8 @@ class PostsStatsService {
222
222
  if (this.urlService && row.attribution_url) {
223
223
  try {
224
224
  // Check if URL service is ready
225
- if (this.urlService.facade.hasFinished && this.urlService.facade.hasFinished()) {
226
- const resource = await this.urlService.facade.resolveUrl(row.attribution_url);
225
+ if (this.urlService.hasFinished && this.urlService.hasFinished()) {
226
+ const resource = await this.urlService.resolveUrl(row.attribution_url);
227
227
  urlExists = !!resource; // Convert to boolean
228
228
  }
229
229
  // If URL service isn't ready, we default to true (clickable)
@@ -1,153 +1,108 @@
1
1
  /*
2
- * These are the default resources and filters.
3
- * They contain minimum filters for public accessibility of resources.
2
+ * Columns a routes.yaml filter must not be evaluated against.
3
+ *
4
+ * Ghost used to answer URLs from a map precomputed at boot, and kept that map
5
+ * lean by dropping these columns from every cached record. A collection filter
6
+ * referencing one therefore matched it as absent, which NQL reads as null. The
7
+ * URL service loads full records and would see the real value, so it strips
8
+ * these before evaluating a filter — otherwise routes.yaml files written
9
+ * against the old behaviour would start routing differently.
10
+ *
11
+ * `lazy-find-resource` strips the same columns so a resolved resource has the
12
+ * shape callers have always seen.
4
13
  */
5
14
 
6
15
  // TODO: switch exclude lists to include lists to make this more explicit
7
16
  module.exports = [
8
17
  {
9
18
  type: 'posts',
10
- modelOptions: {
11
- modelName: 'Post',
12
- filter: 'status:published+type:post',
13
- exclude: [
14
- 'title',
15
- 'mobiledoc',
16
- 'lexical',
17
- 'html',
18
- 'plaintext',
19
- // @TODO: https://github.com/TryGhost/Ghost/issues/10335
20
- // 'page',
21
- 'status',
22
- 'codeinjection_head',
23
- 'codeinjection_foot',
24
- 'meta_title',
25
- 'meta_description',
26
- 'custom_excerpt',
27
- 'og_image',
28
- 'og_title',
29
- 'og_description',
30
- 'twitter_image',
31
- 'twitter_title',
32
- 'twitter_description',
33
- 'custom_template',
34
- 'locale',
35
- 'newsletter_id',
36
- 'show_title_and_feature_image',
37
- 'email_recipient_filter',
38
- 'comment_id',
39
- 'tiers'
40
- ],
41
- withRelated: ['tags', 'authors'],
42
- withRelatedPrimary: {
43
- primary_tag: 'tags',
44
- primary_author: 'authors'
45
- },
46
- withRelatedFields: {
47
- tags: ['tags.id', 'tags.slug'],
48
- authors: ['users.id', 'users.slug']
49
- }
50
- },
51
- events: {
52
- add: 'post.published',
53
- update: 'post.published.edited',
54
- remove: 'post.unpublished'
55
- }
19
+ exclude: [
20
+ 'title',
21
+ 'mobiledoc',
22
+ 'lexical',
23
+ 'html',
24
+ 'plaintext',
25
+ // @TODO: https://github.com/TryGhost/Ghost/issues/10335
26
+ // 'page',
27
+ 'status',
28
+ 'codeinjection_head',
29
+ 'codeinjection_foot',
30
+ 'meta_title',
31
+ 'meta_description',
32
+ 'custom_excerpt',
33
+ 'og_image',
34
+ 'og_title',
35
+ 'og_description',
36
+ 'twitter_image',
37
+ 'twitter_title',
38
+ 'twitter_description',
39
+ 'custom_template',
40
+ 'locale',
41
+ 'newsletter_id',
42
+ 'show_title_and_feature_image',
43
+ 'email_recipient_filter',
44
+ 'comment_id',
45
+ 'tiers'
46
+ ]
56
47
  },
57
48
  {
58
49
  type: 'pages',
59
- modelOptions: {
60
- modelName: 'Post',
61
- exclude: [
62
- 'title',
63
- 'mobiledoc',
64
- 'lexical',
65
- 'html',
66
- 'plaintext',
67
- // @TODO: https://github.com/TryGhost/Ghost/issues/10335
68
- // 'page',
69
- // 'status',
70
- 'codeinjection_head',
71
- 'codeinjection_foot',
72
- 'meta_title',
73
- 'meta_description',
74
- 'custom_excerpt',
75
- 'og_image',
76
- 'og_title',
77
- 'og_description',
78
- 'twitter_image',
79
- 'twitter_title',
80
- 'twitter_description',
81
- 'custom_template',
82
- 'locale',
83
- 'tags',
84
- 'authors',
85
- 'primary_tag',
86
- 'primary_author',
87
- 'newsletter_id',
88
- 'show_title_and_feature_image',
89
- 'email_recipient_filter',
90
- 'comment_id',
91
- 'tiers'
92
- ],
93
- filter: 'status:published+type:page'
94
- },
95
- events: {
96
- add: 'page.published',
97
- update: 'page.published.edited',
98
- remove: 'page.unpublished'
99
- }
50
+ exclude: [
51
+ 'title',
52
+ 'mobiledoc',
53
+ 'lexical',
54
+ 'html',
55
+ 'plaintext',
56
+ // @TODO: https://github.com/TryGhost/Ghost/issues/10335
57
+ // 'page',
58
+ // 'status',
59
+ 'codeinjection_head',
60
+ 'codeinjection_foot',
61
+ 'meta_title',
62
+ 'meta_description',
63
+ 'custom_excerpt',
64
+ 'og_image',
65
+ 'og_title',
66
+ 'og_description',
67
+ 'twitter_image',
68
+ 'twitter_title',
69
+ 'twitter_description',
70
+ 'custom_template',
71
+ 'locale',
72
+ 'tags',
73
+ 'authors',
74
+ 'primary_tag',
75
+ 'primary_author',
76
+ 'newsletter_id',
77
+ 'show_title_and_feature_image',
78
+ 'email_recipient_filter',
79
+ 'comment_id',
80
+ 'tiers'
81
+ ]
100
82
  },
101
83
  {
102
84
  type: 'tags',
103
- keep: ['id', 'slug'],
104
- modelOptions: {
105
- modelName: 'Tag',
106
- exclude: [
107
- 'description',
108
- 'meta_title',
109
- 'meta_description',
110
- 'parent_id'
111
- ],
112
- filter: 'visibility:public',
113
- shouldHavePosts: {
114
- joinTo: 'tag_id',
115
- joinTable: 'posts_tags'
116
- }
117
- },
118
- events: {
119
- add: 'tag.added',
120
- update: ['tag.edited', 'tag.attached', 'tag.detached'],
121
- remove: 'tag.deleted'
122
- }
85
+ exclude: [
86
+ 'description',
87
+ 'meta_title',
88
+ 'meta_description',
89
+ 'parent_id'
90
+ ]
123
91
  },
124
92
  {
125
93
  type: 'authors',
126
- modelOptions: {
127
- modelName: 'User',
128
- exclude: [
129
- 'bio',
130
- 'website',
131
- 'location',
132
- 'facebook',
133
- 'twitter',
134
- 'locale',
135
- 'accessibility',
136
- 'meta_title',
137
- 'meta_description',
138
- 'tour',
139
- 'last_seen'
140
- ],
141
- filter: 'visibility:public',
142
- shouldHavePosts: {
143
- joinTo: 'author_id',
144
- joinTable: 'posts_authors'
145
- }
146
- },
147
- events: {
148
- add: 'user.activated',
149
- update: ['user.activated.edited', 'user.attached', 'user.detached'],
150
- remove: 'user.deleted'
151
- }
94
+ exclude: [
95
+ 'bio',
96
+ 'website',
97
+ 'location',
98
+ 'facebook',
99
+ 'twitter',
100
+ 'locale',
101
+ 'accessibility',
102
+ 'meta_title',
103
+ 'meta_description',
104
+ 'tour',
105
+ 'last_seen'
106
+ ]
152
107
  }
153
108
  ];
@@ -1,50 +1,7 @@
1
- const config = require('../../../shared/config');
2
- const LocalFileCache = require('./local-file-cache');
3
- const UrlService = require('./url-service');
4
- const UrlServiceFacade = require('./url-service-facade');
1
+ const LazyUrlService = require('./lazy-url-service');
2
+ const {createFindResource} = require('./lazy-find-resource');
3
+ const models = require('../../models');
5
4
 
6
- // NOTE: instead of a path we could give UrlService a "data-resolver" of some sort
7
- // so it doesn't have to contain the logic to read data at all. This would be
8
- // a possible improvement in the future
9
- let writeDisabled = false;
10
- let storagePath = config.getContentPath('data');
11
-
12
- // TODO: remove this hack in favor of loading from the content path when it's possible to do so
13
- // by mocking content folders in pre-boot phase
14
- if (process.env.NODE_ENV.startsWith('test')){
15
- storagePath = config.get('paths').urlCache;
16
-
17
- // NOTE: prevents test suites from overwriting cache fixtures.
18
- // A better solution would be injecting a different implementation of the
19
- // cache based on the environment, this approach should do the trick for now
20
- writeDisabled = true;
21
- }
22
-
23
- const cache = new LocalFileCache({storagePath, writeDisabled});
24
- const urlService = new UrlService({cache});
25
-
26
- // Build a lazy backend alongside eager for shadow comparison, gated by the
27
- // existing `lazyRouting` flag (unset by default = pure eager, unchanged).
28
- // models is already loaded via url-service -> resources, so this require is safe.
29
- let lazyUrlService = null;
30
- let fetchRoutableResources = null;
31
- if (config.get('lazyRouting')) {
32
- const LazyUrlService = require('./lazy-url-service');
33
- const {createFindResource} = require('./lazy-find-resource');
34
- const {createFetchRoutableResources} = require('./routable-resources');
35
- const models = require('../../models');
36
- lazyUrlService = new LazyUrlService({findResource: createFindResource(models)});
37
- fetchRoutableResources = createFetchRoutableResources({lazyUrlService});
38
- }
39
-
40
- const urlServiceFacade = lazyUrlService
41
- ? new UrlServiceFacade({urlService, lazyUrlService, compare: true, fetchRoutableResources})
42
- : new UrlServiceFacade({urlService});
43
-
44
- // Singleton: default export remains the eager UrlService for backwards
45
- // compatibility with existing imports. The new facade is exposed alongside
46
- // it via `urlService.facade` so RouterManager and migrating callers can
47
- // reach for it without forcing every consumer to update at once.
48
- urlService.facade = urlServiceFacade;
49
-
50
- module.exports = urlService;
5
+ // Singleton: every caller shares the router registrations made by
6
+ // RouterManager at boot and on every routes.yaml reload.
7
+ module.exports = new LazyUrlService({findResource: createFindResource(models)});
@@ -7,15 +7,17 @@ const POST_SCOPE = { type: 'post', status: 'published' };
7
7
  const PAGE_SCOPE = { type: 'page', status: 'published' };
8
8
  const POST_RELATIONS = ['tags', 'authors'];
9
9
  const RELATION_KEYS = ['tags', 'authors', 'primary_tag', 'primary_author'];
10
- // Drop the same fields the eager resourceConfig excludes so the resolved record
11
- // has the same shape the eager service exposes (no post body, no extra
12
- // author/tag fields). posts_meta is an auto-loaded relation eager never keeps.
10
+ // Drop the same columns the URL service excludes from filter evaluation, so a
11
+ // resolved record keeps the shape callers have always seen (no post body, no
12
+ // extra author/tag fields). posts_meta is an auto-loaded relation Ghost has
13
+ // never exposed here.
13
14
  function excludeFor(type) {
14
15
  const cfg = resourcesConfig.find((c) => c.type === type);
15
- const exclude = (cfg && cfg.modelOptions.exclude) || [];
16
+ const exclude = cfg?.exclude ?? [];
16
17
  return [...exclude, 'posts_meta'];
17
18
  }
18
- // Eager trims relations to {id, slug} via withRelatedFields; match that.
19
+ // Relations are trimmed to {id, slug}: permalinks and filters read nothing
20
+ // else off them, and callers have never seen more.
19
21
  function trimRelation(value) {
20
22
  if (Array.isArray(value)) {
21
23
  return value.map(item => _.pick(item, ['id', 'slug']));
@@ -25,11 +27,11 @@ function trimRelation(value) {
25
27
  }
26
28
  return value;
27
29
  }
28
- function pruneToEagerShape(record, type) {
30
+ function pruneToPublicShape(record, type) {
29
31
  const pruned = _.omit(record, excludeFor(type));
30
32
  if (type === 'pages') {
31
- // Eager always exposes primary_tag/primary_author as null on pages (they
32
- // are virtual Post fields) but never carries the tags/authors arrays.
33
+ // primary_tag/primary_author are always null on pages (they are virtual
34
+ // Post fields), and pages never carry the tags/authors arrays.
33
35
  pruned.primary_tag = null;
34
36
  pruned.primary_author = null;
35
37
  return pruned;
@@ -43,8 +45,9 @@ function pruneToEagerShape(record, type) {
43
45
  }
44
46
  /**
45
47
  * Builds the per-request DB lookup hook injected into LazyUrlService.resolveUrl.
46
- * Visibility rules mirror the eager service so a guessed slug can't surface
47
- * anything the eager path hid; unknown types resolve to null.
48
+ * Visibility rules match the forward lookup's base filters, so a guessed slug
49
+ * can't surface anything a generated URL would have hidden; unknown types
50
+ * resolve to null.
48
51
  */
49
52
  function createFindResource(models) {
50
53
  const loadOne = async (Model, query, type, options = {}) => {
@@ -57,7 +60,7 @@ function createFindResource(models) {
57
60
  if (Array.isArray(record.authors)) {
58
61
  record.primary_author = record.authors[0] ?? null;
59
62
  }
60
- return pruneToEagerShape(record, type);
63
+ return pruneToPublicShape(record, type);
61
64
  };
62
65
  return (type, params) => {
63
66
  switch (type) {
@@ -18,16 +18,18 @@ const PAGE_SCOPE = {type: 'page', status: 'published'};
18
18
  const POST_RELATIONS = ['tags', 'authors'];
19
19
  const RELATION_KEYS = ['tags', 'authors', 'primary_tag', 'primary_author'];
20
20
 
21
- // Drop the same fields the eager resourceConfig excludes so the resolved record
22
- // has the same shape the eager service exposes (no post body, no extra
23
- // author/tag fields). posts_meta is an auto-loaded relation eager never keeps.
21
+ // Drop the same columns the URL service excludes from filter evaluation, so a
22
+ // resolved record keeps the shape callers have always seen (no post body, no
23
+ // extra author/tag fields). posts_meta is an auto-loaded relation Ghost has
24
+ // never exposed here.
24
25
  function excludeFor(type: string): string[] {
25
26
  const cfg = resourcesConfig.find((c: {type: string}) => c.type === type);
26
- const exclude = (cfg && cfg.modelOptions.exclude) || [];
27
+ const exclude = cfg?.exclude ?? [];
27
28
  return [...exclude, 'posts_meta'];
28
29
  }
29
30
 
30
- // Eager trims relations to {id, slug} via withRelatedFields; match that.
31
+ // Relations are trimmed to {id, slug}: permalinks and filters read nothing
32
+ // else off them, and callers have never seen more.
31
33
  function trimRelation(value: unknown): unknown {
32
34
  if (Array.isArray(value)) {
33
35
  return value.map(item => _.pick(item, ['id', 'slug']));
@@ -38,12 +40,12 @@ function trimRelation(value: unknown): unknown {
38
40
  return value;
39
41
  }
40
42
 
41
- function pruneToEagerShape(record: Record<string, unknown>, type: string): Record<string, unknown> {
43
+ function pruneToPublicShape(record: Record<string, unknown>, type: string): Record<string, unknown> {
42
44
  const pruned = _.omit(record, excludeFor(type));
43
45
 
44
46
  if (type === 'pages') {
45
- // Eager always exposes primary_tag/primary_author as null on pages (they
46
- // are virtual Post fields) but never carries the tags/authors arrays.
47
+ // primary_tag/primary_author are always null on pages (they are virtual
48
+ // Post fields), and pages never carry the tags/authors arrays.
47
49
  pruned.primary_tag = null;
48
50
  pruned.primary_author = null;
49
51
  return pruned;
@@ -59,8 +61,9 @@ function pruneToEagerShape(record: Record<string, unknown>, type: string): Recor
59
61
 
60
62
  /**
61
63
  * Builds the per-request DB lookup hook injected into LazyUrlService.resolveUrl.
62
- * Visibility rules mirror the eager service so a guessed slug can't surface
63
- * anything the eager path hid; unknown types resolve to null.
64
+ * Visibility rules match the forward lookup's base filters, so a guessed slug
65
+ * can't surface anything a generated URL would have hidden; unknown types
66
+ * resolve to null.
64
67
  */
65
68
  export function createFindResource(models: Models): FindResource {
66
69
  const loadOne = async (
@@ -78,7 +81,7 @@ export function createFindResource(models: Models): FindResource {
78
81
  if (Array.isArray(record.authors)) {
79
82
  record.primary_author = record.authors[0] ?? null;
80
83
  }
81
- return pruneToEagerShape(record, type);
84
+ return pruneToPublicShape(record, type);
82
85
  };
83
86
 
84
87
  return (type: string, params: ResourceLookupParams): Promise<Record<string, unknown> | null> => {