ghost 6.57.1 → 6.58.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 (747) hide show
  1. package/LICENSE +22 -0
  2. package/bin/validate-adapters.js +1 -5
  3. package/components/ghost-storage-base-3.0.0.tgz +0 -0
  4. package/components/tryghost-adapter-base-cache-0.2.0.tgz +0 -0
  5. package/components/tryghost-adapter-base-jobs-0.0.0.tgz +0 -0
  6. package/components/tryghost-adapter-base-redirects-0.0.0.tgz +0 -0
  7. package/components/tryghost-adapter-base-route-settings-0.0.0.tgz +0 -0
  8. package/components/tryghost-adapter-base-scheduling-0.2.2.tgz +0 -0
  9. package/components/tryghost-adapter-base-sso-0.1.2.tgz +0 -0
  10. package/components/tryghost-admin-api-schema-0.0.0.tgz +0 -0
  11. package/components/tryghost-custom-field-types-0.0.0.tgz +0 -0
  12. package/components/tryghost-i18n-0.0.0.tgz +0 -0
  13. package/components/tryghost-kg-card-factory-5.2.4.tgz +0 -0
  14. package/components/tryghost-kg-clean-basic-html-4.3.4.tgz +0 -0
  15. package/components/tryghost-kg-converters-1.2.5.tgz +0 -0
  16. package/components/tryghost-kg-default-cards-10.3.5.tgz +0 -0
  17. package/components/tryghost-kg-default-nodes-2.2.0.tgz +0 -0
  18. package/components/tryghost-kg-default-transforms-1.3.4.tgz +0 -0
  19. package/components/tryghost-kg-html-to-lexical-1.4.0.tgz +0 -0
  20. package/components/tryghost-kg-lexical-html-renderer-1.5.0.tgz +0 -0
  21. package/components/tryghost-kg-markdown-html-renderer-7.2.4.tgz +0 -0
  22. package/components/tryghost-kg-utils-1.1.4.tgz +0 -0
  23. package/components/tryghost-nql-string-0.0.0.tgz +0 -0
  24. package/components/tryghost-parse-email-address-0.0.0.tgz +0 -0
  25. package/core/boot.js +35 -3
  26. package/core/built/admin/assets/{about-BNojRaxf.js → about-B_BvSyLF.js} +1 -1
  27. package/core/built/admin/assets/{account-migration-DMS8JsM-.js → account-migration-oJUGxnzT.js} +1 -1
  28. package/core/built/admin/assets/activitypub/{account-migration-DHFbePl6.js → account-migration-BpDeIF3G.js} +8 -8
  29. package/core/built/admin/assets/activitypub/activitypub.js +4 -4
  30. package/core/built/admin/assets/activitypub/{avatar-CT4tS2_S.js → avatar-B0SpBPVL.js} +3 -3
  31. package/core/built/admin/assets/activitypub/{avatar-flipboard-ByYWKipo.js → avatar-flipboard-DKt1LGcE.js} +3 -3
  32. package/core/built/admin/assets/activitypub/{bluesky-sharing-srVnSHDz.js → bluesky-sharing-aPMtrS3L.js} +10 -10
  33. package/core/built/admin/assets/activitypub/{chunk-KS7C4IRE-D4HEcEwi.js → chunk-KS7C4IRE-CnTrsgmM.js} +26 -15
  34. package/core/built/admin/assets/activitypub/{content-formatters-C2sos5Ht.js → content-formatters-BORfuA9G.js} +318 -284
  35. package/core/built/admin/assets/activitypub/{copy-B1UBTOoZ.js → copy-D-YvNi2E.js} +2 -2
  36. package/core/built/admin/assets/activitypub/{dist-MPsb2WZ1.js → dist-Dqggkccr.js} +5 -5
  37. package/core/built/admin/assets/activitypub/{domain-DzcM9Dzo.js → domain-CPdiB27_.js} +10 -10
  38. package/core/built/admin/assets/activitypub/{edit-profile-CsQ_4xAk.js → edit-profile-BY2PawIe.js} +7 -7
  39. package/core/built/admin/assets/activitypub/{explore-CJe0DZBK.js → explore-Sp9bgAwq.js} +11 -11
  40. package/core/built/admin/assets/activitypub/{feed-CKV3qWON.js → feed-BjtF4ohL.js} +10 -10
  41. package/core/built/admin/assets/activitypub/{field-DckHfDJf.js → field-BDOYVTg6.js} +4 -4
  42. package/core/built/admin/assets/activitypub/{hash-Dlp8RM55.js → hash-DqXYHgzG.js} +2 -2
  43. package/core/built/admin/assets/activitypub/{inbox-CsPy4R0M.js → inbox-CZ7IOAMn.js} +2 -2
  44. package/core/built/admin/assets/activitypub/{inbox-DAsjzUUe.js → inbox-z1o2j1Tb.js} +11 -11
  45. package/core/built/admin/assets/activitypub/{label-DWyo9E5T.js → label-1jhN-qhD.js} +4 -4
  46. package/core/built/admin/assets/activitypub/layout-BRMezuty.js +1 -0
  47. package/core/built/admin/assets/activitypub/{moderation-B0Inc03M.js → moderation-CZudJi8N.js} +9 -9
  48. package/core/built/admin/assets/activitypub/{note-CSE54lER.js → note-nr_m_5yb.js} +8 -8
  49. package/core/built/admin/assets/activitypub/{notifications-RSwbKqdh.js → notifications-BdcyivbT.js} +10 -10
  50. package/core/built/admin/assets/activitypub/{onboarding-BFDkzeR2.js → onboarding-B4kwav9u.js} +2 -2
  51. package/core/built/admin/assets/activitypub/{onboarding-D6rcBdPe.js → onboarding-DZNElJYP.js} +3 -3
  52. package/core/built/admin/assets/activitypub/{preferences-CE231n2_.js → preferences-CNqy1x9C.js} +13 -13
  53. package/core/built/admin/assets/activitypub/{profile-aaQ1j1Eo.js → profile-DlY4rhbO.js} +15 -15
  54. package/core/built/admin/assets/activitypub/{reply-Cjb0Vs3m.js → reply-DASIN0Ec.js} +2 -2
  55. package/core/built/admin/assets/activitypub/{routes-Djb0mc9k.js → routes-CEHdEZzS.js} +31 -31
  56. package/core/built/admin/assets/activitypub/{separator-D8pROI5n.js → separator-B3k35sUV.js} +4 -4
  57. package/core/built/admin/assets/activitypub/{settings-DMc32IQl.js → settings-CrSV1cux.js} +6 -6
  58. package/core/built/admin/assets/activitypub/{site-DVIcsohX.js → site-CtBUCPBz.js} +6 -6
  59. package/core/built/admin/assets/activitypub/{step-1-9Yey9usF.js → step-1-D9jGWyAy.js} +7 -7
  60. package/core/built/admin/assets/activitypub/{step-2-DdYmKRXV.js → step-2-Jz_enuo9.js} +7 -7
  61. package/core/built/admin/assets/activitypub/{step-3-hdSkcjZU.js → step-3-KpUqpGWi.js} +12 -12
  62. package/core/built/admin/assets/activitypub/{tabs-CUqseYzQ.js → tabs-DvlsxTCI.js} +7 -7
  63. package/core/built/admin/assets/activitypub/{topic-filter-Coni6OXM.js → topic-filter-CIN1E2jg.js} +4 -4
  64. package/core/built/admin/assets/activitypub/{use-activity-pub-queries-MeHTPMQv.js → use-activity-pub-queries-CATFd6YV.js} +4 -4
  65. package/core/built/admin/assets/activitypub/{use-navigate-with-base-path-B046AM38.js → use-navigate-with-base-path-iCkcbMGk.js} +2 -2
  66. package/core/built/admin/assets/activitypub/{use-reply-chain-data-1AO-Xob6.js → use-reply-chain-data-DJ0vhA8V.js} +6 -6
  67. package/core/built/admin/assets/activitypub/{users-BLeiOTHc.js → users-sgJ6GNZX.js} +12 -11
  68. package/core/built/admin/assets/activitypub/{x-BRfRYd16.js → x-Cy2jUiYM.js} +2 -2
  69. package/core/built/admin/assets/add-integration-modal-BW23PDYs.js +1 -0
  70. package/core/built/admin/assets/add-newsletter-modal-M0ls8BKO.js +1 -0
  71. package/core/built/admin/assets/{add-recommendation-modal-D-3LOrdd.js → add-recommendation-modal-B0NeBMzl.js} +1 -1
  72. package/core/built/admin/assets/{analytics-DTIMRhWw.js → analytics-BC2oR8ay.js} +1 -1
  73. package/core/built/admin/assets/announcement-bar-modal-pXBqjQE_.js +1 -0
  74. package/core/built/admin/assets/{api-keys-_iCT4dxr.js → api-keys-BgKr003d.js} +1 -1
  75. package/core/built/admin/assets/{api-keys-Dx4NeNpK.js → api-keys-Df6uv1dT.js} +1 -1
  76. package/core/built/admin/assets/{audience-DkknNqhZ.js → audience-BY8od8If.js} +1 -1
  77. package/core/built/admin/assets/{automated-emails-PayPCT8L.js → automated-emails-28c2Lbb3.js} +1 -1
  78. package/core/built/admin/assets/{automations-DvSU7QhW.js → automations-DCs6Wady.js} +1 -1
  79. package/core/built/admin/assets/{automations-162q5HjL.js → automations-Dzp_QnON.js} +1 -1
  80. package/core/built/admin/assets/{bluesky-sharing-yZ9A_jL8.js → bluesky-sharing-D0P42Cws.js} +1 -1
  81. package/core/built/admin/assets/{breadcrumb-CjOH7LCU.js → breadcrumb-MTj_cKLb.js} +1 -1
  82. package/core/built/admin/assets/card-CiiE7QfM.js +1 -0
  83. package/core/built/admin/assets/{chart-helpers-DGxvWnBT.js → chart-helpers-DcO3k_vA.js} +1 -1
  84. package/core/built/admin/assets/{checkbox-BSUcnNq_.js → checkbox-LmClhqcS.js} +1 -1
  85. package/core/built/admin/assets/{chunk.424.4a27628efdade15c2dab.js → chunk.408.1a258af360eb8d905508.js} +40 -37
  86. package/core/built/admin/assets/{chunk.571.40f093ed6d883993714e.js → chunk.492.a9da46ca956b10116774.js} +1342 -1342
  87. package/core/built/admin/assets/{chunk.571.40f093ed6d883993714e.js.LICENSE.txt → chunk.492.a9da46ca956b10116774.js.LICENSE.txt} +1 -1
  88. package/core/built/admin/assets/chunk.524.4c693c3a00ac91df34fa.js +25 -0
  89. package/core/built/admin/assets/chunk.582.20b600e329e58d12d7c2.js +27 -0
  90. package/core/built/admin/assets/code-editor-view-DqTOUnbM.js +1 -0
  91. package/core/built/admin/assets/code-editor-view-bA0lfxUL.js +1 -0
  92. package/core/built/admin/assets/{debounce-Cx5B_9OI.js → color-picker-CBlJMv3y.js} +2 -2
  93. package/core/built/admin/assets/color-picker-field-Cv9GOJQZ.js +1 -0
  94. package/core/built/admin/assets/{combobox-5rdgDrDV.js → combobox-BbPJzjCp.js} +1 -1
  95. package/core/built/admin/assets/command-BrhXIlDr.js +1 -0
  96. package/core/built/admin/assets/comments-Cu4rD1aJ.js +1 -0
  97. package/core/built/admin/assets/confirmation-provider-BEdrnHns.js +1 -0
  98. package/core/built/admin/assets/{content-api-modal-BtW4Z1-1.js → content-api-modal-BOFWRUkC.js} +1 -1
  99. package/core/built/admin/assets/{copy-field-CEp_XieW.js → copy-field-8biQvNMD.js} +1 -1
  100. package/core/built/admin/assets/custom-field-type-option-CNhAgHbJ.js +1 -0
  101. package/core/built/admin/assets/custom-integration-modal-CrGOI8IB.js +1 -0
  102. package/core/built/admin/assets/{date-range-select-B3Ij1Rqg.js → date-range-select-Bsh4gIek.js} +1 -1
  103. package/core/built/admin/assets/debounce-pscB46sW.js +1 -0
  104. package/core/built/admin/assets/design-and-theme-modal-DWZguwWX.js +23 -0
  105. package/core/built/admin/assets/{dirty-confirm-dialog-YE9L21gY.js → dirty-confirm-dialog-DmdMpgyN.js} +1 -1
  106. package/core/built/admin/assets/{disabled-sources-indicator-uIzbWL7K.js → disabled-sources-indicator-BLnmyWgt.js} +1 -1
  107. package/core/built/admin/assets/dist-4m6pHdc0.js +23 -0
  108. package/core/built/admin/assets/{dist-DCk0UkGx.js → dist-B6bJuxL3.js} +1 -1
  109. package/core/built/admin/assets/{dist-CbHbGtQ-.js → dist-BtaTA7Ii.js} +1 -1
  110. package/core/built/admin/assets/{dist-Q1p9iXwH.js → dist-CZgIBXQN.js} +1 -1
  111. package/core/built/admin/assets/dist-CiHx7vA5.js +6 -0
  112. package/core/built/admin/assets/{dist-ARN6XTcR.js → dist-ECAUrdGc.js} +1 -1
  113. package/core/built/admin/assets/dist-Z97pCNqS.js +11 -0
  114. package/core/built/admin/assets/{dist-t6AXpf_4.js → dist-zwwGt8Yf.js} +1 -1
  115. package/core/built/admin/assets/{domain-DzrOAPY8.js → domain-Dp9TRrFp.js} +1 -1
  116. package/core/built/admin/assets/{dropzone-CzhP33wa.js → dropzone-B21Entqz.js} +1 -1
  117. package/core/built/admin/assets/{edit-profile-oufs4R4n.js → edit-profile-DG6lpMsr.js} +1 -1
  118. package/core/built/admin/assets/editor-CPQOrhrn.js +8 -0
  119. package/core/built/admin/assets/{editor-DtxX27Jz.css → editor-DLioOiRN.css} +1 -1
  120. package/core/built/admin/assets/{embed-signup-form-modal-Ch3s6lqA.js → embed-signup-form-modal-CgWniDha.js} +2 -2
  121. package/core/built/admin/assets/esm-CXo5SEPy.js +2 -0
  122. package/core/built/admin/assets/{explore-CA-R01Br.js → explore-C3rzONJv.js} +1 -1
  123. package/core/built/admin/assets/{feed-ClC8_Gld.js → feed-DpUwS1cU.js} +1 -1
  124. package/core/built/admin/assets/{field-B3OPenbP.js → field-BQqLTgHM.js} +1 -1
  125. package/core/built/admin/assets/{filter-sources-CiPLnG9A.js → filter-sources-FgqoUIL7.js} +1 -1
  126. package/core/built/admin/assets/{filters-yFvybRMe.js → filters-D0uIMD8n.js} +1 -1
  127. package/core/built/admin/assets/filters-DZJT29GW.js +1 -0
  128. package/core/built/admin/assets/{first-promoter-modal-BC0UpYCD.js → first-promoter-modal-DJhQQheG.js} +1 -1
  129. package/core/built/admin/assets/framework-provider-CFLwK5uS.js +4 -0
  130. package/core/built/admin/assets/{ghost-d38c30b866e59f2e06a357b5eb844fe5.css → ghost-68f447a1796b93a1f128b649bac8506d.css} +1 -1
  131. package/core/built/admin/assets/{ghost-d683fbeb945b13155ea669caa5d8db41.js → ghost-ba408063a5922b458b4a8f216cf23251.js} +124 -342
  132. package/core/built/admin/assets/{ghost-dark-1bffd5099ba7a749303133efacf8480b.css → ghost-dark-28ae4899c92022857f3584694bcb50ef.css} +1 -1
  133. package/core/built/admin/assets/{gift-link-modal-BKRuqo-k.js → gift-link-modal-sdFLjND9.js} +1 -1
  134. package/core/built/admin/assets/{gift-links-CVuqLhsZ.js → gift-links-D7BJ9qfe.js} +1 -1
  135. package/core/built/admin/assets/{global-data-provider-RzW6Bnlf.js → global-data-provider-CixmTX00.js} +1 -1
  136. package/core/built/admin/assets/{growth-ClNAldfL.js → growth-0YYkBEeS.js} +1 -1
  137. package/core/built/admin/assets/{growth-Dz8OSG06.js → growth-DpjAPeQT.js} +2 -2
  138. package/core/built/admin/assets/{history-modal-DIVuQ5Ct.js → history-modal-BWJ4-cJ0.js} +1 -1
  139. package/core/built/admin/assets/{hooks-D6EE7BIt.js → hooks-CJepWnbB.js} +1 -1
  140. package/core/built/admin/assets/{html-field-CVZ2sMxw.js → html-field-C-oa5DEl.js} +1 -1
  141. package/core/built/admin/assets/{iframe-buffering-e8vH4-Qn.js → iframe-buffering-Ba9sDpi2.js} +1 -1
  142. package/core/built/admin/assets/{images-Ok8FFJ3A.js → images-3cQgwfTD.js} +1 -1
  143. package/core/built/admin/assets/{inbox-CMUVI6qb.js → inbox-Dz_JblyJ.js} +6 -6
  144. package/core/built/admin/assets/index-BOJzlYiz.js +67 -0
  145. package/core/built/admin/assets/index-Bid6LAyc.css +1 -0
  146. package/core/built/admin/assets/{input-group-2XU-iuh_.js → input-group-DpogNUIt.js} +1 -1
  147. package/core/built/admin/assets/{integrations-BT6_iJvu.js → integrations-B9yYgci5.js} +1 -1
  148. package/core/built/admin/assets/{invite-user-modal-DrZ7xxrZ.js → invite-user-modal-DCiQSiuD.js} +1 -1
  149. package/core/built/admin/assets/{koenig-editor-base-BPj4S760.js → koenig-editor-base-BApy8Q7C.js} +1 -1
  150. package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +8328 -8294
  151. package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +84 -84
  152. package/core/built/admin/assets/{koenig-lexical-Cdjv-m3_.js → koenig-lexical-2KuqRwZI.js} +33 -33
  153. package/core/built/admin/assets/{kpi-card-J8Mj1sDX.js → kpi-card-Ck3tT2Wg.js} +1 -1
  154. package/core/built/admin/assets/{kpi-card-awos0BMH.js → kpi-card-DDIxptaS.js} +1 -1
  155. package/core/built/admin/assets/{kpi-helpers-SEhvH-8E.js → kpi-helpers-ssbuy-hD.js} +1 -1
  156. package/core/built/admin/assets/{kpi-tabs-R6BjsKhd.js → kpi-tabs-BqoIM6bI.js} +1 -1
  157. package/core/built/admin/assets/{label-BMC3dzLI.js → label-DodDsMzn.js} +1 -1
  158. package/core/built/admin/assets/label-picker-Cvvbmzb5.js +1 -0
  159. package/core/built/admin/assets/{labels-DAPjKPy2.js → labels-DqvSR6JF.js} +1 -1
  160. package/core/built/admin/assets/layout-DkkGyev2.js +1 -0
  161. package/core/built/admin/assets/limit-service-BhiEvqcP.js +20 -0
  162. package/core/built/admin/assets/{link-helpers-Bzkk68GD.js → link-helpers-kpbU8TWh.js} +1 -1
  163. package/core/built/admin/assets/luxon-D1RVjjpq.js +1 -0
  164. package/core/built/admin/assets/member-custom-fields-CvGcpaiW.js +1 -0
  165. package/core/built/admin/assets/member-detail-CMCMZ47_.js +1 -0
  166. package/core/built/admin/assets/members-sRl6fNfq.js +11 -0
  167. package/core/built/admin/assets/{moderation-mPjYHgZW.js → moderation-KhKwGqI1.js} +1 -1
  168. package/core/built/admin/assets/{multi-select-combobox-CsoyHAiX.js → multi-select-combobox-nhCff0_K.js} +1 -1
  169. package/core/built/admin/assets/{navigation-modal-D_c0badj.js → navigation-modal-MDJExWDJ.js} +1 -1
  170. package/core/built/admin/assets/newsletter-BIBHumfV.js +1 -0
  171. package/core/built/admin/assets/newsletter-detail-modal-CfjBMH3v.js +1 -0
  172. package/core/built/admin/assets/{newsletter-emails-B-OLfrvr.js → newsletter-emails-ClDL-7dA.js} +1 -1
  173. package/core/built/admin/assets/newsletters-CBe-IPzK.js +1 -0
  174. package/core/built/admin/assets/{newsletters-Du0lzskS.js → newsletters-ILsexy-5.js} +1 -1
  175. package/core/built/admin/assets/{note-CSVsUKBm.js → note-HnNUOt4d.js} +1 -1
  176. package/core/built/admin/assets/{notifications-DV9FRtDw.js → notifications-Cj5e-258.js} +1 -1
  177. package/core/built/admin/assets/nql-lang-CaWrLesS.js +19 -0
  178. package/core/built/admin/assets/{offers-Um6ab71O.js → offers-DMxebaoK.js} +1 -1
  179. package/core/built/admin/assets/offers-container-modal-BHwHtixC.js +1 -0
  180. package/core/built/admin/assets/{onboarding-route--jL5KLPD.js → onboarding-route-D_4jp7Nq.js} +1 -1
  181. package/core/built/admin/assets/overview-CezDdg-F.js +1 -0
  182. package/core/built/admin/assets/overview-D5mM51Lj.js +1 -0
  183. package/core/built/admin/assets/{page-header-DAvDYKO9.js → page-header-VLPJfj_d.js} +1 -1
  184. package/core/built/admin/assets/{pages-BVMnpI2O.js → pages-Gchxp5c7.js} +1 -1
  185. package/core/built/admin/assets/{pintura-modal-jiUCxX0Q.js → pintura-modal-BXXJ8Iaa.js} +1 -1
  186. package/core/built/admin/assets/{portal-frame-D4D4nEO6.js → portal-frame-BLCvF8f-.js} +1 -1
  187. package/core/built/admin/assets/portal-modal-DN80tAcy.js +1 -0
  188. package/core/built/admin/assets/{post-analytics-BhAtiFJp.js → post-analytics-Gv81eN_g.js} +1 -1
  189. package/core/built/admin/assets/post-analytics-header-_ydSY8qO.js +1 -0
  190. package/core/built/admin/assets/{post-analytics-provider-DGg0FUqs.js → post-analytics-provider-O2YjZMhN.js} +1 -1
  191. package/core/built/admin/assets/{post-share-modal-DtFAC132.js → post-share-modal-CzYak_a5.js} +1 -1
  192. package/core/built/admin/assets/{posts-CxG7v0-M.js → posts-DgcUi2rc.js} +1 -1
  193. package/core/built/admin/assets/preferences-gneLb6LV.js +5 -0
  194. package/core/built/admin/assets/{preview-modal-DctYx20m.js → preview-modal-Bkq-tgVm.js} +1 -1
  195. package/core/built/admin/assets/profile-CzXmCNTC.js +1 -0
  196. package/core/built/admin/assets/{radio-group-CI5_Kf_d.js → radio-group-Dsq5ZEbV.js} +1 -1
  197. package/core/built/admin/assets/{referrers-B9QDAfYm.js → referrers-C3a2K8qB.js} +1 -1
  198. package/core/built/admin/assets/{router-provider-DSQfprxH.js → router-provider-CkB_ArLF.js} +1 -1
  199. package/core/built/admin/assets/{select-CkXqNJDJ.js → select-xuZAuDyS.js} +1 -1
  200. package/core/built/admin/assets/{settings-ZCj-W56o.js → settings-Ct8pabhr.js} +1 -1
  201. package/core/built/admin/assets/settings-KSWWQanQ.js +4 -0
  202. package/core/built/admin/assets/{settings-breadcrumbs-DIq31FwA.js → settings-breadcrumbs-DbPGu-Tu.js} +1 -1
  203. package/core/built/admin/assets/{share-modal-BNj14g79.js → share-modal-CdiUx9WM.js} +1 -1
  204. package/core/built/admin/assets/{slack-modal-C6SpMQ-q.js → slack-modal-BP--Z3jE.js} +1 -1
  205. package/core/built/admin/assets/{sort-button-B-k54ow2.js → sort-button-CjfKdlsL.js} +1 -1
  206. package/core/built/admin/assets/{source-icon-Cej3sZM6.js → source-icon-DHj1h6Ts.js} +1 -1
  207. package/core/built/admin/assets/{stats-B2KW8E2y.js → stats-C615kulJ.js} +1 -1
  208. package/core/built/admin/assets/{stats-view-CVzU2-p5.js → stats-view-BSMRdYiN.js} +1 -1
  209. package/core/built/admin/assets/{step-1-Dbn1iIMU.js → step-1-pSdGYtIF.js} +1 -1
  210. package/core/built/admin/assets/{step-2-BahnSuN6.js → step-2-T9Uy4eBD.js} +1 -1
  211. package/core/built/admin/assets/{step-3-CW04e2ZJ.js → step-3-D4uXe_XG.js} +2 -2
  212. package/core/built/admin/assets/{stripe-button-BkBZqaGG.js → stripe-button-Bh4p6Wud.js} +1 -1
  213. package/core/built/admin/assets/stripe-connect-modal-C2vTvepi.js +1 -0
  214. package/core/built/admin/assets/{table-BtLcEi1M.js → table-DghJxZMH.js} +1 -1
  215. package/core/built/admin/assets/{tabs-BaWRfg8j.js → tabs-l9c7FjzI.js} +1 -1
  216. package/core/built/admin/assets/tag-detail-DBw_M2-p.js +2 -0
  217. package/core/built/admin/assets/{tags-BbygUvNB.js → tags-DoWsAG6l.js} +1 -1
  218. package/core/built/admin/assets/{tags-BwCgmr5v.js → tags-EmEvJN75.js} +1 -1
  219. package/core/built/admin/assets/{testimonials-modal--bdzppyh.js → testimonials-modal-BZKePE2T.js} +1 -1
  220. package/core/built/admin/assets/tier-detail-modal-D65pVWsN.js +1 -0
  221. package/core/built/admin/assets/{tiers-Da6kxHQP.js → tiers-8iTFjJWg.js} +1 -1
  222. package/core/built/admin/assets/{toggle-group-CVl-Xigr.js → toggle-group-uJnl42w3.js} +1 -1
  223. package/core/built/admin/assets/{topic-filter-BoRHRbL1.js → topic-filter-BM7hz0kW.js} +1 -1
  224. package/core/built/admin/assets/transistor-modal-VZOGN3od.js +1 -0
  225. package/core/built/admin/assets/{unsplash-modal-CixoRAO2.js → unsplash-modal-CKGfACxF.js} +1 -1
  226. package/core/built/admin/assets/{use-analytics-data-BiWvcf1u.js → use-analytics-data-IxJcSjc9.js} +1 -1
  227. package/core/built/admin/assets/use-check-theme-limit-error-CGp3CGT5.js +1 -0
  228. package/core/built/admin/assets/use-feature-flag-CSq2Lwzt.js +1 -0
  229. package/core/built/admin/assets/use-filter-params-0hcJJuEJ.js +1 -0
  230. package/core/built/admin/assets/{use-filterable-api-iMpDZBxD.js → use-filterable-api-CQBtVG-l.js} +1 -1
  231. package/core/built/admin/assets/{use-growth-stats-Dom8xVzo.js → use-growth-stats-1NW-8eEZ.js} +1 -1
  232. package/core/built/admin/assets/use-limiter-ffwpsZPp.js +2 -0
  233. package/core/built/admin/assets/{use-pintura-config-Bj4QmiVk.js → use-pintura-config-BjFChXV1.js} +1 -1
  234. package/core/built/admin/assets/{use-pintura-editor-DvrslmPE.js → use-pintura-editor-Cb41oJyL.js} +1 -1
  235. package/core/built/admin/assets/{use-post-referrers-pxIHTXFs.js → use-post-referrers-Dp1BnTAK.js} +1 -1
  236. package/core/built/admin/assets/{use-reply-chain-data-CmFe0N6F.js → use-reply-chain-data-C0ZUTkfk.js} +1 -1
  237. package/core/built/admin/assets/{use-setting-group-Cmp_sy-d.js → use-setting-group-Bx8M6FL2.js} +1 -1
  238. package/core/built/admin/assets/{use-settings-navigation-BmROPrls.js → use-settings-navigation-BOZcat_V.js} +1 -1
  239. package/core/built/admin/assets/{use-simple-pagination-D5rL3YwO.js → use-simple-pagination-DsEGSJhe.js} +1 -1
  240. package/core/built/admin/assets/{use-tinybird-query-DP2dMaq7.js → use-tinybird-query-Ci_DiPkX.js} +1 -1
  241. package/core/built/admin/assets/{use-tinybird-token-DrK_skPQ.js → use-tinybird-token-CsUwc722.js} +1 -1
  242. package/core/built/admin/assets/use-upgrade-route-B3_DUiuT.js +1 -0
  243. package/core/built/admin/assets/{use-url-input-ChrUZBFf.js → use-url-input-BEZJpVgN.js} +2 -2
  244. package/core/built/admin/assets/user-detail-modal-595z1N5r.js +1 -0
  245. package/core/built/admin/assets/{users-B6hIds6n.js → users-DmGMPfw7.js} +1 -1
  246. package/core/built/admin/assets/virtual-list-D5ugXyZY.js +1 -0
  247. package/core/built/admin/assets/{web-D71mjB2r.js → web-CAta3lRE.js} +1 -1
  248. package/core/built/admin/assets/web-Ds9_wWJK.js +2 -0
  249. package/core/built/admin/assets/zapier-modal-CcfDZY53.js +1 -0
  250. package/core/built/admin/index.html +12 -12
  251. package/core/frontend/apps/private-blogging/lib/middleware.js +5 -58
  252. package/core/frontend/helpers/ghost_head.js +52 -0
  253. package/core/frontend/meta/asset-url.js +20 -9
  254. package/core/frontend/public/cards.manifest.json +1 -0
  255. package/core/frontend/public/ghost-stats.min.js +1 -1
  256. package/core/frontend/services/assets-minification/card-assets.js +121 -46
  257. package/core/frontend/services/assets-minification/index.js +13 -4
  258. package/core/frontend/services/data/fetch-data.js +7 -14
  259. package/core/frontend/services/llms/service.js +27 -6
  260. package/core/frontend/services/proxy.js +1 -0
  261. package/core/frontend/services/routing/api-adapter.js +11 -5
  262. package/core/frontend/services/routing/collection-router.js +1 -2
  263. package/core/frontend/services/routing/controllers/entry/markdown.js +63 -5
  264. package/core/frontend/services/routing/controllers/entry.js +1 -1
  265. package/core/frontend/services/routing/controllers/previews.js +0 -3
  266. package/core/frontend/services/routing/events.js +2 -1
  267. package/core/frontend/services/routing/parent-router.js +0 -22
  268. package/core/frontend/services/routing/router-manager.js +2 -2
  269. package/core/frontend/services/routing/static-pages-router.js +0 -1
  270. package/core/frontend/services/sitemap/handler.js +3 -4
  271. package/core/frontend/services/sitemap/site-map-manager.js +1 -2
  272. package/core/frontend/services/theme-engine/i18n/i18n.js +0 -33
  273. package/core/frontend/web/middleware/llms-discovery.js +2 -2
  274. package/core/frontend/web/routers/serve-public-file.js +33 -3
  275. package/core/frontend/web/site.js +5 -4
  276. package/core/server/adapters/jobs/InMemoryJobsBackend.js +113 -0
  277. package/core/server/adapters/redirects/S3RedirectsStore.js +33 -13
  278. package/core/server/adapters/route-settings/S3RouteSettingsStore.js +33 -13
  279. package/core/server/adapters/scheduling/scheduling-default.js +6 -7
  280. package/core/server/adapters/storage/LocalStorageBase.js +1 -3
  281. package/core/server/api/endpoints/index.js +0 -4
  282. package/core/server/api/endpoints/member-custom-fields.js +15 -4
  283. package/core/server/api/endpoints/pages.js +3 -11
  284. package/core/server/api/endpoints/posts.js +3 -11
  285. package/core/server/api/endpoints/utils/api-filter-utils.js +15 -1
  286. package/core/server/api/endpoints/utils/serializers/input/settings.js +4 -0
  287. package/core/server/api/endpoints/utils/serializers/output/index.js +0 -4
  288. package/core/server/api/endpoints/utils/serializers/output/mappers/email-batches.js +1 -1
  289. package/core/server/api/endpoints/utils/serializers/output/mappers/snippets.js +0 -1
  290. package/core/server/api/endpoints/utils/serializers/output/member-custom-fields.js +1 -0
  291. package/core/server/data/exporter/table-lists.js +4 -1
  292. package/core/server/data/migrations/utils/schema.js +5 -3
  293. package/core/server/data/migrations/versions/6.57/2026-08-04-18-00-00-store-custom-field-values-as-leaf-rows.js +19 -7
  294. package/core/server/data/migrations/versions/6.58/2026-08-10-08-20-50-add-machine-payments-settings.js +41 -0
  295. package/core/server/data/migrations/versions/6.58/2026-08-10-08-21-00-add-machine-payment-events-table.js +18 -0
  296. package/core/server/data/migrations/versions/6.58/2026-08-10-15-24-09-reset-custom-field-definitions-for-underscored-keys.js +66 -0
  297. package/core/server/data/migrations/versions/6.58/2026-08-11-10-00-00-swap-custom-field-values-to-key-fk.js +65 -0
  298. package/core/server/data/migrations/versions/6.58/2026-08-11-10-34-25-remove-legacy-explore-integration.js +131 -0
  299. package/core/server/data/migrations/versions/6.58/2026-08-11-16-00-00-add-sort-order-to-members-custom-fields.js +13 -0
  300. package/core/server/data/migrations/versions/6.58/2026-08-11-21-22-48-rename-email-batches-provider-id.js +8 -0
  301. package/core/server/data/migrations/versions/6.58/2026-08-13-16-07-33-add-automation-runs-automation-id-created-at-index.js +28 -0
  302. package/core/server/data/schema/README.md +87 -0
  303. package/core/server/data/schema/commands.js +5 -2
  304. package/core/server/data/schema/default-settings/default-settings.json +27 -0
  305. package/core/server/data/schema/fixtures/fixtures.json +0 -21
  306. package/core/server/data/schema/schema.js +37 -9
  307. package/core/server/data/seeders/data-generator.js +3 -1
  308. package/core/server/data/seeders/importers/automation-action-edges-importer.js +38 -0
  309. package/core/server/data/seeders/importers/automation-action-revisions-importer.js +139 -0
  310. package/core/server/data/seeders/importers/automation-actions-importer.js +84 -0
  311. package/core/server/data/seeders/importers/automation-run-steps-importer.js +134 -0
  312. package/core/server/data/seeders/importers/automation-runs-importer.js +97 -0
  313. package/core/server/data/seeders/importers/automations-importer.js +78 -0
  314. package/core/server/data/seeders/importers/benefits-importer.js +1 -1
  315. package/core/server/data/seeders/importers/comment-reports-importer.js +5 -5
  316. package/core/server/data/seeders/importers/comments-importer.js +6 -6
  317. package/core/server/data/seeders/importers/email-batches-importer.js +9 -8
  318. package/core/server/data/seeders/importers/email-recipient-failures-importer.js +1 -1
  319. package/core/server/data/seeders/importers/email-recipients-importer.js +12 -12
  320. package/core/server/data/seeders/importers/emails-importer.js +7 -7
  321. package/core/server/data/seeders/importers/index.js +6 -0
  322. package/core/server/data/seeders/importers/labels-importer.js +4 -4
  323. package/core/server/data/seeders/importers/members-click-events-importer.js +4 -4
  324. package/core/server/data/seeders/importers/members-created-events-importer.js +5 -5
  325. package/core/server/data/seeders/importers/members-feedback-importer.js +7 -7
  326. package/core/server/data/seeders/importers/members-importer.js +5 -5
  327. package/core/server/data/seeders/importers/members-labels-importer.js +1 -1
  328. package/core/server/data/seeders/importers/members-login-events-importer.js +4 -4
  329. package/core/server/data/seeders/importers/members-newsletters-importer.js +1 -1
  330. package/core/server/data/seeders/importers/members-paid-subscription-events-importer.js +1 -1
  331. package/core/server/data/seeders/importers/members-products-importer.js +3 -3
  332. package/core/server/data/seeders/importers/members-status-events-importer.js +4 -4
  333. package/core/server/data/seeders/importers/members-stripe-customers-importer.js +3 -3
  334. package/core/server/data/seeders/importers/members-stripe-customers-subscriptions-importer.js +8 -8
  335. package/core/server/data/seeders/importers/members-subscribe-events-importer.js +3 -3
  336. package/core/server/data/seeders/importers/members-subscription-created-events-importer.js +4 -4
  337. package/core/server/data/seeders/importers/newsletters-importer.js +1 -1
  338. package/core/server/data/seeders/importers/offer-redemptions-importer.js +6 -6
  339. package/core/server/data/seeders/importers/offers-importer.js +4 -4
  340. package/core/server/data/seeders/importers/posts-authors-importer.js +1 -1
  341. package/core/server/data/seeders/importers/posts-importer.js +5 -5
  342. package/core/server/data/seeders/importers/posts-products-importer.js +1 -1
  343. package/core/server/data/seeders/importers/posts-tags-importer.js +1 -1
  344. package/core/server/data/seeders/importers/products-benefits-importer.js +1 -1
  345. package/core/server/data/seeders/importers/products-importer.js +1 -1
  346. package/core/server/data/seeders/importers/recommendation-click-events-importer.js +1 -1
  347. package/core/server/data/seeders/importers/recommendation-subscribe-events-importer.js +1 -1
  348. package/core/server/data/seeders/importers/recommendations-importer.js +1 -1
  349. package/core/server/data/seeders/importers/redirects-importer.js +1 -1
  350. package/core/server/data/seeders/importers/roles-users-importer.js +1 -1
  351. package/core/server/data/seeders/importers/stripe-prices-importer.js +1 -1
  352. package/core/server/data/seeders/importers/stripe-products-importer.js +1 -1
  353. package/core/server/data/seeders/importers/table-importer.js +92 -91
  354. package/core/server/data/seeders/importers/tags-importer.js +3 -3
  355. package/core/server/data/seeders/importers/users-importer.js +3 -3
  356. package/core/server/data/seeders/importers/web-mentions-importer.js +3 -3
  357. package/core/server/data/seeders/utils/database-date.js +14 -18
  358. package/core/server/data/seeders/utils/json-importer.js +1 -1
  359. package/core/server/data/seeders/utils/random.js +8 -7
  360. package/core/server/data/seeders/utils/topological-sort.js +5 -3
  361. package/core/server/data/tinybird/ARCHITECTURE.md +1 -2
  362. package/core/server/models/base/plugins/crud.js +0 -5
  363. package/core/server/models/index.js +2 -0
  364. package/core/server/models/machine-payment-event.js +18 -0
  365. package/core/server/models/member.js +24 -0
  366. package/core/server/models/settings.js +32 -3
  367. package/core/server/models/user.js +1 -1
  368. package/core/server/services/README.md +30 -0
  369. package/core/server/services/activitypub/activity-pub-service.js +2 -3
  370. package/core/server/services/adapter-manager/base-classes.js +3 -1
  371. package/core/server/services/auth/passwordreset.js +47 -51
  372. package/core/server/services/automations/database-automations-repository.js +19 -3
  373. package/core/server/services/automations/poll.js +2 -8
  374. package/core/server/services/comments/comments-service.js +4 -16
  375. package/core/server/services/comments/index.js +1 -3
  376. package/core/server/services/email-analytics/email-analytics-service-wrapper.js +68 -119
  377. package/core/server/services/email-analytics/email-analytics-service.js +73 -229
  378. package/core/server/services/email-analytics/event-processing-result.js +0 -10
  379. package/core/server/services/email-analytics/fetch-mailgun-events.js +25 -0
  380. package/core/server/services/email-analytics/index.js +35 -67
  381. package/core/server/services/email-analytics/lib/queries.js +88 -51
  382. package/core/server/services/email-analytics/newsletter-email-analytics-batch-processor.js +4 -1
  383. package/core/server/services/email-service/batch-sending-service.js +1 -1
  384. package/core/server/services/email-service/email-event-processor.js +12 -12
  385. package/core/server/services/email-service/events/email-bounced-event.js +8 -46
  386. package/core/server/services/email-service/events/email-delivered-event.js +8 -36
  387. package/core/server/services/email-service/events/email-opened-event.js +8 -36
  388. package/core/server/services/email-service/events/email-temporary-bounced-event.js +8 -46
  389. package/core/server/services/email-service/events/email-unsubscribed-event.js +8 -31
  390. package/core/server/services/email-service/events/spam-complaint-event.js +8 -31
  391. package/core/server/services/email-service/newsletter-email-event-storage.js +8 -7
  392. package/core/server/services/email-service/sending-service.js +1 -1
  393. package/core/server/services/email-suppression-list/mailgun-email-suppression-list.js +2 -2
  394. package/core/server/services/email-suppression-list/service.js +1 -3
  395. package/core/server/services/explore-ping/explore-ping-service.js +1 -6
  396. package/core/server/services/explore-ping/index.js +0 -2
  397. package/core/server/services/gifts/index.js +109 -3
  398. package/core/server/services/gifts/jobs/clean-gifts-job.js +1 -1
  399. package/core/server/services/gifts/jobs/send-gift-reminders-job.js +1 -1
  400. package/core/server/services/jobs-service/index.js +36 -0
  401. package/core/server/services/jobs-service/job.js +6 -0
  402. package/core/server/services/jobs-service/jobs-service.js +91 -0
  403. package/core/server/services/jobs-service/register-job-handlers.js +6 -0
  404. package/core/server/services/lib/mailgun-client.js +1 -1
  405. package/core/server/services/machine-payments/README.md +23 -0
  406. package/core/server/services/machine-payments/adapters/mpp-adapter.js +195 -0
  407. package/core/server/services/machine-payments/content-loader.js +89 -0
  408. package/core/server/services/machine-payments/eligibility.js +6 -0
  409. package/core/server/services/machine-payments/events/machine-payment-event-repository.js +58 -0
  410. package/core/server/services/machine-payments/events/machine-payment-event.js +46 -0
  411. package/core/server/services/machine-payments/index.js +87 -0
  412. package/core/server/services/machine-payments/pricing.js +54 -0
  413. package/core/server/services/machine-payments/service.js +275 -0
  414. package/core/server/services/machine-payments/stripe/deposit-address-store.js +157 -0
  415. package/core/server/services/machine-payments/stripe/payment-recorder.js +85 -0
  416. package/core/server/services/machine-payments/stripe/stripe-client-options.js +25 -0
  417. package/core/server/services/machine-payments/types.js +2 -0
  418. package/core/server/services/members/import-export/csv/parse.js +9 -1
  419. package/core/server/services/members/import-export/import/completion-email.js +61 -27
  420. package/core/server/services/members/import-export/import/email-template.js +28 -15
  421. package/core/server/services/members/import-export/import/importer.js +99 -51
  422. package/core/server/services/members/import-export/import/spool.js +1 -1
  423. package/core/server/services/members/import-export/index.js +24 -1
  424. package/core/server/services/members/members-api/services/member-bread-service.js +2 -2
  425. package/core/server/services/members/members-config-provider.js +12 -2
  426. package/core/server/services/members-custom-fields/actions.js +2 -1
  427. package/core/server/services/members-custom-fields/definitions-service.js +109 -27
  428. package/core/server/services/members-custom-fields/filter.js +199 -0
  429. package/core/server/services/members-custom-fields/key.js +37 -0
  430. package/core/server/services/members-custom-fields/queries.js +15 -0
  431. package/core/server/services/members-custom-fields/schema.js +1 -1
  432. package/core/server/services/members-custom-fields/values-service.js +18 -14
  433. package/core/server/services/members-events/last-seen-at-updater.js +1 -1
  434. package/core/server/services/oembed/oembed-service.js +8 -2
  435. package/core/server/services/permissions/can-this.js +4 -1
  436. package/core/server/services/posts/posts-service.js +18 -16
  437. package/core/server/services/public-config/config.js +1 -1
  438. package/core/server/services/route-settings/dynamic-routing-service.js +2 -0
  439. package/core/server/services/settings-helpers/settings-helpers.js +0 -1
  440. package/core/server/services/stats/posts-stats-service.js +0 -2
  441. package/core/server/services/stripe/stripe-api.js +2 -9
  442. package/core/server/web/api/endpoints/admin/middleware.js +0 -1
  443. package/core/server/web/api/endpoints/admin/routes.js +2 -3
  444. package/core/server/web/comments/routes.js +31 -8
  445. package/core/shared/config/defaults.json +17 -2
  446. package/core/shared/config/loader.js +11 -2
  447. package/core/shared/config/overrides.json +2 -0
  448. package/core/shared/config/secrets.js +71 -0
  449. package/core/shared/labs.js +4 -13
  450. package/core/shared/machine-payments.js +30 -0
  451. package/core/shared/private-site-access/index.js +68 -0
  452. package/package.json +48 -43
  453. package/pnpm-lock.yaml +1412 -1583
  454. package/pnpm-workspace.yaml +85 -48
  455. package/bin/validate-adapters.ts +0 -87
  456. package/components/tryghost-adapter-base-scheduling-0.2.1.tgz +0 -0
  457. package/components/tryghost-adapter-base-sso-0.1.1.tgz +0 -0
  458. package/components/tryghost-kg-card-factory-5.2.3.tgz +0 -0
  459. package/components/tryghost-kg-clean-basic-html-4.3.3.tgz +0 -0
  460. package/components/tryghost-kg-converters-1.2.4.tgz +0 -0
  461. package/components/tryghost-kg-default-cards-10.3.4.tgz +0 -0
  462. package/components/tryghost-kg-default-nodes-2.1.5.tgz +0 -0
  463. package/components/tryghost-kg-default-transforms-1.3.3.tgz +0 -0
  464. package/components/tryghost-kg-html-to-lexical-1.3.3.tgz +0 -0
  465. package/components/tryghost-kg-lexical-html-renderer-1.4.3.tgz +0 -0
  466. package/components/tryghost-kg-markdown-html-renderer-7.2.3.tgz +0 -0
  467. package/components/tryghost-kg-utils-1.1.3.tgz +0 -0
  468. package/content/themes/casper/assets/built/casper.js.map +0 -1
  469. package/content/themes/casper/assets/built/global.css.map +0 -1
  470. package/content/themes/casper/assets/built/screen.css.map +0 -1
  471. package/content/themes/source/assets/built/screen.css.map +0 -1
  472. package/content/themes/source/assets/built/source.js.map +0 -1
  473. package/core/built/admin/assets/activitypub/layout-DM_3pqsU.js +0 -1
  474. package/core/built/admin/assets/add-integration-modal-DU9ghGLS.js +0 -1
  475. package/core/built/admin/assets/add-newsletter-modal-DFxuQrYu.js +0 -1
  476. package/core/built/admin/assets/announcement-bar-modal-DGCcezB6.js +0 -1
  477. package/core/built/admin/assets/card-aUHX0hyR.js +0 -1
  478. package/core/built/admin/assets/chunk.524.dce1c51e0bc30fb2718e.js +0 -25
  479. package/core/built/admin/assets/chunk.582.3a430d5c6a744fd475b6.js +0 -27
  480. package/core/built/admin/assets/code-editor-view-BcyKABrG.js +0 -1
  481. package/core/built/admin/assets/color-picker-field-8NoSnhNI.js +0 -1
  482. package/core/built/admin/assets/command-BOYMbZa_.js +0 -1
  483. package/core/built/admin/assets/comments-BhNM5CYl.js +0 -1
  484. package/core/built/admin/assets/confirmation-modal-CYD7x3UQ.js +0 -1
  485. package/core/built/admin/assets/custom-integration-modal-bk3lNEuQ.js +0 -1
  486. package/core/built/admin/assets/design-and-theme-modal-B2xYKS1I.js +0 -23
  487. package/core/built/admin/assets/dist-Bg8bSvLA.js +0 -6
  488. package/core/built/admin/assets/dist-BnFdlebk.js +0 -11
  489. package/core/built/admin/assets/dist-CsvXCJSe.js +0 -23
  490. package/core/built/admin/assets/editor-BBKrunMK.js +0 -8
  491. package/core/built/admin/assets/filters-Bz0HsRie.js +0 -1
  492. package/core/built/admin/assets/framework-provider-CmtnPXIT.js +0 -4
  493. package/core/built/admin/assets/index-DUXM0NlS.js +0 -67
  494. package/core/built/admin/assets/index-Ds2iUoF6.css +0 -1
  495. package/core/built/admin/assets/label-picker-Bnlru5tO.js +0 -1
  496. package/core/built/admin/assets/layout-yR9rlvEw.js +0 -1
  497. package/core/built/admin/assets/limit-modal-COmLevuY.js +0 -1
  498. package/core/built/admin/assets/limit-service-9fwD33lU.js +0 -20
  499. package/core/built/admin/assets/member-custom-fields-BvFKEpxJ.js +0 -1
  500. package/core/built/admin/assets/member-detail-CWdPAe3p.js +0 -1
  501. package/core/built/admin/assets/members-Bnt0ih2R.js +0 -11
  502. package/core/built/admin/assets/newsletter-DR49NyGS.js +0 -1
  503. package/core/built/admin/assets/newsletter-detail-modal-B45pL1pb.js +0 -1
  504. package/core/built/admin/assets/newsletters-DGs5BaKH.js +0 -1
  505. package/core/built/admin/assets/nql-lang-B7faUf8D.js +0 -19
  506. package/core/built/admin/assets/offers-container-modal-B0hFS8nk.js +0 -1
  507. package/core/built/admin/assets/overview-B-ZPNqMo.js +0 -1
  508. package/core/built/admin/assets/overview-D96iwoJi.js +0 -1
  509. package/core/built/admin/assets/portal-modal-BLFdYeDH.js +0 -1
  510. package/core/built/admin/assets/post-analytics-header-DK27VjJm.js +0 -1
  511. package/core/built/admin/assets/preferences-CuWLISHa.js +0 -5
  512. package/core/built/admin/assets/profile-BsKYYtuL.js +0 -1
  513. package/core/built/admin/assets/settings-B4vM-rgV.js +0 -4
  514. package/core/built/admin/assets/stripe-connect-modal-CYDDrSJm.js +0 -1
  515. package/core/built/admin/assets/tag-detail-CmqiC32L.js +0 -1
  516. package/core/built/admin/assets/tier-detail-modal-BZmAsIy4.js +0 -1
  517. package/core/built/admin/assets/transistor-modal-CBPDqEGy.js +0 -1
  518. package/core/built/admin/assets/use-check-theme-limit-error-B14lZukR.js +0 -2
  519. package/core/built/admin/assets/use-feature-flag-BmJoc5WN.js +0 -1
  520. package/core/built/admin/assets/use-filter-params-ChoV72Hw.js +0 -1
  521. package/core/built/admin/assets/use-limiter-Dwg8ivgQ.js +0 -2
  522. package/core/built/admin/assets/user-detail-modal-XODpOqNC.js +0 -1
  523. package/core/built/admin/assets/virtual-list-Dnoafqbk.js +0 -1
  524. package/core/built/admin/assets/web-z71lA1Y3.js +0 -2
  525. package/core/built/admin/assets/zapier-modal-Bp507Um7.js +0 -1
  526. package/core/frontend/meta/og-type.ts +0 -13
  527. package/core/frontend/services/routing/api-adapter.ts +0 -157
  528. package/core/frontend/services/routing/config.ts +0 -59
  529. package/core/frontend/services/routing/controllers/entry/canonical-url.ts +0 -14
  530. package/core/frontend/services/routing/controllers/entry/gift-links.ts +0 -56
  531. package/core/frontend/services/routing/controllers/entry/markdown.ts +0 -72
  532. package/core/frontend/services/routing/controllers/entry.ts +0 -120
  533. package/core/frontend/services/routing/controllers/rss.ts +0 -66
  534. package/core/frontend/services/routing/permalink-adapter.ts +0 -10
  535. package/core/frontend/src/utils/privacy.ts +0 -66
  536. package/core/server/adapters/redirects/FileStore.ts +0 -113
  537. package/core/server/adapters/redirects/S3RedirectsStore.ts +0 -185
  538. package/core/server/adapters/route-settings/FileStore.ts +0 -144
  539. package/core/server/adapters/route-settings/S3RouteSettingsStore.ts +0 -199
  540. package/core/server/adapters/route-settings/utils.ts +0 -17
  541. package/core/server/adapters/scheduling/deps.d.ts +0 -1
  542. package/core/server/adapters/scheduling/error-capture.ts +0 -91
  543. package/core/server/adapters/scheduling/scheduling-default.ts +0 -248
  544. package/core/server/adapters/scheduling/utils.ts +0 -36
  545. package/core/server/adapters/sso/DefaultSSOAdapter.ts +0 -15
  546. package/core/server/adapters/storage/LocalFilesStorage.ts +0 -24
  547. package/core/server/adapters/storage/LocalImagesStorage.ts +0 -24
  548. package/core/server/adapters/storage/LocalMediaStorage.ts +0 -24
  549. package/core/server/adapters/storage/LocalStorageBase.ts +0 -342
  550. package/core/server/adapters/storage/S3Storage.ts +0 -506
  551. package/core/server/adapters/storage/utils.ts +0 -60
  552. package/core/server/api/endpoints/automation-action-links.ts +0 -46
  553. package/core/server/api/endpoints/explore.js +0 -18
  554. package/core/server/api/endpoints/gift-links.ts +0 -87
  555. package/core/server/api/endpoints/libraries.d.ts +0 -2
  556. package/core/server/api/endpoints/member-commenting.ts +0 -92
  557. package/core/server/api/endpoints/member-custom-fields.ts +0 -106
  558. package/core/server/api/endpoints/utils/api-filter-utils.ts +0 -22
  559. package/core/server/api/endpoints/utils/gift-link-access.ts +0 -82
  560. package/core/server/api/endpoints/utils/public-cache-keys.ts +0 -47
  561. package/core/server/api/endpoints/utils/serializers/input/member-commenting.ts +0 -29
  562. package/core/server/api/endpoints/utils/serializers/output/explore.js +0 -11
  563. package/core/server/api/endpoints/utils/serializers/output/gift-links.ts +0 -21
  564. package/core/server/api/endpoints/utils/serializers/output/member-commenting.ts +0 -8
  565. package/core/server/api/endpoints/utils/serializers/output/member-custom-fields.ts +0 -25
  566. package/core/server/api/endpoints/utils/serializers/output/members.d.ts +0 -20
  567. package/core/server/api/endpoints/utils/serializers/output/posts-csv-transform.ts +0 -46
  568. package/core/server/api/endpoints/utils/serializers/output/stream-csv-response.ts +0 -47
  569. package/core/server/api/endpoints/utils/validate-email-sender-fields.ts +0 -42
  570. package/core/server/data/importer/email-template.ts +0 -213
  571. package/core/server/data/seeders/utils/topological-sort.ts +0 -48
  572. package/core/server/lib/auto-filling-map.ts +0 -23
  573. package/core/server/lib/bootstrap-socket.ts +0 -114
  574. package/core/server/lib/case-keys.ts +0 -30
  575. package/core/server/lib/common/to-plain.ts +0 -25
  576. package/core/server/lib/db-date.ts +0 -8
  577. package/core/server/lib/get-inbox-links.ts +0 -276
  578. package/core/server/lib/post-revisions.ts +0 -152
  579. package/core/server/lib/soonest-timer.ts +0 -57
  580. package/core/server/models/base/plugins/bulk-filters.ts +0 -35
  581. package/core/server/models/role-utils.ts +0 -56
  582. package/core/server/services/activitypub/activity-pub-service.ts +0 -216
  583. package/core/server/services/adapter-manager/adapter-manager.ts +0 -253
  584. package/core/server/services/adapter-manager/adapter-paths.ts +0 -26
  585. package/core/server/services/adapter-manager/base-classes.ts +0 -22
  586. package/core/server/services/adapter-manager/index.ts +0 -16
  587. package/core/server/services/adapter-manager/types.ts +0 -45
  588. package/core/server/services/adapter-manager/utils.ts +0 -308
  589. package/core/server/services/auth/reset-authentication.ts +0 -72
  590. package/core/server/services/automations/automations-api.ts +0 -396
  591. package/core/server/services/automations/automations-repository.ts +0 -218
  592. package/core/server/services/automations/constants.ts +0 -4
  593. package/core/server/services/automations/database-automations-repository.ts +0 -1513
  594. package/core/server/services/automations/database-date.ts +0 -26
  595. package/core/server/services/automations/fake-wait-hours-multiplier.ts +0 -12
  596. package/core/server/services/automations/get-scheduler-idempotency-key.ts +0 -8
  597. package/core/server/services/automations/mailgun-message-id.ts +0 -27
  598. package/core/server/services/automations/poll.ts +0 -325
  599. package/core/server/services/automations/scheduler-poll-time.ts +0 -38
  600. package/core/server/services/automations/service.ts +0 -131
  601. package/core/server/services/automations/stale-lock-cutoff.ts +0 -5
  602. package/core/server/services/comments/email-templates/new-comment-reply.txt.ts +0 -25
  603. package/core/server/services/comments/email-templates/new-comment.txt.ts +0 -25
  604. package/core/server/services/comments/email-templates/report.txt.ts +0 -34
  605. package/core/server/services/custom-redirects/redirect-config-parser.ts +0 -148
  606. package/core/server/services/custom-redirects/redirects-service.ts +0 -181
  607. package/core/server/services/custom-redirects/utils.ts +0 -7
  608. package/core/server/services/donations/donation-bookshelf-repository.ts +0 -63
  609. package/core/server/services/donations/donation-payment-event.ts +0 -51
  610. package/core/server/services/email-address/email-address-parser.d.ts +0 -12
  611. package/core/server/services/email-address/email-address-service.ts +0 -241
  612. package/core/server/services/email-analytics/automation-email-analytics-batch-processor.ts +0 -130
  613. package/core/server/services/email-analytics/batch-event-processor.ts +0 -18
  614. package/core/server/services/email-analytics/email-analytics-provider-mailgun.js +0 -57
  615. package/core/server/services/email-analytics/event-processing-result.ts +0 -66
  616. package/core/server/services/email-analytics/events/start-automation-email-analytics-job-event.ts +0 -14
  617. package/core/server/services/email-analytics/events/start-email-analytics-job-event.ts +0 -15
  618. package/core/server/services/email-analytics/index.ts +0 -109
  619. package/core/server/services/email-analytics/jobs/email-analytics-job-scheduler.ts +0 -126
  620. package/core/server/services/email-analytics/lib/queries.ts +0 -341
  621. package/core/server/services/email-service/domain-warming-service.ts +0 -91
  622. package/core/server/services/explore/explore-service.js +0 -59
  623. package/core/server/services/explore/index.js +0 -18
  624. package/core/server/services/explore-ping/explore-ping-service.ts +0 -198
  625. package/core/server/services/explore-ping/index.ts +0 -42
  626. package/core/server/services/files/file-type-utils.ts +0 -56
  627. package/core/server/services/gift-links/actions.ts +0 -51
  628. package/core/server/services/gift-links/codec.ts +0 -16
  629. package/core/server/services/gift-links/index.ts +0 -20
  630. package/core/server/services/gift-links/models.ts +0 -22
  631. package/core/server/services/gift-links/schema.ts +0 -33
  632. package/core/server/services/gift-links/serializers.ts +0 -20
  633. package/core/server/services/gift-links/service.ts +0 -95
  634. package/core/server/services/gifts/constants.ts +0 -3
  635. package/core/server/services/gifts/email-templates/gift-purchase-confirmation.ts +0 -43
  636. package/core/server/services/gifts/email-templates/gift-reminder.ts +0 -50
  637. package/core/server/services/gifts/gift-bookshelf-repository.ts +0 -366
  638. package/core/server/services/gifts/gift-checkout-offer.ts +0 -127
  639. package/core/server/services/gifts/gift-codec.ts +0 -62
  640. package/core/server/services/gifts/gift-controller.ts +0 -51
  641. package/core/server/services/gifts/gift-email-renderer.ts +0 -97
  642. package/core/server/services/gifts/gift-email-service.ts +0 -158
  643. package/core/server/services/gifts/gift-reminder-scheduler.ts +0 -107
  644. package/core/server/services/gifts/gift-schema.ts +0 -39
  645. package/core/server/services/gifts/gift-service-wrapper.js +0 -142
  646. package/core/server/services/gifts/gift-service.ts +0 -1034
  647. package/core/server/services/gifts/gift.ts +0 -234
  648. package/core/server/services/identity-tokens/identity-token-service.ts +0 -36
  649. package/core/server/services/indexnow-ping/constants.ts +0 -32
  650. package/core/server/services/indexnow-ping/index.ts +0 -35
  651. package/core/server/services/indexnow-ping/indexnow-ping-service.ts +0 -311
  652. package/core/server/services/internal-keys/index.ts +0 -53
  653. package/core/server/services/lib/dynamic-redirect-manager.d.ts +0 -20
  654. package/core/server/services/lib/in-memory-repository.ts +0 -78
  655. package/core/server/services/lib/member-signup-contexts.ts +0 -22
  656. package/core/server/services/link-redirection/link-redirect.ts +0 -24
  657. package/core/server/services/member-welcome-emails/constants.ts +0 -35
  658. package/core/server/services/members/commenting/index.ts +0 -2
  659. package/core/server/services/members/commenting/member-commenting-codec.ts +0 -73
  660. package/core/server/services/members/commenting/member-commenting.ts +0 -69
  661. package/core/server/services/members/create-paid-member-shim.ts +0 -40
  662. package/core/server/services/members/import-export/config.ts +0 -34
  663. package/core/server/services/members/import-export/csv/formula.ts +0 -14
  664. package/core/server/services/members/import-export/csv/index.ts +0 -3
  665. package/core/server/services/members/import-export/csv/parse.ts +0 -69
  666. package/core/server/services/members/import-export/csv/serialize.ts +0 -18
  667. package/core/server/services/members/import-export/export/exporter.ts +0 -325
  668. package/core/server/services/members/import-export/import/completion-email.ts +0 -146
  669. package/core/server/services/members/import-export/import/importer.ts +0 -489
  670. package/core/server/services/members/import-export/import/reader.ts +0 -33
  671. package/core/server/services/members/import-export/import/row.ts +0 -56
  672. package/core/server/services/members/import-export/import/spool.ts +0 -38
  673. package/core/server/services/members/import-export/index.ts +0 -143
  674. package/core/server/services/members/index.d.ts +0 -32
  675. package/core/server/services/members-custom-fields/actions.ts +0 -62
  676. package/core/server/services/members-custom-fields/codec.ts +0 -13
  677. package/core/server/services/members-custom-fields/config.ts +0 -38
  678. package/core/server/services/members-custom-fields/definitions-service.ts +0 -413
  679. package/core/server/services/members-custom-fields/index.ts +0 -50
  680. package/core/server/services/members-custom-fields/models.ts +0 -15
  681. package/core/server/services/members-custom-fields/queries.ts +0 -13
  682. package/core/server/services/members-custom-fields/schema.ts +0 -71
  683. package/core/server/services/members-custom-fields/serializers.ts +0 -22
  684. package/core/server/services/members-custom-fields/storage.ts +0 -122
  685. package/core/server/services/members-custom-fields/values-service.ts +0 -269
  686. package/core/server/services/notifications/notification-email.ts +0 -66
  687. package/core/server/services/notifications/sanitize-email-html.ts +0 -35
  688. package/core/server/services/post-scheduling/index.ts +0 -13
  689. package/core/server/services/post-scheduling/post-scheduling.ts +0 -133
  690. package/core/server/services/recommendations/service/bookshelf-click-event-repository.ts +0 -49
  691. package/core/server/services/recommendations/service/bookshelf-recommendation-repository.ts +0 -117
  692. package/core/server/services/recommendations/service/bookshelf-repository.ts +0 -192
  693. package/core/server/services/recommendations/service/bookshelf-subscribe-event-repository.ts +0 -49
  694. package/core/server/services/recommendations/service/click-event.ts +0 -32
  695. package/core/server/services/recommendations/service/in-memory-recommendation-repository.ts +0 -20
  696. package/core/server/services/recommendations/service/incoming-recommendation-controller.ts +0 -51
  697. package/core/server/services/recommendations/service/incoming-recommendation-email-renderer.ts +0 -37
  698. package/core/server/services/recommendations/service/incoming-recommendation-service.ts +0 -159
  699. package/core/server/services/recommendations/service/index.ts +0 -15
  700. package/core/server/services/recommendations/service/libraries.d.ts +0 -2
  701. package/core/server/services/recommendations/service/recommendation-controller.ts +0 -257
  702. package/core/server/services/recommendations/service/recommendation-metadata-service.ts +0 -132
  703. package/core/server/services/recommendations/service/recommendation-repository.ts +0 -13
  704. package/core/server/services/recommendations/service/recommendation-service.ts +0 -285
  705. package/core/server/services/recommendations/service/recommendation.ts +0 -200
  706. package/core/server/services/recommendations/service/subscribe-event.ts +0 -32
  707. package/core/server/services/recommendations/service/unsafe-data.ts +0 -217
  708. package/core/server/services/recommendations/service/well-known-service.ts +0 -47
  709. package/core/server/services/remote-flags/index.ts +0 -101
  710. package/core/server/services/remote-flags/remote-flags-service.ts +0 -236
  711. package/core/server/services/remote-flags/resolve.ts +0 -108
  712. package/core/server/services/route-settings/route-settings-parser.ts +0 -455
  713. package/core/server/services/route-settings/validation-errors.ts +0 -271
  714. package/core/server/services/route-settings/yaml-parser.d.ts +0 -4
  715. package/core/server/services/slack-ping/constants.ts +0 -15
  716. package/core/server/services/slack-ping/index.ts +0 -35
  717. package/core/server/services/slack-ping/slack-ping-service.ts +0 -295
  718. package/core/server/services/staff/email-templates/donation.txt.ts +0 -26
  719. package/core/server/services/staff/email-templates/gift.txt.ts +0 -27
  720. package/core/server/services/staff/email-templates/new-free-signup.txt.ts +0 -15
  721. package/core/server/services/staff/email-templates/new-gift-subscription.txt.ts +0 -26
  722. package/core/server/services/staff/email-templates/new-milestone-received.txt.ts +0 -20
  723. package/core/server/services/staff/email-templates/new-paid-cancellation.txt.ts +0 -15
  724. package/core/server/services/staff/email-templates/new-paid-started.txt.ts +0 -15
  725. package/core/server/services/staff/email-templates/recommendation-received.txt.ts +0 -23
  726. package/core/server/services/staff/email-templates/types.ts +0 -13
  727. package/core/server/services/url/lazy-find-resource.ts +0 -104
  728. package/core/server/services/url/lazy-url-service.ts +0 -647
  729. package/core/server/services/url/permalink-matcher.ts +0 -119
  730. package/core/server/services/url/router-filter.ts +0 -80
  731. package/core/server/services/verification/verification-webhook-service.ts +0 -137
  732. package/core/shared/config/helpers.ts +0 -133
  733. package/core/shared/config/index.ts +0 -12
  734. package/core/shared/config/loader.ts +0 -87
  735. package/core/shared/config/utils.ts +0 -104
  736. package/core/shared/errify.ts +0 -31
  737. package/core/shared/events-ts/index.ts +0 -8
  738. package/core/shared/events-ts/post-deleted-event.ts +0 -15
  739. package/core/shared/events-ts/posts-bulk-add-tags-event.ts +0 -13
  740. package/core/shared/events-ts/posts-bulk-destroyed-event.ts +0 -13
  741. package/core/shared/events-ts/posts-bulk-featured-event.ts +0 -13
  742. package/core/shared/events-ts/posts-bulk-unfeatured-event.ts +0 -13
  743. package/core/shared/events-ts/posts-bulk-unpublished-event.ts +0 -13
  744. package/core/shared/events-ts/posts-bulk-unscheduled-event.ts +0 -13
  745. package/core/shared/labs-flag-overrides.ts +0 -35
  746. package/core/shared/one-at-a-time.ts +0 -47
  747. package/core/shared/url-utils.ts +0 -20
