emdash 0.16.0 → 0.17.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 (562) hide show
  1. package/dist/{adapters-C4yd_UJR.d.mts → adapters-C5AWLJSD.d.mts} +1 -1
  2. package/dist/{adapters-C4yd_UJR.d.mts.map → adapters-C5AWLJSD.d.mts.map} +1 -1
  3. package/dist/{allowed-origins-D0fFk9a6.mjs → allowed-origins-CyYLEJkp.mjs} +2 -2
  4. package/dist/{allowed-origins-D0fFk9a6.mjs.map → allowed-origins-CyYLEJkp.mjs.map} +1 -1
  5. package/dist/api/route-utils.d.mts +3 -3
  6. package/dist/api/route-utils.mjs +16 -16
  7. package/dist/api/schemas/index.d.mts +2 -2
  8. package/dist/api/schemas/index.mjs +3 -3
  9. package/dist/{api-BNKqxyFX.mjs → api-Dmz40c2V.mjs} +44 -22
  10. package/dist/api-Dmz40c2V.mjs.map +1 -0
  11. package/dist/{api-tokens-ucpcNXDt.mjs → api-tokens-VrXNiNvV.mjs} +2 -2
  12. package/dist/{api-tokens-ucpcNXDt.mjs.map → api-tokens-VrXNiNvV.mjs.map} +1 -1
  13. package/dist/{apply-BOPaD-s9.mjs → apply-CgamLmed.mjs} +93 -31
  14. package/dist/apply-CgamLmed.mjs.map +1 -0
  15. package/dist/astro/index.d.mts +10 -10
  16. package/dist/astro/index.mjs +19 -3
  17. package/dist/astro/index.mjs.map +1 -1
  18. package/dist/astro/middleware/auth.d.mts +9 -9
  19. package/dist/astro/middleware/auth.mjs +6 -6
  20. package/dist/astro/middleware/redirect.d.mts.map +1 -1
  21. package/dist/astro/middleware/redirect.mjs +9 -5
  22. package/dist/astro/middleware/redirect.mjs.map +1 -1
  23. package/dist/astro/middleware/request-context.mjs +2 -2
  24. package/dist/astro/middleware/setup.mjs +1 -1
  25. package/dist/astro/middleware.mjs +66 -65
  26. package/dist/astro/middleware.mjs.map +1 -1
  27. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +5 -5
  28. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +5 -5
  29. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +4 -4
  30. package/dist/astro/routes/api/admin/api-tokens/index.mjs +5 -5
  31. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.d.mts +8 -0
  32. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.d.mts.map +1 -0
  33. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +23 -0
  34. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs.map +1 -0
  35. package/dist/astro/routes/api/admin/byline-fields/_slug_.d.mts +10 -0
  36. package/dist/astro/routes/api/admin/byline-fields/_slug_.d.mts.map +1 -0
  37. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +55 -0
  38. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs.map +1 -0
  39. package/dist/astro/routes/api/admin/byline-fields/index.d.mts +9 -0
  40. package/dist/astro/routes/api/admin/byline-fields/index.d.mts.map +1 -0
  41. package/dist/astro/routes/api/admin/byline-fields/index.mjs +43 -0
  42. package/dist/astro/routes/api/admin/byline-fields/index.mjs.map +1 -0
  43. package/dist/astro/routes/api/admin/byline-fields/reorder.d.mts +8 -0
  44. package/dist/astro/routes/api/admin/byline-fields/reorder.d.mts.map +1 -0
  45. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +27 -0
  46. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs.map +1 -0
  47. package/dist/astro/routes/api/admin/bylines/_id_/index.d.mts.map +1 -1
  48. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +27 -28
  49. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
  50. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +13 -12
  51. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -1
  52. package/dist/astro/routes/api/admin/bylines/index.mjs +15 -13
  53. package/dist/astro/routes/api/admin/bylines/index.mjs.map +1 -1
  54. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +10 -10
  55. package/dist/astro/routes/api/admin/comments/_id_.mjs +5 -5
  56. package/dist/astro/routes/api/admin/comments/bulk.mjs +8 -8
  57. package/dist/astro/routes/api/admin/comments/counts.mjs +5 -5
  58. package/dist/astro/routes/api/admin/comments/index.mjs +8 -8
  59. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +4 -4
  60. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
  61. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +4 -4
  62. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +4 -4
  63. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +35 -34
  64. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  65. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +35 -34
  66. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  67. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +34 -33
  68. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  69. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +34 -33
  70. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  71. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +34 -33
  72. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  73. package/dist/astro/routes/api/admin/plugins/index.mjs +34 -33
  74. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  75. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +3 -3
  76. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +34 -33
  77. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  78. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +34 -33
  79. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  80. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +34 -33
  81. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  82. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +34 -33
  83. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  84. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +35 -34
  85. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  86. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +34 -33
  87. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
  88. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +35 -34
  89. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  90. package/dist/astro/routes/api/admin/plugins/updates.mjs +34 -33
  91. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  92. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +34 -33
  93. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  94. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +3 -3
  95. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +34 -33
  96. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  97. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +2 -2
  98. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +2 -2
  99. package/dist/astro/routes/api/admin/users/_id_/index.mjs +5 -5
  100. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +3 -3
  101. package/dist/astro/routes/api/admin/users/index.mjs +5 -5
  102. package/dist/astro/routes/api/auth/dev-bypass.mjs +5 -5
  103. package/dist/astro/routes/api/auth/invite/accept.mjs +2 -2
  104. package/dist/astro/routes/api/auth/invite/complete.mjs +9 -9
  105. package/dist/astro/routes/api/auth/invite/index.mjs +6 -6
  106. package/dist/astro/routes/api/auth/invite/register-options.mjs +8 -8
  107. package/dist/astro/routes/api/auth/logout.mjs +3 -3
  108. package/dist/astro/routes/api/auth/magic-link/send.mjs +8 -8
  109. package/dist/astro/routes/api/auth/magic-link/verify.mjs +3 -3
  110. package/dist/astro/routes/api/auth/me.d.mts.map +1 -1
  111. package/dist/astro/routes/api/auth/me.mjs +18 -11
  112. package/dist/astro/routes/api/auth/me.mjs.map +1 -1
  113. package/dist/astro/routes/api/auth/mode.mjs +1 -1
  114. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +3 -3
  115. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  116. package/dist/astro/routes/api/auth/passkey/_id_.mjs +5 -5
  117. package/dist/astro/routes/api/auth/passkey/index.mjs +2 -2
  118. package/dist/astro/routes/api/auth/passkey/options.mjs +10 -10
  119. package/dist/astro/routes/api/auth/passkey/register/options.mjs +8 -8
  120. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +9 -9
  121. package/dist/astro/routes/api/auth/passkey/verify.mjs +9 -9
  122. package/dist/astro/routes/api/auth/signup/complete.mjs +9 -9
  123. package/dist/astro/routes/api/auth/signup/request.mjs +8 -8
  124. package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
  125. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +11 -11
  126. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +3 -3
  127. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +3 -3
  128. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
  129. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +3 -3
  130. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +9 -9
  131. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +6 -6
  132. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
  133. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +3 -3
  134. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +6 -6
  135. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.d.mts.map +1 -1
  136. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +18 -13
  137. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  138. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +3 -3
  139. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +3 -3
  140. package/dist/astro/routes/api/content/_collection_/_id_.d.mts.map +1 -1
  141. package/dist/astro/routes/api/content/_collection_/_id_.mjs +9 -7
  142. package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
  143. package/dist/astro/routes/api/content/_collection_/index.mjs +6 -6
  144. package/dist/astro/routes/api/content/_collection_/trash.mjs +6 -6
  145. package/dist/astro/routes/api/dashboard.mjs +7 -7
  146. package/dist/astro/routes/api/dev/emails.mjs +3 -3
  147. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  148. package/dist/astro/routes/api/import/probe.mjs +10 -10
  149. package/dist/astro/routes/api/import/wordpress/analyze.mjs +4 -4
  150. package/dist/astro/routes/api/import/wordpress/execute.d.mts +9 -9
  151. package/dist/astro/routes/api/import/wordpress/execute.mjs +11 -10
  152. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  153. package/dist/astro/routes/api/import/wordpress/media.mjs +8 -8
  154. package/dist/astro/routes/api/import/wordpress/prepare.mjs +9 -9
  155. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +8 -8
  156. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  157. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +10 -10
  158. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +1 -1
  159. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +13 -11
  160. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  161. package/dist/astro/routes/api/manifest.mjs +4 -4
  162. package/dist/astro/routes/api/mcp.mjs +34 -30
  163. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  164. package/dist/astro/routes/api/media/_id_/confirm.mjs +6 -6
  165. package/dist/astro/routes/api/media/_id_.mjs +6 -6
  166. package/dist/astro/routes/api/media/file/_...key_.mjs +2 -2
  167. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +3 -3
  168. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +3 -3
  169. package/dist/astro/routes/api/media/providers/index.mjs +3 -3
  170. package/dist/astro/routes/api/media/upload-url.mjs +8 -8
  171. package/dist/astro/routes/api/media.d.mts.map +1 -1
  172. package/dist/astro/routes/api/media.mjs +13 -12
  173. package/dist/astro/routes/api/media.mjs.map +1 -1
  174. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +7 -7
  175. package/dist/astro/routes/api/menus/_name_/items.mjs +7 -7
  176. package/dist/astro/routes/api/menus/_name_/reorder.mjs +7 -7
  177. package/dist/astro/routes/api/menus/_name_/translations.mjs +7 -7
  178. package/dist/astro/routes/api/menus/_name_.mjs +7 -7
  179. package/dist/astro/routes/api/menus/index.mjs +7 -7
  180. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  181. package/dist/astro/routes/api/oauth/device/authorize.mjs +6 -6
  182. package/dist/astro/routes/api/oauth/device/code.mjs +9 -9
  183. package/dist/astro/routes/api/oauth/device/token.mjs +8 -8
  184. package/dist/astro/routes/api/oauth/register.mjs +3 -3
  185. package/dist/astro/routes/api/oauth/token/refresh.mjs +6 -6
  186. package/dist/astro/routes/api/oauth/token/revoke.mjs +6 -6
  187. package/dist/astro/routes/api/oauth/token.mjs +6 -6
  188. package/dist/astro/routes/api/openapi.json.mjs +10 -7
  189. package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
  190. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +4 -4
  191. package/dist/astro/routes/api/redirects/404s/index.mjs +8 -8
  192. package/dist/astro/routes/api/redirects/404s/summary.mjs +8 -8
  193. package/dist/astro/routes/api/redirects/_id_.mjs +9 -9
  194. package/dist/astro/routes/api/redirects/index.mjs +9 -9
  195. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +3 -3
  196. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
  197. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +34 -33
  198. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  199. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +34 -33
  200. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  201. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +34 -33
  202. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  203. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +34 -33
  204. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  205. package/dist/astro/routes/api/schema/collections/index.mjs +34 -33
  206. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  207. package/dist/astro/routes/api/schema/index.mjs +6 -6
  208. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +34 -33
  209. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  210. package/dist/astro/routes/api/schema/orphans/index.mjs +34 -33
  211. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  212. package/dist/astro/routes/api/search/enable.mjs +9 -9
  213. package/dist/astro/routes/api/search/index.mjs +8 -8
  214. package/dist/astro/routes/api/search/rebuild.mjs +9 -9
  215. package/dist/astro/routes/api/search/stats.mjs +6 -6
  216. package/dist/astro/routes/api/search/suggest.mjs +8 -8
  217. package/dist/astro/routes/api/sections/_slug_.mjs +8 -8
  218. package/dist/astro/routes/api/sections/index.mjs +8 -8
  219. package/dist/astro/routes/api/settings/email.mjs +4 -4
  220. package/dist/astro/routes/api/settings.mjs +11 -11
  221. package/dist/astro/routes/api/setup/admin-verify.mjs +10 -10
  222. package/dist/astro/routes/api/setup/admin.mjs +9 -9
  223. package/dist/astro/routes/api/setup/dev-bypass.mjs +24 -23
  224. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  225. package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
  226. package/dist/astro/routes/api/setup/index.mjs +24 -23
  227. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  228. package/dist/astro/routes/api/setup/status.mjs +4 -4
  229. package/dist/astro/routes/api/snapshot.mjs +5 -5
  230. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +12 -12
  231. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +12 -12
  232. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +12 -12
  233. package/dist/astro/routes/api/taxonomies/index.mjs +12 -12
  234. package/dist/astro/routes/api/themes/preview.mjs +5 -5
  235. package/dist/astro/routes/api/typegen.mjs +5 -5
  236. package/dist/astro/routes/api/well-known/auth.mjs +1 -1
  237. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  238. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  239. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +6 -6
  240. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +8 -8
  241. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +8 -8
  242. package/dist/astro/routes/api/widget-areas/_name_.mjs +5 -5
  243. package/dist/astro/routes/api/widget-areas/index.mjs +8 -8
  244. package/dist/astro/routes/api/widget-components.mjs +3 -3
  245. package/dist/astro/routes/robots.txt.mjs +6 -6
  246. package/dist/astro/routes/sitemap-_collection_.xml.mjs +8 -8
  247. package/dist/astro/routes/sitemap.xml.mjs +7 -7
  248. package/dist/astro/types.d.mts +13 -12
  249. package/dist/astro/types.d.mts.map +1 -1
  250. package/dist/auth/providers/github.d.mts +1 -1
  251. package/dist/auth/providers/google.d.mts +1 -1
  252. package/dist/{authorize-Bn4S4DUT.mjs → authorize-_wWM_44T.mjs} +2 -2
  253. package/dist/{authorize-Bn4S4DUT.mjs.map → authorize-_wWM_44T.mjs.map} +1 -1
  254. package/dist/byline-BrIVWLm-.mjs +925 -0
  255. package/dist/byline-BrIVWLm-.mjs.map +1 -0
  256. package/dist/{bylines-B2_XmnSU.d.mts → byline-fields-BNy7Ng1U.d.mts} +154 -26
  257. package/dist/byline-fields-BNy7Ng1U.d.mts.map +1 -0
  258. package/dist/byline-fields-DC3Wkk-U.mjs +123 -0
  259. package/dist/byline-fields-DC3Wkk-U.mjs.map +1 -0
  260. package/dist/byline-fields-Dr-xcb6S.mjs +238 -0
  261. package/dist/byline-fields-Dr-xcb6S.mjs.map +1 -0
  262. package/dist/byline-registry-CxK5g559.mjs +406 -0
  263. package/dist/byline-registry-CxK5g559.mjs.map +1 -0
  264. package/dist/{bylines-n6nykUyI.mjs → bylines-C_POWmGT.mjs} +25 -11
  265. package/dist/{bylines-n6nykUyI.mjs.map → bylines-C_POWmGT.mjs.map} +1 -1
  266. package/dist/bylines-sqExMElV.mjs +204 -0
  267. package/dist/bylines-sqExMElV.mjs.map +1 -0
  268. package/dist/{cache-BcI1yUjR.mjs → cache-wsDkA8ru.mjs} +2 -2
  269. package/dist/{cache-BcI1yUjR.mjs.map → cache-wsDkA8ru.mjs.map} +1 -1
  270. package/dist/{challenge-store-Dng1SxKT.mjs → challenge-store-DGwuCc4R.mjs} +1 -1
  271. package/dist/{challenge-store-Dng1SxKT.mjs.map → challenge-store-DGwuCc4R.mjs.map} +1 -1
  272. package/dist/{chunks-cYG4SnIP.mjs → chunks-BAYkM-CF.mjs} +2 -2
  273. package/dist/{chunks-cYG4SnIP.mjs.map → chunks-BAYkM-CF.mjs.map} +1 -1
  274. package/dist/cli/index.mjs +29 -23
  275. package/dist/cli/index.mjs.map +1 -1
  276. package/dist/client/cf-access.d.mts +1 -1
  277. package/dist/client/index.d.mts +2 -1
  278. package/dist/client/index.d.mts.map +1 -1
  279. package/dist/client/index.mjs +4 -2
  280. package/dist/client/index.mjs.map +1 -1
  281. package/dist/{comment-C76G-9tz.mjs → comment-Cd29aktf.mjs} +2 -2
  282. package/dist/{comment-C76G-9tz.mjs.map → comment-Cd29aktf.mjs.map} +1 -1
  283. package/dist/{comments-CCxFFGY1.mjs → comments-B7ufhkxN.mjs} +3 -3
  284. package/dist/{comments-CCxFFGY1.mjs.map → comments-B7ufhkxN.mjs.map} +1 -1
  285. package/dist/{components-Dx3DM0gg.mjs → components-CTfpu3PZ.mjs} +1 -1
  286. package/dist/{components-Dx3DM0gg.mjs.map → components-CTfpu3PZ.mjs.map} +1 -1
  287. package/dist/{content-8voQNTXX.mjs → content-BbqKo3Kc.mjs} +22 -3
  288. package/dist/content-BbqKo3Kc.mjs.map +1 -0
  289. package/dist/{context-B7qiYrz2.mjs → context-BsF1rhoI.mjs} +9 -9
  290. package/dist/{context-B7qiYrz2.mjs.map → context-BsF1rhoI.mjs.map} +1 -1
  291. package/dist/{cron-Bd3b3iuj.mjs → cron-DZovZUnC.mjs} +1 -1
  292. package/dist/{cron-Bd3b3iuj.mjs.map → cron-DZovZUnC.mjs.map} +1 -1
  293. package/dist/{dashboard-BeaFSPpx.mjs → dashboard-BwIX9r-X.mjs} +4 -4
  294. package/dist/{dashboard-BeaFSPpx.mjs.map → dashboard-BwIX9r-X.mjs.map} +1 -1
  295. package/dist/db/index.d.mts +3 -3
  296. package/dist/db/index.mjs +1 -1
  297. package/dist/db/libsql.d.mts +1 -1
  298. package/dist/db/postgres.d.mts +1 -1
  299. package/dist/db/sqlite.d.mts +1 -1
  300. package/dist/{db-errors-BiYqoX-n.mjs → db-errors-CtzxKBxe.mjs} +1 -1
  301. package/dist/{db-errors-BiYqoX-n.mjs.map → db-errors-CtzxKBxe.mjs.map} +1 -1
  302. package/dist/{default-BvTAYCzx.mjs → default-xLFNSsZ9.mjs} +1 -1
  303. package/dist/{default-BvTAYCzx.mjs.map → default-xLFNSsZ9.mjs.map} +1 -1
  304. package/dist/{device-flow-B9oG8PwP.mjs → device-flow-ptLrVINd.mjs} +4 -4
  305. package/dist/{device-flow-B9oG8PwP.mjs.map → device-flow-ptLrVINd.mjs.map} +1 -1
  306. package/dist/{email-console-CubRll9q.mjs → email-console-DHT2Fbpj.mjs} +1 -1
  307. package/dist/{email-console-CubRll9q.mjs.map → email-console-DHT2Fbpj.mjs.map} +1 -1
  308. package/dist/{error-ChfADBuu.mjs → error-npZWBSb7.mjs} +7 -3
  309. package/dist/error-npZWBSb7.mjs.map +1 -0
  310. package/dist/{escape-Cg6kMELH.mjs → escape-bIyGoW5W.mjs} +1 -1
  311. package/dist/{escape-Cg6kMELH.mjs.map → escape-bIyGoW5W.mjs.map} +1 -1
  312. package/dist/{fts-manager-C_b-4x8u.mjs → fts-manager-DmUAk-kQ.mjs} +2 -2
  313. package/dist/{fts-manager-C_b-4x8u.mjs.map → fts-manager-DmUAk-kQ.mjs.map} +1 -1
  314. package/dist/{hash-DlUxGhQS.mjs → hash-9w3pd3-m.mjs} +1 -1
  315. package/dist/{hash-DlUxGhQS.mjs.map → hash-9w3pd3-m.mjs.map} +1 -1
  316. package/dist/{import-DG80rC_I.mjs → import-Dh8bWmyq.mjs} +3 -3
  317. package/dist/{import-DG80rC_I.mjs.map → import-Dh8bWmyq.mjs.map} +1 -1
  318. package/dist/{index-BPZFAcgE.d.mts → index-CjKdMZ3U.d.mts} +39 -17
  319. package/dist/index-CjKdMZ3U.d.mts.map +1 -0
  320. package/dist/{index-CC42STEm.d.mts → index-D60_SzHG.d.mts} +3 -3
  321. package/dist/{index-CC42STEm.d.mts.map → index-D60_SzHG.d.mts.map} +1 -1
  322. package/dist/index.d.mts +17 -17
  323. package/dist/index.mjs +55 -54
  324. package/dist/{load-CLFRjk9r.mjs → load-DsoLq7ex.mjs} +2 -2
  325. package/dist/{load-CLFRjk9r.mjs.map → load-DsoLq7ex.mjs.map} +1 -1
  326. package/dist/{loader-D-vIJjfY.mjs → loader-CJ6lWO0d.mjs} +75 -19
  327. package/dist/loader-CJ6lWO0d.mjs.map +1 -0
  328. package/dist/{manifest-schema-Czqf0TLu.mjs → manifest-schema-Cj-YrzrF.mjs} +1 -1
  329. package/dist/{manifest-schema-Czqf0TLu.mjs.map → manifest-schema-Cj-YrzrF.mjs.map} +1 -1
  330. package/dist/media/index.d.mts +1 -1
  331. package/dist/media/index.mjs +2 -2
  332. package/dist/media/local-runtime.d.mts +11 -11
  333. package/dist/media/local-runtime.mjs +5 -5
  334. package/dist/{media-allowlist-BNloC69x.mjs → media-allowlist-CMcoYIjQ.mjs} +2 -2
  335. package/dist/{media-allowlist-BNloC69x.mjs.map → media-allowlist-CMcoYIjQ.mjs.map} +1 -1
  336. package/dist/{media-CKQd8AYU.mjs → media-jk_HzzOl.mjs} +7 -2
  337. package/dist/media-jk_HzzOl.mjs.map +1 -0
  338. package/dist/{menus-arUNspyU.mjs → menus-B-5-3aon.mjs} +2 -2
  339. package/dist/{menus-arUNspyU.mjs.map → menus-B-5-3aon.mjs.map} +1 -1
  340. package/dist/{menus-C-nWT5Tu.mjs → menus-CyMO6GBx.mjs} +27 -11
  341. package/dist/menus-CyMO6GBx.mjs.map +1 -0
  342. package/dist/{mime-KV5TqkMN.mjs → mime-CCEzze7W.mjs} +1 -1
  343. package/dist/{mime-KV5TqkMN.mjs.map → mime-CCEzze7W.mjs.map} +1 -1
  344. package/dist/{mode-CaaiebZI.mjs → mode-BjlXswIw.mjs} +1 -1
  345. package/dist/{mode-CaaiebZI.mjs.map → mode-BjlXswIw.mjs.map} +1 -1
  346. package/dist/{normalize-CN5kRSMC.mjs → normalize-DVV8nbrL.mjs} +1 -1
  347. package/dist/{normalize-CN5kRSMC.mjs.map → normalize-DVV8nbrL.mjs.map} +1 -1
  348. package/dist/{oauth-authorization-CTMeVfvj.mjs → oauth-authorization-DvBAL75d.mjs} +4 -4
  349. package/dist/{oauth-authorization-CTMeVfvj.mjs.map → oauth-authorization-DvBAL75d.mjs.map} +1 -1
  350. package/dist/{oauth-clients-eJCbkVSG.mjs → oauth-clients-8mPDStMv.mjs} +1 -1
  351. package/dist/{oauth-clients-eJCbkVSG.mjs.map → oauth-clients-8mPDStMv.mjs.map} +1 -1
  352. package/dist/{oauth-state-store-vOSdOeGe.mjs → oauth-state-store-BJ7YtrfD.mjs} +1 -1
  353. package/dist/{oauth-state-store-vOSdOeGe.mjs.map → oauth-state-store-BJ7YtrfD.mjs.map} +1 -1
  354. package/dist/{oauth-user-lookup-3JwsVw6N.mjs → oauth-user-lookup-BdDSDvjF.mjs} +1 -1
  355. package/dist/{oauth-user-lookup-3JwsVw6N.mjs.map → oauth-user-lookup-BdDSDvjF.mjs.map} +1 -1
  356. package/dist/{options-DhV-gwJb.d.mts → options-tb7DJROi.d.mts} +3 -3
  357. package/dist/{options-DhV-gwJb.d.mts.map → options-tb7DJROi.d.mts.map} +1 -1
  358. package/dist/page/index.d.mts +2 -2
  359. package/dist/{parse-DHbXfvxO.mjs → parse-4zO5Y2DL.mjs} +2 -2
  360. package/dist/{parse-DHbXfvxO.mjs.map → parse-4zO5Y2DL.mjs.map} +1 -1
  361. package/dist/{passkey-config-BloQOT3y.mjs → passkey-config-BDVM86Tj.mjs} +1 -1
  362. package/dist/{passkey-config-BloQOT3y.mjs.map → passkey-config-BDVM86Tj.mjs.map} +1 -1
  363. package/dist/{placeholder-KCkkCtgQ.d.mts → placeholder-B9lUUEmj.d.mts} +1 -1
  364. package/dist/{placeholder-KCkkCtgQ.d.mts.map → placeholder-B9lUUEmj.d.mts.map} +1 -1
  365. package/dist/{placeholder-LqmHqvBw.mjs → placeholder-BZxr8W1j.mjs} +1 -1
  366. package/dist/{placeholder-LqmHqvBw.mjs.map → placeholder-BZxr8W1j.mjs.map} +1 -1
  367. package/dist/plugin-types.d.mts +1 -1
  368. package/dist/plugin-utils.d.mts +9 -9
  369. package/dist/plugins/adapt-sandbox-entry.d.mts +9 -9
  370. package/dist/plugins/adapt-sandbox-entry.mjs +2 -2
  371. package/dist/{preview-D4z0WONU.mjs → preview-BfuRkVKW.mjs} +2 -2
  372. package/dist/{preview-D4z0WONU.mjs.map → preview-BfuRkVKW.mjs.map} +1 -1
  373. package/dist/{public-url-CUWWFME2.mjs → public-url-egRHCy1m.mjs} +1 -1
  374. package/dist/{public-url-CUWWFME2.mjs.map → public-url-egRHCy1m.mjs.map} +1 -1
  375. package/dist/{query-7m6-l0f_.mjs → query-CuvjwhrE.mjs} +12 -12
  376. package/dist/{query-7m6-l0f_.mjs.map → query-CuvjwhrE.mjs.map} +1 -1
  377. package/dist/{rate-limit-D8RAXN8b.mjs → rate-limit-D6VQqBk_.mjs} +2 -2
  378. package/dist/{rate-limit-D8RAXN8b.mjs.map → rate-limit-D6VQqBk_.mjs.map} +1 -1
  379. package/dist/{redirect-CjfDGrTd.mjs → redirect-BZUJltlj.mjs} +2 -2
  380. package/dist/{redirect-CjfDGrTd.mjs.map → redirect-BZUJltlj.mjs.map} +1 -1
  381. package/dist/{redirect-BINiRYq4.mjs → redirect-Cw3JTlmj.mjs} +1 -1
  382. package/dist/{redirect-BINiRYq4.mjs.map → redirect-Cw3JTlmj.mjs.map} +1 -1
  383. package/dist/{redirects-COMLwsV5.mjs → redirects-C0L9JUk4.mjs} +19 -6
  384. package/dist/redirects-C0L9JUk4.mjs.map +1 -0
  385. package/dist/{redirects-CowoEHdE.mjs → redirects-DnYuqsEf.mjs} +3 -3
  386. package/dist/{redirects-CowoEHdE.mjs.map → redirects-DnYuqsEf.mjs.map} +1 -1
  387. package/dist/{registry-Cyp-dx6J.mjs → registry-Dn6gsx3L.mjs} +13 -5
  388. package/dist/{registry-Cyp-dx6J.mjs.map → registry-Dn6gsx3L.mjs.map} +1 -1
  389. package/dist/{request-cache-dzCt8TZB.mjs → request-cache-BYMs-BGX.mjs} +23 -2
  390. package/dist/{request-cache-dzCt8TZB.mjs.map → request-cache-BYMs-BGX.mjs.map} +1 -1
  391. package/dist/{request-meta-C_Cjii-T.mjs → request-meta-7ByVLxB-.mjs} +2 -2
  392. package/dist/{request-meta-C_Cjii-T.mjs.map → request-meta-7ByVLxB-.mjs.map} +1 -1
  393. package/dist/{resolve-D6sM-SgF.mjs → resolve-BqYMVG0D.mjs} +1 -1
  394. package/dist/{resolve-D6sM-SgF.mjs.map → resolve-BqYMVG0D.mjs.map} +1 -1
  395. package/dist/{runner-DSQBurMS.d.mts → runner-DM1yR5qd.d.mts} +2 -2
  396. package/dist/{runner-DSQBurMS.d.mts.map → runner-DM1yR5qd.d.mts.map} +1 -1
  397. package/dist/{runner-Drnvs96u.mjs → runner-eAgyIkeg.mjs} +284 -158
  398. package/dist/runner-eAgyIkeg.mjs.map +1 -0
  399. package/dist/runtime.d.mts +10 -10
  400. package/dist/runtime.mjs +2 -2
  401. package/dist/{schema-CI9mYPX3.mjs → schema--mYZX4D7.mjs} +5 -5
  402. package/dist/{schema-CI9mYPX3.mjs.map → schema--mYZX4D7.mjs.map} +1 -1
  403. package/dist/{search-DKz_mGBP.mjs → search-C6U_NvZI.mjs} +4 -4
  404. package/dist/{search-DKz_mGBP.mjs.map → search-C6U_NvZI.mjs.map} +1 -1
  405. package/dist/{secrets-rPdhEBkD.mjs → secrets-YYbTgB1w.mjs} +1 -1
  406. package/dist/{secrets-rPdhEBkD.mjs.map → secrets-YYbTgB1w.mjs.map} +1 -1
  407. package/dist/{sections-DBbCDIAT.mjs → sections-Ba-rJLKb.mjs} +3 -3
  408. package/dist/{sections-DBbCDIAT.mjs.map → sections-Ba-rJLKb.mjs.map} +1 -1
  409. package/dist/seed/index.d.mts +2 -2
  410. package/dist/seed/index.mjs +18 -17
  411. package/dist/seo/index.d.mts +1 -1
  412. package/dist/{seo-BGCyDlkb.mjs → seo-BTzb5ksq.mjs} +2 -2
  413. package/dist/{seo-BGCyDlkb.mjs.map → seo-BTzb5ksq.mjs.map} +1 -1
  414. package/dist/{seo-Dq707mNQ.mjs → seo-DfjLvu8i.mjs} +1 -1
  415. package/dist/{seo-Dq707mNQ.mjs.map → seo-DfjLvu8i.mjs.map} +1 -1
  416. package/dist/{service-B0H7U1Y9.mjs → service-Cn-kIfZn.mjs} +3 -3
  417. package/dist/{service-B0H7U1Y9.mjs.map → service-Cn-kIfZn.mjs.map} +1 -1
  418. package/dist/{settings-DfwNyQkf.mjs → settings-C65OSm41.mjs} +3 -3
  419. package/dist/{settings-DfwNyQkf.mjs.map → settings-C65OSm41.mjs.map} +1 -1
  420. package/dist/{settings-BSXRtTzk.mjs → settings-ChlQbwU0.mjs} +4 -4
  421. package/dist/{settings-BSXRtTzk.mjs.map → settings-ChlQbwU0.mjs.map} +1 -1
  422. package/dist/{setup-complete-MzzN9u0b.mjs → setup-complete-VoEZfasi.mjs} +1 -1
  423. package/dist/{setup-complete-MzzN9u0b.mjs.map → setup-complete-VoEZfasi.mjs.map} +1 -1
  424. package/dist/{setup-nonce-DXuriHsg.mjs → setup-nonce-Bm0uKqmf.mjs} +1 -1
  425. package/dist/{setup-nonce-DXuriHsg.mjs.map → setup-nonce-Bm0uKqmf.mjs.map} +1 -1
  426. package/dist/{site-url-xkhw1tcz.mjs → site-url-Cm8-sJy7.mjs} +1 -1
  427. package/dist/{site-url-xkhw1tcz.mjs.map → site-url-Cm8-sJy7.mjs.map} +1 -1
  428. package/dist/{ssrf-MZ-zrG6-.mjs → ssrf-BsVGIE0Z.mjs} +1 -1
  429. package/dist/{ssrf-MZ-zrG6-.mjs.map → ssrf-BsVGIE0Z.mjs.map} +1 -1
  430. package/dist/storage/local.d.mts +1 -1
  431. package/dist/storage/local.mjs +1 -1
  432. package/dist/storage/s3.d.mts +1 -1
  433. package/dist/storage/s3.mjs +1 -1
  434. package/dist/{taxonomies-CcvrMLbR.mjs → taxonomies-CgpzAU6F.mjs} +8 -8
  435. package/dist/{taxonomies-CcvrMLbR.mjs.map → taxonomies-CgpzAU6F.mjs.map} +1 -1
  436. package/dist/{taxonomies-4vx0nmMr.mjs → taxonomies-D72gTOg_.mjs} +4 -4
  437. package/dist/{taxonomies-4vx0nmMr.mjs.map → taxonomies-D72gTOg_.mjs.map} +1 -1
  438. package/dist/{taxonomy-zqGQUqgu.mjs → taxonomy-BBK-UAEo.mjs} +3 -3
  439. package/dist/{taxonomy-zqGQUqgu.mjs.map → taxonomy-BBK-UAEo.mjs.map} +1 -1
  440. package/dist/{tokens-N8otWMmj.mjs → tokens-Bx2afeT-.mjs} +1 -1
  441. package/dist/{tokens-N8otWMmj.mjs.map → tokens-Bx2afeT-.mjs.map} +1 -1
  442. package/dist/{transport-B6CHddbu.mjs → transport--Ck3RBin.mjs} +1 -1
  443. package/dist/{transport-B6CHddbu.mjs.map → transport--Ck3RBin.mjs.map} +1 -1
  444. package/dist/{transport-C2MGqtL6.d.mts → transport-OnMNbsIA.d.mts} +1 -1
  445. package/dist/{transport-C2MGqtL6.d.mts.map → transport-OnMNbsIA.d.mts.map} +1 -1
  446. package/dist/{trusted-proxy-97pajC2f.mjs → trusted-proxy-B4AfnoAp.mjs} +1 -1
  447. package/dist/{trusted-proxy-97pajC2f.mjs.map → trusted-proxy-B4AfnoAp.mjs.map} +1 -1
  448. package/dist/types-D8bhH891.mjs +125 -0
  449. package/dist/{types-DSZl1Dsv.mjs.map → types-D8bhH891.mjs.map} +1 -1
  450. package/dist/{types-DGHWRQgr.d.mts → types-DMwSpvcw.d.mts} +2 -2
  451. package/dist/{types-DGHWRQgr.d.mts.map → types-DMwSpvcw.d.mts.map} +1 -1
  452. package/dist/{types-bYmRn_Uy.d.mts → types-DWnN7weG.d.mts} +1 -1
  453. package/dist/{types-bYmRn_Uy.d.mts.map → types-DWnN7weG.d.mts.map} +1 -1
  454. package/dist/{types-Dgo6y-Ut.d.mts → types-DX6v9KzJ.d.mts} +1 -1
  455. package/dist/{types-Dgo6y-Ut.d.mts.map → types-DX6v9KzJ.d.mts.map} +1 -1
  456. package/dist/{types-DaqNzqVt.d.mts → types-DawhLFwy.d.mts} +35 -1
  457. package/dist/{types-DaqNzqVt.d.mts.map → types-DawhLFwy.d.mts.map} +1 -1
  458. package/dist/{types-CpUuGcd5.d.mts → types-DbCWhHet.d.mts} +8 -2
  459. package/dist/{types-CpUuGcd5.d.mts.map → types-DbCWhHet.d.mts.map} +1 -1
  460. package/dist/{types-Cd9UCu3t.mjs → types-DpFmlNyB.mjs} +1 -1
  461. package/dist/{types-Cd9UCu3t.mjs.map → types-DpFmlNyB.mjs.map} +1 -1
  462. package/dist/{types-D599-ruj.d.mts → types-Qa7-HJJC.d.mts} +1 -1
  463. package/dist/{types-D599-ruj.d.mts.map → types-Qa7-HJJC.d.mts.map} +1 -1
  464. package/dist/{types-B0bmgwMG.mjs → types-SF1DwGf2.mjs} +2 -2
  465. package/dist/types-SF1DwGf2.mjs.map +1 -0
  466. package/dist/{types-DaYDYW6g.d.mts → types-i8_uzhMD.d.mts} +40 -2
  467. package/dist/types-i8_uzhMD.d.mts.map +1 -0
  468. package/dist/{types-CkDSF81F.d.mts → types-kwqCOUxj.d.mts} +1 -1
  469. package/dist/{types-CkDSF81F.d.mts.map → types-kwqCOUxj.d.mts.map} +1 -1
  470. package/dist/{user-hUSOaIJy.mjs → user-X4rtyO4Y.mjs} +2 -2
  471. package/dist/{user-hUSOaIJy.mjs.map → user-X4rtyO4Y.mjs.map} +1 -1
  472. package/dist/{utils-C3wTAP-P.mjs → utils-C4Ih4DML.mjs} +1 -1
  473. package/dist/{utils-C3wTAP-P.mjs.map → utils-C4Ih4DML.mjs.map} +1 -1
  474. package/dist/{validate-IGltez8n.mjs → validate-DactmcJG.mjs} +23 -3
  475. package/dist/validate-DactmcJG.mjs.map +1 -0
  476. package/dist/{validate-DQtHw9NT.d.mts → validate-Dy6nkNls.d.mts} +25 -5
  477. package/dist/{validate-DQtHw9NT.d.mts.map → validate-Dy6nkNls.d.mts.map} +1 -1
  478. package/dist/{validation-Bmymau7y.mjs → validation-BYA4i85b.mjs} +6 -6
  479. package/dist/{validation-Bmymau7y.mjs.map → validation-BYA4i85b.mjs.map} +1 -1
  480. package/dist/version-FGcv0ooe.mjs +7 -0
  481. package/dist/{version-BTc87L3L.mjs.map → version-FGcv0ooe.mjs.map} +1 -1
  482. package/dist/{widgets-yHQa4c6c.mjs → widgets-DG-1jxnz.mjs} +3 -3
  483. package/dist/{widgets-yHQa4c6c.mjs.map → widgets-DG-1jxnz.mjs.map} +1 -1
  484. package/dist/{zod-generator-B80aap1J.mjs → zod-generator-BNAObjSt.mjs} +3 -3
  485. package/dist/{zod-generator-B80aap1J.mjs.map → zod-generator-BNAObjSt.mjs.map} +1 -1
  486. package/package.json +7 -7
  487. package/src/api/errors.ts +7 -0
  488. package/src/api/handlers/byline-fields.ts +212 -0
  489. package/src/api/handlers/bylines.ts +126 -5
  490. package/src/api/handlers/content.ts +43 -2
  491. package/src/api/handlers/media.ts +2 -0
  492. package/src/api/openapi/document.ts +3 -0
  493. package/src/api/schemas/byline-fields.ts +188 -0
  494. package/src/api/schemas/bylines.ts +42 -0
  495. package/src/api/schemas/content.ts +2 -0
  496. package/src/api/schemas/index.ts +1 -0
  497. package/src/api/schemas/media.ts +2 -0
  498. package/src/astro/integration/routes.ts +27 -0
  499. package/src/astro/middleware/redirect.ts +5 -1
  500. package/src/astro/routes/api/admin/byline-fields/[slug]/usage.ts +36 -0
  501. package/src/astro/routes/api/admin/byline-fields/[slug].ts +92 -0
  502. package/src/astro/routes/api/admin/byline-fields/index.ts +66 -0
  503. package/src/astro/routes/api/admin/byline-fields/reorder.ts +39 -0
  504. package/src/astro/routes/api/admin/bylines/[id]/index.ts +23 -21
  505. package/src/astro/routes/api/admin/bylines/index.ts +1 -0
  506. package/src/astro/routes/api/auth/me.ts +21 -10
  507. package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +15 -3
  508. package/src/astro/routes/api/content/[collection]/[id].ts +3 -1
  509. package/src/astro/routes/api/media.ts +1 -0
  510. package/src/astro/types.ts +1 -0
  511. package/src/bylines/field-defs-cache.ts +138 -0
  512. package/src/bylines/index.ts +37 -4
  513. package/src/cli/commands/content.ts +4 -2
  514. package/src/client/index.ts +4 -1
  515. package/src/components/InlinePortableTextEditor.tsx +69 -0
  516. package/src/content/converters/portable-text-to-prosemirror.ts +7 -0
  517. package/src/content/converters/prosemirror-to-portable-text.ts +16 -0
  518. package/src/content/converters/types.ts +10 -0
  519. package/src/database/migrations/041_content_locale_list_index.ts +47 -0
  520. package/src/database/migrations/042_byline_fields.ts +157 -0
  521. package/src/database/migrations/runner.ts +4 -0
  522. package/src/database/repositories/byline.ts +758 -50
  523. package/src/database/repositories/content.ts +43 -3
  524. package/src/database/repositories/media.ts +14 -0
  525. package/src/database/repositories/types.ts +38 -0
  526. package/src/database/types.ts +44 -0
  527. package/src/emdash-runtime.ts +4 -1
  528. package/src/index.ts +1 -0
  529. package/src/loader.ts +98 -10
  530. package/src/mcp/server.ts +10 -1
  531. package/src/request-cache.ts +23 -0
  532. package/src/schema/byline-registry.ts +671 -0
  533. package/src/schema/registry.ts +14 -0
  534. package/src/schema/types.ts +133 -0
  535. package/src/seed/apply.ts +101 -14
  536. package/src/seed/types.ts +21 -0
  537. package/src/seed/validate.ts +39 -0
  538. package/dist/api-BNKqxyFX.mjs.map +0 -1
  539. package/dist/apply-BOPaD-s9.mjs.map +0 -1
  540. package/dist/byline-BDylH_m4.mjs +0 -404
  541. package/dist/byline-BDylH_m4.mjs.map +0 -1
  542. package/dist/bylines-B2_XmnSU.d.mts.map +0 -1
  543. package/dist/bylines-B7TFEvFf.mjs +0 -118
  544. package/dist/bylines-B7TFEvFf.mjs.map +0 -1
  545. package/dist/content-8voQNTXX.mjs.map +0 -1
  546. package/dist/error-ChfADBuu.mjs.map +0 -1
  547. package/dist/index-BPZFAcgE.d.mts.map +0 -1
  548. package/dist/loader-D-vIJjfY.mjs.map +0 -1
  549. package/dist/media-CKQd8AYU.mjs.map +0 -1
  550. package/dist/menus-C-nWT5Tu.mjs.map +0 -1
  551. package/dist/redirects-COMLwsV5.mjs.map +0 -1
  552. package/dist/runner-Drnvs96u.mjs.map +0 -1
  553. package/dist/setup-Cf_TyOv5.mjs +0 -137
  554. package/dist/setup-Cf_TyOv5.mjs.map +0 -1
  555. package/dist/types-B0bmgwMG.mjs.map +0 -1
  556. package/dist/types-DSZl1Dsv.mjs +0 -83
  557. package/dist/types-DaYDYW6g.d.mts.map +0 -1
  558. package/dist/validate-IGltez8n.mjs.map +0 -1
  559. package/dist/version-BTc87L3L.mjs +0 -7
  560. /package/dist/{api-tokens-iPIHAY8N.mjs → api-tokens-B6VgoE6M.mjs} +0 -0
  561. /package/dist/{ssrf-BIcd-aXW.mjs → ssrf-BvgVcfNQ.mjs} +0 -0
  562. /package/dist/{types-1NNkmTIn.mjs → types-Cj2S6FuC.mjs} +0 -0