@@ -1,647 +0,0 @@
1
- const debug = require('@tryghost/debug')('services:url:lazy');
2
- const errors = require('@tryghost/errors');
3
- const logging = require('@tryghost/logging');
4
- const localUtils = require('../../../shared/url-utils').default;
5
- const {matchPermalink, toLookupParams} = require('./permalink-matcher');
6
- const {buildFilter, filterMatches, routerTypeOf} = require('./router-filter');
7
- const {fetchRoutableResources: defaultFetchRoutableResources} = require('./routable-resources');
8
- const urlConfig = require('./config');
9
-
10
- import type {CompiledFilter} from './router-filter';
11
- import type {PermalinkParams} from './permalink-matcher';
12
-
13
- /**
14
- * Routing-level resource. `type` is one of the plural router keys
15
- * ('posts', 'pages', 'tags', 'authors'). Concrete records carry additional
16
- * fields (slug, published_at, primary_tag, ...) read by the permalink
17
- * templates and router filters.
18
- */
19
- export interface Resource {
20
- type: string;
21
- id: string;
22
- [key: string]: unknown;
23
- }
24
-
25
- export interface UrlOptions {
26
- absolute?: boolean;
27
- withSubdirectory?: boolean;
28
- // Diagnostic only: the producing api endpoint and the fetch shape its
29
- // input serializer settled on, threaded from the output serializer so a
30
- // thin-resource report names what under-fetched. Ignored by URL
31
- // generation; read only into that report.
32
- serializerContext?: {
33
- apiType?: string;
34
- docName?: string;
35
- method?: string;
36
- withRelated?: unknown;
37
- columns?: unknown;
38
- forcedUrlRelations?: unknown;
39
- };
40
- }
41
-
42
- /**
43
- * On-demand enumeration of the routable rows of a type. Injectable so tests
44
- * can drive `getRoutableResources` without a database.
45
- */
46
- export type FetchRoutableResources = (
47
- type: string,
48
- options: {columns?: string[]; requiredFields?: string[]; requiredRelations?: string[]}
49
- ) => Promise<Array<Record<string, unknown>>>;
50
-
51
- export type ResourceLookupParams = {id: string} | {slug: string};
52
-
53
- export type FindResource = (
54
- routerType: string,
55
- params: ResourceLookupParams
56
- ) => Promise<Record<string, unknown> | null>;
57
-
58
- interface RouterConfig {
59
- identifier: string;
60
- filter: string | null;
61
- resourceType: string;
62
- permalink: string;
63
- compiledFilter: CompiledFilter | null;
64
- }
65
-
66
- // Per-resource-type gate on which rows get a URL at all — the forward-lookup
67
- // counterpart of the fetch filters in routable-resources.js. `fields` lists
68
- // the record columns each filter reads; a resource that reaches URL generation
69
- // must carry them (see _missingBaseFields).
70
- //
71
- // Authors are intentionally absent: users.visibility is schema-pinned to
72
- // 'public' (isIn: [['public']]), so the visibility:public author filter never
73
- // excludes anyone — every author is routable, and serialized authors drop
74
- // visibility anyway (#10438).
75
- const BASE_FILTERS: Record<string, {filter: string; fields: string[]}> = {
76
- posts: {filter: 'status:published+type:post', fields: ['status', 'type']},
77
- pages: {filter: 'status:published+type:page', fields: ['status', 'type']},
78
- tags: {filter: 'visibility:public', fields: ['visibility']}
79
- };
80
-
81
- interface BaseFilter {
82
- filter: string;
83
- compiledFilter: CompiledFilter;
84
- fields: string[];
85
- }
86
-
87
- // Why a resource could not be routed: the columns it was missing, and which
88
- // filter needed them. Reported, then degraded to /404/.
89
- interface ThinResource {
90
- resourceType: string;
91
- missing: string[];
92
- baseFilter?: string;
93
- routerIdentifier?: string;
94
- filter?: string | null;
95
- }
96
-
97
- function buildBaseFilters(): Map<string, BaseFilter> {
98
- const baseFilters = new Map<string, BaseFilter>();
99
- for (const [type, {filter, fields}] of Object.entries(BASE_FILTERS)) {
100
- const compiledFilter = buildFilter(filter);
101
- if (compiledFilter) {
102
- baseFilters.set(type, {filter, compiledFilter, fields});
103
- }
104
- }
105
- return baseFilters;
106
- }
107
-
108
- // Columns a router filter must not see (the `exclude` lists in
109
- // services/url/config.js), keyed by resourceType. Ghost previously answered
110
- // URLs from a precomputed cache that dropped these columns, so a filter
111
- // referencing one matched it as absent — NQL reads absent as null. This
112
- // service loads full records and would see the real value, so it strips them
113
- // before evaluating router filters (and neither requires nor force-loads
114
- // them), keeping routes.yaml files that rely on that behaviour working. The
115
- // base filter above is unaffected — it runs against the full record.
116
- function buildExcludedFilterFields(): Map<string, Set<string>> {
117
- const excluded = new Map<string, Set<string>>();
118
- for (const entry of urlConfig) {
119
- const exclude = entry?.exclude;
120
- if (Array.isArray(exclude)) {
121
- excluded.set(entry.type, new Set(exclude));
122
- }
123
- }
124
- return excluded;
125
- }
126
-
127
- const EMPTY_FIELD_SET: ReadonlySet<string> = new Set();
128
-
129
- // 1, 10, 100, ... — exact for integers, unlike a log10 comparison.
130
- function isPowerOfTen(n: number): boolean {
131
- let power = 1;
132
- while (power < n) {
133
- power *= 10;
134
- }
135
- return power === n;
136
- }
137
-
138
- // Relation roots are loaded via getRequiredRelations (as withRelated), not as
139
- // scalar columns; `page`/`type` are the router-type discriminator, always set
140
- // on the resource. Everything else a router filter references is a scalar
141
- // own-column the resource must carry to be routed.
142
- const FILTER_NON_SCALAR_FIELDS = new Set([
143
- 'tag', 'tags', 'author', 'authors', 'primary_tag', 'primary_author', 'page', 'type'
144
- ]);
145
-
146
- // Scalar (own-column) fields a router filter reads, e.g. 'featured' from
147
- // 'featured:true'. Dotted clauses (e.g. tags.visibility) are relation
148
- // sub-fields and skipped — getRequiredRelations loads those relations.
149
- //
150
- // Only field names at an NQL expression boundary (start of the filter, or after
151
- // a `+`/`,`/`(` combinator) are matched, so colon-bearing values — URLs,
152
- // timestamps like 2020-01-01T00:00:00 — aren't mistaken for fields.
153
- function filterScalarFields(filter: string | null): string[] {
154
- if (!filter) {
155
- return [];
156
- }
157
- const fields = new Set<string>();
158
- const matcher = /(?:^|[+,(])\s*(\w+)(\.\w+)?:/g;
159
- let match;
160
- while ((match = matcher.exec(filter)) !== null) {
161
- const [, root, sub] = match;
162
- if (sub || FILTER_NON_SCALAR_FIELDS.has(root)) {
163
- continue;
164
- }
165
- fields.add(root);
166
- }
167
- return [...fields];
168
- }
169
-
170
- interface LazyUrlServiceDeps {
171
- urlUtils?: typeof localUtils;
172
- findResource: FindResource;
173
- fetchRoutableResources?: FetchRoutableResources;
174
- }
175
-
176
- const ROUTER_TYPE_TO_DB_TYPE: Record<string, string> = {posts: 'post', pages: 'page'};
177
-
178
- /**
179
- * Ghost's URL service: computes URLs and ownership per call from the
180
- * registered router configs. Forward lookups are pure; resolveUrl and
181
- * getRoutableResources are the only DB-touching paths, and only through the
182
- * injected findResource / fetchRoutableResources hooks.
183
- */
184
- export class LazyUrlService {
185
- private urlUtils: typeof localUtils;
186
- private findResource: FindResource;
187
- private fetchRoutableResources: FetchRoutableResources;
188
- // Router configs in registration order, which is also their priority.
189
- private routerConfigs: RouterConfig[];
190
- private requiredRelations: string[] | null;
191
- private baseFilters: Map<string, BaseFilter>;
192
- private excludedFilterFields: Map<string, Set<string>>;
193
- // True once routers have been registered. Cleared by reset() so the
194
- // route-reload window re-gates the maintenance middleware.
195
- private routersReady: boolean;
196
- // How many times each thin-resource cause has been seen — see
197
- // _degradeThinResource.
198
- private reportedThinResources: Map<string, number>;
199
-
200
- constructor({
201
- urlUtils = localUtils,
202
- findResource,
203
- fetchRoutableResources = defaultFetchRoutableResources
204
- }: LazyUrlServiceDeps) {
205
- if (typeof findResource !== 'function') {
206
- throw new errors.IncorrectUsageError({
207
- message: 'LazyUrlService requires a findResource function'
208
- });
209
- }
210
- this.urlUtils = urlUtils;
211
- this.findResource = findResource;
212
- this.fetchRoutableResources = fetchRoutableResources;
213
- this.routerConfigs = [];
214
- this.requiredRelations = null;
215
- this.baseFilters = buildBaseFilters();
216
- this.excludedFilterFields = buildExcludedFilterFields();
217
- this.routersReady = false;
218
- this.reportedThinResources = new Map();
219
- }
220
-
221
- onRouterAddedType(identifier: string, filter: string | null, resourceType: string, permalink: string): void {
222
- debug('onRouterAddedType', identifier, resourceType, permalink, filter);
223
- this.routerConfigs.push({
224
- identifier,
225
- filter,
226
- resourceType,
227
- permalink,
228
- compiledFilter: buildFilter(filter)
229
- });
230
- this.requiredRelations = null;
231
- this.routersReady = true;
232
- }
233
-
234
- onRouterUpdated(): void {
235
- // Defensive: a router update could change a filter the cache derived
236
- // from, so drop it and recompute lazily on next read.
237
- this.requiredRelations = null;
238
- }
239
-
240
- reset(): void {
241
- this.routerConfigs = [];
242
- this.requiredRelations = null;
243
- this.routersReady = false;
244
- this.reportedThinResources.clear();
245
- }
246
-
247
- getRequiredRelations(): string[] {
248
- if (this.requiredRelations !== null) {
249
- return [...this.requiredRelations];
250
- }
251
- const required = new Set<string>();
252
- for (const config of this.routerConfigs) {
253
- if (config.filter) {
254
- if (/\btags?\b/.test(config.filter) || /\bprimary_tag\b/.test(config.filter)) {
255
- required.add('tags');
256
- }
257
- if (/\bauthors?\b/.test(config.filter) || /\bprimary_author\b/.test(config.filter)) {
258
- required.add('authors');
259
- }
260
- }
261
- if (config.permalink) {
262
- if (/\bprimary_tag\b/.test(config.permalink)) {
263
- required.add('tags');
264
- }
265
- if (/\bprimary_author\b/.test(config.permalink)) {
266
- required.add('authors');
267
- }
268
- }
269
- }
270
- this.requiredRelations = [...required];
271
- return [...this.requiredRelations];
272
- }
273
-
274
- // Columns a resource of this type must carry for the service to build
275
- // its URL: its base-filter columns plus the scalar columns its routers'
276
- // permalinks substitute and filters read. Relations are covered separately
277
- // by getRequiredRelations.
278
- getRequiredFields(routerType: string): string[] {
279
- const fields = new Set<string>();
280
- const excluded = this._excludedFilterFieldsFor(routerType);
281
- const base = this.baseFilters.get(routerType);
282
- if (base) {
283
- base.fields.forEach(field => fields.add(field));
284
- }
285
- for (const config of this.routerConfigs) {
286
- if (config.resourceType !== routerType) {
287
- continue;
288
- }
289
- if (/\bslug\b/.test(config.permalink)) {
290
- fields.add('slug');
291
- }
292
- if (/\bid\b/.test(config.permalink)) {
293
- fields.add('id');
294
- }
295
- if (/\b(year|month|day)\b/.test(config.permalink)) {
296
- fields.add('published_at');
297
- }
298
- // primary_tag/primary_author are computed attributes the model
299
- // only attaches when `options.columns` names them, so they must
300
- // be forced like scalar columns — the tags/authors relations
301
- // (via getRequiredRelations) alone don't surface them on a
302
- // `?fields=url` query.
303
- for (const computed of ['primary_tag', 'primary_author'] as const) {
304
- if (new RegExp(`\\b${computed}\\b`).test(config.permalink) ||
305
- (config.filter && new RegExp(`\\b${computed}\\b`).test(config.filter))) {
306
- fields.add(computed);
307
- }
308
- }
309
- // Skip the columns a router filter must not see: their filters are
310
- // evaluated against an absent value, so requiring them would
311
- // force-load a column that can't affect the result (see
312
- // buildExcludedFilterFields).
313
- filterScalarFields(config.filter).forEach((field) => {
314
- if (!excluded.has(field)) {
315
- fields.add(field);
316
- }
317
- });
318
- }
319
- return [...fields];
320
- }
321
-
322
- hasFinished(): boolean {
323
- return this.routersReady;
324
- }
325
-
326
- /**
327
- * All routable rows of a type. The columns URL computation needs come
328
- * from the active routing config, so the rows are never thin for it;
329
- * callers name any extra columns they want back.
330
- */
331
- async getRoutableResources(type: string, {columns = []}: {columns?: string[]} = {}): Promise<Array<Record<string, unknown>>> {
332
- return this.fetchRoutableResources(type, {
333
- columns,
334
- requiredFields: this.getRequiredFields(type),
335
- requiredRelations: this.getRequiredRelations()
336
- });
337
- }
338
-
339
- /**
340
- * A thin resource — one missing a column its base filter or a router
341
- * filter reads — is a caller bug: we cannot tell whether it routes. It is
342
- * reported and degraded to /404/ rather than thrown, because 500ing a page
343
- * that does route is worse than a 404 on one that may not.
344
- */
345
- getUrlForResource(resource: Resource, options: UrlOptions = {}): string {
346
- const routerType = routerTypeOf(resource);
347
- if (!routerType) {
348
- return this.notFoundUrl(options);
349
- }
350
-
351
- const record = this._recordForFilter(resource);
352
- // The router (collection) filter is evaluated against the reduced
353
- // column set (see buildExcludedFilterFields); the base filter keeps the
354
- // full record, since it reads status / type / visibility.
355
- const filterRecord = this._recordForRouterFilter(record, routerType);
356
-
357
- // Only resources that pass the per-type base filter (visibility:public
358
- // tags, status:published posts) get a URL. Checked only when a router
359
- // for the type exists, since otherwise the resource 404s regardless.
360
- if (this._hasRouterForType(routerType)) {
361
- const missing = this._missingBaseFields(routerType, resource);
362
- if (missing) {
363
- return this._degradeThinResource(resource, missing, options);
364
- }
365
- if (!this._baseFilterMatches(routerType, record)) {
366
- return this.notFoundUrl(options);
367
- }
368
- }
369
-
370
- for (const config of this.routerConfigs) {
371
- if (config.resourceType !== routerType) {
372
- continue;
373
- }
374
- const missing = this._missingRouterFields(config, resource, routerType);
375
- if (missing) {
376
- return this._degradeThinResource(resource, missing, options);
377
- }
378
- if (filterMatches(config.compiledFilter, filterRecord)) {
379
- const path = this.urlUtils.replacePermalink(config.permalink, resource);
380
- return this._formatPath(path, options);
381
- }
382
- }
383
- return this.notFoundUrl(options);
384
- }
385
-
386
- ownsResource(routerIdentifier: string, resource: Resource | null): boolean {
387
- if (!resource) {
388
- return false;
389
- }
390
- const routerType = routerTypeOf(resource);
391
- if (!routerType) {
392
- return false;
393
- }
394
- // A resource failing its base filter has no URL, so no router owns it.
395
- // Mirrors the base-filter gate in getUrlForResource.
396
- const record = this._recordForFilter(resource);
397
- if (!this._baseFilterMatches(routerType, record)) {
398
- return false;
399
- }
400
- const filterRecord = this._recordForRouterFilter(record, routerType);
401
- // Ownership is exclusive: only the first matching router of the type
402
- // owns the resource.
403
- const owner = this.routerConfigs.find(
404
- c => c.resourceType === routerType && filterMatches(c.compiledFilter, filterRecord)
405
- );
406
- return !!owner && owner.identifier === routerIdentifier;
407
- }
408
-
409
- async resolveUrl(urlPath: string): Promise<Resource | null> {
410
- // Memoize per call so routers sharing a resourceType+permalink shape (or
411
- // fallthrough across filters) don't repeat the same DB lookup.
412
- const lookupCache = new Map<string, Record<string, unknown> | null>();
413
- for (const config of this.routerConfigs) {
414
- const params = matchPermalink(config.permalink, urlPath);
415
- if (!params) {
416
- continue;
417
- }
418
- // matchPermalink only matches permalinks that capture a queryable
419
- // column, so this always yields a usable lookup.
420
- const lookupParams = toLookupParams(params);
421
- const cacheKey = `${config.resourceType}:${JSON.stringify(lookupParams)}`;
422
- let resource: Record<string, unknown> | null;
423
- if (lookupCache.has(cacheKey)) {
424
- resource = lookupCache.get(cacheKey) ?? null;
425
- } else {
426
- resource = await this.findResource(config.resourceType, lookupParams);
427
- lookupCache.set(cacheKey, resource);
428
- }
429
- if (!resource) {
430
- continue;
431
- }
432
- // Normalize the same way the forward paths do so page: filters are
433
- // evaluated against an identical shape regardless of findResource.
434
- // The base filter is enforced upstream by findResource's query
435
- // scoping (visibility:public / status:published), so only the
436
- // router filter needs re-checking here.
437
- const record = this._recordForRouterFilter(
438
- this._recordForFilter(resource as Resource),
439
- config.resourceType
440
- );
441
- if (!filterMatches(config.compiledFilter, record)) {
442
- continue;
443
- }
444
- if (!this._matchesCanonicalUrl(config, params, resource)) {
445
- continue;
446
- }
447
- return Object.assign({}, resource, {type: config.resourceType}) as Resource;
448
- }
449
- return null;
450
- }
451
-
452
- // Only a URL that equals the resource's own generated (canonical) URL
453
- // resolves, so we regenerate the record's URL for this permalink and
454
- // confirm the captured params match it. Without this, derived/relation
455
- // segments the query can't filter on (year/month, primary_tag) would
456
- // resolve any slug, 200-ing a URL that has no page.
457
- private _matchesCanonicalUrl(config: RouterConfig, params: PermalinkParams, resource: Record<string, unknown>): boolean {
458
- const canonicalPath = this.urlUtils.replacePermalink(config.permalink, resource);
459
- const canonicalParams = matchPermalink(config.permalink, canonicalPath);
460
- if (!canonicalParams) {
461
- return false;
462
- }
463
- const captured = params as Record<string, string>;
464
- const canonical = canonicalParams as Record<string, string>;
465
- return Object.keys(captured).every(key => canonical[key] === captured[key]);
466
- }
467
-
468
- // Reports which columns were missing alongside what the caller handed over
469
- // — the resource's shape, and what the active routing config needs — so
470
- // the fetch that under-fetched can be found from the log line alone.
471
- //
472
- // Reported on the first occurrence of each distinct cause, then at each
473
- // order of magnitude. A caller that under-fetches does so for every row it
474
- // serializes, so a browse over a large collection would otherwise emit one
475
- // error per row — but reporting only once would hide that the problem is
476
- // still happening, and how widely. `occurrences` carries that instead.
477
- // Cleared on reset(), since a new routing config can make a previously
478
- // thin resource fine (or newly broken).
479
- private _degradeThinResource(resource: Resource, thin: ThinResource, options: UrlOptions): string {
480
- const producedBy = options.serializerContext;
481
- // The producer is part of the key: two endpoints under-fetching the
482
- // same way are two bugs, and the endpoint set is small enough that
483
- // this cannot flood.
484
- const key = [
485
- thin.resourceType,
486
- thin.routerIdentifier ?? '',
487
- thin.missing.join(','),
488
- producedBy ? `${producedBy.apiType}:${producedBy.docName}:${producedBy.method}` : ''
489
- ].join('|');
490
- const occurrences = (this.reportedThinResources.get(key) ?? 0) + 1;
491
- this.reportedThinResources.set(key, occurrences);
492
- if (!isPowerOfTen(occurrences)) {
493
- return this.notFoundUrl(options);
494
- }
495
-
496
- logging.error(new errors.InternalServerError({
497
- message: 'URL service could not build a URL, degraded to /404/',
498
- code: 'LAZY_URL_RESOLUTION_ERROR',
499
- errorDetails: {
500
- method: 'getUrlForResource',
501
- type: resource.type,
502
- id: resource.id,
503
- status: (resource as Record<string, unknown>).status,
504
- resourceKeys: Object.keys(resource),
505
- requiredRelations: this.getRequiredRelations(),
506
- occurrences,
507
- ...(producedBy ? {serializer: producedBy} : {}),
508
- ...thin
509
- }
510
- }));
511
- return this.notFoundUrl(options);
512
- }
513
-
514
- private _hasRouterForType(routerType: string): boolean {
515
- return this.routerConfigs.some(config => config.resourceType === routerType);
516
- }
517
-
518
- private _baseFilterMatches(routerType: string, record: Record<string, unknown>): boolean {
519
- const base = this.baseFilters.get(routerType);
520
- if (!base) {
521
- return true;
522
- }
523
- return filterMatches(base.compiledFilter, record);
524
- }
525
-
526
- // A resource that reaches URL generation must carry the columns its base
527
- // filter reads (status for posts/pages, visibility for tags) — production
528
- // callers always do, via full models or the serializers' force-load.
529
- // Without them the filter can't be evaluated at all, so we cannot tell a
530
- // genuine miss from a caller that under-fetched.
531
- private _missingBaseFields(routerType: string, resource: Resource): ThinResource | null {
532
- const base = this.baseFilters.get(routerType);
533
- if (!base) {
534
- return null;
535
- }
536
- const r = resource as Record<string, unknown>;
537
- const missing = base.fields.filter(field => r[field] === undefined);
538
- if (missing.length === 0) {
539
- return null;
540
- }
541
- return {resourceType: routerType, baseFilter: base.filter, missing};
542
- }
543
-
544
- // Normalizes the plural router type to the singular DB value for filter
545
- // evaluation only, so `page:` filters in routes.yaml match.
546
- private _recordForFilter(resource: Resource): Record<string, unknown> {
547
- const record = resource as Record<string, unknown>;
548
- const dbType = ROUTER_TYPE_TO_DB_TYPE[record.type as string];
549
- return dbType ? {...record, type: dbType} : record;
550
- }
551
-
552
- private _excludedFilterFieldsFor(routerType: string): ReadonlySet<string> {
553
- return this.excludedFilterFields.get(routerType) ?? EMPTY_FIELD_SET;
554
- }
555
-
556
- // Strips the columns a router/collection filter must not see, so an
557
- // excluded column reads as absent (→ null in NQL) rather than its real
558
- // value. Only affects filters that reference an excluded column; every
559
- // other filter sees an identical record.
560
- private _recordForRouterFilter(record: Record<string, unknown>, routerType: string): Record<string, unknown> {
561
- const excluded = this._excludedFilterFieldsFor(routerType);
562
- if (excluded.size === 0) {
563
- return record;
564
- }
565
- const stripped: Record<string, unknown> = {};
566
- for (const key of Object.keys(record)) {
567
- if (!excluded.has(key)) {
568
- stripped[key] = record[key];
569
- }
570
- }
571
- return stripped;
572
- }
573
-
574
- private _formatPath(path: string, options: UrlOptions): string {
575
- if (options.absolute) {
576
- return this.urlUtils.createUrl(path, options.absolute);
577
- }
578
- if (options.withSubdirectory) {
579
- return this.urlUtils.createUrl(path, false, true);
580
- }
581
- return path;
582
- }
583
-
584
- /**
585
- * The /404/ a resource gets when nothing routes it, formatted for the given
586
- * options. Deliberately omits the argument `_formatPath` passes.
587
- *
588
- * The subdirectory is not lost by that omission: `createUrl` takes it from
589
- * its own base whenever the url is relative, so a subdirectory install gets
590
- * `/blog/404/` from here either way. The third argument `_formatPath`
591
- * passes is `trailingSlash`, and `/404/` already ends in one.
592
- */
593
- private notFoundUrl(options: UrlOptions = {}): string {
594
- if (options.absolute) {
595
- return this.urlUtils.createUrl('/404/', options.absolute);
596
- }
597
- if (options.withSubdirectory) {
598
- return this.urlUtils.createUrl('/404/', false);
599
- }
600
- return '/404/';
601
- }
602
-
603
- // A filtered router that references a relation the resource doesn't carry
604
- // can't be evaluated, so the resource would 404 for a reason that has
605
- // nothing to do with the routing config. Callers must hand over
606
- // fully-inflated resources; a thin one is reported rather than silently
607
- // 404'd (see getUrlForResource).
608
- private _missingRouterFields(config: RouterConfig, resource: Resource, routerType: string): ThinResource | null {
609
- if (!config.filter) {
610
- return null;
611
- }
612
- const r = resource as Record<string, unknown>;
613
- const missing: string[] = [];
614
- if (/\btags?\b/.test(config.filter) && !Array.isArray(r.tags)) {
615
- missing.push('tags');
616
- }
617
- if (/\bauthors?\b/.test(config.filter) && !Array.isArray(r.authors)) {
618
- missing.push('authors');
619
- }
620
- if (/\bprimary_tag\b/.test(config.filter) && r.primary_tag === undefined) {
621
- missing.push('primary_tag');
622
- }
623
- if (/\bprimary_author\b/.test(config.filter) && r.primary_author === undefined) {
624
- missing.push('primary_author');
625
- }
626
- // Excluded columns are never required — their filters match them as
627
- // absent, so a resource lacking one is not thin here.
628
- const excluded = this._excludedFilterFieldsFor(routerType);
629
- for (const field of filterScalarFields(config.filter)) {
630
- if (!excluded.has(field) && r[field] === undefined) {
631
- missing.push(field);
632
- }
633
- }
634
- if (missing.length === 0) {
635
- return null;
636
- }
637
- return {
638
- resourceType: routerType,
639
- routerIdentifier: config.identifier,
640
- filter: config.filter,
641
- missing
642
- };
643
- }
644
- }
645
-
646
- module.exports = LazyUrlService;
647
- module.exports.LazyUrlService = LazyUrlService;