@@ -17,6 +17,9 @@ import { EmDashValidationError, encodeCursor, decodeCursor } from "./types.js";
17
17
  // Regex pattern for ULID validation
18
18
  const ULID_PATTERN = /^[0-9A-Z]{26}$/;
19
19
 
20
+ // LIKE wildcards that must be escaped so user search input is matched literally.
21
+ const LIKE_WILDCARD_RE = /[\\%_]/g;
22
+
20
23
  /**
21
24
  * System columns that exist in every ec_* table
22
25
  */
@@ -489,6 +492,8 @@ export class ContentRepository {
489
492
  query = query.where("locale" as any, "=", options.where.locale);
490
493
  }
491
494
 
495
+ query = this.applySearchFilter(query, options.where);
496
+
492
497
  // Handle cursor pagination — decodeCursor throws InvalidCursorError
493
498
  // on malformed input; let it propagate so handlers surface a
494
499
  // structured INVALID_CURSOR rather than silently returning page 1.
@@ -519,8 +524,8 @@ export class ContentRepository {
519
524
  .limit(limit + 1);
520
525
 
521
526
  // Run the page fetch and the unbounded count together — the UI needs
522
- // both to render a stable denominator, and issuing them in parallel
523
- // on SQLite is essentially free.
527
+ // both to render a stable denominator (kept on every page intentionally),
528
+ // and issuing them in parallel on SQLite is essentially free.
524
529
  const [rows, total] = await Promise.all([query.execute(), this.count(type, options.where)]);
525
530
  const hasMore = rows.length > limit;
526
531
  const items = rows.slice(0, limit);
@@ -753,12 +758,45 @@ export class ContentRepository {
753
758
  return Number(result?.count || 0);
754
759
  }
755
760
 
761
+ /**
762
+ * Apply the optional case-insensitive `q` substring filter across the
763
+ * handler-resolved `searchColumns` (OR'd). User input is treated literally
764
+ * (LIKE wildcards escaped) and `lower()` is applied on both sides for
765
+ * SQLite/Postgres case-insensitive parity.
766
+ */
767
+ private applySearchFilter<QB extends { where: (cb: (eb: any) => unknown) => QB }>(
768
+ query: QB,
769
+ where?: { q?: string; searchColumns?: string[] },
770
+ ): QB {
771
+ const term = where?.q?.trim();
772
+ const columns = where?.searchColumns;
773
+ if (!term || !columns || columns.length === 0) return query;
774
+
775
+ const escaped = term.replace(LIKE_WILDCARD_RE, (c) => `\\${c}`);
776
+ const pattern = `%${escaped}%`;
777
+
778
+ return query.where((eb) =>
779
+ eb.or(
780
+ columns.map((col) => {
781
+ validateIdentifier(col, "search column");
782
+ return eb(sql`lower(${sql.ref(col)})`, "like", sql`lower(${pattern}) escape '\\'`);
783
+ }),
784
+ ),
785
+ );
786
+ }
787
+
756
788
  /**
757
789
  * Count content items
758
790
  */
759
791
  async count(
760
792
  type: string,
761
- where?: { status?: string; authorId?: string; locale?: string },
793
+ where?: {
794
+ status?: string;
795
+ authorId?: string;
796
+ locale?: string;
797
+ q?: string;
798
+ searchColumns?: string[];
799
+ },
762
800
  ): Promise<number> {
763
801
  const tableName = getTableName(type);
764
802
 
@@ -779,6 +817,8 @@ export class ContentRepository {
779
817
  query = query.where("locale" as any, "=", where.locale);
780
818
  }
781
819
 
820
+ query = this.applySearchFilter(query, where);
821
+
782
822
  const result = await query.executeTakeFirst();
783
823
  return Number(result?.count || 0);
784
824
  }
@@ -81,6 +81,8 @@ export interface FindManyMediaOptions {
81
81
  /** Filter by MIME type. Pass a string for a single prefix/exact, or an array to match any. Strings ending with "/" are treated as LIKE prefix matches; others are exact equality. */
82
82
  mimeType?: string | readonly string[];
83
83
  status?: MediaStatus | "all"; // Filter by status, defaults to "ready"
84
+ /** Case-insensitive substring matched against the filename (covers filename and extension). */
85
+ q?: string;
84
86
  }
85
87
 
86
88
  /**
@@ -250,6 +252,18 @@ export class MediaRepository {
250
252
  query = query.where((eb) => mimeMatchExpr(eb, mimeFilters));
251
253
  }
252
254
 
255
+ // Case-insensitive filename substring search (also matches extensions).
256
+ // LIKE wildcards in the term are escaped so they're treated literally.
257
+ const term = options.q?.trim();
258
+ if (term) {
259
+ const pattern = `%${escapeLike(term)}%`;
260
+ query = query.where(
261
+ sql<string>`lower(filename)`,
262
+ "like",
263
+ sql<string>`lower(${pattern}) escape '\\'`,
264
+ );
265
+ }
266
+
253
267
  // Default to only showing ready items
254
268
  if (options.status !== "all") {
255
269
  query = query.where("status", "=", options.status ?? "ready");
@@ -1,3 +1,4 @@
1
+ import type { CustomFieldValue } from "../../schema/types.js";
1
2
  import { encodeBase64, decodeBase64 } from "../../utils/base64.js";
2
3
 
3
4
  /**
@@ -58,6 +59,25 @@ export interface BylineSummary {
58
59
  displayName: string;
59
60
  bio: string | null;
60
61
  avatarMediaId: string | null;
62
+ /**
63
+ * The avatar media's storage key, folded in by a LEFT JOIN on the
64
+ * `media` table during content byline hydration. Non-null only when the
65
+ * byline has an avatar AND was loaded through the content-credit hydration
66
+ * path (`getContentBylines` / `getContentBylinesMany`, i.e. the
67
+ * `entry.data.bylines` populated by `getEmDashCollection` / `getEmDashEntry`).
68
+ * The plain byline finders (`findById`, `findBySlug`, …) leave it null.
69
+ *
70
+ * Lets list pages build a direct storage URL for an author avatar without a
71
+ * per-byline `MediaRepository.findById`, avoiding an N+1 when many distinct
72
+ * authors appear on one page.
73
+ *
74
+ * Optional so adding it is a non-breaking change for existing code that
75
+ * constructs a `BylineSummary` literal; the repositories always populate it
76
+ * (to `null` when there's no avatar or no media join).
77
+ */
78
+ avatarStorageKey?: string | null;
79
+ /** Avatar media alt text, from the same media join. Null when not joined. */
80
+ avatarAlt?: string | null;
61
81
  websiteUrl: string | null;
62
82
  userId: string | null;
63
83
  isGuest: boolean;
@@ -76,6 +96,16 @@ export interface BylineSummary {
76
96
  * populate it.
77
97
  */
78
98
  translationGroup: string | null;
99
+ /**
100
+ * Custom field values registered via the byline-fields schema (migration
101
+ * 041, Discussion #1174). Optional in the TypeScript shape so existing
102
+ * object-literal consumers (test fixtures, plugin renderers) stay
103
+ * source-compatible; the runtime always returns `{}` when no fields are
104
+ * registered. Translatable values reflect this row's locale; non-
105
+ * translatable values are shared across every locale variant of the
106
+ * byline's `translation_group`.
107
+ */
108
+ customFields?: Record<string, CustomFieldValue>;
79
109
  }
80
110
 
81
111
  export interface ContentBylineCredit {
@@ -91,6 +121,14 @@ export interface FindManyOptions {
91
121
  status?: string;
92
122
  authorId?: string;
93
123
  locale?: string;
124
+ /** Case-insensitive substring to match against `searchColumns`. */
125
+ q?: string;
126
+ /**
127
+ * Columns the `q` substring filter is applied to (OR'd together).
128
+ * Resolved by the handler from the collection's display fields so the
129
+ * repository stays generic. Each name is validated as a SQL identifier.
130
+ */
131
+ searchColumns?: string[];
94
132
  };
95
133
  orderBy?: {
96
134
  field: string;
@@ -437,6 +437,9 @@ export interface Database {
437
437
  _emdash_404_log: NotFoundLogTable;
438
438
  _emdash_bylines: BylineTable;
439
439
  _emdash_content_bylines: ContentBylineTable;
440
+ _emdash_byline_fields: BylineFieldTable;
441
+ _emdash_byline_field_values: BylineFieldValueTable;
442
+ _emdash_byline_field_group_values: BylineFieldGroupValueTable;
440
443
  _emdash_rate_limits: RateLimitTable;
441
444
  }
442
445
 
@@ -529,6 +532,47 @@ export interface ContentBylineTable {
529
532
  created_at: Generated<string>;
530
533
  }
531
534
 
535
+ // Byline custom fields (migration 041, Discussion #1174)
536
+ //
537
+ // `_emdash_byline_fields` stores definitions; values land in either
538
+ // `_emdash_byline_field_values` (translatable, keyed by byline row id) or
539
+ // `_emdash_byline_field_group_values` (non-translatable, keyed by
540
+ // translation_group). Per-field `translatable` flag picks the home table.
541
+
542
+ export interface BylineFieldTable {
543
+ id: string;
544
+ slug: string;
545
+ label: string;
546
+ /** One of: 'string', 'text', 'url', 'boolean', 'select'. v1 subset. */
547
+ type: string;
548
+ required: Generated<number>; // 0 or 1
549
+ /** 0 = group-shared, 1 = per-locale. Defaults to 1 at the DB level. */
550
+ translatable: Generated<number>;
551
+ /** JSON: `{ options?: string[] }` for `select`-type fields. */
552
+ validation: string | null;
553
+ sort_order: Generated<number>;
554
+ created_at: Generated<string>;
555
+ updated_at: Generated<string>;
556
+ }
557
+
558
+ export interface BylineFieldValueTable {
559
+ byline_id: string;
560
+ field_id: string;
561
+ /** JSON-encoded value (`CustomFieldValue` after parse). */
562
+ value: string | null;
563
+ created_at: Generated<string>;
564
+ updated_at: Generated<string>;
565
+ }
566
+
567
+ export interface BylineFieldGroupValueTable {
568
+ translation_group: string;
569
+ field_id: string;
570
+ /** JSON-encoded value (`CustomFieldValue` after parse). */
571
+ value: string | null;
572
+ created_at: Generated<string>;
573
+ updated_at: Generated<string>;
574
+ }
575
+
532
576
  // Rate Limits
533
577
 
534
578
  export interface RateLimitTable {
@@ -2122,6 +2122,7 @@ export class EmDashRuntime {
2122
2122
  orderBy?: string;
2123
2123
  order?: "asc" | "desc";
2124
2124
  locale?: string;
2125
+ q?: string;
2125
2126
  },
2126
2127
  ) {
2127
2128
  return handleContentList(this.db, collection, params);
@@ -2271,6 +2272,7 @@ export class EmDashRuntime {
2271
2272
  noIndex?: boolean;
2272
2273
  };
2273
2274
  publishedAt?: string | null;
2275
+ locale?: string;
2274
2276
  /** Skip revision creation (used by autosave) */
2275
2277
  skipRevision?: boolean;
2276
2278
  _rev?: string;
@@ -2279,7 +2281,7 @@ export class EmDashRuntime {
2279
2281
  // Resolve slug → ID if needed (before any lookups)
2280
2282
  const { ContentRepository } = await import("./database/repositories/content.js");
2281
2283
  const repo = new ContentRepository(this.db);
2282
- const resolvedItem = await repo.findByIdOrSlug(collection, id);
2284
+ const resolvedItem = await repo.findByIdOrSlug(collection, id, body.locale);
2283
2285
  const resolvedId = resolvedItem?.id ?? id;
2284
2286
 
2285
2287
  // Validate _rev early — before draft revision writes which modify updated_at.
@@ -2555,6 +2557,7 @@ export class EmDashRuntime {
2555
2557
  cursor?: string;
2556
2558
  limit?: number;
2557
2559
  mimeType?: string | readonly string[];
2560
+ q?: string;
2558
2561
  }) {
2559
2562
  return handleMediaList(this.db, params);
2560
2563
  }
package/src/index.ts CHANGED
@@ -96,6 +96,7 @@ export type {
96
96
  PortableTextTextBlock,
97
97
  PortableTextImageBlock,
98
98
  PortableTextCodeBlock,
99
+ PortableTextHtmlBlock,
99
100
  PortableTextUnknownBlock,
100
101
  ProseMirrorMark,
101
102
  ProseMirrorNode,
package/src/loader.ts CHANGED
@@ -25,8 +25,28 @@ import { isMissingColumnError, isMissingTableError } from "./utils/db-errors.js"
25
25
  const FIELD_NAME_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
26
26
 
27
27
  /**
28
- * System columns that are not part of the content data
28
+ * SEO columns joined in from `_emdash_seo` on the single-entry path, mapped to
29
+ * aliased result keys. SEO lives in a side table, so a LEFT JOIN folds it into
30
+ * the entry load at zero extra query cost; the result is surfaced as a nested
31
+ * `data.seo` object (see extractSeo) rather than flat fields.
32
+ *
33
+ * The `_emdash_` prefix on the aliases guarantees they can never collide with
34
+ * a content field. Field slugs must match `/^[a-z][a-z0-9_]*$/`, so a user can
35
+ * legitimately define a `seo_title` field; selecting the joined column under
36
+ * its bare name would shadow that field in the result set and drop the user's
37
+ * value. The prefix (illegal as a leading slug char) sidesteps this entirely.
29
38
  */
39
+ const SEO_COLUMN_ALIASES: Record<string, string> = {
40
+ seo_title: "_emdash_seo_title",
41
+ seo_description: "_emdash_seo_description",
42
+ seo_image: "_emdash_seo_image",
43
+ seo_canonical: "_emdash_seo_canonical",
44
+ seo_no_index: "_emdash_seo_no_index",
45
+ };
46
+
47
+ /** Aliased SEO result keys — excluded from generic field mapping. */
48
+ const SEO_ALIAS_COLUMNS = Object.values(SEO_COLUMN_ALIASES);
49
+
30
50
  /**
31
51
  * System columns excluded from entry.data
32
52
  * Note: slug is intentionally NOT excluded - it's useful as data.slug in templates
@@ -47,8 +67,46 @@ const SYSTEM_COLUMNS = new Set([
47
67
  "draft_revision_id",
48
68
  "locale",
49
69
  "translation_group",
70
+ // Aliased SEO columns joined from _emdash_seo on the single-entry path.
71
+ // Surfaced as a nested data.seo object (see extractSeo), never as flat
72
+ // fields. The aliases are _emdash_-prefixed so they can't shadow a user
73
+ // field named e.g. `seo_title`.
74
+ ...SEO_ALIAS_COLUMNS,
50
75
  ]);
51
76
 
77
+ /** Resolved SEO shape attached to `entry.data.seo`. Mirrors `ContentSeo`. */
78
+ interface EntrySeo {
79
+ title: string | null;
80
+ description: string | null;
81
+ image: string | null;
82
+ canonical: string | null;
83
+ noIndex: boolean;
84
+ }
85
+
86
+ /**
87
+ * Build a `data.seo` object from the joined `_emdash_seo` columns on a row.
88
+ *
89
+ * Returns `null` when no SEO row exists (LEFT JOIN miss → `seo_no_index` is
90
+ * NULL, since the column is `NOT NULL DEFAULT 0` whenever a row is present).
91
+ * Returning null keeps the `seo` key off entries that have none, so
92
+ * `getSeoMeta()` falls back to its defaults exactly as before.
93
+ */
94
+ function extractSeo(row: Record<string, unknown>): EntrySeo | null {
95
+ const noIndex = row[SEO_COLUMN_ALIASES.seo_no_index];
96
+ if (noIndex === null || noIndex === undefined) return null;
97
+ const title = row[SEO_COLUMN_ALIASES.seo_title];
98
+ const description = row[SEO_COLUMN_ALIASES.seo_description];
99
+ const image = row[SEO_COLUMN_ALIASES.seo_image];
100
+ const canonical = row[SEO_COLUMN_ALIASES.seo_canonical];
101
+ return {
102
+ title: typeof title === "string" ? title : null,
103
+ description: typeof description === "string" ? description : null,
104
+ image: typeof image === "string" ? image : null,
105
+ canonical: typeof canonical === "string" ? canonical : null,
106
+ noIndex: noIndex === 1,
107
+ };
108
+ }
109
+
52
110
  /**
53
111
  * Get the table name for a collection type
54
112
  */
@@ -809,18 +867,36 @@ export function emdashLoader(): LiveLoader<EntryData, EntryFilter, CollectionFil
809
867
 
810
868
  // Use raw SQL for dynamic table name, match by slug or id
811
869
  // When locale is specified, prefer locale-scoped slug match,
812
- // but IDs are globally unique so always check id without locale scope
870
+ // but IDs are globally unique so always check id without locale scope.
871
+ //
872
+ // LEFT JOIN _emdash_seo folds per-entry SEO (canonical, noindex,
873
+ // etc.) into this single query at zero extra round-trip cost. The
874
+ // joined columns are surfaced as a nested data.seo object via
875
+ // extractSeo() and excluded from the generic field mapping. SEO is
876
+ // 1:1 with content (PK on collection+content_id), so the join never
877
+ // multiplies rows.
878
+ const seoSelect = sql.join(
879
+ Object.entries(SEO_COLUMN_ALIASES).map(
880
+ ([col, alias]) => sql`${sql.ref(`s.${col}`)} AS ${sql.ref(alias)}`,
881
+ ),
882
+ );
813
883
  const result = locale
814
884
  ? await sql<Record<string, unknown>>`
815
- SELECT * FROM ${sql.ref(tableName)}
816
- WHERE deleted_at IS NULL
817
- AND ((slug = ${id} AND locale = ${locale}) OR id = ${id})
885
+ SELECT c.*, ${seoSelect}
886
+ FROM ${sql.ref(tableName)} AS c
887
+ LEFT JOIN ${sql.ref("_emdash_seo")} AS s
888
+ ON s.collection = ${type} AND s.content_id = c.id
889
+ WHERE c.deleted_at IS NULL
890
+ AND ((c.slug = ${id} AND c.locale = ${locale}) OR c.id = ${id})
818
891
  LIMIT 1
819
892
  `.execute(db)
820
893
  : await sql<Record<string, unknown>>`
821
- SELECT * FROM ${sql.ref(tableName)}
822
- WHERE deleted_at IS NULL
823
- AND (slug = ${id} OR id = ${id})
894
+ SELECT c.*, ${seoSelect}
895
+ FROM ${sql.ref(tableName)} AS c
896
+ LEFT JOIN ${sql.ref("_emdash_seo")} AS s
897
+ ON s.collection = ${type} AND s.content_id = c.id
898
+ WHERE c.deleted_at IS NULL
899
+ AND (c.slug = ${id} OR c.id = ${id})
824
900
  LIMIT 1
825
901
  `.execute(db);
826
902
 
@@ -872,11 +948,20 @@ export function emdashLoader(): LiveLoader<EntryData, EntryFilter, CollectionFil
872
948
  revLocale !== "" &&
873
949
  (revLocale !== i18nConfig.defaultLocale || i18nConfig.prefixDefaultLocale);
874
950
  const revId = shouldPrefixRev ? `${revLocale}/${revSlug}` : revSlug;
951
+ // SEO is not revisioned — it comes from the content row's
952
+ // joined _emdash_seo columns, not the revision snapshot.
953
+ const revEntryData: Record<string, unknown> = {
954
+ ...systemData,
955
+ slug,
956
+ ...mapRevisionData(parsed),
957
+ };
958
+ const revSeo = extractSeo(row);
959
+ if (revSeo) revEntryData.seo = revSeo;
875
960
  return {
876
961
  id: revId,
877
962
  slug,
878
963
  status: rowStr(row, "status", "draft"),
879
- data: { ...systemData, slug, ...mapRevisionData(parsed) },
964
+ data: revEntryData,
880
965
  cacheHint: {
881
966
  tags: [rowStr(row, "id")],
882
967
  lastModified: row.updated_at ? new Date(rowStr(row, "updated_at")) : undefined,
@@ -885,11 +970,14 @@ export function emdashLoader(): LiveLoader<EntryData, EntryFilter, CollectionFil
885
970
  }
886
971
  }
887
972
 
973
+ const entryData = mapRowToData(row);
974
+ const entrySeo = extractSeo(row);
975
+ if (entrySeo) entryData.seo = entrySeo;
888
976
  return {
889
977
  id: entryId,
890
978
  slug: rowStr(row, "slug"),
891
979
  status: rowStr(row, "status", "draft"),
892
- data: mapRowToData(row),
980
+ data: entryData,
893
981
  cacheHint: {
894
982
  tags: [rowStr(row, "id")],
895
983
  lastModified: row.updated_at ? new Date(rowStr(row, "updated_at")) : undefined,
package/src/mcp/server.ts CHANGED
@@ -632,6 +632,12 @@ export function createMcpServer(): McpServer {
632
632
  inputSchema: z.object({
633
633
  collection: z.string().describe("Collection slug"),
634
634
  id: z.string().describe("Content item ID or slug"),
635
+ locale: z
636
+ .string()
637
+ .optional()
638
+ .describe(
639
+ "Locale to scope slug lookup (e.g. 'fr'). Only affects slug resolution; IDs are globally unique.",
640
+ ),
635
641
  data: z
636
642
  .record(z.string(), z.unknown())
637
643
  .optional()
@@ -677,7 +683,7 @@ export function createMcpServer(): McpServer {
677
683
  const { emdash, userId, userRole } = getExtra(extra);
678
684
 
679
685
  // Fetch item to check ownership
680
- const existing = await emdash.handleContentGet(args.collection, args.id);
686
+ const existing = await emdash.handleContentGet(args.collection, args.id, args.locale);
681
687
  if (!existing.success) {
682
688
  return unwrap(existing);
683
689
  }
@@ -713,6 +719,7 @@ export function createMcpServer(): McpServer {
713
719
  data: args.data,
714
720
  slug: args.slug,
715
721
  authorId: userId,
722
+ locale: args.locale,
716
723
  seo: args.seo,
717
724
  bylines: args.bylines,
718
725
  publishedAt: args.publishedAt,
@@ -736,6 +743,7 @@ export function createMcpServer(): McpServer {
736
743
  data: args.data,
737
744
  slug: args.slug,
738
745
  authorId: userId,
746
+ locale: args.locale,
739
747
  seo: args.seo,
740
748
  bylines: args.bylines,
741
749
  publishedAt: args.publishedAt,
@@ -751,6 +759,7 @@ export function createMcpServer(): McpServer {
751
759
  data: args.data,
752
760
  slug: args.slug,
753
761
  authorId: userId,
762
+ locale: args.locale,
754
763
  seo: args.seo,
755
764
  bylines: args.bylines,
756
765
  publishedAt: args.publishedAt,
@@ -111,3 +111,26 @@ export function setRequestCacheEntry<T>(key: string, value: T): void {
111
111
  if (cache.has(key)) return;
112
112
  cache.set(key, Promise.resolve(value));
113
113
  }
114
+
115
+ /**
116
+ * Remove a key from the request-scoped cache.
117
+ *
118
+ * Used by write paths that need to invalidate a downstream read cache —
119
+ * `setRequestCacheEntry` deliberately doesn't overwrite, and `requestCached`
120
+ * returns the cached promise even after the underlying data has changed.
121
+ * Without an explicit clear, a `read → write → read` sequence in a single
122
+ * request can return stale data on the second read.
123
+ *
124
+ * Concrete case: `BylineRepository.update` invalidates
125
+ * `byline-field-group-values:${translation_group}` after writing a
126
+ * non-translatable custom-field value, so the post-update `findById`
127
+ * (and any later reads in the same request) see the fresh value.
128
+ *
129
+ * No-ops outside a request context.
130
+ */
131
+ export function clearRequestCacheEntry(key: string): void {
132
+ const ctx = getRequestContext();
133
+ if (!ctx) return;
134
+ const cache = store.get(ctx);
135
+ cache?.delete(key);
136
+ }