emdash 1.3.0 → 1.4.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 (970) hide show
  1. package/dist/{activation-Dim4YMM7.mjs → activation-CGlyigmg.mjs} +3 -3
  2. package/dist/{activation-Dim4YMM7.mjs.map → activation-CGlyigmg.mjs.map} +1 -1
  3. package/dist/{adapters-F_xorvWv.d.mts → adapters-D9a1PfqH.d.mts} +1 -1
  4. package/dist/{adapters-F_xorvWv.d.mts.map → adapters-D9a1PfqH.d.mts.map} +1 -1
  5. package/dist/{after-PcEvMY_6.mjs → after-32yNRvd2.mjs} +5 -2
  6. package/dist/{after-PcEvMY_6.mjs.map → after-32yNRvd2.mjs.map} +1 -1
  7. package/dist/api/route-utils.d.mts +4 -4
  8. package/dist/api/route-utils.mjs +50 -49
  9. package/dist/api/route-utils.mjs.map +1 -1
  10. package/dist/api/schemas/index.d.mts +1 -1
  11. package/dist/api/schemas/index.mjs +7 -7
  12. package/dist/{api-D-7BNHoz.mjs → api--PYoyeTo.mjs} +121 -48
  13. package/dist/api--PYoyeTo.mjs.map +1 -0
  14. package/dist/api-tokens-DqSlkDVI.mjs +9 -0
  15. package/dist/api-tokens-DqSlkDVI.mjs.map +1 -0
  16. package/dist/{api-tokens-Bx38ZCQp.mjs → api-tokens-GNCsIegW.mjs} +3 -3
  17. package/dist/{api-tokens-Bx38ZCQp.mjs.map → api-tokens-GNCsIegW.mjs.map} +1 -1
  18. package/dist/{apply-T7ATgzCh.mjs → apply-DVnupNeS.mjs} +149 -91
  19. package/dist/apply-DVnupNeS.mjs.map +1 -0
  20. package/dist/{approvals-D-m6wvGl.mjs → approvals-DTtYSB27.mjs} +2 -2
  21. package/dist/{approvals-D-m6wvGl.mjs.map → approvals-DTtYSB27.mjs.map} +1 -1
  22. package/dist/{artifacts-htGyfCSt.mjs → artifacts-Dvdp2KK-.mjs} +29 -13
  23. package/dist/artifacts-Dvdp2KK-.mjs.map +1 -0
  24. package/dist/astro/image-endpoint.mjs +12 -2
  25. package/dist/astro/image-endpoint.mjs.map +1 -1
  26. package/dist/astro/index.d.mts +15 -14
  27. package/dist/astro/index.d.mts.map +1 -1
  28. package/dist/astro/index.mjs +59 -8
  29. package/dist/astro/index.mjs.map +1 -1
  30. package/dist/astro/middleware/auth.d.mts +13 -12
  31. package/dist/astro/middleware/auth.d.mts.map +1 -1
  32. package/dist/astro/middleware/auth.mjs +10 -8
  33. package/dist/astro/middleware/auth.mjs.map +1 -1
  34. package/dist/astro/middleware/media-usage-write-fence.mjs +5 -5
  35. package/dist/astro/middleware/redirect.d.mts.map +1 -1
  36. package/dist/astro/middleware/redirect.mjs +129 -49
  37. package/dist/astro/middleware/redirect.mjs.map +1 -1
  38. package/dist/astro/middleware/request-context.d.mts.map +1 -1
  39. package/dist/astro/middleware/request-context.mjs +18 -9
  40. package/dist/astro/middleware/request-context.mjs.map +1 -1
  41. package/dist/astro/middleware.d.mts +13 -12
  42. package/dist/astro/middleware.d.mts.map +1 -1
  43. package/dist/astro/middleware.mjs +111 -101
  44. package/dist/astro/middleware.mjs.map +1 -1
  45. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +11 -11
  46. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +11 -11
  47. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +6 -6
  48. package/dist/astro/routes/api/admin/api-tokens/index.mjs +7 -7
  49. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +6 -6
  50. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +14 -14
  51. package/dist/astro/routes/api/admin/byline-fields/index.mjs +14 -14
  52. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +14 -14
  53. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +25 -25
  54. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +25 -25
  55. package/dist/astro/routes/api/admin/bylines/index.mjs +25 -25
  56. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +17 -17
  57. package/dist/astro/routes/api/admin/comments/_id_.mjs +8 -8
  58. package/dist/astro/routes/api/admin/comments/bulk.mjs +16 -16
  59. package/dist/astro/routes/api/admin/comments/counts.mjs +8 -8
  60. package/dist/astro/routes/api/admin/comments/index.mjs +16 -16
  61. package/dist/astro/routes/api/admin/core-update.mjs +6 -6
  62. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +5 -5
  63. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +4 -4
  64. package/dist/astro/routes/api/admin/media-usage/activation.mjs +18 -18
  65. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +19 -19
  66. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +19 -19
  67. package/dist/astro/routes/api/admin/media-usage/progress.mjs +22 -21
  68. package/dist/astro/routes/api/admin/media-usage/progress.mjs.map +1 -1
  69. package/dist/astro/routes/api/admin/media-usage/repair.mjs +26 -25
  70. package/dist/astro/routes/api/admin/media-usage/repair.mjs.map +1 -1
  71. package/dist/astro/routes/api/admin/media-usage/work/index.mjs +19 -19
  72. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +19 -19
  73. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +4 -4
  74. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +4 -4
  75. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +7 -7
  76. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +7 -7
  77. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +66 -65
  78. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  79. package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +5 -5
  80. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +66 -65
  81. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
  82. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +66 -65
  83. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  84. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +73 -72
  85. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  86. package/dist/astro/routes/api/admin/plugins/index.mjs +66 -65
  87. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  88. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +4 -4
  89. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +66 -65
  90. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  91. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +73 -72
  92. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  93. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +66 -65
  94. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  95. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +66 -65
  96. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  97. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +74 -73
  98. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  99. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +4 -4
  100. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +68 -67
  101. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  102. package/dist/astro/routes/api/admin/plugins/registry/publisher-handle.mjs +4 -4
  103. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs +67 -66
  104. package/dist/astro/routes/api/admin/plugins/registry/verify.mjs.map +1 -1
  105. package/dist/astro/routes/api/admin/plugins/updates.mjs +66 -65
  106. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  107. package/dist/astro/routes/api/admin/scheduled-policy-rejections/_collection_/_id_.mjs +5 -5
  108. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +66 -65
  109. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  110. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +4 -4
  111. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +66 -65
  112. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  113. package/dist/astro/routes/api/admin/transfer/_...path_.mjs +3 -3
  114. package/dist/astro/routes/api/admin/transfer/approvals/_id_/approve.mjs +33 -32
  115. package/dist/astro/routes/api/admin/transfer/approvals/_id_/approve.mjs.map +1 -1
  116. package/dist/astro/routes/api/admin/transfer/approvals/_id_/deny.mjs +33 -32
  117. package/dist/astro/routes/api/admin/transfer/approvals/_id_/deny.mjs.map +1 -1
  118. package/dist/astro/routes/api/admin/transfer/approvals/index.mjs +35 -34
  119. package/dist/astro/routes/api/admin/transfer/approvals/index.mjs.map +1 -1
  120. package/dist/astro/routes/api/admin/transfer/capabilities.mjs +35 -34
  121. package/dist/astro/routes/api/admin/transfer/capabilities.mjs.map +1 -1
  122. package/dist/astro/routes/api/admin/transfer/exports/_id_/advance.mjs +35 -34
  123. package/dist/astro/routes/api/admin/transfer/exports/_id_/advance.mjs.map +1 -1
  124. package/dist/astro/routes/api/admin/transfer/exports/_id_/archive.mjs +36 -35
  125. package/dist/astro/routes/api/admin/transfer/exports/_id_/archive.mjs.map +1 -1
  126. package/dist/astro/routes/api/admin/transfer/exports/_id_/files/_...path_.mjs +36 -35
  127. package/dist/astro/routes/api/admin/transfer/exports/_id_/files/_...path_.mjs.map +1 -1
  128. package/dist/astro/routes/api/admin/transfer/exports/_id_/index.mjs +35 -34
  129. package/dist/astro/routes/api/admin/transfer/exports/_id_/index.mjs.map +1 -1
  130. package/dist/astro/routes/api/admin/transfer/exports/_id_/manifest.mjs +36 -35
  131. package/dist/astro/routes/api/admin/transfer/exports/_id_/manifest.mjs.map +1 -1
  132. package/dist/astro/routes/api/admin/transfer/exports/index.mjs +37 -36
  133. package/dist/astro/routes/api/admin/transfer/exports/index.mjs.map +1 -1
  134. package/dist/astro/routes/api/admin/transfer/imports/_id_/abandon.mjs +35 -34
  135. package/dist/astro/routes/api/admin/transfer/imports/_id_/abandon.mjs.map +1 -1
  136. package/dist/astro/routes/api/admin/transfer/imports/_id_/advance.mjs +35 -34
  137. package/dist/astro/routes/api/admin/transfer/imports/_id_/advance.mjs.map +1 -1
  138. package/dist/astro/routes/api/admin/transfer/imports/_id_/analyze.mjs +37 -36
  139. package/dist/astro/routes/api/admin/transfer/imports/_id_/analyze.mjs.map +1 -1
  140. package/dist/astro/routes/api/admin/transfer/imports/_id_/cancel.mjs +35 -34
  141. package/dist/astro/routes/api/admin/transfer/imports/_id_/cancel.mjs.map +1 -1
  142. package/dist/astro/routes/api/admin/transfer/imports/_id_/execute.mjs +37 -36
  143. package/dist/astro/routes/api/admin/transfer/imports/_id_/execute.mjs.map +1 -1
  144. package/dist/astro/routes/api/admin/transfer/imports/_id_/files/_...path_.mjs +35 -34
  145. package/dist/astro/routes/api/admin/transfer/imports/_id_/files/_...path_.mjs.map +1 -1
  146. package/dist/astro/routes/api/admin/transfer/imports/_id_/index.mjs +35 -34
  147. package/dist/astro/routes/api/admin/transfer/imports/_id_/index.mjs.map +1 -1
  148. package/dist/astro/routes/api/admin/transfer/imports/_id_/missing.mjs +37 -36
  149. package/dist/astro/routes/api/admin/transfer/imports/_id_/missing.mjs.map +1 -1
  150. package/dist/astro/routes/api/admin/transfer/imports/_id_/plan.mjs +35 -34
  151. package/dist/astro/routes/api/admin/transfer/imports/_id_/plan.mjs.map +1 -1
  152. package/dist/astro/routes/api/admin/transfer/imports/_id_/receipt.mjs +35 -34
  153. package/dist/astro/routes/api/admin/transfer/imports/_id_/receipt.mjs.map +1 -1
  154. package/dist/astro/routes/api/admin/transfer/imports/index.mjs +37 -36
  155. package/dist/astro/routes/api/admin/transfer/imports/index.mjs.map +1 -1
  156. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +4 -4
  157. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +3 -3
  158. package/dist/astro/routes/api/admin/users/_id_/index.mjs +12 -12
  159. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +4 -4
  160. package/dist/astro/routes/api/admin/users/index.mjs +11 -11
  161. package/dist/astro/routes/api/auth/dev-bypass.mjs +3 -3
  162. package/dist/astro/routes/api/auth/handover.mjs +5 -5
  163. package/dist/astro/routes/api/auth/invite/accept.mjs +3 -3
  164. package/dist/astro/routes/api/auth/invite/complete.mjs +15 -15
  165. package/dist/astro/routes/api/auth/invite/index.mjs +12 -12
  166. package/dist/astro/routes/api/auth/invite/register-options.mjs +13 -13
  167. package/dist/astro/routes/api/auth/logout.mjs +3 -3
  168. package/dist/astro/routes/api/auth/magic-link/send.mjs +14 -14
  169. package/dist/astro/routes/api/auth/magic-link/verify.mjs +13 -13
  170. package/dist/astro/routes/api/auth/me.mjs +12 -12
  171. package/dist/astro/routes/api/auth/mode.mjs +3 -3
  172. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +8 -8
  173. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +1 -1
  174. package/dist/astro/routes/api/auth/passkey/_id_.mjs +11 -11
  175. package/dist/astro/routes/api/auth/passkey/index.mjs +3 -3
  176. package/dist/astro/routes/api/auth/passkey/options.mjs +15 -15
  177. package/dist/astro/routes/api/auth/passkey/register/options.mjs +13 -13
  178. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +13 -13
  179. package/dist/astro/routes/api/auth/passkey/verify.mjs +15 -15
  180. package/dist/astro/routes/api/auth/signup/complete.mjs +15 -15
  181. package/dist/astro/routes/api/auth/signup/request.mjs +13 -13
  182. package/dist/astro/routes/api/auth/signup/verify.mjs +3 -3
  183. package/dist/astro/routes/api/calendar.mjs +12 -12
  184. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +12 -12
  185. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +17 -17
  186. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +4 -4
  187. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +15 -15
  188. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +4 -4
  189. package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs +15 -15
  190. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +4 -4
  191. package/dist/astro/routes/api/content/_collection_/_id_/plugin-extensions/_pluginId_/_kind_/_extensionId_.mjs +9 -9
  192. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +29 -28
  193. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs.map +1 -1
  194. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +15 -15
  195. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +34 -33
  196. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
  197. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +34 -33
  198. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
  199. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +4 -4
  200. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +4 -4
  201. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +15 -15
  202. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.d.mts.map +1 -1
  203. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +35 -27
  204. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  205. package/dist/astro/routes/api/content/_collection_/_id_/translations.d.mts.map +1 -1
  206. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +8 -4
  207. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs.map +1 -1
  208. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +15 -15
  209. package/dist/astro/routes/api/content/_collection_/_id_.mjs +15 -15
  210. package/dist/astro/routes/api/content/_collection_/authors.mjs +4 -4
  211. package/dist/astro/routes/api/content/_collection_/index.mjs +12 -12
  212. package/dist/astro/routes/api/content/_collection_/trash.mjs +12 -12
  213. package/dist/astro/routes/api/dashboard.mjs +22 -16
  214. package/dist/astro/routes/api/dashboard.mjs.map +1 -1
  215. package/dist/astro/routes/api/dev/emails.mjs +3 -3
  216. package/dist/astro/routes/api/dev/scheduled-tasks.mjs +97 -95
  217. package/dist/astro/routes/api/dev/scheduled-tasks.mjs.map +1 -1
  218. package/dist/astro/routes/api/health.mjs +4 -4
  219. package/dist/astro/routes/api/import/probe.d.mts +4 -3
  220. package/dist/astro/routes/api/import/probe.d.mts.map +1 -1
  221. package/dist/astro/routes/api/import/probe.mjs +27 -25
  222. package/dist/astro/routes/api/import/probe.mjs.map +1 -1
  223. package/dist/astro/routes/api/import/wordpress/analyze.d.mts +4 -3
  224. package/dist/astro/routes/api/import/wordpress/analyze.d.mts.map +1 -1
  225. package/dist/astro/routes/api/import/wordpress/analyze.mjs +7 -29
  226. package/dist/astro/routes/api/import/wordpress/analyze.mjs.map +1 -1
  227. package/dist/astro/routes/api/import/wordpress/execute.d.mts +14 -13
  228. package/dist/astro/routes/api/import/wordpress/execute.d.mts.map +1 -1
  229. package/dist/astro/routes/api/import/wordpress/execute.mjs +29 -29
  230. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  231. package/dist/astro/routes/api/import/wordpress/media.d.mts +13 -12
  232. package/dist/astro/routes/api/import/wordpress/media.d.mts.map +1 -1
  233. package/dist/astro/routes/api/import/wordpress/media.mjs +14 -14
  234. package/dist/astro/routes/api/import/wordpress/prepare.mjs +19 -19
  235. package/dist/astro/routes/api/import/wordpress/prepare.mjs.map +1 -1
  236. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +14 -13
  237. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts.map +1 -1
  238. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +25 -24
  239. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
  240. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  241. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +27 -25
  242. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs.map +1 -1
  243. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +14 -13
  244. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts.map +1 -1
  245. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +39 -38
  246. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  247. package/dist/astro/routes/api/manifest.mjs +4 -4
  248. package/dist/astro/routes/api/mcp.mjs +99 -83
  249. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  250. package/dist/astro/routes/api/media/_id_/confirm.mjs +16 -16
  251. package/dist/astro/routes/api/media/_id_/replace.mjs +12 -12
  252. package/dist/astro/routes/api/media/_id_/upload.mjs +6 -6
  253. package/dist/astro/routes/api/media/_id_/usage.mjs +28 -27
  254. package/dist/astro/routes/api/media/_id_/usage.mjs.map +1 -1
  255. package/dist/astro/routes/api/media/_id_.mjs +26 -25
  256. package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
  257. package/dist/astro/routes/api/media/asset/_id_/_filename_.mjs +5 -5
  258. package/dist/astro/routes/api/media/file/_...key_.d.mts.map +1 -1
  259. package/dist/astro/routes/api/media/file/_...key_.mjs +62 -8
  260. package/dist/astro/routes/api/media/file/_...key_.mjs.map +1 -1
  261. package/dist/astro/routes/api/media/folders/_id_.mjs +13 -13
  262. package/dist/astro/routes/api/media/folders/index.mjs +13 -13
  263. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +4 -4
  264. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +4 -4
  265. package/dist/astro/routes/api/media/providers/index.mjs +4 -4
  266. package/dist/astro/routes/api/media/upload-url.mjs +15 -15
  267. package/dist/astro/routes/api/media.mjs +30 -29
  268. package/dist/astro/routes/api/media.mjs.map +1 -1
  269. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +17 -15
  270. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs.map +1 -1
  271. package/dist/astro/routes/api/menus/_name_/items.mjs +17 -15
  272. package/dist/astro/routes/api/menus/_name_/items.mjs.map +1 -1
  273. package/dist/astro/routes/api/menus/_name_/reorder.mjs +17 -15
  274. package/dist/astro/routes/api/menus/_name_/reorder.mjs.map +1 -1
  275. package/dist/astro/routes/api/menus/_name_/translations.mjs +17 -15
  276. package/dist/astro/routes/api/menus/_name_/translations.mjs.map +1 -1
  277. package/dist/astro/routes/api/menus/_name_.mjs +17 -15
  278. package/dist/astro/routes/api/menus/_name_.mjs.map +1 -1
  279. package/dist/astro/routes/api/menus/index.mjs +17 -15
  280. package/dist/astro/routes/api/menus/index.mjs.map +1 -1
  281. package/dist/astro/routes/api/oauth/authorize.mjs +2 -2
  282. package/dist/astro/routes/api/oauth/device/authorize.mjs +6 -6
  283. package/dist/astro/routes/api/oauth/device/code.mjs +8 -8
  284. package/dist/astro/routes/api/oauth/device/token.mjs +8 -8
  285. package/dist/astro/routes/api/oauth/register.mjs +5 -5
  286. package/dist/astro/routes/api/oauth/token/refresh.mjs +6 -6
  287. package/dist/astro/routes/api/oauth/token/revoke.mjs +6 -6
  288. package/dist/astro/routes/api/oauth/token.d.mts.map +1 -1
  289. package/dist/astro/routes/api/oauth/token.mjs +7 -7
  290. package/dist/astro/routes/api/oauth/token.mjs.map +1 -1
  291. package/dist/astro/routes/api/openapi.json.mjs +12 -12
  292. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +9 -9
  293. package/dist/astro/routes/api/redirects/404s/index.mjs +20 -19
  294. package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
  295. package/dist/astro/routes/api/redirects/404s/summary.mjs +20 -19
  296. package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
  297. package/dist/astro/routes/api/redirects/_id_.mjs +21 -20
  298. package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
  299. package/dist/astro/routes/api/redirects/index.mjs +21 -20
  300. package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
  301. package/dist/astro/routes/api/relations/_id_/index.mjs +34 -33
  302. package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
  303. package/dist/astro/routes/api/relations/index.mjs +34 -33
  304. package/dist/astro/routes/api/relations/index.mjs.map +1 -1
  305. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +4 -4
  306. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +15 -15
  307. package/dist/astro/routes/api/schema/block-types/_slug_/index.mjs +66 -65
  308. package/dist/astro/routes/api/schema/block-types/_slug_/index.mjs.map +1 -1
  309. package/dist/astro/routes/api/schema/block-types/_slug_/versions/_version_/activate.mjs +66 -65
  310. package/dist/astro/routes/api/schema/block-types/_slug_/versions/_version_/activate.mjs.map +1 -1
  311. package/dist/astro/routes/api/schema/block-types/index.mjs +66 -65
  312. package/dist/astro/routes/api/schema/block-types/index.mjs.map +1 -1
  313. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +66 -65
  314. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  315. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +66 -65
  316. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  317. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +66 -65
  318. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  319. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +66 -65
  320. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  321. package/dist/astro/routes/api/schema/collections/index.mjs +66 -65
  322. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  323. package/dist/astro/routes/api/schema/collections/reorder.mjs +66 -65
  324. package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
  325. package/dist/astro/routes/api/schema/index.mjs +17 -16
  326. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  327. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +66 -65
  328. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  329. package/dist/astro/routes/api/schema/orphans/index.mjs +66 -65
  330. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  331. package/dist/astro/routes/api/search/enable.mjs +20 -18
  332. package/dist/astro/routes/api/search/enable.mjs.map +1 -1
  333. package/dist/astro/routes/api/search/index.mjs +19 -17
  334. package/dist/astro/routes/api/search/index.mjs.map +1 -1
  335. package/dist/astro/routes/api/search/rebuild.mjs +20 -18
  336. package/dist/astro/routes/api/search/rebuild.mjs.map +1 -1
  337. package/dist/astro/routes/api/search/stats.mjs +13 -11
  338. package/dist/astro/routes/api/search/stats.mjs.map +1 -1
  339. package/dist/astro/routes/api/search/suggest.mjs +19 -17
  340. package/dist/astro/routes/api/search/suggest.mjs.map +1 -1
  341. package/dist/astro/routes/api/sections/_slug_.mjs +19 -17
  342. package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
  343. package/dist/astro/routes/api/sections/index.mjs +19 -17
  344. package/dist/astro/routes/api/sections/index.mjs.map +1 -1
  345. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +7 -7
  346. package/dist/astro/routes/api/settings/backups/archives/index.mjs +7 -7
  347. package/dist/astro/routes/api/settings/backups/export.mjs +7 -7
  348. package/dist/astro/routes/api/settings/backups/index.mjs +8 -8
  349. package/dist/astro/routes/api/settings/domain-notify.mjs +7 -7
  350. package/dist/astro/routes/api/settings/domain.mjs +19 -17
  351. package/dist/astro/routes/api/settings/domain.mjs.map +1 -1
  352. package/dist/astro/routes/api/settings/email.mjs +5 -5
  353. package/dist/astro/routes/api/settings.mjs +25 -23
  354. package/dist/astro/routes/api/settings.mjs.map +1 -1
  355. package/dist/astro/routes/api/setup/admin-verify.mjs +18 -18
  356. package/dist/astro/routes/api/setup/admin.mjs +14 -14
  357. package/dist/astro/routes/api/setup/dev-bypass.mjs +45 -44
  358. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  359. package/dist/astro/routes/api/setup/dev-reset.mjs +3 -3
  360. package/dist/astro/routes/api/setup/index.mjs +48 -47
  361. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  362. package/dist/astro/routes/api/setup/status.mjs +4 -4
  363. package/dist/astro/routes/api/site/domain-proof.mjs +17 -15
  364. package/dist/astro/routes/api/site/domain-proof.mjs.map +1 -1
  365. package/dist/astro/routes/api/snapshot.mjs +9 -9
  366. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +25 -24
  367. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs.map +1 -1
  368. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +25 -24
  369. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
  370. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +25 -24
  371. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
  372. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +25 -24
  373. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
  374. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +25 -24
  375. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs.map +1 -1
  376. package/dist/astro/routes/api/taxonomies/_name_.mjs +25 -24
  377. package/dist/astro/routes/api/taxonomies/_name_.mjs.map +1 -1
  378. package/dist/astro/routes/api/taxonomies/bulk-tag.mjs +35 -34
  379. package/dist/astro/routes/api/taxonomies/bulk-tag.mjs.map +1 -1
  380. package/dist/astro/routes/api/taxonomies/index.mjs +25 -24
  381. package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
  382. package/dist/astro/routes/api/themes/preview.mjs +6 -6
  383. package/dist/astro/routes/api/typegen.mjs +5 -5
  384. package/dist/astro/routes/api/visual-editing/action-token.mjs +5 -5
  385. package/dist/astro/routes/api/visual-editing/content/_collection_/_id_/publish.mjs +17 -17
  386. package/dist/astro/routes/api/visual-editing/toolbar-labels.mjs +3 -3
  387. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +1 -1
  388. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +1 -1
  389. package/dist/astro/routes/api/widget-areas/_name_/reorder.d.mts.map +1 -1
  390. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +24 -13
  391. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs.map +1 -1
  392. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.d.mts.map +1 -1
  393. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +22 -17
  394. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs.map +1 -1
  395. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +21 -17
  396. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs.map +1 -1
  397. package/dist/astro/routes/api/widget-areas/_name_.mjs +14 -10
  398. package/dist/astro/routes/api/widget-areas/_name_.mjs.map +1 -1
  399. package/dist/astro/routes/api/widget-areas/index.mjs +21 -17
  400. package/dist/astro/routes/api/widget-areas/index.mjs.map +1 -1
  401. package/dist/astro/routes/api/widget-components.mjs +3 -3
  402. package/dist/astro/routes/robots.txt.mjs +16 -14
  403. package/dist/astro/routes/robots.txt.mjs.map +1 -1
  404. package/dist/astro/routes/sitemap-_collection_.xml.mjs +18 -16
  405. package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
  406. package/dist/astro/routes/sitemap.xml.mjs +16 -14
  407. package/dist/astro/routes/sitemap.xml.mjs.map +1 -1
  408. package/dist/astro/types.d.mts +22 -20
  409. package/dist/astro/types.d.mts.map +1 -1
  410. package/dist/{audit-_gieLVGU.mjs → audit-B8XE-0UV.mjs} +2 -2
  411. package/dist/{audit-_gieLVGU.mjs.map → audit-B8XE-0UV.mjs.map} +1 -1
  412. package/dist/auth/providers/github.d.mts +1 -1
  413. package/dist/auth/providers/google.d.mts +1 -1
  414. package/dist/auth/providers/microsoft.d.mts +1 -1
  415. package/dist/{authorize-DPFBGbE6.mjs → authorize-NJgp8kLI.mjs} +2 -2
  416. package/dist/{authorize-DPFBGbE6.mjs.map → authorize-NJgp8kLI.mjs.map} +1 -1
  417. package/dist/{backup-3FgVxiDJ.mjs → backup-8rPSJ28a.mjs} +4 -4
  418. package/dist/{backup-3FgVxiDJ.mjs.map → backup-8rPSJ28a.mjs.map} +1 -1
  419. package/dist/{block-types-CYcG56JB.mjs → block-types-BbOrfnWs.mjs} +5 -5
  420. package/dist/{block-types-CYcG56JB.mjs.map → block-types-BbOrfnWs.mjs.map} +1 -1
  421. package/dist/{block-values-gCX4HBSl.mjs → block-values-Dg0-8PPS.mjs} +4 -4
  422. package/dist/{block-values-gCX4HBSl.mjs.map → block-values-Dg0-8PPS.mjs.map} +1 -1
  423. package/dist/{byline-BR1qhyiw.mjs → byline-DHJS-GGb.mjs} +123 -38
  424. package/dist/byline-DHJS-GGb.mjs.map +1 -0
  425. package/dist/{byline-fields-BLXZnX7N.mjs → byline-fields-CiR8FvvF.mjs} +3 -3
  426. package/dist/{byline-fields-BLXZnX7N.mjs.map → byline-fields-CiR8FvvF.mjs.map} +1 -1
  427. package/dist/{byline-fields-4ClDC88c.mjs → byline-fields-D6KYsEa7.mjs} +2 -2
  428. package/dist/{byline-fields-4ClDC88c.mjs.map → byline-fields-D6KYsEa7.mjs.map} +1 -1
  429. package/dist/{byline-registry-dvt4N3xV.mjs → byline-registry-BhzpO41z.mjs} +3 -3
  430. package/dist/{byline-registry-dvt4N3xV.mjs.map → byline-registry-BhzpO41z.mjs.map} +1 -1
  431. package/dist/{bylines-CVOvRUL7.mjs → bylines-Bsg5cH4S.mjs} +7 -7
  432. package/dist/bylines-Bsg5cH4S.mjs.map +1 -0
  433. package/dist/{bylines-DxOs9B7z.mjs → bylines-f_ZEc6Sn.mjs} +8 -8
  434. package/dist/{bylines-DxOs9B7z.mjs.map → bylines-f_ZEc6Sn.mjs.map} +1 -1
  435. package/dist/{cache-CEU9wo_h.mjs → cache-5DHbpEWu.mjs} +4 -4
  436. package/dist/{cache-CEU9wo_h.mjs.map → cache-5DHbpEWu.mjs.map} +1 -1
  437. package/dist/{capture-triggers-CT6dK9zd.mjs → capture-triggers-BezAvWcB.mjs} +2 -2
  438. package/dist/{capture-triggers-CT6dK9zd.mjs.map → capture-triggers-BezAvWcB.mjs.map} +1 -1
  439. package/dist/{challenge-store-C17BYx2-.mjs → challenge-store-B1C0V4b3.mjs} +1 -1
  440. package/dist/{challenge-store-C17BYx2-.mjs.map → challenge-store-B1C0V4b3.mjs.map} +1 -1
  441. package/dist/{chunks-xC4UD5-S.mjs → chunks-DiW8VMwz.mjs} +2 -2
  442. package/dist/{chunks-xC4UD5-S.mjs.map → chunks-DiW8VMwz.mjs.map} +1 -1
  443. package/dist/cli/index.mjs +53 -52
  444. package/dist/cli/index.mjs.map +1 -1
  445. package/dist/client/cf-access.d.mts +1 -1
  446. package/dist/client/index.d.mts +61 -61
  447. package/dist/client/index.d.mts.map +1 -1
  448. package/dist/client/index.mjs +3 -2
  449. package/dist/client/index.mjs.map +1 -1
  450. package/dist/{collection-slugs-cache-e09QeJQt.mjs → collection-slugs-cache-DIrLjqH-.mjs} +20 -14
  451. package/dist/collection-slugs-cache-DIrLjqH-.mjs.map +1 -0
  452. package/dist/{comment-UvIWDKcW.mjs → comment-DB74Zpa4.mjs} +18 -8
  453. package/dist/comment-DB74Zpa4.mjs.map +1 -0
  454. package/dist/{comment-reaction-dGp6_FRo.mjs → comment-reaction-BScxIWUn.mjs} +2 -2
  455. package/dist/{comment-reaction-dGp6_FRo.mjs.map → comment-reaction-BScxIWUn.mjs.map} +1 -1
  456. package/dist/{comments-pej-_BUO.mjs → comments-Cor_zKml.mjs} +3 -3
  457. package/dist/{comments-pej-_BUO.mjs.map → comments-Cor_zKml.mjs.map} +1 -1
  458. package/dist/config-Cs_AwWXI.mjs +106 -0
  459. package/dist/config-Cs_AwWXI.mjs.map +1 -0
  460. package/dist/{config-CFMojMFK.d.mts → config-D44_8G9J.d.mts} +3 -1
  461. package/dist/config-D44_8G9J.d.mts.map +1 -0
  462. package/dist/{config-Bsm_u_oE.d.mts → config-sDhZvkLR.d.mts} +56 -20
  463. package/dist/config-sDhZvkLR.d.mts.map +1 -0
  464. package/dist/{content-DQSRZTVw.mjs → content-BKHUVsE5.mjs} +67 -30
  465. package/dist/content-BKHUVsE5.mjs.map +1 -0
  466. package/dist/{content-list-query-CYKcY6Vi.d.mts → content-list-query-ByP4jRpZ.d.mts} +1 -1
  467. package/dist/{content-list-query-CYKcY6Vi.d.mts.map → content-list-query-ByP4jRpZ.d.mts.map} +1 -1
  468. package/dist/{content-policy-Dm32n9C6.mjs → content-policy-BmE0MPZY.mjs} +1 -1
  469. package/dist/{content-policy-Dm32n9C6.mjs.map → content-policy-BmE0MPZY.mjs.map} +1 -1
  470. package/dist/{content-repair-DNh5--x5.mjs → content-repair-Ukdxoq-R.mjs} +4 -4
  471. package/dist/{content-repair-DNh5--x5.mjs.map → content-repair-Ukdxoq-R.mjs.map} +1 -1
  472. package/dist/{context-BYptmCN0.mjs → context-CzjejcsE.mjs} +32 -33
  473. package/dist/context-CzjejcsE.mjs.map +1 -0
  474. package/dist/{credits-B9iORdWB.mjs → credits-BKREepht.mjs} +3 -3
  475. package/dist/{credits-B9iORdWB.mjs.map → credits-BKREepht.mjs.map} +1 -1
  476. package/dist/{dashboard-D0jcgBD7.mjs → dashboard-ynr1qJWM.mjs} +10 -9
  477. package/dist/dashboard-ynr1qJWM.mjs.map +1 -0
  478. package/dist/database/migration-lock.mjs +1 -1
  479. package/dist/db/index.d.mts +3 -3
  480. package/dist/db/index.mjs +3 -3
  481. package/dist/db/libsql-migrations.d.mts +1 -1
  482. package/dist/db/libsql-migrations.mjs +5 -5
  483. package/dist/db/libsql.d.mts +1 -1
  484. package/dist/db/postgres-migrations.d.mts +1 -1
  485. package/dist/db/postgres-migrations.mjs +5 -5
  486. package/dist/db/postgres.d.mts +1 -1
  487. package/dist/db/sqlite-migrations.d.mts +1 -1
  488. package/dist/db/sqlite-migrations.mjs +5 -5
  489. package/dist/db/sqlite.d.mts +1 -1
  490. package/dist/{db-errors-CBD5yMro.mjs → db-errors-unnO6yiZ.mjs} +12 -2
  491. package/dist/db-errors-unnO6yiZ.mjs.map +1 -0
  492. package/dist/deferred-tasks-wlMFJL95.d.mts +10 -0
  493. package/dist/deferred-tasks-wlMFJL95.d.mts.map +1 -0
  494. package/dist/{destination-r2zIAZ2S.mjs → destination-DR3IHjmy.mjs} +1 -1
  495. package/dist/{destination-r2zIAZ2S.mjs.map → destination-DR3IHjmy.mjs.map} +1 -1
  496. package/dist/{device-flow-BkFKBoAn.mjs → device-flow-D1U392GC.mjs} +3 -5
  497. package/dist/device-flow-D1U392GC.mjs.map +1 -0
  498. package/dist/{dialect-helpers-7_IqPdh9.mjs → dialect-helpers-B1XN2HGB.mjs} +10 -3
  499. package/dist/dialect-helpers-B1XN2HGB.mjs.map +1 -0
  500. package/dist/{direct-executor-Cbxzg4qe.mjs → direct-executor-Bs2g0ake.mjs} +4 -4
  501. package/dist/{direct-executor-Cbxzg4qe.mjs.map → direct-executor-Bs2g0ake.mjs.map} +1 -1
  502. package/dist/{dist-Cfu8mMBs.mjs → dist-BUmWMTbN.mjs} +1 -1
  503. package/dist/{dist-Cfu8mMBs.mjs.map → dist-BUmWMTbN.mjs.map} +1 -1
  504. package/dist/{email-locale-BJ8DjTzZ.mjs → email-locale-Bs3HFdnq.mjs} +1 -1
  505. package/dist/{email-locale-BJ8DjTzZ.mjs.map → email-locale-Bs3HFdnq.mjs.map} +1 -1
  506. package/dist/{emdash-runtime-DVi7vtXC.mjs → emdash-runtime-C8T-pZpS.mjs} +108 -62
  507. package/dist/emdash-runtime-C8T-pZpS.mjs.map +1 -0
  508. package/dist/{enrich-Duu4sV3a.mjs → enrich-DFlfnd3u.mjs} +3 -3
  509. package/dist/{enrich-Duu4sV3a.mjs.map → enrich-DFlfnd3u.mjs.map} +1 -1
  510. package/dist/{entry-lock-C7VX0NGK.d.mts → entry-lock-BulbgPBX.d.mts} +23 -23
  511. package/dist/{entry-lock-C7VX0NGK.d.mts.map → entry-lock-BulbgPBX.d.mts.map} +1 -1
  512. package/dist/{entry-lock-Df6-XhIu.mjs → entry-lock-CRVmruM0.mjs} +4 -4
  513. package/dist/{entry-lock-Df6-XhIu.mjs.map → entry-lock-CRVmruM0.mjs.map} +1 -1
  514. package/dist/{entry-lock-DLxCffFW.mjs → entry-lock-D-zJQ4q6.mjs} +3 -3
  515. package/dist/{entry-lock-DLxCffFW.mjs.map → entry-lock-D-zJQ4q6.mjs.map} +1 -1
  516. package/dist/{entry-locks-DJAqVweV.mjs → entry-locks-CJ9uhqg1.mjs} +2 -2
  517. package/dist/{entry-locks-DJAqVweV.mjs.map → entry-locks-CJ9uhqg1.mjs.map} +1 -1
  518. package/dist/{env-types-C3FCVBWe.mjs → env-types-BE3bCvfP.mjs} +5 -5
  519. package/dist/{env-types-C3FCVBWe.mjs.map → env-types-BE3bCvfP.mjs.map} +1 -1
  520. package/dist/{error-CVWeIOku.mjs → error-BCMgPxdn.mjs} +3 -3
  521. package/dist/{error-CVWeIOku.mjs.map → error-BCMgPxdn.mjs.map} +1 -1
  522. package/dist/{errors-BOYNdIo3.mjs → errors-8gJqv-XV.mjs} +15 -2
  523. package/dist/{errors-BOYNdIo3.mjs.map → errors-8gJqv-XV.mjs.map} +1 -1
  524. package/dist/{fence-C3MUitUN.mjs → fence-Dagicj14.mjs} +4 -4
  525. package/dist/{fence-C3MUitUN.mjs.map → fence-Dagicj14.mjs.map} +1 -1
  526. package/dist/{field-map-Bft9LKak.mjs → field-map-BSXdNGt5.mjs} +11 -10
  527. package/dist/field-map-BSXdNGt5.mjs.map +1 -0
  528. package/dist/{focal-point-JX8kcOTQ.mjs → focal-point-CgCcr1Ca.mjs} +1 -1
  529. package/dist/{focal-point-JX8kcOTQ.mjs.map → focal-point-CgCcr1Ca.mjs.map} +1 -1
  530. package/dist/{fts-manager-Beg3e4bI.mjs → fts-manager-6861qcwk.mjs} +68 -22
  531. package/dist/fts-manager-6861qcwk.mjs.map +1 -0
  532. package/dist/{gc-ByyAYiYE.mjs → gc-CNkXB3mE.mjs} +8 -8
  533. package/dist/{gc-ByyAYiYE.mjs.map → gc-CNkXB3mE.mjs.map} +1 -1
  534. package/dist/{hook-result-BrdLyOdI.d.mts → hook-result-f8t7hIuu.d.mts} +1 -1
  535. package/dist/{hook-result-BrdLyOdI.d.mts.map → hook-result-f8t7hIuu.d.mts.map} +1 -1
  536. package/dist/{hreflang-CY_F5OjF.d.mts → hreflang-8dUOJAPJ.d.mts} +2 -2
  537. package/dist/{hreflang-CY_F5OjF.d.mts.map → hreflang-8dUOJAPJ.d.mts.map} +1 -1
  538. package/dist/{hreflang-C8Jb-hrf.mjs → hreflang-BW5A4FLK.mjs} +8 -8
  539. package/dist/{hreflang-C8Jb-hrf.mjs.map → hreflang-BW5A4FLK.mjs.map} +1 -1
  540. package/dist/{http-route-dispatch-CyeW6iPv.mjs → http-route-dispatch-rXKvTNm9.mjs} +5 -5
  541. package/dist/{http-route-dispatch-CyeW6iPv.mjs.map → http-route-dispatch-rXKvTNm9.mjs.map} +1 -1
  542. package/dist/{identity-Cael5uTT.mjs → identity-CPRRSovU.mjs} +3 -3
  543. package/dist/{identity-Cael5uTT.mjs.map → identity-CPRRSovU.mjs.map} +1 -1
  544. package/dist/{import-BUXjdZUn.mjs → import-yVbfPyfd.mjs} +5 -5
  545. package/dist/{import-BUXjdZUn.mjs.map → import-yVbfPyfd.mjs.map} +1 -1
  546. package/dist/index-VM7Fzxwe.d.mts +260 -0
  547. package/dist/index-VM7Fzxwe.d.mts.map +1 -0
  548. package/dist/index.d.mts +25 -24
  549. package/dist/index.mjs +89 -88
  550. package/dist/{install-finalization-3JX5qQEA.mjs → install-finalization-RU6VrHOX.mjs} +1 -1
  551. package/dist/{install-finalization-3JX5qQEA.mjs.map → install-finalization-RU6VrHOX.mjs.map} +1 -1
  552. package/dist/{json-recordset-BUjxhr77.mjs → json-recordset-D0WhN2UA.mjs} +2 -2
  553. package/dist/{json-recordset-BUjxhr77.mjs.map → json-recordset-D0WhN2UA.mjs.map} +1 -1
  554. package/dist/{lifecycle-7vUJeFRe.mjs → lifecycle-B8d7Rdqx.mjs} +1 -1
  555. package/dist/{lifecycle-7vUJeFRe.mjs.map → lifecycle-B8d7Rdqx.mjs.map} +1 -1
  556. package/dist/{load-CdAG9wz-.mjs → load-D4xtzm6h.mjs} +2 -2
  557. package/dist/{load-CdAG9wz-.mjs.map → load-D4xtzm6h.mjs.map} +1 -1
  558. package/dist/{loader-CswroUbe.mjs → loader-DhnedqY4.mjs} +199 -101
  559. package/dist/loader-DhnedqY4.mjs.map +1 -0
  560. package/dist/{loops-uA4iTOzd.mjs → loops-B2YS-Zzr.mjs} +2 -2
  561. package/dist/{loops-uA4iTOzd.mjs.map → loops-B2YS-Zzr.mjs.map} +1 -1
  562. package/dist/{manifest-builder-B8zjuH3f.mjs → manifest-builder-g1FLviel.mjs} +10 -3
  563. package/dist/manifest-builder-g1FLviel.mjs.map +1 -0
  564. package/dist/media/image-endpoint.d.mts +3 -2
  565. package/dist/media/image-endpoint.d.mts.map +1 -1
  566. package/dist/media/image-endpoint.mjs +17 -8
  567. package/dist/media/image-endpoint.mjs.map +1 -1
  568. package/dist/media/index.d.mts +1 -1
  569. package/dist/media/index.mjs +7 -6
  570. package/dist/media/index.mjs.map +1 -1
  571. package/dist/media/local-runtime.d.mts +15 -14
  572. package/dist/media/local-runtime.d.mts.map +1 -1
  573. package/dist/media/local-runtime.mjs +20 -15
  574. package/dist/media/local-runtime.mjs.map +1 -1
  575. package/dist/{media-1WC65OCB.mjs → media-BR4_t-Wd.mjs} +3 -3
  576. package/dist/{media-1WC65OCB.mjs.map → media-BR4_t-Wd.mjs.map} +1 -1
  577. package/dist/{media--dJRU6i2.mjs → media-CikS-q6E.mjs} +4 -4
  578. package/dist/{media--dJRU6i2.mjs.map → media-CikS-q6E.mjs.map} +1 -1
  579. package/dist/{media-Bws9f18T.mjs → media-DepNLhPq.mjs} +14 -4
  580. package/dist/media-DepNLhPq.mjs.map +1 -0
  581. package/dist/{media-allowlist-BJB7MFx6.mjs → media-allowlist-BMBLqyWh.mjs} +2 -2
  582. package/dist/{media-allowlist-BJB7MFx6.mjs.map → media-allowlist-BMBLqyWh.mjs.map} +1 -1
  583. package/dist/{media-folders-Dn3C16B8.mjs → media-folders-CI0Wydfo.mjs} +2 -2
  584. package/dist/{media-folders-Dn3C16B8.mjs.map → media-folders-CI0Wydfo.mjs.map} +1 -1
  585. package/dist/{media-usage-CF0WVcLO.mjs → media-usage-X1_20MY-.mjs} +8 -8
  586. package/dist/{media-usage-CF0WVcLO.mjs.map → media-usage-X1_20MY-.mjs.map} +1 -1
  587. package/dist/{media-usage-activation-C9HwVw5w.mjs → media-usage-activation-bWusy3M2.mjs} +3 -3
  588. package/dist/{media-usage-activation-C9HwVw5w.mjs.map → media-usage-activation-bWusy3M2.mjs.map} +1 -1
  589. package/dist/{media-usage-work-m3AWTmmC.mjs → media-usage-work-B2RaoJIa.mjs} +4 -4
  590. package/dist/{media-usage-work-m3AWTmmC.mjs.map → media-usage-work-B2RaoJIa.mjs.map} +1 -1
  591. package/dist/{media-usage-work-CkLa5-nc.mjs → media-usage-work-BCK2J-v_.mjs} +7 -7
  592. package/dist/{media-usage-work-CkLa5-nc.mjs.map → media-usage-work-BCK2J-v_.mjs.map} +1 -1
  593. package/dist/{menus-BCVSSp1z.mjs → menus-B0Qqv_cS.mjs} +176 -92
  594. package/dist/menus-B0Qqv_cS.mjs.map +1 -0
  595. package/dist/{menus-Cl4kwdt7.mjs → menus-oypxT1pI.mjs} +134 -53
  596. package/dist/menus-oypxT1pI.mjs.map +1 -0
  597. package/dist/{menus-BSzwObhV.mjs → menus-uEAxWAm1.mjs} +3 -3
  598. package/dist/{menus-BSzwObhV.mjs.map → menus-uEAxWAm1.mjs.map} +1 -1
  599. package/dist/migrations/index.d.mts +1 -1
  600. package/dist/migrations/index.mjs +5 -5
  601. package/dist/{mime-B5M9R53H.mjs → mime-D1We9jUx.mjs} +1 -1
  602. package/dist/{mime-B5M9R53H.mjs.map → mime-D1We9jUx.mjs.map} +1 -1
  603. package/dist/{normalize-BuWa0lvd.mjs → normalize-Cx-bNwhP.mjs} +41 -12
  604. package/dist/normalize-Cx-bNwhP.mjs.map +1 -0
  605. package/dist/{oauth-authorization-TpEJrYB7.mjs → oauth-authorization-CPLgBrdo.mjs} +19 -6
  606. package/dist/oauth-authorization-CPLgBrdo.mjs.map +1 -0
  607. package/dist/{oauth-state-store-CHMn_mwc.mjs → oauth-state-store-BndCfRum.mjs} +1 -1
  608. package/dist/{oauth-state-store-CHMn_mwc.mjs.map → oauth-state-store-BndCfRum.mjs.map} +1 -1
  609. package/dist/object-cache/memory.d.mts +1 -1
  610. package/dist/{object-cache-Bo6DGaC9.mjs → object-cache-DmKr09La.mjs} +21 -4
  611. package/dist/{object-cache-Bo6DGaC9.mjs.map → object-cache-DmKr09La.mjs.map} +1 -1
  612. package/dist/{options-DJWaq3Ie.d.mts → options-BUUgroHg.d.mts} +3 -3
  613. package/dist/{options-DJWaq3Ie.d.mts.map → options-BUUgroHg.d.mts.map} +1 -1
  614. package/dist/page/index.d.mts +2 -2
  615. package/dist/page/index.mjs +16 -14
  616. package/dist/page/index.mjs.map +1 -1
  617. package/dist/{parse-DgQ2NABT.mjs → parse-B_b6gZxG.mjs} +2 -2
  618. package/dist/{parse-DgQ2NABT.mjs.map → parse-B_b6gZxG.mjs.map} +1 -1
  619. package/dist/{parse-CWHOFc6z.d.mts → parse-Dndx1QmN.d.mts} +3 -3
  620. package/dist/{parse-CWHOFc6z.d.mts.map → parse-Dndx1QmN.d.mts.map} +1 -1
  621. package/dist/{passkey-config-D0kdzEao.mjs → passkey-config-D2Lua5__.mjs} +1 -1
  622. package/dist/{passkey-config-D0kdzEao.mjs.map → passkey-config-D2Lua5__.mjs.map} +1 -1
  623. package/dist/{patterns-CMNnYCgf.mjs → patterns-CryGz_EV.mjs} +1 -1
  624. package/dist/{patterns-CMNnYCgf.mjs.map → patterns-CryGz_EV.mjs.map} +1 -1
  625. package/dist/{placeholder-D41vk11_.d.mts → placeholder-CSKu5OkD.d.mts} +9 -1
  626. package/dist/placeholder-CSKu5OkD.d.mts.map +1 -0
  627. package/dist/plugin-test-runtime.d.mts +17 -15
  628. package/dist/plugin-test-runtime.d.mts.map +1 -1
  629. package/dist/plugin-test-runtime.mjs +99 -98
  630. package/dist/plugin-types.d.mts +2 -2
  631. package/dist/plugin-utils.d.mts +13 -12
  632. package/dist/plugin-utils.d.mts.map +1 -1
  633. package/dist/plugins/adapt-sandbox-entry.d.mts +13 -12
  634. package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
  635. package/dist/plugins/host.d.mts +5 -5
  636. package/dist/plugins/host.mjs +48 -47
  637. package/dist/{policy-DLQ--Hnm.mjs → policy-BPugqmeV.mjs} +13 -5
  638. package/dist/policy-BPugqmeV.mjs.map +1 -0
  639. package/dist/{protocol-79kUO7jP.d.mts → protocol-PoAfD_9W.d.mts} +2 -2
  640. package/dist/{protocol-79kUO7jP.d.mts.map → protocol-PoAfD_9W.d.mts.map} +1 -1
  641. package/dist/{public-plugin-api-routes-BuAMJ8nN.mjs → public-plugin-api-routes-CMljrTby.mjs} +9 -9
  642. package/dist/{public-plugin-api-routes-BuAMJ8nN.mjs.map → public-plugin-api-routes-CMljrTby.mjs.map} +1 -1
  643. package/dist/{public-submission-Di3TsgzX.mjs → public-submission-ayqoyee4.mjs} +10 -10
  644. package/dist/{public-submission-Di3TsgzX.mjs.map → public-submission-ayqoyee4.mjs.map} +1 -1
  645. package/dist/query-BFHjCzSh.mjs +37 -0
  646. package/dist/query-BFHjCzSh.mjs.map +1 -0
  647. package/dist/{query-CpnRlBh8.mjs → query-D62NntCZ.mjs} +55 -65
  648. package/dist/query-D62NntCZ.mjs.map +1 -0
  649. package/dist/{query-haKvLAWl.mjs → query-LmPY2y0C.mjs} +5 -5
  650. package/dist/{query-haKvLAWl.mjs.map → query-LmPY2y0C.mjs.map} +1 -1
  651. package/dist/{rate-limit-Xp4d0NBY.mjs → rate-limit-C04Llsoc.mjs} +3 -3
  652. package/dist/{rate-limit-Xp4d0NBY.mjs.map → rate-limit-C04Llsoc.mjs.map} +1 -1
  653. package/dist/{redirect-DiS_3mA4.mjs → redirect-DjLdw427.mjs} +6 -6
  654. package/dist/{redirect-DiS_3mA4.mjs.map → redirect-DjLdw427.mjs.map} +1 -1
  655. package/dist/{redirect-paths-CNYq7w80.mjs → redirect-paths-DOaVBp6E.mjs} +1 -1
  656. package/dist/{redirect-paths-CNYq7w80.mjs.map → redirect-paths-DOaVBp6E.mjs.map} +1 -1
  657. package/dist/{redirects-BHpy-VsZ.mjs → redirects-Cpq1catN.mjs} +6 -6
  658. package/dist/{redirects-BHpy-VsZ.mjs.map → redirects-Cpq1catN.mjs.map} +1 -1
  659. package/dist/{redirects-BEVSRMa2.mjs → redirects-CyvvZrCJ.mjs} +2 -2
  660. package/dist/{redirects-BEVSRMa2.mjs.map → redirects-CyvvZrCJ.mjs.map} +1 -1
  661. package/dist/{registry-TUVaid9Z.mjs → registry-B0-O575m.mjs} +25 -20
  662. package/dist/registry-B0-O575m.mjs.map +1 -0
  663. package/dist/{relations-CA_QuMTU.mjs → relations-WIOojTL4.mjs} +24 -11
  664. package/dist/relations-WIOojTL4.mjs.map +1 -0
  665. package/dist/{request-cache-C4CIo5ad.mjs → request-cache-5z2WzWmh.mjs} +1 -1
  666. package/dist/{request-cache-C4CIo5ad.mjs.map → request-cache-5z2WzWmh.mjs.map} +1 -1
  667. package/dist/request-context.d.mts +12 -1
  668. package/dist/request-context.d.mts.map +1 -1
  669. package/dist/request-context.mjs.map +1 -1
  670. package/dist/{resolve-DwNM-CXl.mjs → resolve-BNnm8EkB.mjs} +14 -13
  671. package/dist/{resolve-DwNM-CXl.mjs.map → resolve-BNnm8EkB.mjs.map} +1 -1
  672. package/dist/{resolve-D-kqyKns.mjs → resolve-DdNXBJSr.mjs} +4 -4
  673. package/dist/resolve-DdNXBJSr.mjs.map +1 -0
  674. package/dist/{revision-BVp8S0e_.mjs → revision-Dx7Uth1X.mjs} +5 -5
  675. package/dist/{revision-BVp8S0e_.mjs.map → revision-Dx7Uth1X.mjs.map} +1 -1
  676. package/dist/{routes-BerZFrvV.mjs → routes-avqgc-8r.mjs} +3 -3
  677. package/dist/{routes-BerZFrvV.mjs.map → routes-avqgc-8r.mjs.map} +1 -1
  678. package/dist/{runner-C5NeAkBQ.mjs → runner-Bkkfk4O8.mjs} +78 -4
  679. package/dist/runner-Bkkfk4O8.mjs.map +1 -0
  680. package/dist/{runner-BObHz5FC.d.mts → runner-Dfgp6-S_.d.mts} +7 -2
  681. package/dist/runner-Dfgp6-S_.d.mts.map +1 -0
  682. package/dist/runtime.d.mts +14 -13
  683. package/dist/runtime.d.mts.map +1 -1
  684. package/dist/runtime.mjs +8 -6
  685. package/dist/runtime.mjs.map +1 -1
  686. package/dist/schema/project-env-types.mjs +43 -42
  687. package/dist/schema/project-env-types.mjs.map +1 -1
  688. package/dist/{schema-DJRfvM_o.mjs → schema-B-3rntlX.mjs} +11 -11
  689. package/dist/{schema-DJRfvM_o.mjs.map → schema-B-3rntlX.mjs.map} +1 -1
  690. package/dist/{schema-C4OBuv6Z.mjs → schema-BqBlUZtb.mjs} +4 -4
  691. package/dist/{schema-C4OBuv6Z.mjs.map → schema-BqBlUZtb.mjs.map} +1 -1
  692. package/dist/{scopes-BU03K7Uo.mjs → scopes-DNaY7Ey0.mjs} +3 -3
  693. package/dist/{scopes-BU03K7Uo.mjs.map → scopes-DNaY7Ey0.mjs.map} +1 -1
  694. package/dist/{search-DfVzks89.mjs → search-BPWTnpnD.mjs} +32 -32
  695. package/dist/search-BPWTnpnD.mjs.map +1 -0
  696. package/dist/{secrets-Cc_O3Kp-.mjs → secrets-Dswzrz3k.mjs} +2 -2
  697. package/dist/{secrets-Cc_O3Kp-.mjs.map → secrets-Dswzrz3k.mjs.map} +1 -1
  698. package/dist/{sections-BMy4JVUz.mjs → sections-rSao6rBG.mjs} +3 -3
  699. package/dist/{sections-BMy4JVUz.mjs.map → sections-rSao6rBG.mjs.map} +1 -1
  700. package/dist/seed/index.d.mts +2 -2
  701. package/dist/seed/index.mjs +42 -41
  702. package/dist/seo/index.d.mts +3 -3
  703. package/dist/seo/index.mjs +30 -28
  704. package/dist/seo/index.mjs.map +1 -1
  705. package/dist/{seo-VZYOEy8f.mjs → seo-B_H_pqOd.mjs} +3 -3
  706. package/dist/{seo-VZYOEy8f.mjs.map → seo-B_H_pqOd.mjs.map} +1 -1
  707. package/dist/{service-Bo_usgSk.mjs → service-DpiUQVpp.mjs} +2 -2
  708. package/dist/{service-Bo_usgSk.mjs.map → service-DpiUQVpp.mjs.map} +1 -1
  709. package/dist/{session-user-DlpPdf8L.mjs → session-user-DiE4JKPP.mjs} +4 -4
  710. package/dist/{session-user-DlpPdf8L.mjs.map → session-user-DiE4JKPP.mjs.map} +1 -1
  711. package/dist/{settings-DS914jjE.mjs → settings--XlUdUaI.mjs} +3 -3
  712. package/dist/{settings-DS914jjE.mjs.map → settings--XlUdUaI.mjs.map} +1 -1
  713. package/dist/{settings-CWb84sDm.mjs → settings-D932YP2-.mjs} +111 -44
  714. package/dist/settings-D932YP2-.mjs.map +1 -0
  715. package/dist/{setup-complete-BuNxAUiN.mjs → setup-complete-qsJYWutC.mjs} +2 -2
  716. package/dist/{setup-complete-BuNxAUiN.mjs.map → setup-complete-qsJYWutC.mjs.map} +1 -1
  717. package/dist/{setup-nonce-BnEAX0iy.mjs → setup-nonce-CBFgUFXw.mjs} +1 -1
  718. package/dist/{setup-nonce-BnEAX0iy.mjs.map → setup-nonce-CBFgUFXw.mjs.map} +1 -1
  719. package/dist/{site-domain-Bq5j5bVg.mjs → site-domain-oRGS_JfA.mjs} +2 -2
  720. package/dist/{site-domain-Bq5j5bVg.mjs.map → site-domain-oRGS_JfA.mjs.map} +1 -1
  721. package/dist/{sitemap-name-BTg2NJJv.mjs → sitemap-name-B8QP8wud.mjs} +1 -1
  722. package/dist/{sitemap-name-BTg2NJJv.mjs.map → sitemap-name-B8QP8wud.mjs.map} +1 -1
  723. package/dist/{slugify-bu2-jKia.mjs → slugify-BDEG9pLk.mjs} +1 -1
  724. package/dist/{slugify-bu2-jKia.mjs.map → slugify-BDEG9pLk.mjs.map} +1 -1
  725. package/dist/{snapshot-DYsG4uOq.mjs → snapshot-BjaXDZQ5.mjs} +2 -2
  726. package/dist/{snapshot-DYsG4uOq.mjs.map → snapshot-BjaXDZQ5.mjs.map} +1 -1
  727. package/dist/{stage-D8DWgPcO.mjs → stage-CZQnXM_G.mjs} +3 -3
  728. package/dist/{stage-D8DWgPcO.mjs.map → stage-CZQnXM_G.mjs.map} +1 -1
  729. package/dist/{staged-CD_imitH.mjs → staged-ByBmPFtX.mjs} +3 -3
  730. package/dist/{staged-CD_imitH.mjs.map → staged-ByBmPFtX.mjs.map} +1 -1
  731. package/dist/storage/local.d.mts +1 -1
  732. package/dist/storage/s3.d.mts +1 -1
  733. package/dist/{storage-query-DRyu3bSU.d.mts → storage-query-BFp06Y0s.d.mts} +22 -10
  734. package/dist/storage-query-BFp06Y0s.d.mts.map +1 -0
  735. package/dist/{taxonomies-Dd9JJv_a.mjs → taxonomies-5SR76j11.mjs} +15 -17
  736. package/dist/taxonomies-5SR76j11.mjs.map +1 -0
  737. package/dist/{taxonomies-ChnU7Mc8.mjs → taxonomies-B__VmCKQ.mjs} +64 -58
  738. package/dist/taxonomies-B__VmCKQ.mjs.map +1 -0
  739. package/dist/{taxonomy-C_C_LBAU.mjs → taxonomy-CMI5fczd.mjs} +30 -17
  740. package/dist/taxonomy-CMI5fczd.mjs.map +1 -0
  741. package/dist/{transaction-BVYIo_yu.mjs → transaction-CkoQ5wqQ.mjs} +1 -1
  742. package/dist/{transaction-BVYIo_yu.mjs.map → transaction-CkoQ5wqQ.mjs.map} +1 -1
  743. package/dist/{transfer-WmWiR3xf.mjs → transfer-BbKfufJ4.mjs} +2 -2
  744. package/dist/{transfer-WmWiR3xf.mjs.map → transfer-BbKfufJ4.mjs.map} +1 -1
  745. package/dist/{transfer-ClH6w6BV.mjs → transfer-DTGblAj2.mjs} +71 -34
  746. package/dist/{transfer-ClH6w6BV.mjs.map → transfer-DTGblAj2.mjs.map} +1 -1
  747. package/dist/{transfer-download--ofRj9Cw.mjs → transfer-download-D9LQEDX0.mjs} +1 -1
  748. package/dist/{transfer-download--ofRj9Cw.mjs.map → transfer-download-D9LQEDX0.mjs.map} +1 -1
  749. package/dist/{transport-DxiXnbXk.d.mts → transport-Dm5QzpT_.d.mts} +1 -1
  750. package/dist/{transport-DxiXnbXk.d.mts.map → transport-Dm5QzpT_.d.mts.map} +1 -1
  751. package/dist/{transport-BjbqNiPI.mjs → transport-Dzpn5b3i.mjs} +4 -3
  752. package/dist/transport-Dzpn5b3i.mjs.map +1 -0
  753. package/dist/{turnstile-CJwvsOqw.mjs → turnstile-Cs2wfkJG.mjs} +1 -1
  754. package/dist/{turnstile-CJwvsOqw.mjs.map → turnstile-Cs2wfkJG.mjs.map} +1 -1
  755. package/dist/{types-BA3ey2QH.d.mts → types-BAsCk5KU.d.mts} +1 -1
  756. package/dist/{types-BA3ey2QH.d.mts.map → types-BAsCk5KU.d.mts.map} +1 -1
  757. package/dist/{types-RLgeIpnF.d.mts → types-BuvSwT9Y.d.mts} +8 -7
  758. package/dist/{types-RLgeIpnF.d.mts.map → types-BuvSwT9Y.d.mts.map} +1 -1
  759. package/dist/{types-CNB-dj6F.d.mts → types-C4KT3Md2.d.mts} +10 -6
  760. package/dist/types-C4KT3Md2.d.mts.map +1 -0
  761. package/dist/{types-DvqVxZXa.d.mts → types-CVXHwIBB.d.mts} +1 -1
  762. package/dist/{types-DvqVxZXa.d.mts.map → types-CVXHwIBB.d.mts.map} +1 -1
  763. package/dist/{types-BGmQ0uXs.mjs → types-C_asjp1J.mjs} +1 -1
  764. package/dist/types-C_asjp1J.mjs.map +1 -0
  765. package/dist/{types-DHO7Pd25.d.mts → types-CadaL_k8.d.mts} +1 -1
  766. package/dist/{types-DHO7Pd25.d.mts.map → types-CadaL_k8.d.mts.map} +1 -1
  767. package/dist/{types-QoPHm-2w.d.mts → types-CjftrmZR.d.mts} +3 -3
  768. package/dist/{types-QoPHm-2w.d.mts.map → types-CjftrmZR.d.mts.map} +1 -1
  769. package/dist/{types-DCFavOii.d.mts → types-DKwRUA-x.d.mts} +1 -1
  770. package/dist/{types-DCFavOii.d.mts.map → types-DKwRUA-x.d.mts.map} +1 -1
  771. package/dist/{types-D2NEXtgB.mjs → types-DwhEvIVb.mjs} +8 -2
  772. package/dist/types-DwhEvIVb.mjs.map +1 -0
  773. package/dist/{types-Bwpzb5o6.d.mts → types-GwAyS5SH.d.mts} +1 -1
  774. package/dist/{types-Bwpzb5o6.d.mts.map → types-GwAyS5SH.d.mts.map} +1 -1
  775. package/dist/{types-slSqujQL.d.mts → types-uU2YNYSt.d.mts} +6 -1
  776. package/dist/types-uU2YNYSt.d.mts.map +1 -0
  777. package/dist/{update-check-BxNg9T6N.mjs → update-check-ABBJgg6M.mjs} +4 -4
  778. package/dist/{update-check-BxNg9T6N.mjs.map → update-check-ABBJgg6M.mjs.map} +1 -1
  779. package/dist/{url-Dn3IStq8.mjs → url-DTfGDJhI.mjs} +1 -1
  780. package/dist/{url-Dn3IStq8.mjs.map → url-DTfGDJhI.mjs.map} +1 -1
  781. package/dist/{user-BlCTKVAm.mjs → user-By8SzQxS.mjs} +3 -3
  782. package/dist/{user-BlCTKVAm.mjs.map → user-By8SzQxS.mjs.map} +1 -1
  783. package/dist/{utils-TPt7w2cS.mjs → utils-D5uOi6WS.mjs} +13 -5
  784. package/dist/utils-D5uOi6WS.mjs.map +1 -0
  785. package/dist/{index-BB9sVisO.d.mts → utils-Szp4iBQB.d.mts} +9 -256
  786. package/dist/utils-Szp4iBQB.d.mts.map +1 -0
  787. package/dist/{validate-emKxGC5F.d.mts → validate-DDvxy6qG.d.mts} +8 -8
  788. package/dist/{validate-emKxGC5F.d.mts.map → validate-DDvxy6qG.d.mts.map} +1 -1
  789. package/dist/{validate-DxYhJQA-.mjs → validate-Dz-TIOFB.mjs} +7 -7
  790. package/dist/{validate-DxYhJQA-.mjs.map → validate-Dz-TIOFB.mjs.map} +1 -1
  791. package/dist/{validation-Ckq4vsVg.mjs → validation-Fc9ZSUS_.mjs} +17 -16
  792. package/dist/{validation-Ckq4vsVg.mjs.map → validation-Fc9ZSUS_.mjs.map} +1 -1
  793. package/dist/version-Bu6Nlbb5.mjs +7 -0
  794. package/dist/{version-DHmGpcch.mjs.map → version-Bu6Nlbb5.mjs.map} +1 -1
  795. package/dist/version-DqB7LIO7.mjs +49 -0
  796. package/dist/version-DqB7LIO7.mjs.map +1 -0
  797. package/dist/{widgets-DA5XmvVC.mjs → widgets-BUx_Mf2q.mjs} +18 -5
  798. package/dist/widgets-BUx_Mf2q.mjs.map +1 -0
  799. package/dist/{wxr-taxonomies-RgRG0d5e.mjs → wxr-taxonomies-DbJtWrWM.mjs} +7 -6
  800. package/dist/wxr-taxonomies-DbJtWrWM.mjs.map +1 -0
  801. package/dist/{wxr-taxonomies-CrMonejI.d.mts → wxr-taxonomies-Dy2i2ON3.d.mts} +1 -1
  802. package/dist/wxr-taxonomies-Dy2i2ON3.d.mts.map +1 -0
  803. package/dist/{zod-generator-D0JKy94C.mjs → zod-generator--nlM0930.mjs} +5 -4
  804. package/dist/zod-generator--nlM0930.mjs.map +1 -0
  805. package/package.json +5 -5
  806. package/src/api/handlers/bulk-tag.ts +11 -3
  807. package/src/api/handlers/bylines.ts +6 -2
  808. package/src/api/handlers/content.ts +154 -23
  809. package/src/api/handlers/dashboard.ts +13 -6
  810. package/src/api/handlers/device-flow.ts +1 -3
  811. package/src/api/handlers/menus.ts +27 -13
  812. package/src/api/handlers/oauth-authorization.ts +1 -3
  813. package/src/api/handlers/relations.ts +15 -1
  814. package/src/api/handlers/taxonomies.ts +27 -17
  815. package/src/astro/image-endpoint.ts +23 -2
  816. package/src/astro/integration/admin-nav.ts +52 -0
  817. package/src/astro/integration/index.ts +7 -0
  818. package/src/astro/integration/runtime.ts +14 -0
  819. package/src/astro/integration/shims/use-sync-external-store-with-selector.js +2 -0
  820. package/src/astro/integration/shims/use-sync-external-store.js +4 -1
  821. package/src/astro/integration/vite-config.ts +16 -8
  822. package/src/astro/middleware/auth.ts +9 -2
  823. package/src/astro/middleware/redirect.ts +158 -63
  824. package/src/astro/middleware/request-context.ts +1 -0
  825. package/src/astro/middleware.ts +17 -4
  826. package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +4 -1
  827. package/src/astro/routes/api/content/[collection]/[id]/translations.ts +14 -1
  828. package/src/astro/routes/api/dashboard.ts +2 -0
  829. package/src/astro/routes/api/import/wordpress/analyze.ts +5 -29
  830. package/src/astro/routes/api/import/wordpress-plugin/execute.ts +3 -3
  831. package/src/astro/routes/api/media/file/[...key].ts +31 -7
  832. package/src/astro/routes/api/oauth/token.ts +5 -1
  833. package/src/astro/routes/api/widget-areas/[name]/reorder.ts +7 -1
  834. package/src/astro/routes/api/widget-areas/[name]/widgets/[id].ts +3 -1
  835. package/src/astro/routes/api/widget-areas/[name]/widgets.ts +2 -1
  836. package/src/astro/routes/api/widget-areas/[name].ts +2 -1
  837. package/src/astro/routes/api/widget-areas/index.ts +2 -1
  838. package/src/astro/types.ts +4 -3
  839. package/src/auth/api-tokens.ts +3 -0
  840. package/src/auth/types.ts +6 -0
  841. package/src/cleanup.ts +44 -0
  842. package/src/cli/commands/export-seed.ts +6 -4
  843. package/src/cli/commands/login.ts +2 -4
  844. package/src/client/index.ts +1 -0
  845. package/src/client/transport.ts +11 -7
  846. package/src/components/EmDashImage.astro +14 -2
  847. package/src/components/InlinePortableTextEditor.tsx +4 -1
  848. package/src/components/inline-bubble-menu.tsx +109 -95
  849. package/src/components/inline-image.tsx +54 -48
  850. package/src/database/dialect-helpers.ts +10 -3
  851. package/src/database/migrations/content-sized.ts +82 -0
  852. package/src/database/migrations/policy.ts +28 -2
  853. package/src/database/migrations/runner.ts +48 -0
  854. package/src/database/repositories/byline.ts +95 -31
  855. package/src/database/repositories/comment.ts +17 -7
  856. package/src/database/repositories/content.ts +96 -23
  857. package/src/database/repositories/media.ts +17 -0
  858. package/src/database/repositories/menu.ts +236 -139
  859. package/src/database/repositories/taxonomy-def.ts +9 -2
  860. package/src/database/repositories/taxonomy.ts +47 -14
  861. package/src/database/repositories/types.ts +14 -3
  862. package/src/database/types.ts +1 -1
  863. package/src/emdash-runtime.ts +60 -17
  864. package/src/fields/image.ts +1 -0
  865. package/src/i18n/config.ts +58 -10
  866. package/src/i18n/normalize.ts +16 -2
  867. package/src/i18n/query.ts +47 -0
  868. package/src/i18n/resolve.ts +8 -3
  869. package/src/import/utils.ts +15 -2
  870. package/src/import/wxr-taxonomies.ts +3 -2
  871. package/src/index.ts +1 -0
  872. package/src/loader.ts +183 -114
  873. package/src/mcp/server.ts +28 -1
  874. package/src/media/caption.ts +30 -0
  875. package/src/media/content-disposition.ts +56 -0
  876. package/src/media/image-endpoint.ts +13 -6
  877. package/src/media/local-runtime.ts +3 -0
  878. package/src/media/normalize.ts +17 -8
  879. package/src/media/responsive.ts +12 -2
  880. package/src/media/types.ts +16 -3
  881. package/src/media/usage/content-fields.ts +2 -1
  882. package/src/menus/index.ts +158 -36
  883. package/src/migrations/manifest.ts +1 -0
  884. package/src/object-cache/index.ts +22 -0
  885. package/src/plugin-test-runtime.ts +1 -0
  886. package/src/plugins/byline-access.ts +3 -1
  887. package/src/plugins/context.ts +1 -2
  888. package/src/plugins/storage-indexes.ts +7 -3
  889. package/src/query.ts +67 -53
  890. package/src/redirects/artifacts.ts +39 -5
  891. package/src/references/field-map.ts +6 -4
  892. package/src/request-context.ts +8 -0
  893. package/src/schema/collection-slugs-cache.ts +31 -17
  894. package/src/schema/registry.ts +9 -0
  895. package/src/schema/types.ts +7 -6
  896. package/src/schema/zod-generator.ts +2 -1
  897. package/src/search/fts-manager.ts +103 -31
  898. package/src/search/query.ts +31 -64
  899. package/src/seed/apply.ts +221 -109
  900. package/src/seed/types.ts +6 -4
  901. package/src/settings/index.ts +135 -35
  902. package/src/settings/version.ts +54 -0
  903. package/src/taxonomies/index.ts +99 -85
  904. package/src/taxonomies/term-counts.ts +2 -1
  905. package/src/transfer/import/advance.ts +12 -1
  906. package/src/transfer/import/scaffold.ts +7 -1
  907. package/src/transfer/import/stages.ts +53 -2
  908. package/src/utils/db-errors.ts +15 -0
  909. package/src/utils/revalidating-cache.ts +85 -0
  910. package/src/virtual-modules.d.ts +1 -0
  911. package/src/visual-editing/toolbar.ts +7 -2
  912. package/src/widgets/index.ts +27 -13
  913. package/dist/api-D-7BNHoz.mjs.map +0 -1
  914. package/dist/api-tokens-CdP49zVF.mjs +0 -3
  915. package/dist/apply-T7ATgzCh.mjs.map +0 -1
  916. package/dist/artifacts-htGyfCSt.mjs.map +0 -1
  917. package/dist/byline-BR1qhyiw.mjs.map +0 -1
  918. package/dist/bylines-CVOvRUL7.mjs.map +0 -1
  919. package/dist/collection-slugs-cache-e09QeJQt.mjs.map +0 -1
  920. package/dist/comment-UvIWDKcW.mjs.map +0 -1
  921. package/dist/config-Bsm_u_oE.d.mts.map +0 -1
  922. package/dist/config-CFMojMFK.d.mts.map +0 -1
  923. package/dist/config-CvmjJcVw.mjs +0 -73
  924. package/dist/config-CvmjJcVw.mjs.map +0 -1
  925. package/dist/content-DQSRZTVw.mjs.map +0 -1
  926. package/dist/context-BYptmCN0.mjs.map +0 -1
  927. package/dist/dashboard-D0jcgBD7.mjs.map +0 -1
  928. package/dist/db-errors-CBD5yMro.mjs.map +0 -1
  929. package/dist/deferred-tasks-ZvUECSzI.d.mts +0 -9
  930. package/dist/deferred-tasks-ZvUECSzI.d.mts.map +0 -1
  931. package/dist/device-flow-BkFKBoAn.mjs.map +0 -1
  932. package/dist/dialect-helpers-7_IqPdh9.mjs.map +0 -1
  933. package/dist/emdash-runtime-DVi7vtXC.mjs.map +0 -1
  934. package/dist/field-defs-cache-Dez5iWJJ.mjs +0 -77
  935. package/dist/field-defs-cache-Dez5iWJJ.mjs.map +0 -1
  936. package/dist/field-map-Bft9LKak.mjs.map +0 -1
  937. package/dist/fts-manager-Beg3e4bI.mjs.map +0 -1
  938. package/dist/index-BB9sVisO.d.mts.map +0 -1
  939. package/dist/loader-CswroUbe.mjs.map +0 -1
  940. package/dist/manifest-builder-B8zjuH3f.mjs.map +0 -1
  941. package/dist/media-Bws9f18T.mjs.map +0 -1
  942. package/dist/menus-BCVSSp1z.mjs.map +0 -1
  943. package/dist/menus-Cl4kwdt7.mjs.map +0 -1
  944. package/dist/normalize-BuWa0lvd.mjs.map +0 -1
  945. package/dist/oauth-authorization-TpEJrYB7.mjs.map +0 -1
  946. package/dist/placeholder-D41vk11_.d.mts.map +0 -1
  947. package/dist/policy-DLQ--Hnm.mjs.map +0 -1
  948. package/dist/query-CpnRlBh8.mjs.map +0 -1
  949. package/dist/registry-TUVaid9Z.mjs.map +0 -1
  950. package/dist/relations-CA_QuMTU.mjs.map +0 -1
  951. package/dist/resolve-D-kqyKns.mjs.map +0 -1
  952. package/dist/runner-BObHz5FC.d.mts.map +0 -1
  953. package/dist/runner-C5NeAkBQ.mjs.map +0 -1
  954. package/dist/search-DfVzks89.mjs.map +0 -1
  955. package/dist/settings-CWb84sDm.mjs.map +0 -1
  956. package/dist/storage-query-DRyu3bSU.d.mts.map +0 -1
  957. package/dist/taxonomies-ChnU7Mc8.mjs.map +0 -1
  958. package/dist/taxonomies-Dd9JJv_a.mjs.map +0 -1
  959. package/dist/taxonomy-C_C_LBAU.mjs.map +0 -1
  960. package/dist/transport-BjbqNiPI.mjs.map +0 -1
  961. package/dist/types-BGmQ0uXs.mjs.map +0 -1
  962. package/dist/types-CNB-dj6F.d.mts.map +0 -1
  963. package/dist/types-D2NEXtgB.mjs.map +0 -1
  964. package/dist/types-slSqujQL.d.mts.map +0 -1
  965. package/dist/utils-TPt7w2cS.mjs.map +0 -1
  966. package/dist/version-DHmGpcch.mjs +0 -7
  967. package/dist/widgets-DA5XmvVC.mjs.map +0 -1
  968. package/dist/wxr-taxonomies-CrMonejI.d.mts.map +0 -1
  969. package/dist/wxr-taxonomies-RgRG0d5e.mjs.map +0 -1
  970. package/dist/zod-generator-D0JKy94C.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-DwhEvIVb.mjs","names":[],"sources":["../src/database/repositories/types.ts"],"sourcesContent":["import type { ContentFieldFilters } from \"../../content-list-query.js\";\nimport type { CustomFieldValue } from \"../../schema/types.js\";\nimport { encodeBase64, decodeBase64 } from \"../../utils/base64.js\";\n\n/**\n * Hard cap on cursor length. Cursors we issue are short JSON-in-base64\n * blobs; a real cursor is well under 200 chars. This guards against\n * malicious callers passing megabyte-sized strings to force the base64\n * decoder to allocate (decodeBase64 is O(N) in input size). The MCP and\n * REST schemas also clamp at 2048 — this 4096 cap is a defense-in-depth\n * floor inside the repository helpers.\n */\nexport const MAX_CURSOR_LENGTH = 4096;\n\nexport interface CreateContentInput {\n\t/** Explicit content ID for stable seed imports. Omit to generate a ULID. */\n\tid?: string;\n\ttype: string;\n\tslug?: string | null;\n\tdata: Record<string, unknown>;\n\tstatus?: string;\n\tauthorId?: string;\n\tprimaryBylineId?: string | null;\n\tlocale?: string;\n\ttranslationOf?: string;\n\t/** Field columns selected atomically from `translationOf` during the insert. */\n\tinheritFields?: string[];\n\tpublishedAt?: string | null;\n\t/** Override created_at (ISO 8601). Used by importers to preserve original dates. */\n\tcreatedAt?: string | null;\n}\n\nexport interface UpdateContentInput {\n\t/** Stored locale, supplied by the content handler for alias-aware slug checks. */\n\tlocale?: string;\n\tdata?: Record<string, unknown>;\n\tstatus?: string;\n\tslug?: string | null;\n\tpublishedAt?: string | null;\n\tscheduledAt?: string | null;\n\t/** Entry owner (`ec_{collection}.author_id`). */\n\tauthorId?: string | null;\n\t/** Revision author, separate from entry ownership. */\n\trevisionAuthorId?: string | null;\n\tprimaryBylineId?: string | null;\n\t/** `null` drops the entry's draft revision pointer. */\n\tdraftRevisionId?: null;\n}\n\n/** SEO fields for content items */\nexport interface ContentSeo {\n\ttitle: string | null;\n\tdescription: string | null;\n\timage: string | null;\n\tcanonical: string | null;\n\tnoIndex: boolean;\n}\n\n/** Input for updating SEO fields on content */\nexport interface ContentSeoInput {\n\ttitle?: string | null;\n\tdescription?: string | null;\n\timage?: string | null;\n\tcanonical?: string | null;\n\tnoIndex?: boolean;\n}\n\nexport interface BylineSummary {\n\tid: string;\n\tslug: string;\n\tdisplayName: string;\n\tbio: string | null;\n\tavatarMediaId: string | null;\n\t/**\n\t * The avatar media's storage key, folded in by a LEFT JOIN on the\n\t * `media` table. Populated by the content-credit hydration path\n\t * (`getContentBylines` / `getContentBylinesMany`, i.e. the\n\t * `entry.data.bylines` populated by `getEmDashCollection` /\n\t * `getEmDashEntry`) and by the single-row finders (`findById`,\n\t * `findBySlug`, `findByUserId`, `findByUserIds`). `findMany` doesn't\n\t * join media, so it leaves this null.\n\t *\n\t * Lets a page build a direct storage URL for an author avatar without a\n\t * per-byline `MediaRepository.findById`, avoiding an N+1 when many distinct\n\t * authors appear on one page.\n\t *\n\t * Optional so adding it is a non-breaking change for existing code that\n\t * constructs a `BylineSummary` literal; the repositories always populate it\n\t * (to `null` when there's no avatar or no media join).\n\t */\n\tavatarStorageKey?: string | null;\n\t/** Avatar media alt text, from the same media join. Null when not joined. */\n\tavatarAlt?: string | null;\n\t/**\n\t * Avatar media blurhash (LQIP placeholder, migration 024), folded in by the\n\t * same media join as `avatarStorageKey`. Lets a renderer paint a blurred\n\t * placeholder while the full avatar loads, with no extra media lookup.\n\t * Null when the byline has no avatar, the media row has no blurhash, or the\n\t * byline came from `findMany`, which doesn't join media.\n\t */\n\tavatarBlurhash?: string | null;\n\t/**\n\t * Avatar media dominant colour (LQIP placeholder, migration 024), from the\n\t * same media join. Null under the same conditions as `avatarBlurhash`.\n\t */\n\tavatarDominantColor?: string | null;\n\twebsiteUrl: string | null;\n\tuserId: string | null;\n\tisGuest: boolean;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\t/**\n\t * Locale this byline row is presented in. Added by migration 040.\n\t * `(slug, locale)` is unique; a single slug can repeat across locales.\n\t */\n\tlocale: string;\n\t/**\n\t * Shared across translations of the same byline. Added by migration 040.\n\t * `_emdash_content_bylines.byline_id` and `ec_*.primary_byline_id` store\n\t * this value, so a credit spans every locale variant of a byline.\n\t * Nullable in storage for backwards compatibility; new rows always\n\t * populate it.\n\t */\n\ttranslationGroup: string | null;\n\t/**\n\t * Custom field values registered via the byline-fields schema (migration\n\t * 041, Discussion #1174). Optional in the TypeScript shape so existing\n\t * object-literal consumers (test fixtures, plugin renderers) stay\n\t * source-compatible; the runtime always returns `{}` when no fields are\n\t * registered. Translatable values reflect this row's locale; non-\n\t * translatable values are shared across every locale variant of the\n\t * byline's `translation_group`.\n\t */\n\tcustomFields?: Record<string, CustomFieldValue>;\n}\n\nexport interface ContentBylineCredit {\n\tbyline: BylineSummary;\n\tsortOrder: number;\n\troleLabel: string | null;\n\t/** Whether this credit was explicitly assigned or inferred from authorId */\n\tsource?: \"explicit\" | \"inferred\";\n}\n\n/** A whitelisted timestamp column a content-list date range can filter on. */\nexport type ContentDateField = \"createdAt\" | \"updatedAt\" | \"publishedAt\";\n\n/**\n * Inclusive date-range filter for a single whitelisted timestamp column.\n * Bounds are compared lexicographically against the stored ISO 8601 strings,\n * which is correct because every timestamp is written via `toISOString()`.\n * Callers wanting an inclusive upper bound should pass an end-of-day value\n * (e.g. `2024-12-31T23:59:59.999Z`); the repository does not widen `to`.\n */\nexport interface ContentDateFilter {\n\tfield: ContentDateField;\n\tfrom?: string;\n\tto?: string;\n}\n\n/**\n * Byline filter for a content list.\n *\n * `mode: \"any\"` matches entries credited to at least one of `bylineIds`;\n * `mode: \"none\"` matches entries with no credit at all.\n *\n * `bylineIds` are `translation_group` values — what\n * `_emdash_content_bylines.byline_id` stores since migration 040 — so a filter\n * matches a byline across every locale variant.\n *\n * By default only explicit credits count. `includeInferred` widens the filter\n * to the byline the list actually renders, which for an entry with no credits\n * is the one linked to its `author_id` (see `hydrateBylinesMany`).\n */\nexport interface ContentBylineFilter {\n\tmode: \"any\" | \"none\";\n\t/** Ignored when `mode` is `\"none\"`. An empty list matches nothing. */\n\tbylineIds?: string[];\n\tincludeInferred?: boolean;\n\t/**\n\t * Locale a credit has to resolve at — the locale the list is scoped to.\n\t * Applies to explicit credits as well as inferred ones, since a byline\n\t * group credited to an entry renders only where it has a row at that\n\t * locale. Defaults to each entry's own locale when the list spans locales.\n\t */\n\tlocale?: string;\n}\n\nexport interface FindManyOptions {\n\twhere?: {\n\t\tstatus?: string;\n\t\tauthorId?: string;\n\t\tlocale?: string;\n\t\t/** Case-insensitive substring to match against `searchColumns`. */\n\t\tq?: string;\n\t\t/**\n\t\t * Columns the `q` substring filter is applied to (OR'd together).\n\t\t * Resolved by the handler from the slug and the collection's display\n\t\t * fields and fields marked searchable, keeping only fields that have a\n\t\t * column. Each name is validated as a SQL identifier.\n\t\t */\n\t\tsearchColumns?: string[];\n\t\t/**\n\t\t * Serve `q` from the collection's FTS5 index (`_emdash_fts_<slug>`)\n\t\t * instead of an unindexable substring LIKE. Set by the handler only\n\t\t * when the collection has search enabled and the index exists\n\t\t * (SQLite only). The repository combines a token-prefix MATCH with\n\t\t * an index-served slug prefix so slug lookups keep working.\n\t\t */\n\t\tuseFts?: boolean;\n\t\t/** Inclusive date range over a whitelisted timestamp column. */\n\t\tdateFilter?: ContentDateFilter;\n\t\t/** Restrict to entries by their byline credits. */\n\t\tbylineFilter?: ContentBylineFilter;\n\t\t/** AND-combined filters over custom fields explicitly marked as indexed. */\n\t\tfieldFilters?: ContentFieldFilters;\n\t};\n\torderBy?: {\n\t\tfield: string;\n\t\tdirection: \"asc\" | \"desc\";\n\t};\n\t/**\n\t * Extra field slugs allowed as `orderBy` beyond the system columns — the\n\t * collection's configured titleField/dateField. Resolved by the\n\t * handler server-side so `orderBy` stays a closed set per request.\n\t */\n\tsortableExtras?: string[];\n\tlimit?: number;\n\tcursor?: string; // Base64-encoded JSON: {orderValue: string, id: string}\n\t/** Rows to skip before the page, for numbered pages. Cannot be combined with `cursor`. */\n\toffset?: number;\n}\n\nexport interface FindManyResult<T> {\n\titems: T[];\n\tnextCursor?: string; // Base64-encoded JSON: {orderValue: string, id: string}\n\t/**\n\t * Total number of rows matching the where clause (ignoring pagination).\n\t * Optional because not every caller needs it; repositories that compute\n\t * it should set it so the UI can render a stable pagination denominator.\n\t */\n\ttotal?: number;\n}\n\n/**\n * Order value stamped into a cursor over a *staged* reference selection, whose\n * anchor is a translation group rather than a row in the link table.\n *\n * A preview and a public render page the same field from different places, so a\n * cursor can cross that boundary in either direction — the draft publishes, or\n * the preview session ends, mid-pagination. Both sides recognise this marker so\n * they can tell a foreign cursor from a malformed one and restart the field's\n * page rather than failing or silently emptying it.\n */\nexport const STAGED_CURSOR_MARKER = \"staged\";\n\n/**\n * Boundary for a single ordered field inside a cursor.\n *\n * `missing` distinguishes \"the document has no value for this field\" from\n * \"the document stores JSON `null`\". SQLite can only tell these apart at the\n * SQL layer, but PostgreSQL orders `data::jsonb->'field'` differently for the\n * two cases, so the seek boundary must carry both possibilities.\n */\nexport interface SortFieldBoundary {\n\tvalue?: unknown;\n\tmissing?: boolean;\n}\n\n/** Encode a cursor from order value + id, optionally carrying the ordered field values. */\nexport function encodeCursor(\n\torderValue: string,\n\tid: string,\n\tsortValues?: SortFieldBoundary[],\n): string {\n\tconst payload: { orderValue: string; id: string; sortValues?: SortFieldBoundary[] } = {\n\t\torderValue,\n\t\tid,\n\t};\n\tif (sortValues !== undefined && sortValues.length > 0) {\n\t\tpayload.sortValues = sortValues;\n\t}\n\treturn encodeBase64(JSON.stringify(payload));\n}\n\n/**\n * Thrown when a pagination cursor cannot be decoded.\n *\n * Repository callers should let this propagate; handler catch blocks\n * map it to a structured `INVALID_CURSOR` error so client pagination\n * bugs surface immediately rather than silently re-fetching the first\n * page.\n */\nexport class InvalidCursorError extends Error {\n\tconstructor(cursor: string) {\n\t\tconst display = cursor.length > 50 ? `${cursor.slice(0, 47)}...` : cursor;\n\t\tsuper(`Invalid pagination cursor: ${display}`);\n\t\tthis.name = \"InvalidCursorError\";\n\t}\n}\n\nfunction isSortFieldBoundary(item: unknown): item is SortFieldBoundary {\n\tif (item === null || typeof item !== \"object\") {\n\t\treturn false;\n\t}\n\tconst candidate = item as { value?: unknown; missing?: unknown };\n\tif (candidate.missing !== undefined && typeof candidate.missing !== \"boolean\") {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nfunction normalizeSortBoundary(item: unknown): SortFieldBoundary {\n\tif (isSortFieldBoundary(item)) {\n\t\treturn { value: item.value, missing: item.missing };\n\t}\n\t// Fall back for plain values that predate the structured boundary format.\n\treturn { value: item, missing: false };\n}\n\n/**\n * Decode a cursor to order value + id.\n *\n * Throws `InvalidCursorError` if the cursor is empty, not valid base64,\n * not valid JSON, or doesn't contain string `orderValue` and `id` fields.\n */\nexport function decodeCursor(cursor: string): {\n\torderValue: string;\n\tid: string;\n\tsortValues?: SortFieldBoundary[];\n} {\n\tif (!cursor) throw new InvalidCursorError(cursor);\n\tif (cursor.length > MAX_CURSOR_LENGTH) throw new InvalidCursorError(cursor);\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(decodeBase64(cursor));\n\t} catch {\n\t\tthrow new InvalidCursorError(cursor);\n\t}\n\tif (parsed === null || typeof parsed !== \"object\") {\n\t\tthrow new InvalidCursorError(cursor);\n\t}\n\tconst candidate = parsed as { orderValue?: unknown; id?: unknown; sortValues?: unknown };\n\tif (typeof candidate.orderValue !== \"string\" || typeof candidate.id !== \"string\") {\n\t\tthrow new InvalidCursorError(cursor);\n\t}\n\tlet sortValues: SortFieldBoundary[] | undefined;\n\tif (candidate.sortValues !== undefined) {\n\t\tif (!Array.isArray(candidate.sortValues)) {\n\t\t\tthrow new InvalidCursorError(cursor);\n\t\t}\n\t\tsortValues = candidate.sortValues.map(normalizeSortBoundary);\n\t}\n\treturn {\n\t\torderValue: candidate.orderValue,\n\t\tid: candidate.id,\n\t\tsortValues,\n\t};\n}\n\nexport interface ContentItem {\n\tid: string;\n\ttype: string;\n\tslug: string | null;\n\tstatus: string;\n\tdata: Record<string, unknown>;\n\tauthorId: string | null;\n\tprimaryBylineId: string | null;\n\tbyline?: BylineSummary | null;\n\tbylines?: ContentBylineCredit[];\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tpublishedAt: string | null;\n\tscheduledAt: string | null;\n\tliveRevisionId: string | null;\n\tdraftRevisionId: string | null;\n\tversion: number;\n\tlocale: string | null;\n\ttranslationGroup: string | null;\n\t/** SEO metadata — only populated for collections with `has_seo` enabled */\n\tseo?: ContentSeo;\n\t/**\n\t * For collections that support `revisions`: when a draft revision exists,\n\t * `data` reflects the unsaved draft and `liveData` carries the currently-\n\t * published values. When no draft exists, `liveData` is undefined.\n\t *\n\t * Hydrated by `EmDashRuntime.hydrateDraftData()` — repositories themselves\n\t * never set this field; it's purely a runtime-overlay concept that gives\n\t * agents a clear picture of \"draft vs. live\" without re-fetching the\n\t * revision history.\n\t */\n\tliveData?: Record<string, unknown>;\n\t/**\n\t * First page of each reference field's resolved selection, keyed by field\n\t * slug. Only populated when the caller opts in via `handleContentGet`'s\n\t * `referenceOptions` param (see content.ts) — hydration is never\n\t * unconditional because it can leak draft ids/slugs to callers without\n\t * `content:read_drafts`.\n\t *\n\t * Shape mirrors `EntryRef` from `api/handlers/relations.ts`, duplicated\n\t * here (rather than imported) so the database layer doesn't depend on\n\t * the api/handlers layer.\n\t */\n\treferences?: Record<\n\t\tstring,\n\t\t{\n\t\t\tchildren: Array<{\n\t\t\t\tid: string;\n\t\t\t\tslug: string | null;\n\t\t\t\tcollection: string;\n\t\t\t\ttitle: string | null;\n\t\t\t\tlocale: string | null;\n\t\t\t\ttranslationGroup: string | null;\n\t\t\t\tsortOrder?: number;\n\t\t\t}>;\n\t\t\tnextCursor?: string;\n\t\t}\n\t>;\n}\n\nexport class EmDashValidationError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic details?: unknown,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"EmDashValidationError\";\n\t}\n}\n\nexport class ContentCollectionNotFoundError extends Error {\n\tconstructor(collection: string) {\n\t\tsuper(`Collection '${collection}' not found`);\n\t\tthis.name = \"ContentCollectionNotFoundError\";\n\t}\n}\n\n/**\n * Thrown by `publish()` when called with `requireDue` for a row that is no\n * longer due (its `scheduled_at` was cleared or pushed into the future between\n * selection and publish — e.g. an editor unscheduled it). Lets the scheduled\n * sweep skip the row silently rather than treating it as a publish failure.\n */\nexport class ScheduledNotDueError extends Error {\n\tconstructor(message = \"Content is no longer scheduled to publish\") {\n\t\tsuper(message);\n\t\tthis.name = \"ScheduledNotDueError\";\n\t}\n}\n\nexport class ContentMutationConflictError extends Error {\n\tconstructor(message = \"Content changed while the operation was in progress\") {\n\t\tsuper(message);\n\t\tthis.name = \"ContentMutationConflictError\";\n\t}\n}\n\nexport class ContentSlugConflictError extends Error {\n\tconstructor() {\n\t\tsuper(\"The slug is already used by another content entry\");\n\t\tthis.name = \"ContentSlugConflictError\";\n\t}\n}\n"],"mappings":";;;;;;;;;;;AAYA,MAAa,oBAAoB;;;;;;;;;;;AAkPjC,MAAa,uBAAuB;;AAgBpC,SAAgB,aACf,YACA,IACA,YACS;CACT,MAAM,UAAgF;EACrF;EACA;EACA;AACD,KAAI,eAAe,UAAa,WAAW,SAAS,EACnD,SAAQ,aAAa;AAEtB,QAAO,aAAa,KAAK,UAAU,QAAQ,CAAC;;;;;;;;;;AAW7C,IAAa,qBAAb,cAAwC,MAAM;CAC7C,YAAY,QAAgB;EAC3B,MAAM,UAAU,OAAO,SAAS,KAAK,GAAG,OAAO,MAAM,GAAG,GAAG,CAAC,OAAO;AACnE,QAAM,8BAA8B,UAAU;AAC9C,OAAK,OAAO;;;AAId,SAAS,oBAAoB,MAA0C;AACtE,KAAI,SAAS,QAAQ,OAAO,SAAS,SACpC,QAAO;CAER,MAAM,YAAY;AAClB,KAAI,UAAU,YAAY,UAAa,OAAO,UAAU,YAAY,UACnE,QAAO;AAER,QAAO;;AAGR,SAAS,sBAAsB,MAAkC;AAChE,KAAI,oBAAoB,KAAK,CAC5B,QAAO;EAAE,OAAO,KAAK;EAAO,SAAS,KAAK;EAAS;AAGpD,QAAO;EAAE,OAAO;EAAM,SAAS;EAAO;;;;;;;;AASvC,SAAgB,aAAa,QAI3B;AACD,KAAI,CAAC,OAAQ,OAAM,IAAI,mBAAmB,OAAO;AACjD,KAAI,OAAO,SAAS,kBAAmB,OAAM,IAAI,mBAAmB,OAAO;CAC3E,IAAI;AACJ,KAAI;AACH,WAAS,KAAK,MAAM,aAAa,OAAO,CAAC;SAClC;AACP,QAAM,IAAI,mBAAmB,OAAO;;AAErC,KAAI,WAAW,QAAQ,OAAO,WAAW,SACxC,OAAM,IAAI,mBAAmB,OAAO;CAErC,MAAM,YAAY;AAClB,KAAI,OAAO,UAAU,eAAe,YAAY,OAAO,UAAU,OAAO,SACvE,OAAM,IAAI,mBAAmB,OAAO;CAErC,IAAI;AACJ,KAAI,UAAU,eAAe,QAAW;AACvC,MAAI,CAAC,MAAM,QAAQ,UAAU,WAAW,CACvC,OAAM,IAAI,mBAAmB,OAAO;AAErC,eAAa,UAAU,WAAW,IAAI,sBAAsB;;AAE7D,QAAO;EACN,YAAY,UAAU;EACtB,IAAI,UAAU;EACd;EACA;;AA+DF,IAAa,wBAAb,cAA2C,MAAM;CAChD,YACC,SACA,AAAO,SACN;AACD,QAAM,QAAQ;EAFP;AAGP,OAAK,OAAO;;;AAId,IAAa,iCAAb,cAAoD,MAAM;CACzD,YAAY,YAAoB;AAC/B,QAAM,eAAe,WAAW,aAAa;AAC7C,OAAK,OAAO;;;;;;;;;AAUd,IAAa,uBAAb,cAA0C,MAAM;CAC/C,YAAY,UAAU,6CAA6C;AAClE,QAAM,QAAQ;AACd,OAAK,OAAO;;;AAId,IAAa,+BAAb,cAAkD,MAAM;CACvD,YAAY,UAAU,uDAAuD;AAC5E,QAAM,QAAQ;AACd,OAAK,OAAO;;;AAId,IAAa,2BAAb,cAA8C,MAAM;CACnD,cAAc;AACb,QAAM,oDAAoD;AAC1D,OAAK,OAAO"}
@@ -224,4 +224,4 @@ declare class EmDashStorageError extends Error {
224
224
  }
225
225
  //#endregion
226
226
  export { EmDashStorageError as a, ListResult as c, SignedUploadOptions as d, SignedUploadUrl as f, UploadResult as h, DownloadResult as i, LocalStorageConfig as l, StorageDescriptor as m, CreateStorageFn as n, FileInfo as o, Storage as p, DownloadOptions as r, ListOptions as s, ByteRange as t, S3StorageConfig as u };
227
- //# sourceMappingURL=types-Bwpzb5o6.d.mts.map
227
+ //# sourceMappingURL=types-GwAyS5SH.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types-Bwpzb5o6.d.mts","names":[],"sources":["../src/storage/types.ts"],"mappings":";;AAUA;;;;;;;;UAAiB,eAAA;EAoBhB;EAlBA,QAAA;EAkBS;EAhBT,MAAA;EAsBkC;;;;AAUnC;EA1BC,WAAA;;;;;;EAMA,eAAA;EAwBc;EAtBd,MAAA;EAiC0B;EA/B1B,SAAA;AAAA;;;;UAMgB,kBAAA;EAyByD;EAvBzE,SAAA;EA4B4B;EA1B5B,OAAA;AAAA;;;;UAMgB,iBAAA;EA0BZ;EAxBJ,UAAA;EA8BoB;EA5BpB,MAAA,EAAQ,MAAA;AAAA;;;;;;AAqCT;;;KA1BY,eAAA,IAAmB,MAAA,EAAQ,MAAA,sBAA4B,OAAA;;AAqCnE;;UAhCiB,YAAA;EAkCK;EAhCrB,GAAA;EA2Ce;EAzCf,GAAA;EAyCmB;EAvCnB,IAAA;AAAA;;;;KAMW,SAAA;EAEP,MAAA;EAAgB,MAAA;AAAA;EAEhB,MAAA;AAAA;;;;UAKY,eAAA;EAoCP;;;;EA/BT,KAAA,GAAQ,SAAA;AAAA;;;;UAMQ,cAAA;EAuChB;EArCA,IAAA,EAAM,cAAA,CAAe,UAAA;EAuCZ;EArCT,WAAA;EA2CgB;EAzChB,IAAA;;;;;EAKA,KAAA;IAAU,MAAA;IAAgB,MAAA;EAAA;EA8CF;EA5CxB,YAAA,GAAe,IAAA;AAAA;;;;UAMC,eAAA;EA8ChB;EA5CA,GAAA;EA4CI;EA1CJ,MAAA;EAgD2B;EA9C3B,OAAA,EAAS,MAAA;EA8CkB;EA5C3B,SAAA;AAAA;;;;UAMgB,mBAAA;EAoDO;EAlDvB,GAAA;EAwDO;EAtDP,WAAA;EAsD4C;EApD5C,IAAA;EAwDY;EAtDZ,SAAA;AAAA;;;;UAMgB,UAAA;EAqED;EAnEf,KAAA,EAAO,QAAA;EAmEsB;EAjE7B,UAAA;AAAA;;;;UAMgB,QAAA;EAiCf;EA/BD,GAAA;EAgCO;EA9BP,IAAA;EA8B6B;EA5B7B,YAAA,EAAc,IAAA;EA6Bb;EA3BD,IAAA;AAAA;;;;UAMgB,WAAA;EA6BgB;EA3BhC,MAAA;EA2BkD;EAzBlD,KAAA;EA+BA;EA7BA,MAAA;AAAA;;;;;;UAQgB,OAAA;EA+Ba;;;EA3B7B,MAAA,CAAO,OAAA;IACN,GAAA;IACA,IAAA,EAAM,MAAA,GAAS,UAAA,GAAa,cAAA,CAAe,UAAA;IAC3C,WAAA,UAmCD;IAjCC,YAAA;EAAA,IACG,OAAA,CAAQ,YAAA;EAsCS;;AAMtB;EAvCC,QAAA,CAAS,GAAA,UAAa,OAAA,GAAU,eAAA,GAAkB,OAAA,CAAQ,cAAA;;;;;EAM1D,MAAA,CAAO,GAAA,WAAc,OAAA;;;;EAKrB,MAAA,CAAO,GAAA,WAAc,OAAA;EAgCW;;;EA3BhC,IAAA,CAAK,OAAA,GAAU,WAAA,GAAc,OAAA,CAAQ,UAAA;;;;;EAMrC,kBAAA,CAAmB,OAAA,EAAS,mBAAA,GAAsB,OAAA,CAAQ,eAAA;;;;EAK1D,YAAA,CAAa,GAAA;;;;;EAMb,qBAAA;AAAA;;;;cAMY,kBAAA,SAA2B,KAAA;EAG/B,IAAA;EACS,KAAA;cAFhB,OAAA,UACO,IAAA,UACS,KAAA;AAAA"}
1
+ {"version":3,"file":"types-GwAyS5SH.d.mts","names":[],"sources":["../src/storage/types.ts"],"mappings":";;AAUA;;;;;;;;UAAiB,eAAA;EAoBhB;EAlBA,QAAA;EAkBS;EAhBT,MAAA;EAsBkC;;;;AAUnC;EA1BC,WAAA;;;;;;EAMA,eAAA;EAwBc;EAtBd,MAAA;EAiC0B;EA/B1B,SAAA;AAAA;;;;UAMgB,kBAAA;EAyByD;EAvBzE,SAAA;EA4B4B;EA1B5B,OAAA;AAAA;;;;UAMgB,iBAAA;EA0BZ;EAxBJ,UAAA;EA8BoB;EA5BpB,MAAA,EAAQ,MAAA;AAAA;;;;;;AAqCT;;;KA1BY,eAAA,IAAmB,MAAA,EAAQ,MAAA,sBAA4B,OAAA;;AAqCnE;;UAhCiB,YAAA;EAkCK;EAhCrB,GAAA;EA2Ce;EAzCf,GAAA;EAyCmB;EAvCnB,IAAA;AAAA;;;;KAMW,SAAA;EAEP,MAAA;EAAgB,MAAA;AAAA;EAEhB,MAAA;AAAA;;;;UAKY,eAAA;EAoCP;;;;EA/BT,KAAA,GAAQ,SAAA;AAAA;;;;UAMQ,cAAA;EAuChB;EArCA,IAAA,EAAM,cAAA,CAAe,UAAA;EAuCZ;EArCT,WAAA;EA2CgB;EAzChB,IAAA;;;;;EAKA,KAAA;IAAU,MAAA;IAAgB,MAAA;EAAA;EA8CF;EA5CxB,YAAA,GAAe,IAAA;AAAA;;;;UAMC,eAAA;EA8ChB;EA5CA,GAAA;EA4CI;EA1CJ,MAAA;EAgD2B;EA9C3B,OAAA,EAAS,MAAA;EA8CkB;EA5C3B,SAAA;AAAA;;;;UAMgB,mBAAA;EAoDO;EAlDvB,GAAA;EAwDO;EAtDP,WAAA;EAsD4C;EApD5C,IAAA;EAwDY;EAtDZ,SAAA;AAAA;;;;UAMgB,UAAA;EAqED;EAnEf,KAAA,EAAO,QAAA;EAmEsB;EAjE7B,UAAA;AAAA;;;;UAMgB,QAAA;EAiCf;EA/BD,GAAA;EAgCO;EA9BP,IAAA;EA8B6B;EA5B7B,YAAA,EAAc,IAAA;EA6Bb;EA3BD,IAAA;AAAA;;;;UAMgB,WAAA;EA6BgB;EA3BhC,MAAA;EA2BkD;EAzBlD,KAAA;EA+BA;EA7BA,MAAA;AAAA;;;;;;UAQgB,OAAA;EA+Ba;;;EA3B7B,MAAA,CAAO,OAAA;IACN,GAAA;IACA,IAAA,EAAM,MAAA,GAAS,UAAA,GAAa,cAAA,CAAe,UAAA;IAC3C,WAAA,UAmCD;IAjCC,YAAA;EAAA,IACG,OAAA,CAAQ,YAAA;EAsCS;;AAMtB;EAvCC,QAAA,CAAS,GAAA,UAAa,OAAA,GAAU,eAAA,GAAkB,OAAA,CAAQ,cAAA;;;;;EAM1D,MAAA,CAAO,GAAA,WAAc,OAAA;;;;EAKrB,MAAA,CAAO,GAAA,WAAc,OAAA;EAgCW;;;EA3BhC,IAAA,CAAK,OAAA,GAAU,WAAA,GAAc,OAAA,CAAQ,UAAA;;;;;EAMrC,kBAAA,CAAmB,OAAA,EAAS,mBAAA,GAAsB,OAAA,CAAQ,eAAA;;;;EAK1D,YAAA,CAAa,GAAA;;;;;EAMb,qBAAA;AAAA;;;;cAMY,kBAAA,SAA2B,KAAA;EAG/B,IAAA;EACS,KAAA;cAFhB,OAAA,UACO,IAAA,UACS,KAAA;AAAA"}
@@ -149,6 +149,11 @@ interface AuthProviderAdminExports {
149
149
  * Rendered as an expandable section on the login page.
150
150
  */
151
151
  LoginForm?: react.ComponentType;
152
+ /**
153
+ * Optional help text shown below the provider's LoginForm. Providers can
154
+ * export a string or a component; components keep text localisable.
155
+ */
156
+ loginHelp?: string | react.ComponentType;
152
157
  /**
153
158
  * Setup wizard step for creating the admin account via this provider.
154
159
  * When present, this provider appears as an option in the setup wizard's
@@ -201,4 +206,4 @@ interface ExternalAuthConfig {
201
206
  }
202
207
  //#endregion
203
208
  export { AuthResult as a, AuthProviderModule as i, AuthProviderAdminExports as n, AuthRouteDescriptor as o, AuthProviderDescriptor as r, ExternalAuthConfig as s, AuthDescriptor as t };
204
- //# sourceMappingURL=types-slSqujQL.d.mts.map
209
+ //# sourceMappingURL=types-uU2YNYSt.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-uU2YNYSt.d.mts","names":[],"sources":["../src/auth/types.ts"],"mappings":";;;;;;AAgBA;;;;;;;;;;;;UAAiB,UAAA;EAmBc;EAjB9B,KAAA;EAiB8B;EAf9B,IAAA;EA2BA;EAzBA,IAAA;EA8BM;EA5BN,OAAA;EAqCgB;EAnChB,QAAA,GAAW,MAAA;AAAA;;;;;;;UASK,cAAA;EAkCH;;;;EA7Bb,IAAA;EA6BmE;AAwBpE;;;;EA9CC,UAAA;EAsFuD;;;EAjFvD,MAAA;AAAA;;;;;;;UASgB,kBAAA;EAsEN;;;;;;;EA9DV,YAAA,CAAa,OAAA,EAAS,OAAA,EAAS,MAAA,YAAkB,OAAA,CAAQ,UAAA;AAAA;;;;AAoF1D;;;;;;;;;;;;;;UA5DiB,sBAAA;EAsFhB;EApFA,EAAA;EAoF4C;EAjF5C,KAAA;EAiFsD;EA9EtD,MAAA;EAoFkC;;;;;;EA5ElC,UAAA;EAoHA;;;;EA9GA,MAAA,GAAS,mBAAA;;;;;;EAOT,YAAA;;;;;;;;EASA,OAAA,GAAU,MAAA;IAEP,OAAA,GAAU,KAAA;IAA0B,aAAA,GAAgB,KAAA;EAAA;AAAA;;;;UAOvC,mBAAA;;EAEhB,OAAA;;EAEA,UAAA;AAAA;;;;;;;UASgB,wBAAA;;;;;;EAMhB,WAAA,GANwC,KAAA,CAMV,aAAA;;;;;;EAO9B,SAAA,GAP2C,KAAA,CAOf,aAAA;;;;;EAM5B,SAAA,YANyC,KAAA,CAMJ,aAAA;;;;;;EAOrC,SAAA,GAPkD,KAAA,CAOtB,aAAA;IAAgB,UAAA;EAAA;AAAA;;;;UAM5B,kBAAA;;;;;EAKhB,aAAA;;;;;EAMA,WAAA;;;;;;EAOA,SAAA;;;;;;EAOA,QAAA;;;;;;;;;;;;;;EAeA,WAAA,GAAc,MAAA;AAAA"}
@@ -1,8 +1,8 @@
1
- import { t as after } from "./after-PcEvMY_6.mjs";
1
+ import { t as after } from "./after-32yNRvd2.mjs";
2
2
  import { t as OptionsRepository } from "./options-DhrI7eMv.mjs";
3
3
  import { a as parseDurationSeconds } from "./config-DBU6iUQB.mjs";
4
- import { n as VERSION } from "./version-DHmGpcch.mjs";
5
- import { t as ErrorCode } from "./errors-BOYNdIo3.mjs";
4
+ import { n as VERSION } from "./version-Bu6Nlbb5.mjs";
5
+ import { t as ErrorCode } from "./errors-8gJqv-XV.mjs";
6
6
 
7
7
  //#region src/api/handlers/update-check.ts
8
8
  /** Options-table key for the cached registry result. */
@@ -158,4 +158,4 @@ async function handleCoreUpdateStatus(db, options) {
158
158
 
159
159
  //#endregion
160
160
  export { minimumReleaseAgeSeconds as n, handleCoreUpdateStatus as t };
161
- //# sourceMappingURL=update-check-BxNg9T6N.mjs.map
161
+ //# sourceMappingURL=update-check-ABBJgg6M.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"update-check-BxNg9T6N.mjs","names":[],"sources":["../src/api/handlers/update-check.ts"],"sourcesContent":["/**\n * Core update status handler.\n *\n * Caches the publish times of stable `emdash` releases from the npm\n * registry in the options table, and reports the newest release that has\n * been public for the minimum release age when it is newer than the\n * running `VERSION`. A stale or missing cache schedules a deferred refresh.\n */\n\nimport type { Kysely } from \"kysely\";\n\nimport { after } from \"../../after.js\";\nimport { OptionsRepository } from \"../../database/repositories/options.js\";\nimport type { Database } from \"../../database/types.js\";\nimport { parseDurationSeconds } from \"../../registry/config.js\";\nimport { VERSION } from \"../../version.js\";\nimport { ErrorCode } from \"../errors.js\";\nimport type { ApiResult } from \"../types.js\";\n\n/** Options-table key for the cached registry result. */\nexport const CORE_UPDATE_OPTION = \"emdash:core_update_check\";\n\n/** Check the registry at most once per day, whether or not the check succeeds. */\nconst CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;\n\n/** npm packument for `emdash`: the `latest` dist-tag and each version's publish time. */\nconst REGISTRY_URL = \"https://registry.npmjs.org/emdash\";\n\n/** Default time a release must be public before admins are told about it. */\nexport const DEFAULT_MINIMUM_RELEASE_AGE = \"24h\";\n\nconst REGISTRY_TIMEOUT_MS = 10_000;\n\n/** Cached registry state, stored in the options table. */\ninterface CoreUpdateCache {\n\t/** Publish time (ISO) of each non-deprecated stable release up to the `latest` dist-tag. */\n\treleases: Record<string, string>;\n\t/** ISO timestamp of the last registry check. */\n\tcheckedAt: string;\n}\n\nexport interface CoreUpdateStatus {\n\t/** The running EmDash version (`\"dev\"` in uncompiled dev/test runs). */\n\tcurrent: string;\n\t/**\n\t * Newest stable release that has been public for the minimum release\n\t * age, or null when no check has completed yet.\n\t */\n\tlatest: string | null;\n\tupdateAvailable: boolean;\n\t/** ISO timestamp of the last registry check, if any. */\n\tcheckedAt: string | null;\n}\n\nconst SEMVER_RE = /^(\\d+)\\.(\\d+)\\.(\\d+)(-.+)?$/;\nconst STABLE_RE = /^\\d+\\.\\d+\\.\\d+$/;\n\n/**\n * True when `latest` is a strictly newer release than `current`.\n *\n * Handles plain `major.minor.patch` versions. Anything unparsable —\n * including the `\"dev\"` fallback version — compares as \"not newer\", so\n * dev/test runs never show the banner. On an equal base version, a stable\n * release is newer than a prerelease of it, so a site running\n * `0.24.0-beta.1` is notified when `0.24.0` ships. Prerelease identifiers\n * are not compared to each other.\n */\nexport function isNewerVersion(latest: string, current: string): boolean {\n\tconst l = SEMVER_RE.exec(latest);\n\tconst c = SEMVER_RE.exec(current);\n\tif (!l || !c) return false;\n\tfor (let i = 1; i <= 3; i++) {\n\t\tconst a = Number(l[i]);\n\t\tconst b = Number(c[i]);\n\t\tif (a !== b) return a > b;\n\t}\n\treturn !l[4] && !!c[4];\n}\n\nfunction field(value: unknown, key: string): unknown {\n\treturn typeof value === \"object\" && value !== null && Object.hasOwn(value, key)\n\t\t? (Reflect.get(value, key) as unknown)\n\t\t: undefined;\n}\n\n/**\n * Fetch the stable releases and their publish times from the npm registry\n * and cache them. Exported for tests; production callers go through\n * `handleCoreUpdateStatus`, which defers this via `after()`.\n */\nexport async function refreshCoreUpdateCache(\n\tdb: Kysely<Database>,\n\tfetchImpl: typeof fetch = fetch,\n): Promise<void> {\n\tconst response = await fetchImpl(REGISTRY_URL, {\n\t\theaders: { accept: \"application/json\" },\n\t\tsignal: AbortSignal.timeout(REGISTRY_TIMEOUT_MS),\n\t});\n\tif (!response.ok) {\n\t\tthrow new Error(`registry responded ${response.status}`);\n\t}\n\tconst body: unknown = await response.json();\n\tconst latest = field(field(body, \"dist-tags\"), \"latest\");\n\tif (typeof latest !== \"string\" || !STABLE_RE.test(latest)) {\n\t\tthrow new Error(\"registry response missing a valid version\");\n\t}\n\tconst time = field(body, \"time\");\n\tconst versions = field(body, \"versions\");\n\tconst releases: Record<string, string> = {};\n\tif (typeof time === \"object\" && time !== null) {\n\t\tfor (const [version, publishedAt] of Object.entries(time)) {\n\t\t\tif (!STABLE_RE.test(version) || isNewerVersion(version, latest)) continue;\n\t\t\tconst manifest = field(versions, version);\n\t\t\tif (manifest === undefined || field(manifest, \"deprecated\") !== undefined) continue;\n\t\t\tif (typeof publishedAt !== \"string\" || Number.isNaN(Date.parse(publishedAt))) continue;\n\t\t\treleases[version] = publishedAt;\n\t\t}\n\t}\n\tif (!releases[latest]) {\n\t\tthrow new Error(\"registry response missing a publish time for the latest version\");\n\t}\n\tconst cache: CoreUpdateCache = { releases, checkedAt: new Date().toISOString() };\n\tawait new OptionsRepository(db).set(CORE_UPDATE_OPTION, cache);\n}\n\nfunction parseCache(value: unknown): CoreUpdateCache | null {\n\tconst releases = field(value, \"releases\");\n\tconst checkedAt = field(value, \"checkedAt\");\n\tif (typeof releases !== \"object\" || releases === null || typeof checkedAt !== \"string\") {\n\t\treturn null;\n\t}\n\t// An unparsable checkedAt would make the staleness math NaN (never\n\t// stale), freezing a corrupt cache forever — treat it as no cache so\n\t// the next request schedules a refresh that overwrites it.\n\tif (Number.isNaN(Date.parse(checkedAt))) return null;\n\tconst valid: Record<string, string> = {};\n\tfor (const [version, publishedAt] of Object.entries(releases)) {\n\t\tif (\n\t\t\tSTABLE_RE.test(version) &&\n\t\t\ttypeof publishedAt === \"string\" &&\n\t\t\t!Number.isNaN(Date.parse(publishedAt))\n\t\t) {\n\t\t\tvalid[version] = publishedAt;\n\t\t}\n\t}\n\treturn { releases: valid, checkedAt };\n}\n\n/** The newest release published at least `minimumAgeMs` before `now`. */\nfunction newestReleased(\n\treleases: Record<string, string>,\n\tnow: Date,\n\tminimumAgeMs: number,\n): string | null {\n\tlet newest: string | null = null;\n\tfor (const [version, publishedAt] of Object.entries(releases)) {\n\t\tif (now.getTime() - Date.parse(publishedAt) < minimumAgeMs) continue;\n\t\tif (!newest || isNewerVersion(version, newest)) newest = version;\n\t}\n\treturn newest;\n}\n\n/**\n * Seconds a release must be public before it is reported, from the\n * `updateCheck` option. Throws on an invalid duration.\n */\nexport function minimumReleaseAgeSeconds(\n\toption: boolean | { minimumReleaseAge?: string | number } | null | undefined,\n): number {\n\tconst age = typeof option === \"object\" ? option?.minimumReleaseAge : undefined;\n\treturn parseDurationSeconds(age ?? DEFAULT_MINIMUM_RELEASE_AGE);\n}\n\n/**\n * Report the cached update status and, when the cache is stale (or\n * missing), kick a deferred registry refresh. Never blocks on the\n * network: the first request after install/expiry reports the previous\n * state and the next request sees the refreshed one.\n */\nexport async function handleCoreUpdateStatus(\n\tdb: Kysely<Database>,\n\toptions?: { now?: Date; enabled?: boolean; minimumReleaseAgeSeconds?: number; current?: string },\n): Promise<ApiResult<CoreUpdateStatus>> {\n\tconst current = options?.current ?? VERSION;\n\tif (options?.enabled === false) {\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: { current, latest: null, updateAvailable: false, checkedAt: null },\n\t\t};\n\t}\n\n\ttry {\n\t\tconst repo = new OptionsRepository(db);\n\t\tconst cache = parseCache(await repo.get(CORE_UPDATE_OPTION));\n\n\t\tconst now = options?.now ?? new Date();\n\t\tconst minimumAgeMs =\n\t\t\t(options?.minimumReleaseAgeSeconds ?? minimumReleaseAgeSeconds(undefined)) * 1000;\n\t\tconst stale = !cache || now.getTime() - Date.parse(cache.checkedAt) >= CHECK_INTERVAL_MS;\n\t\t// A \"dev\" version can never compare as outdated, so skip the\n\t\t// registry round-trip entirely in uncompiled dev/test runs.\n\t\tif (stale && current !== \"dev\") {\n\t\t\tafter(async () => {\n\t\t\t\ttry {\n\t\t\t\t\tawait refreshCoreUpdateCache(db);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.warn(\"[update-check] registry refresh failed:\", error);\n\t\t\t\t\tconst latestCache = parseCache(await repo.get(CORE_UPDATE_OPTION));\n\t\t\t\t\tif (latestCache?.checkedAt !== cache?.checkedAt) return;\n\t\t\t\t\tconst retryLater: CoreUpdateCache = {\n\t\t\t\t\t\treleases: cache?.releases ?? {},\n\t\t\t\t\t\tcheckedAt: new Date().toISOString(),\n\t\t\t\t\t};\n\t\t\t\t\tawait repo.set(CORE_UPDATE_OPTION, retryLater);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tconst latest = cache ? newestReleased(cache.releases, now, minimumAgeMs) : null;\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: {\n\t\t\t\tcurrent,\n\t\t\t\tlatest,\n\t\t\t\tupdateAvailable: latest ? isNewerVersion(latest, current) : false,\n\t\t\t\tcheckedAt: cache?.checkedAt ?? null,\n\t\t\t},\n\t\t};\n\t} catch (error) {\n\t\tconsole.error(\"[update-check] status read failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: ErrorCode.UPDATE_CHECK_ERROR, message: \"Failed to read update status\" },\n\t\t};\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"update-check-ABBJgg6M.mjs","names":[],"sources":["../src/api/handlers/update-check.ts"],"sourcesContent":["/**\n * Core update status handler.\n *\n * Caches the publish times of stable `emdash` releases from the npm\n * registry in the options table, and reports the newest release that has\n * been public for the minimum release age when it is newer than the\n * running `VERSION`. A stale or missing cache schedules a deferred refresh.\n */\n\nimport type { Kysely } from \"kysely\";\n\nimport { after } from \"../../after.js\";\nimport { OptionsRepository } from \"../../database/repositories/options.js\";\nimport type { Database } from \"../../database/types.js\";\nimport { parseDurationSeconds } from \"../../registry/config.js\";\nimport { VERSION } from \"../../version.js\";\nimport { ErrorCode } from \"../errors.js\";\nimport type { ApiResult } from \"../types.js\";\n\n/** Options-table key for the cached registry result. */\nexport const CORE_UPDATE_OPTION = \"emdash:core_update_check\";\n\n/** Check the registry at most once per day, whether or not the check succeeds. */\nconst CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;\n\n/** npm packument for `emdash`: the `latest` dist-tag and each version's publish time. */\nconst REGISTRY_URL = \"https://registry.npmjs.org/emdash\";\n\n/** Default time a release must be public before admins are told about it. */\nexport const DEFAULT_MINIMUM_RELEASE_AGE = \"24h\";\n\nconst REGISTRY_TIMEOUT_MS = 10_000;\n\n/** Cached registry state, stored in the options table. */\ninterface CoreUpdateCache {\n\t/** Publish time (ISO) of each non-deprecated stable release up to the `latest` dist-tag. */\n\treleases: Record<string, string>;\n\t/** ISO timestamp of the last registry check. */\n\tcheckedAt: string;\n}\n\nexport interface CoreUpdateStatus {\n\t/** The running EmDash version (`\"dev\"` in uncompiled dev/test runs). */\n\tcurrent: string;\n\t/**\n\t * Newest stable release that has been public for the minimum release\n\t * age, or null when no check has completed yet.\n\t */\n\tlatest: string | null;\n\tupdateAvailable: boolean;\n\t/** ISO timestamp of the last registry check, if any. */\n\tcheckedAt: string | null;\n}\n\nconst SEMVER_RE = /^(\\d+)\\.(\\d+)\\.(\\d+)(-.+)?$/;\nconst STABLE_RE = /^\\d+\\.\\d+\\.\\d+$/;\n\n/**\n * True when `latest` is a strictly newer release than `current`.\n *\n * Handles plain `major.minor.patch` versions. Anything unparsable —\n * including the `\"dev\"` fallback version — compares as \"not newer\", so\n * dev/test runs never show the banner. On an equal base version, a stable\n * release is newer than a prerelease of it, so a site running\n * `0.24.0-beta.1` is notified when `0.24.0` ships. Prerelease identifiers\n * are not compared to each other.\n */\nexport function isNewerVersion(latest: string, current: string): boolean {\n\tconst l = SEMVER_RE.exec(latest);\n\tconst c = SEMVER_RE.exec(current);\n\tif (!l || !c) return false;\n\tfor (let i = 1; i <= 3; i++) {\n\t\tconst a = Number(l[i]);\n\t\tconst b = Number(c[i]);\n\t\tif (a !== b) return a > b;\n\t}\n\treturn !l[4] && !!c[4];\n}\n\nfunction field(value: unknown, key: string): unknown {\n\treturn typeof value === \"object\" && value !== null && Object.hasOwn(value, key)\n\t\t? (Reflect.get(value, key) as unknown)\n\t\t: undefined;\n}\n\n/**\n * Fetch the stable releases and their publish times from the npm registry\n * and cache them. Exported for tests; production callers go through\n * `handleCoreUpdateStatus`, which defers this via `after()`.\n */\nexport async function refreshCoreUpdateCache(\n\tdb: Kysely<Database>,\n\tfetchImpl: typeof fetch = fetch,\n): Promise<void> {\n\tconst response = await fetchImpl(REGISTRY_URL, {\n\t\theaders: { accept: \"application/json\" },\n\t\tsignal: AbortSignal.timeout(REGISTRY_TIMEOUT_MS),\n\t});\n\tif (!response.ok) {\n\t\tthrow new Error(`registry responded ${response.status}`);\n\t}\n\tconst body: unknown = await response.json();\n\tconst latest = field(field(body, \"dist-tags\"), \"latest\");\n\tif (typeof latest !== \"string\" || !STABLE_RE.test(latest)) {\n\t\tthrow new Error(\"registry response missing a valid version\");\n\t}\n\tconst time = field(body, \"time\");\n\tconst versions = field(body, \"versions\");\n\tconst releases: Record<string, string> = {};\n\tif (typeof time === \"object\" && time !== null) {\n\t\tfor (const [version, publishedAt] of Object.entries(time)) {\n\t\t\tif (!STABLE_RE.test(version) || isNewerVersion(version, latest)) continue;\n\t\t\tconst manifest = field(versions, version);\n\t\t\tif (manifest === undefined || field(manifest, \"deprecated\") !== undefined) continue;\n\t\t\tif (typeof publishedAt !== \"string\" || Number.isNaN(Date.parse(publishedAt))) continue;\n\t\t\treleases[version] = publishedAt;\n\t\t}\n\t}\n\tif (!releases[latest]) {\n\t\tthrow new Error(\"registry response missing a publish time for the latest version\");\n\t}\n\tconst cache: CoreUpdateCache = { releases, checkedAt: new Date().toISOString() };\n\tawait new OptionsRepository(db).set(CORE_UPDATE_OPTION, cache);\n}\n\nfunction parseCache(value: unknown): CoreUpdateCache | null {\n\tconst releases = field(value, \"releases\");\n\tconst checkedAt = field(value, \"checkedAt\");\n\tif (typeof releases !== \"object\" || releases === null || typeof checkedAt !== \"string\") {\n\t\treturn null;\n\t}\n\t// An unparsable checkedAt would make the staleness math NaN (never\n\t// stale), freezing a corrupt cache forever — treat it as no cache so\n\t// the next request schedules a refresh that overwrites it.\n\tif (Number.isNaN(Date.parse(checkedAt))) return null;\n\tconst valid: Record<string, string> = {};\n\tfor (const [version, publishedAt] of Object.entries(releases)) {\n\t\tif (\n\t\t\tSTABLE_RE.test(version) &&\n\t\t\ttypeof publishedAt === \"string\" &&\n\t\t\t!Number.isNaN(Date.parse(publishedAt))\n\t\t) {\n\t\t\tvalid[version] = publishedAt;\n\t\t}\n\t}\n\treturn { releases: valid, checkedAt };\n}\n\n/** The newest release published at least `minimumAgeMs` before `now`. */\nfunction newestReleased(\n\treleases: Record<string, string>,\n\tnow: Date,\n\tminimumAgeMs: number,\n): string | null {\n\tlet newest: string | null = null;\n\tfor (const [version, publishedAt] of Object.entries(releases)) {\n\t\tif (now.getTime() - Date.parse(publishedAt) < minimumAgeMs) continue;\n\t\tif (!newest || isNewerVersion(version, newest)) newest = version;\n\t}\n\treturn newest;\n}\n\n/**\n * Seconds a release must be public before it is reported, from the\n * `updateCheck` option. Throws on an invalid duration.\n */\nexport function minimumReleaseAgeSeconds(\n\toption: boolean | { minimumReleaseAge?: string | number } | null | undefined,\n): number {\n\tconst age = typeof option === \"object\" ? option?.minimumReleaseAge : undefined;\n\treturn parseDurationSeconds(age ?? DEFAULT_MINIMUM_RELEASE_AGE);\n}\n\n/**\n * Report the cached update status and, when the cache is stale (or\n * missing), kick a deferred registry refresh. Never blocks on the\n * network: the first request after install/expiry reports the previous\n * state and the next request sees the refreshed one.\n */\nexport async function handleCoreUpdateStatus(\n\tdb: Kysely<Database>,\n\toptions?: { now?: Date; enabled?: boolean; minimumReleaseAgeSeconds?: number; current?: string },\n): Promise<ApiResult<CoreUpdateStatus>> {\n\tconst current = options?.current ?? VERSION;\n\tif (options?.enabled === false) {\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: { current, latest: null, updateAvailable: false, checkedAt: null },\n\t\t};\n\t}\n\n\ttry {\n\t\tconst repo = new OptionsRepository(db);\n\t\tconst cache = parseCache(await repo.get(CORE_UPDATE_OPTION));\n\n\t\tconst now = options?.now ?? new Date();\n\t\tconst minimumAgeMs =\n\t\t\t(options?.minimumReleaseAgeSeconds ?? minimumReleaseAgeSeconds(undefined)) * 1000;\n\t\tconst stale = !cache || now.getTime() - Date.parse(cache.checkedAt) >= CHECK_INTERVAL_MS;\n\t\t// A \"dev\" version can never compare as outdated, so skip the\n\t\t// registry round-trip entirely in uncompiled dev/test runs.\n\t\tif (stale && current !== \"dev\") {\n\t\t\tafter(async () => {\n\t\t\t\ttry {\n\t\t\t\t\tawait refreshCoreUpdateCache(db);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.warn(\"[update-check] registry refresh failed:\", error);\n\t\t\t\t\tconst latestCache = parseCache(await repo.get(CORE_UPDATE_OPTION));\n\t\t\t\t\tif (latestCache?.checkedAt !== cache?.checkedAt) return;\n\t\t\t\t\tconst retryLater: CoreUpdateCache = {\n\t\t\t\t\t\treleases: cache?.releases ?? {},\n\t\t\t\t\t\tcheckedAt: new Date().toISOString(),\n\t\t\t\t\t};\n\t\t\t\t\tawait repo.set(CORE_UPDATE_OPTION, retryLater);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tconst latest = cache ? newestReleased(cache.releases, now, minimumAgeMs) : null;\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: {\n\t\t\t\tcurrent,\n\t\t\t\tlatest,\n\t\t\t\tupdateAvailable: latest ? isNewerVersion(latest, current) : false,\n\t\t\t\tcheckedAt: cache?.checkedAt ?? null,\n\t\t\t},\n\t\t};\n\t} catch (error) {\n\t\tconsole.error(\"[update-check] status read failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: ErrorCode.UPDATE_CHECK_ERROR, message: \"Failed to read update status\" },\n\t\t};\n\t}\n}\n"],"mappings":"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"}
@@ -101,4 +101,4 @@ function isSafeUrlFieldValue(value) {
101
101
 
102
102
  //#endregion
103
103
  export { sanitizeHref as i, isSafeUrlFieldValue as n, isSafeUrlFieldWriteValue as r, isSafeHref as t };
104
- //# sourceMappingURL=url-Dn3IStq8.mjs.map
104
+ //# sourceMappingURL=url-DTfGDJhI.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"url-Dn3IStq8.mjs","names":[],"sources":["../src/utils/url.ts"],"sourcesContent":["/**\n * URL scheme validation utilities\n *\n * Prevents XSS via dangerous URL schemes (javascript:, data:, vbscript:, etc.)\n * by allowlisting known-safe schemes before rendering into href attributes.\n */\n\n/**\n * Matches URLs that are safe to render in href attributes.\n *\n * Allowed:\n * - http:// and https://\n * - mailto: and tel:\n * - Relative paths (starting with /)\n * - Fragment links (starting with #)\n * - Protocol-relative URLs are NOT allowed (starting with //) as they can\n * redirect to attacker-controlled hosts.\n */\nconst SAFE_ABSOLUTE_URL_RE = /^(https?:|mailto:|tel:)/i;\nconst SITE_RELATIVE_HREF_RE = /^(\\/(?![/\\\\])|#)/;\nconst URL_SCHEME_RE = /^([a-z][a-z0-9+.-]*):/i;\nconst URL_BASE = new URL(\"https://emdash.invalid/\");\n\nfunction containsHrefControl(value: string): boolean {\n\tfor (const character of value) {\n\t\tconst codePoint = character.codePointAt(0);\n\t\tif (codePoint !== undefined && (codePoint <= 0x1f || codePoint === 0x7f)) return true;\n\t}\n\treturn false;\n}\n\nfunction resolvesOnSite(value: string): boolean {\n\ttry {\n\t\treturn new URL(value, URL_BASE).origin === URL_BASE.origin;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Returns the URL unchanged if it uses a safe scheme, otherwise returns \"#\".\n *\n * Use this at the render layer as the primary defense against XSS via\n * dangerous URL schemes like `javascript:`, `data:`, or `vbscript:`.\n *\n * @example\n * ```ts\n * sanitizeHref(\"https://example.com\") // \"https://example.com\"\n * sanitizeHref(\"/about\") // \"/about\"\n * sanitizeHref(\"#section\") // \"#section\"\n * sanitizeHref(\"mailto:a@b.com\") // \"mailto:a@b.com\"\n * sanitizeHref(\"javascript:alert(1)\") // \"#\"\n * sanitizeHref(\"data:text/html,<script>\") // \"#\"\n * sanitizeHref(\"\") // \"#\"\n * ```\n */\nexport function sanitizeHref(url: string | undefined | null): string {\n\tif (!url) return \"#\";\n\treturn isSafeHref(url) ? url : \"#\";\n}\n\n/**\n * Returns true if the URL uses a safe scheme for rendering in href attributes.\n */\nexport function isSafeHref(url: string): boolean {\n\tif (containsHrefControl(url)) return false;\n\tif (SAFE_ABSOLUTE_URL_RE.test(url)) return URL.canParse(url);\n\treturn SITE_RELATIVE_HREF_RE.test(url) && resolvesOnSite(url);\n}\n\nconst ALLOWED_URL_SCHEMES = new Set([\"http\", \"https\", \"mailto\", \"tel\"]);\n\n/**\n * Returns true if the value names a URL scheme other than http, https,\n * mailto, or tel, as a browser would resolve it in an href.\n */\nexport function hasUnsafeUrlScheme(value: string): boolean {\n\tconst stripped = value.replace(/[\\t\\n\\r]/g, \"\").trimStart();\n\tconst scheme = URL_SCHEME_RE.exec(stripped)?.[1];\n\treturn scheme !== undefined && !ALLOWED_URL_SCHEMES.has(scheme.toLowerCase());\n}\n\n/**\n * Returns true when a repository write may keep the value. Repository callers\n * preserve legacy scheme-less values, but reject anything a browser resolves\n * off-site or to a script-capable scheme.\n */\nexport function isSafeUrlFieldWriteValue(value: string): boolean {\n\tif (containsHrefControl(value) || hasUnsafeUrlScheme(value)) return false;\n\tconst candidate = value.trimStart();\n\tconst scheme = URL_SCHEME_RE.exec(candidate)?.[1];\n\tif (scheme !== undefined) return ALLOWED_URL_SCHEMES.has(scheme.toLowerCase());\n\treturn resolvesOnSite(candidate);\n}\n\n/**\n * Returns true if the value may be stored in a `url` content field: a safe\n * href per {@link isSafeHref} that is either site-relative or a parseable\n * absolute URL.\n */\nexport function isSafeUrlFieldValue(value: string): boolean {\n\treturn isSafeHref(value);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAkBA,MAAM,uBAAuB;AAC7B,MAAM,wBAAwB;AAC9B,MAAM,gBAAgB;AACtB,MAAM,WAAW,IAAI,IAAI,0BAA0B;AAEnD,SAAS,oBAAoB,OAAwB;AACpD,MAAK,MAAM,aAAa,OAAO;EAC9B,MAAM,YAAY,UAAU,YAAY,EAAE;AAC1C,MAAI,cAAc,WAAc,aAAa,MAAQ,cAAc,KAAO,QAAO;;AAElF,QAAO;;AAGR,SAAS,eAAe,OAAwB;AAC/C,KAAI;AACH,SAAO,IAAI,IAAI,OAAO,SAAS,CAAC,WAAW,SAAS;SAC7C;AACP,SAAO;;;;;;;;;;;;;;;;;;;;AAqBT,SAAgB,aAAa,KAAwC;AACpE,KAAI,CAAC,IAAK,QAAO;AACjB,QAAO,WAAW,IAAI,GAAG,MAAM;;;;;AAMhC,SAAgB,WAAW,KAAsB;AAChD,KAAI,oBAAoB,IAAI,CAAE,QAAO;AACrC,KAAI,qBAAqB,KAAK,IAAI,CAAE,QAAO,IAAI,SAAS,IAAI;AAC5D,QAAO,sBAAsB,KAAK,IAAI,IAAI,eAAe,IAAI;;AAG9D,MAAM,sBAAsB,IAAI,IAAI;CAAC;CAAQ;CAAS;CAAU;CAAM,CAAC;;;;;AAMvE,SAAgB,mBAAmB,OAAwB;CAC1D,MAAM,WAAW,MAAM,QAAQ,aAAa,GAAG,CAAC,WAAW;CAC3D,MAAM,SAAS,cAAc,KAAK,SAAS,GAAG;AAC9C,QAAO,WAAW,UAAa,CAAC,oBAAoB,IAAI,OAAO,aAAa,CAAC;;;;;;;AAQ9E,SAAgB,yBAAyB,OAAwB;AAChE,KAAI,oBAAoB,MAAM,IAAI,mBAAmB,MAAM,CAAE,QAAO;CACpE,MAAM,YAAY,MAAM,WAAW;CACnC,MAAM,SAAS,cAAc,KAAK,UAAU,GAAG;AAC/C,KAAI,WAAW,OAAW,QAAO,oBAAoB,IAAI,OAAO,aAAa,CAAC;AAC9E,QAAO,eAAe,UAAU;;;;;;;AAQjC,SAAgB,oBAAoB,OAAwB;AAC3D,QAAO,WAAW,MAAM"}
1
+ {"version":3,"file":"url-DTfGDJhI.mjs","names":[],"sources":["../src/utils/url.ts"],"sourcesContent":["/**\n * URL scheme validation utilities\n *\n * Prevents XSS via dangerous URL schemes (javascript:, data:, vbscript:, etc.)\n * by allowlisting known-safe schemes before rendering into href attributes.\n */\n\n/**\n * Matches URLs that are safe to render in href attributes.\n *\n * Allowed:\n * - http:// and https://\n * - mailto: and tel:\n * - Relative paths (starting with /)\n * - Fragment links (starting with #)\n * - Protocol-relative URLs are NOT allowed (starting with //) as they can\n * redirect to attacker-controlled hosts.\n */\nconst SAFE_ABSOLUTE_URL_RE = /^(https?:|mailto:|tel:)/i;\nconst SITE_RELATIVE_HREF_RE = /^(\\/(?![/\\\\])|#)/;\nconst URL_SCHEME_RE = /^([a-z][a-z0-9+.-]*):/i;\nconst URL_BASE = new URL(\"https://emdash.invalid/\");\n\nfunction containsHrefControl(value: string): boolean {\n\tfor (const character of value) {\n\t\tconst codePoint = character.codePointAt(0);\n\t\tif (codePoint !== undefined && (codePoint <= 0x1f || codePoint === 0x7f)) return true;\n\t}\n\treturn false;\n}\n\nfunction resolvesOnSite(value: string): boolean {\n\ttry {\n\t\treturn new URL(value, URL_BASE).origin === URL_BASE.origin;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Returns the URL unchanged if it uses a safe scheme, otherwise returns \"#\".\n *\n * Use this at the render layer as the primary defense against XSS via\n * dangerous URL schemes like `javascript:`, `data:`, or `vbscript:`.\n *\n * @example\n * ```ts\n * sanitizeHref(\"https://example.com\") // \"https://example.com\"\n * sanitizeHref(\"/about\") // \"/about\"\n * sanitizeHref(\"#section\") // \"#section\"\n * sanitizeHref(\"mailto:a@b.com\") // \"mailto:a@b.com\"\n * sanitizeHref(\"javascript:alert(1)\") // \"#\"\n * sanitizeHref(\"data:text/html,<script>\") // \"#\"\n * sanitizeHref(\"\") // \"#\"\n * ```\n */\nexport function sanitizeHref(url: string | undefined | null): string {\n\tif (!url) return \"#\";\n\treturn isSafeHref(url) ? url : \"#\";\n}\n\n/**\n * Returns true if the URL uses a safe scheme for rendering in href attributes.\n */\nexport function isSafeHref(url: string): boolean {\n\tif (containsHrefControl(url)) return false;\n\tif (SAFE_ABSOLUTE_URL_RE.test(url)) return URL.canParse(url);\n\treturn SITE_RELATIVE_HREF_RE.test(url) && resolvesOnSite(url);\n}\n\nconst ALLOWED_URL_SCHEMES = new Set([\"http\", \"https\", \"mailto\", \"tel\"]);\n\n/**\n * Returns true if the value names a URL scheme other than http, https,\n * mailto, or tel, as a browser would resolve it in an href.\n */\nexport function hasUnsafeUrlScheme(value: string): boolean {\n\tconst stripped = value.replace(/[\\t\\n\\r]/g, \"\").trimStart();\n\tconst scheme = URL_SCHEME_RE.exec(stripped)?.[1];\n\treturn scheme !== undefined && !ALLOWED_URL_SCHEMES.has(scheme.toLowerCase());\n}\n\n/**\n * Returns true when a repository write may keep the value. Repository callers\n * preserve legacy scheme-less values, but reject anything a browser resolves\n * off-site or to a script-capable scheme.\n */\nexport function isSafeUrlFieldWriteValue(value: string): boolean {\n\tif (containsHrefControl(value) || hasUnsafeUrlScheme(value)) return false;\n\tconst candidate = value.trimStart();\n\tconst scheme = URL_SCHEME_RE.exec(candidate)?.[1];\n\tif (scheme !== undefined) return ALLOWED_URL_SCHEMES.has(scheme.toLowerCase());\n\treturn resolvesOnSite(candidate);\n}\n\n/**\n * Returns true if the value may be stored in a `url` content field: a safe\n * href per {@link isSafeHref} that is either site-relative or a parseable\n * absolute URL.\n */\nexport function isSafeUrlFieldValue(value: string): boolean {\n\treturn isSafeHref(value);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAkBA,MAAM,uBAAuB;AAC7B,MAAM,wBAAwB;AAC9B,MAAM,gBAAgB;AACtB,MAAM,WAAW,IAAI,IAAI,0BAA0B;AAEnD,SAAS,oBAAoB,OAAwB;AACpD,MAAK,MAAM,aAAa,OAAO;EAC9B,MAAM,YAAY,UAAU,YAAY,EAAE;AAC1C,MAAI,cAAc,WAAc,aAAa,MAAQ,cAAc,KAAO,QAAO;;AAElF,QAAO;;AAGR,SAAS,eAAe,OAAwB;AAC/C,KAAI;AACH,SAAO,IAAI,IAAI,OAAO,SAAS,CAAC,WAAW,SAAS;SAC7C;AACP,SAAO;;;;;;;;;;;;;;;;;;;;AAqBT,SAAgB,aAAa,KAAwC;AACpE,KAAI,CAAC,IAAK,QAAO;AACjB,QAAO,WAAW,IAAI,GAAG,MAAM;;;;;AAMhC,SAAgB,WAAW,KAAsB;AAChD,KAAI,oBAAoB,IAAI,CAAE,QAAO;AACrC,KAAI,qBAAqB,KAAK,IAAI,CAAE,QAAO,IAAI,SAAS,IAAI;AAC5D,QAAO,sBAAsB,KAAK,IAAI,IAAI,eAAe,IAAI;;AAG9D,MAAM,sBAAsB,IAAI,IAAI;CAAC;CAAQ;CAAS;CAAU;CAAM,CAAC;;;;;AAMvE,SAAgB,mBAAmB,OAAwB;CAC1D,MAAM,WAAW,MAAM,QAAQ,aAAa,GAAG,CAAC,WAAW;CAC3D,MAAM,SAAS,cAAc,KAAK,SAAS,GAAG;AAC9C,QAAO,WAAW,UAAa,CAAC,oBAAoB,IAAI,OAAO,aAAa,CAAC;;;;;;;AAQ9E,SAAgB,yBAAyB,OAAwB;AAChE,KAAI,oBAAoB,MAAM,IAAI,mBAAmB,MAAM,CAAE,QAAO;CACpE,MAAM,YAAY,MAAM,WAAW;CACnC,MAAM,SAAS,cAAc,KAAK,UAAU,GAAG;AAC/C,KAAI,WAAW,OAAW,QAAO,oBAAoB,IAAI,OAAO,aAAa,CAAC;AAC9E,QAAO,eAAe,UAAU;;;;;;;AAQjC,SAAgB,oBAAoB,OAAwB;AAC3D,QAAO,WAAW,MAAM"}
@@ -1,5 +1,5 @@
1
- import { n as chunks, t as SQL_BATCH_SIZE } from "./chunks-xC4UD5-S.mjs";
2
- import { c as decodeCursor, l as encodeCursor } from "./types-D2NEXtgB.mjs";
1
+ import { n as chunks, t as SQL_BATCH_SIZE } from "./chunks-DiW8VMwz.mjs";
2
+ import { l as decodeCursor, u as encodeCursor } from "./types-DwhEvIVb.mjs";
3
3
  import { ulid } from "ulidx";
4
4
 
5
5
  //#region src/database/repositories/user.ts
@@ -168,4 +168,4 @@ var UserRepository = class UserRepository {
168
168
 
169
169
  //#endregion
170
170
  export { UserRepository as t };
171
- //# sourceMappingURL=user-BlCTKVAm.mjs.map
171
+ //# sourceMappingURL=user-By8SzQxS.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"user-BlCTKVAm.mjs","names":[],"sources":["../src/database/repositories/user.ts"],"sourcesContent":["import type { Kysely, Selectable, Updateable } from \"kysely\";\nimport { ulid } from \"ulidx\";\n\nimport { chunks, SQL_BATCH_SIZE } from \"../../utils/chunks.js\";\nimport type { Database, UserTable } from \"../types.js\";\nimport { encodeCursor, decodeCursor, type FindManyResult } from \"./types.js\";\n\ntype UserRow = Selectable<UserTable>;\n\n/**\n * Valid role levels matching the database schema.\n * 10=subscriber, 20=contributor, 30=author, 40=editor, 50=admin\n */\nexport type UserRole = 10 | 20 | 30 | 40 | 50;\n\n/** String role names for convenience APIs */\nexport type UserRoleName = \"subscriber\" | \"contributor\" | \"author\" | \"editor\" | \"admin\";\n\nexport interface User {\n\tid: string;\n\temail: string;\n\tname: string | null;\n\trole: UserRole;\n\tavatarUrl: string | null;\n\temailVerified: boolean;\n\tdata: Record<string, unknown> | null;\n\tcreatedAt: string;\n}\n\nexport interface CreateUserInput {\n\temail: string;\n\tname?: string;\n\trole?: UserRole | UserRoleName;\n\tavatarUrl?: string;\n\tdata?: Record<string, unknown>;\n}\n\nexport interface UpdateUserInput {\n\tname?: string;\n\trole?: UserRole | UserRoleName;\n\tavatarUrl?: string | null;\n\tdata?: Record<string, unknown>;\n}\n\n/**\n * User repository for CRUD operations\n */\nexport class UserRepository {\n\tconstructor(private db: Kysely<Database>) {}\n\n\t/**\n\t * Create a new user\n\t */\n\tasync create(input: CreateUserInput): Promise<User> {\n\t\tconst id = ulid();\n\n\t\tconst row: Omit<UserTable, \"created_at\" | \"updated_at\" | \"disabled\"> = {\n\t\t\tid,\n\t\t\temail: input.email.toLowerCase(),\n\t\t\tname: input.name ?? null,\n\t\t\trole: UserRepository.resolveRole(input.role ?? 10),\n\t\t\tavatar_url: input.avatarUrl ?? null,\n\t\t\temail_verified: 0,\n\t\t\tdata: input.data ? JSON.stringify(input.data) : null,\n\t\t};\n\n\t\tawait this.db.insertInto(\"users\").values(row).execute();\n\n\t\tconst user = await this.findById(id);\n\t\tif (!user) {\n\t\t\tthrow new Error(\"Failed to create user\");\n\t\t}\n\t\treturn user;\n\t}\n\n\t/**\n\t * Find user by ID\n\t */\n\tasync findById(id: string): Promise<User | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"users\")\n\t\t\t.selectAll()\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.executeTakeFirst();\n\n\t\treturn row ? this.rowToUser(row) : null;\n\t}\n\n\t/**\n\t * Batch-resolve users by ID. Returns only the users that exist; missing\n\t * IDs are silently dropped. Chunked at `SQL_BATCH_SIZE` to stay within\n\t * D1's bind-parameter limit.\n\t */\n\tasync findByIds(ids: string[]): Promise<User[]> {\n\t\tconst unique = [...new Set(ids)].filter((id) => id.length > 0);\n\t\tif (unique.length === 0) return [];\n\n\t\tconst out: User[] = [];\n\t\tfor (const batch of chunks(unique, SQL_BATCH_SIZE)) {\n\t\t\tconst rows = await this.db.selectFrom(\"users\").selectAll().where(\"id\", \"in\", batch).execute();\n\t\t\tfor (const row of rows) out.push(this.rowToUser(row));\n\t\t}\n\t\treturn out;\n\t}\n\n\t/**\n\t * Find user by email (case-insensitive)\n\t */\n\tasync findByEmail(email: string): Promise<User | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"users\")\n\t\t\t.selectAll()\n\t\t\t.where(\"email\", \"=\", email.toLowerCase())\n\t\t\t.executeTakeFirst();\n\n\t\treturn row ? this.rowToUser(row) : null;\n\t}\n\n\t/**\n\t * List all users with cursor-based pagination\n\t */\n\tasync findMany(\n\t\toptions: {\n\t\t\trole?: UserRole | UserRoleName;\n\t\t\tlimit?: number;\n\t\t\tcursor?: string;\n\t\t} = {},\n\t): Promise<FindManyResult<User>> {\n\t\tconst limit = Math.min(Math.max(1, options.limit || 50), 100);\n\n\t\tlet query = this.db\n\t\t\t.selectFrom(\"users\")\n\t\t\t.selectAll()\n\t\t\t.orderBy(\"created_at\", \"desc\")\n\t\t\t.orderBy(\"id\", \"desc\")\n\t\t\t.limit(limit + 1);\n\n\t\tif (options.role !== undefined) {\n\t\t\tquery = query.where(\"role\", \"=\", UserRepository.resolveRole(options.role));\n\t\t}\n\n\t\tif (options.cursor) {\n\t\t\tconst decoded = decodeCursor(options.cursor);\n\t\t\tquery = query.where((eb) =>\n\t\t\t\teb.or([\n\t\t\t\t\teb(\"created_at\", \"<\", decoded.orderValue),\n\t\t\t\t\teb.and([eb(\"created_at\", \"=\", decoded.orderValue), eb(\"id\", \"<\", decoded.id)]),\n\t\t\t\t]),\n\t\t\t);\n\t\t}\n\n\t\tconst rows = await query.execute();\n\t\tconst items = rows.slice(0, limit).map((row) => this.rowToUser(row));\n\t\tconst result: FindManyResult<User> = { items };\n\n\t\tif (rows.length > limit && items.length > 0) {\n\t\t\tconst last = items.at(-1)!;\n\t\t\tresult.nextCursor = encodeCursor(last.createdAt, last.id);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Update a user\n\t */\n\tasync update(id: string, input: UpdateUserInput): Promise<User | null> {\n\t\tconst existing = await this.findById(id);\n\t\tif (!existing) return null;\n\n\t\tconst updates: Updateable<UserTable> = {};\n\t\tif (input.name !== undefined) updates.name = input.name;\n\t\tif (input.role !== undefined) updates.role = UserRepository.resolveRole(input.role);\n\t\tif (input.avatarUrl !== undefined) updates.avatar_url = input.avatarUrl;\n\t\tif (input.data !== undefined) updates.data = JSON.stringify(input.data);\n\n\t\tif (Object.keys(updates).length > 0) {\n\t\t\tawait this.db.updateTable(\"users\").set(updates).where(\"id\", \"=\", id).execute();\n\t\t}\n\n\t\treturn this.findById(id);\n\t}\n\n\t/**\n\t * Delete a user\n\t */\n\tasync delete(id: string): Promise<boolean> {\n\t\tconst result = await this.db.deleteFrom(\"users\").where(\"id\", \"=\", id).executeTakeFirst();\n\n\t\treturn (result.numDeletedRows ?? 0) > 0;\n\t}\n\n\t/**\n\t * Count users\n\t */\n\tasync count(role?: UserRole | UserRoleName): Promise<number> {\n\t\tlet query = this.db.selectFrom(\"users\").select((eb) => eb.fn.count(\"id\").as(\"count\"));\n\n\t\tif (role !== undefined) {\n\t\t\tquery = query.where(\"role\", \"=\", UserRepository.resolveRole(role));\n\t\t}\n\n\t\tconst result = await query.executeTakeFirst();\n\t\treturn Number(result?.count || 0);\n\t}\n\n\t/**\n\t * Check if email exists\n\t */\n\tasync emailExists(email: string): Promise<boolean> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"users\")\n\t\t\t.select(\"id\")\n\t\t\t.where(\"email\", \"=\", email.toLowerCase())\n\t\t\t.executeTakeFirst();\n\n\t\treturn !!row;\n\t}\n\n\t/**\n\t * Convert database row to User object\n\t */\n\tprivate rowToUser(row: UserRow): User {\n\t\treturn {\n\t\t\tid: row.id,\n\t\t\temail: row.email,\n\t\t\tname: row.name,\n\t\t\trole: UserRepository.toRole(row.role),\n\t\t\tavatarUrl: row.avatar_url,\n\t\t\temailVerified: row.email_verified === 1,\n\t\t\tdata: row.data ? JSON.parse(row.data) : null,\n\t\t\tcreatedAt: row.created_at,\n\t\t};\n\t}\n\n\t/** Map of role name strings to numeric levels */\n\tprivate static readonly ROLE_NAME_TO_LEVEL: Record<UserRoleName, UserRole> = {\n\t\tsubscriber: 10,\n\t\tcontributor: 20,\n\t\tauthor: 30,\n\t\teditor: 40,\n\t\tadmin: 50,\n\t};\n\n\t/** Valid numeric role levels */\n\tprivate static readonly VALID_LEVELS = new Set<number>([10, 20, 30, 40, 50]);\n\n\t/**\n\t * Resolve a role name or number to a valid numeric UserRole.\n\t * Accepts both string names (\"admin\") and numeric levels (50).\n\t */\n\tstatic resolveRole(role: UserRole | UserRoleName): UserRole {\n\t\tif (typeof role === \"string\") {\n\t\t\tconst level = UserRepository.ROLE_NAME_TO_LEVEL[role];\n\t\t\tif (level === undefined) {\n\t\t\t\tthrow new Error(`Invalid role name: ${role}`);\n\t\t\t}\n\t\t\treturn level;\n\t\t}\n\t\tif (!UserRepository.VALID_LEVELS.has(role)) {\n\t\t\tthrow new Error(`Invalid role level: ${role}`);\n\t\t}\n\t\treturn role;\n\t}\n\n\t/**\n\t * Convert a raw DB integer to a typed UserRole.\n\t * Falls back to subscriber (10) for unknown values.\n\t */\n\tprivate static toRole(level: number): UserRole {\n\t\tif (UserRepository.VALID_LEVELS.has(level)) return level as UserRole;\n\t\treturn 10;\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"user-By8SzQxS.mjs","names":[],"sources":["../src/database/repositories/user.ts"],"sourcesContent":["import type { Kysely, Selectable, Updateable } from \"kysely\";\nimport { ulid } from \"ulidx\";\n\nimport { chunks, SQL_BATCH_SIZE } from \"../../utils/chunks.js\";\nimport type { Database, UserTable } from \"../types.js\";\nimport { encodeCursor, decodeCursor, type FindManyResult } from \"./types.js\";\n\ntype UserRow = Selectable<UserTable>;\n\n/**\n * Valid role levels matching the database schema.\n * 10=subscriber, 20=contributor, 30=author, 40=editor, 50=admin\n */\nexport type UserRole = 10 | 20 | 30 | 40 | 50;\n\n/** String role names for convenience APIs */\nexport type UserRoleName = \"subscriber\" | \"contributor\" | \"author\" | \"editor\" | \"admin\";\n\nexport interface User {\n\tid: string;\n\temail: string;\n\tname: string | null;\n\trole: UserRole;\n\tavatarUrl: string | null;\n\temailVerified: boolean;\n\tdata: Record<string, unknown> | null;\n\tcreatedAt: string;\n}\n\nexport interface CreateUserInput {\n\temail: string;\n\tname?: string;\n\trole?: UserRole | UserRoleName;\n\tavatarUrl?: string;\n\tdata?: Record<string, unknown>;\n}\n\nexport interface UpdateUserInput {\n\tname?: string;\n\trole?: UserRole | UserRoleName;\n\tavatarUrl?: string | null;\n\tdata?: Record<string, unknown>;\n}\n\n/**\n * User repository for CRUD operations\n */\nexport class UserRepository {\n\tconstructor(private db: Kysely<Database>) {}\n\n\t/**\n\t * Create a new user\n\t */\n\tasync create(input: CreateUserInput): Promise<User> {\n\t\tconst id = ulid();\n\n\t\tconst row: Omit<UserTable, \"created_at\" | \"updated_at\" | \"disabled\"> = {\n\t\t\tid,\n\t\t\temail: input.email.toLowerCase(),\n\t\t\tname: input.name ?? null,\n\t\t\trole: UserRepository.resolveRole(input.role ?? 10),\n\t\t\tavatar_url: input.avatarUrl ?? null,\n\t\t\temail_verified: 0,\n\t\t\tdata: input.data ? JSON.stringify(input.data) : null,\n\t\t};\n\n\t\tawait this.db.insertInto(\"users\").values(row).execute();\n\n\t\tconst user = await this.findById(id);\n\t\tif (!user) {\n\t\t\tthrow new Error(\"Failed to create user\");\n\t\t}\n\t\treturn user;\n\t}\n\n\t/**\n\t * Find user by ID\n\t */\n\tasync findById(id: string): Promise<User | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"users\")\n\t\t\t.selectAll()\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.executeTakeFirst();\n\n\t\treturn row ? this.rowToUser(row) : null;\n\t}\n\n\t/**\n\t * Batch-resolve users by ID. Returns only the users that exist; missing\n\t * IDs are silently dropped. Chunked at `SQL_BATCH_SIZE` to stay within\n\t * D1's bind-parameter limit.\n\t */\n\tasync findByIds(ids: string[]): Promise<User[]> {\n\t\tconst unique = [...new Set(ids)].filter((id) => id.length > 0);\n\t\tif (unique.length === 0) return [];\n\n\t\tconst out: User[] = [];\n\t\tfor (const batch of chunks(unique, SQL_BATCH_SIZE)) {\n\t\t\tconst rows = await this.db.selectFrom(\"users\").selectAll().where(\"id\", \"in\", batch).execute();\n\t\t\tfor (const row of rows) out.push(this.rowToUser(row));\n\t\t}\n\t\treturn out;\n\t}\n\n\t/**\n\t * Find user by email (case-insensitive)\n\t */\n\tasync findByEmail(email: string): Promise<User | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"users\")\n\t\t\t.selectAll()\n\t\t\t.where(\"email\", \"=\", email.toLowerCase())\n\t\t\t.executeTakeFirst();\n\n\t\treturn row ? this.rowToUser(row) : null;\n\t}\n\n\t/**\n\t * List all users with cursor-based pagination\n\t */\n\tasync findMany(\n\t\toptions: {\n\t\t\trole?: UserRole | UserRoleName;\n\t\t\tlimit?: number;\n\t\t\tcursor?: string;\n\t\t} = {},\n\t): Promise<FindManyResult<User>> {\n\t\tconst limit = Math.min(Math.max(1, options.limit || 50), 100);\n\n\t\tlet query = this.db\n\t\t\t.selectFrom(\"users\")\n\t\t\t.selectAll()\n\t\t\t.orderBy(\"created_at\", \"desc\")\n\t\t\t.orderBy(\"id\", \"desc\")\n\t\t\t.limit(limit + 1);\n\n\t\tif (options.role !== undefined) {\n\t\t\tquery = query.where(\"role\", \"=\", UserRepository.resolveRole(options.role));\n\t\t}\n\n\t\tif (options.cursor) {\n\t\t\tconst decoded = decodeCursor(options.cursor);\n\t\t\tquery = query.where((eb) =>\n\t\t\t\teb.or([\n\t\t\t\t\teb(\"created_at\", \"<\", decoded.orderValue),\n\t\t\t\t\teb.and([eb(\"created_at\", \"=\", decoded.orderValue), eb(\"id\", \"<\", decoded.id)]),\n\t\t\t\t]),\n\t\t\t);\n\t\t}\n\n\t\tconst rows = await query.execute();\n\t\tconst items = rows.slice(0, limit).map((row) => this.rowToUser(row));\n\t\tconst result: FindManyResult<User> = { items };\n\n\t\tif (rows.length > limit && items.length > 0) {\n\t\t\tconst last = items.at(-1)!;\n\t\t\tresult.nextCursor = encodeCursor(last.createdAt, last.id);\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Update a user\n\t */\n\tasync update(id: string, input: UpdateUserInput): Promise<User | null> {\n\t\tconst existing = await this.findById(id);\n\t\tif (!existing) return null;\n\n\t\tconst updates: Updateable<UserTable> = {};\n\t\tif (input.name !== undefined) updates.name = input.name;\n\t\tif (input.role !== undefined) updates.role = UserRepository.resolveRole(input.role);\n\t\tif (input.avatarUrl !== undefined) updates.avatar_url = input.avatarUrl;\n\t\tif (input.data !== undefined) updates.data = JSON.stringify(input.data);\n\n\t\tif (Object.keys(updates).length > 0) {\n\t\t\tawait this.db.updateTable(\"users\").set(updates).where(\"id\", \"=\", id).execute();\n\t\t}\n\n\t\treturn this.findById(id);\n\t}\n\n\t/**\n\t * Delete a user\n\t */\n\tasync delete(id: string): Promise<boolean> {\n\t\tconst result = await this.db.deleteFrom(\"users\").where(\"id\", \"=\", id).executeTakeFirst();\n\n\t\treturn (result.numDeletedRows ?? 0) > 0;\n\t}\n\n\t/**\n\t * Count users\n\t */\n\tasync count(role?: UserRole | UserRoleName): Promise<number> {\n\t\tlet query = this.db.selectFrom(\"users\").select((eb) => eb.fn.count(\"id\").as(\"count\"));\n\n\t\tif (role !== undefined) {\n\t\t\tquery = query.where(\"role\", \"=\", UserRepository.resolveRole(role));\n\t\t}\n\n\t\tconst result = await query.executeTakeFirst();\n\t\treturn Number(result?.count || 0);\n\t}\n\n\t/**\n\t * Check if email exists\n\t */\n\tasync emailExists(email: string): Promise<boolean> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"users\")\n\t\t\t.select(\"id\")\n\t\t\t.where(\"email\", \"=\", email.toLowerCase())\n\t\t\t.executeTakeFirst();\n\n\t\treturn !!row;\n\t}\n\n\t/**\n\t * Convert database row to User object\n\t */\n\tprivate rowToUser(row: UserRow): User {\n\t\treturn {\n\t\t\tid: row.id,\n\t\t\temail: row.email,\n\t\t\tname: row.name,\n\t\t\trole: UserRepository.toRole(row.role),\n\t\t\tavatarUrl: row.avatar_url,\n\t\t\temailVerified: row.email_verified === 1,\n\t\t\tdata: row.data ? JSON.parse(row.data) : null,\n\t\t\tcreatedAt: row.created_at,\n\t\t};\n\t}\n\n\t/** Map of role name strings to numeric levels */\n\tprivate static readonly ROLE_NAME_TO_LEVEL: Record<UserRoleName, UserRole> = {\n\t\tsubscriber: 10,\n\t\tcontributor: 20,\n\t\tauthor: 30,\n\t\teditor: 40,\n\t\tadmin: 50,\n\t};\n\n\t/** Valid numeric role levels */\n\tprivate static readonly VALID_LEVELS = new Set<number>([10, 20, 30, 40, 50]);\n\n\t/**\n\t * Resolve a role name or number to a valid numeric UserRole.\n\t * Accepts both string names (\"admin\") and numeric levels (50).\n\t */\n\tstatic resolveRole(role: UserRole | UserRoleName): UserRole {\n\t\tif (typeof role === \"string\") {\n\t\t\tconst level = UserRepository.ROLE_NAME_TO_LEVEL[role];\n\t\t\tif (level === undefined) {\n\t\t\t\tthrow new Error(`Invalid role name: ${role}`);\n\t\t\t}\n\t\t\treturn level;\n\t\t}\n\t\tif (!UserRepository.VALID_LEVELS.has(role)) {\n\t\t\tthrow new Error(`Invalid role level: ${role}`);\n\t\t}\n\t\treturn role;\n\t}\n\n\t/**\n\t * Convert a raw DB integer to a typed UserRole.\n\t * Falls back to subscriber (10) for unknown values.\n\t */\n\tprivate static toRole(level: number): UserRole {\n\t\tif (UserRepository.VALID_LEVELS.has(level)) return level as UserRole;\n\t\treturn 10;\n\t}\n}\n"],"mappings":";;;;;;;;AA+CA,IAAa,iBAAb,MAAa,eAAe;CAC3B,YAAY,AAAQ,IAAsB;EAAtB;;;;;CAKpB,MAAM,OAAO,OAAuC;EACnD,MAAM,KAAK,MAAM;EAEjB,MAAM,MAAiE;GACtE;GACA,OAAO,MAAM,MAAM,aAAa;GAChC,MAAM,MAAM,QAAQ;GACpB,MAAM,eAAe,YAAY,MAAM,QAAQ,GAAG;GAClD,YAAY,MAAM,aAAa;GAC/B,gBAAgB;GAChB,MAAM,MAAM,OAAO,KAAK,UAAU,MAAM,KAAK,GAAG;GAChD;AAED,QAAM,KAAK,GAAG,WAAW,QAAQ,CAAC,OAAO,IAAI,CAAC,SAAS;EAEvD,MAAM,OAAO,MAAM,KAAK,SAAS,GAAG;AACpC,MAAI,CAAC,KACJ,OAAM,IAAI,MAAM,wBAAwB;AAEzC,SAAO;;;;;CAMR,MAAM,SAAS,IAAkC;EAChD,MAAM,MAAM,MAAM,KAAK,GACrB,WAAW,QAAQ,CACnB,WAAW,CACX,MAAM,MAAM,KAAK,GAAG,CACpB,kBAAkB;AAEpB,SAAO,MAAM,KAAK,UAAU,IAAI,GAAG;;;;;;;CAQpC,MAAM,UAAU,KAAgC;EAC/C,MAAM,SAAS,CAAC,GAAG,IAAI,IAAI,IAAI,CAAC,CAAC,QAAQ,OAAO,GAAG,SAAS,EAAE;AAC9D,MAAI,OAAO,WAAW,EAAG,QAAO,EAAE;EAElC,MAAM,MAAc,EAAE;AACtB,OAAK,MAAM,SAAS,OAAO,QAAQ,eAAe,EAAE;GACnD,MAAM,OAAO,MAAM,KAAK,GAAG,WAAW,QAAQ,CAAC,WAAW,CAAC,MAAM,MAAM,MAAM,MAAM,CAAC,SAAS;AAC7F,QAAK,MAAM,OAAO,KAAM,KAAI,KAAK,KAAK,UAAU,IAAI,CAAC;;AAEtD,SAAO;;;;;CAMR,MAAM,YAAY,OAAqC;EACtD,MAAM,MAAM,MAAM,KAAK,GACrB,WAAW,QAAQ,CACnB,WAAW,CACX,MAAM,SAAS,KAAK,MAAM,aAAa,CAAC,CACxC,kBAAkB;AAEpB,SAAO,MAAM,KAAK,UAAU,IAAI,GAAG;;;;;CAMpC,MAAM,SACL,UAII,EAAE,EAC0B;EAChC,MAAM,QAAQ,KAAK,IAAI,KAAK,IAAI,GAAG,QAAQ,SAAS,GAAG,EAAE,IAAI;EAE7D,IAAI,QAAQ,KAAK,GACf,WAAW,QAAQ,CACnB,WAAW,CACX,QAAQ,cAAc,OAAO,CAC7B,QAAQ,MAAM,OAAO,CACrB,MAAM,QAAQ,EAAE;AAElB,MAAI,QAAQ,SAAS,OACpB,SAAQ,MAAM,MAAM,QAAQ,KAAK,eAAe,YAAY,QAAQ,KAAK,CAAC;AAG3E,MAAI,QAAQ,QAAQ;GACnB,MAAM,UAAU,aAAa,QAAQ,OAAO;AAC5C,WAAQ,MAAM,OAAO,OACpB,GAAG,GAAG,CACL,GAAG,cAAc,KAAK,QAAQ,WAAW,EACzC,GAAG,IAAI,CAAC,GAAG,cAAc,KAAK,QAAQ,WAAW,EAAE,GAAG,MAAM,KAAK,QAAQ,GAAG,CAAC,CAAC,CAC9E,CAAC,CACF;;EAGF,MAAM,OAAO,MAAM,MAAM,SAAS;EAClC,MAAM,QAAQ,KAAK,MAAM,GAAG,MAAM,CAAC,KAAK,QAAQ,KAAK,UAAU,IAAI,CAAC;EACpE,MAAM,SAA+B,EAAE,OAAO;AAE9C,MAAI,KAAK,SAAS,SAAS,MAAM,SAAS,GAAG;GAC5C,MAAM,OAAO,MAAM,GAAG,GAAG;AACzB,UAAO,aAAa,aAAa,KAAK,WAAW,KAAK,GAAG;;AAG1D,SAAO;;;;;CAMR,MAAM,OAAO,IAAY,OAA8C;AAEtE,MAAI,CADa,MAAM,KAAK,SAAS,GAAG,CACzB,QAAO;EAEtB,MAAM,UAAiC,EAAE;AACzC,MAAI,MAAM,SAAS,OAAW,SAAQ,OAAO,MAAM;AACnD,MAAI,MAAM,SAAS,OAAW,SAAQ,OAAO,eAAe,YAAY,MAAM,KAAK;AACnF,MAAI,MAAM,cAAc,OAAW,SAAQ,aAAa,MAAM;AAC9D,MAAI,MAAM,SAAS,OAAW,SAAQ,OAAO,KAAK,UAAU,MAAM,KAAK;AAEvE,MAAI,OAAO,KAAK,QAAQ,CAAC,SAAS,EACjC,OAAM,KAAK,GAAG,YAAY,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,MAAM,KAAK,GAAG,CAAC,SAAS;AAG/E,SAAO,KAAK,SAAS,GAAG;;;;;CAMzB,MAAM,OAAO,IAA8B;AAG1C,WAFe,MAAM,KAAK,GAAG,WAAW,QAAQ,CAAC,MAAM,MAAM,KAAK,GAAG,CAAC,kBAAkB,EAEzE,kBAAkB,KAAK;;;;;CAMvC,MAAM,MAAM,MAAiD;EAC5D,IAAI,QAAQ,KAAK,GAAG,WAAW,QAAQ,CAAC,QAAQ,OAAO,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,QAAQ,CAAC;AAErF,MAAI,SAAS,OACZ,SAAQ,MAAM,MAAM,QAAQ,KAAK,eAAe,YAAY,KAAK,CAAC;EAGnE,MAAM,SAAS,MAAM,MAAM,kBAAkB;AAC7C,SAAO,OAAO,QAAQ,SAAS,EAAE;;;;;CAMlC,MAAM,YAAY,OAAiC;AAOlD,SAAO,CAAC,CANI,MAAM,KAAK,GACrB,WAAW,QAAQ,CACnB,OAAO,KAAK,CACZ,MAAM,SAAS,KAAK,MAAM,aAAa,CAAC,CACxC,kBAAkB;;;;;CAQrB,AAAQ,UAAU,KAAoB;AACrC,SAAO;GACN,IAAI,IAAI;GACR,OAAO,IAAI;GACX,MAAM,IAAI;GACV,MAAM,eAAe,OAAO,IAAI,KAAK;GACrC,WAAW,IAAI;GACf,eAAe,IAAI,mBAAmB;GACtC,MAAM,IAAI,OAAO,KAAK,MAAM,IAAI,KAAK,GAAG;GACxC,WAAW,IAAI;GACf;;;CAIF,OAAwB,qBAAqD;EAC5E,YAAY;EACZ,aAAa;EACb,QAAQ;EACR,QAAQ;EACR,OAAO;EACP;;CAGD,OAAwB,eAAe,IAAI,IAAY;EAAC;EAAI;EAAI;EAAI;EAAI;EAAG,CAAC;;;;;CAM5E,OAAO,YAAY,MAAyC;AAC3D,MAAI,OAAO,SAAS,UAAU;GAC7B,MAAM,QAAQ,eAAe,mBAAmB;AAChD,OAAI,UAAU,OACb,OAAM,IAAI,MAAM,sBAAsB,OAAO;AAE9C,UAAO;;AAER,MAAI,CAAC,eAAe,aAAa,IAAI,KAAK,CACzC,OAAM,IAAI,MAAM,uBAAuB,OAAO;AAE/C,SAAO;;;;;;CAOR,OAAe,OAAO,OAAyB;AAC9C,MAAI,eAAe,aAAa,IAAI,MAAM,CAAE,QAAO;AACnD,SAAO"}
@@ -1,5 +1,5 @@
1
- import { d as RESERVED_FIELD_SLUGS } from "./types-BGmQ0uXs.mjs";
2
- import { n as slugify } from "./slugify-bu2-jKia.mjs";
1
+ import { d as RESERVED_FIELD_SLUGS, u as RESERVED_COLLECTION_SLUGS } from "./types-C_asjp1J.mjs";
2
+ import { n as slugify } from "./slugify-BDEG9pLk.mjs";
3
3
  import mime from "mime/lite";
4
4
 
5
5
  //#region src/import/utils.ts
@@ -107,11 +107,19 @@ const POST_TYPE_TO_COLLECTION = {
107
107
  event: "events",
108
108
  faq: "faqs"
109
109
  };
110
+ const INVALID_COLLECTION_SLUG_CHARS = /[^a-z0-9_]/g;
111
+ /** Turn a WordPress post type name into a valid, non-reserved collection slug. */
112
+ function sanitizeCollectionSlug(slug) {
113
+ const sanitized = slug.toLowerCase().replace(INVALID_COLLECTION_SLUG_CHARS, "_").replace(LEADING_NON_ALPHA_CHARS, "");
114
+ if (!sanitized) return "imported";
115
+ if (RESERVED_COLLECTION_SLUGS.includes(sanitized)) return `wp_${sanitized}`;
116
+ return sanitized;
117
+ }
110
118
  /**
111
119
  * Map WordPress post type to EmDash collection name
112
120
  */
113
121
  function mapPostTypeToCollection(postType) {
114
- return POST_TYPE_TO_COLLECTION[postType] || postType;
122
+ return POST_TYPE_TO_COLLECTION[postType] || sanitizeCollectionSlug(postType);
115
123
  }
116
124
  /**
117
125
  * Map WordPress meta key to EmDash field slug
@@ -438,5 +446,5 @@ function checkSchemaCompatibility(requiredFields, existingCollection) {
438
446
  }
439
447
 
440
448
  //#endregion
441
- export { resolveImportByline as _, getFilenameFromUrl as a, isInternalMetaKey as c, isTypeCompatible as d, mapMetaKeyToField as f, relativizeContentLinks as g, normalizeUrl as h, checkSchemaCompatibility as i, isInternalPostType as l, mapWpStatus as m, FEATURED_IMAGE_FIELD as n, guessMimeType as o, mapPostTypeToCollection as p, buildAttachmentMap as r, inferMetaType as s, BASE_REQUIRED_FIELDS as t, isPluginBookkeepingMeta as u, sanitizeFieldSlug as v };
442
- //# sourceMappingURL=utils-TPt7w2cS.mjs.map
449
+ export { resolveImportByline as _, getFilenameFromUrl as a, isInternalMetaKey as c, isTypeCompatible as d, mapMetaKeyToField as f, relativizeContentLinks as g, normalizeUrl as h, checkSchemaCompatibility as i, isInternalPostType as l, mapWpStatus as m, FEATURED_IMAGE_FIELD as n, guessMimeType as o, mapPostTypeToCollection as p, buildAttachmentMap as r, inferMetaType as s, BASE_REQUIRED_FIELDS as t, isPluginBookkeepingMeta as u, sanitizeCollectionSlug as v, sanitizeFieldSlug as y };
450
+ //# sourceMappingURL=utils-D5uOi6WS.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils-D5uOi6WS.mjs","names":["slugifyFn"],"sources":["../src/import/utils.ts"],"sourcesContent":["/**\n * Shared import utilities\n *\n * Common constants and functions used across all WordPress import sources.\n */\n\nimport type { PortableTextBlock } from \"@emdash-cms/gutenberg-to-portable-text\";\nimport mime from \"mime/lite\";\n\nimport { RESERVED_COLLECTION_SLUGS, RESERVED_FIELD_SLUGS } from \"../schema/types.js\";\nimport type { ImportFieldDef, CollectionSchemaStatus } from \"./types.js\";\n\n// =============================================================================\n// Constants\n// =============================================================================\n\n/** Internal WordPress post types that should be excluded from import */\nexport const INTERNAL_POST_TYPES = [\n\t\"revision\",\n\t\"nav_menu_item\",\n\t\"custom_css\",\n\t\"customize_changeset\",\n\t\"oembed_cache\",\n\t\"wp_global_styles\",\n\t\"wp_navigation\",\n\t\"wp_template\",\n\t\"wp_template_part\",\n\t\"attachment\", // Handled separately as media\n\t\"wp_block\", // Handled separately as sections (reusable blocks)\n\t\"acf-field-group\",\n\t\"acf-field\",\n\t\"acf-post-type\",\n\t\"acf-taxonomy\",\n\t\"acf-ui-options-page\",\n];\n\n/** Internal meta key prefixes to filter out */\nexport const INTERNAL_META_PREFIXES = [\"_edit_\", \"_wp_\"];\n\nconst NUMERIC_PATTERN = /^-?\\d+(\\.\\d+)?$/;\nconst TRAILING_SLASHES = /\\/+$/;\nconst WP_JSON_SUFFIX = /\\/wp-json\\/?.*$/;\n\n/** Specific internal meta keys */\nexport const INTERNAL_META_KEYS = [\"_edit_last\", \"_edit_lock\", \"_pingme\", \"_encloseme\"];\n\n/** Base fields required for any WordPress import */\nexport const BASE_REQUIRED_FIELDS: ImportFieldDef[] = [\n\t{ slug: \"title\", label: \"Title\", type: \"string\", required: true, searchable: true },\n\t{ slug: \"content\", label: \"Content\", type: \"portableText\", required: false, searchable: true },\n\t{ slug: \"excerpt\", label: \"Excerpt\", type: \"text\", required: false },\n];\n\n/** Featured image field - only added to post types that have _thumbnail_id */\nexport const FEATURED_IMAGE_FIELD: ImportFieldDef = {\n\tslug: \"featured_image\",\n\tlabel: \"Featured Image\",\n\ttype: \"image\",\n\trequired: false,\n};\n\n// =============================================================================\n// Type Guards\n// =============================================================================\n\n/**\n * Check if a post type is internal/should be excluded\n */\nexport function isInternalPostType(type: string): boolean {\n\treturn INTERNAL_POST_TYPES.includes(type);\n}\n\n/**\n * Check if a meta key is internal/should be filtered out\n */\nexport function isInternalMetaKey(key: string): boolean {\n\t// Check specific keys\n\tif (INTERNAL_META_KEYS.includes(key)) return true;\n\n\t// Check prefixes\n\tfor (const prefix of INTERNAL_META_PREFIXES) {\n\t\tif (key.startsWith(prefix)) return true;\n\t}\n\n\t// Keep these useful ones\n\tif (key === \"_thumbnail_id\") return false;\n\tif (key.startsWith(\"_yoast_\")) return false;\n\tif (key.startsWith(\"_rank_math_\")) return false;\n\n\t// Other underscore prefixes are usually internal\n\tif (key.startsWith(\"_\")) return true;\n\n\treturn false;\n}\n\n// =============================================================================\n// Status Mapping\n// =============================================================================\n\n/** Valid WordPress statuses */\nexport type WpStatus = \"publish\" | \"draft\" | \"pending\" | \"private\" | \"future\";\n\n/**\n * Map WordPress status to normalized status\n */\nexport function mapWpStatus(status: string | undefined): WpStatus {\n\tswitch (status) {\n\t\tcase \"publish\":\n\t\t\treturn \"publish\";\n\t\tcase \"draft\":\n\t\t\treturn \"draft\";\n\t\tcase \"pending\":\n\t\t\treturn \"pending\";\n\t\tcase \"private\":\n\t\t\treturn \"private\";\n\t\tcase \"future\":\n\t\t\treturn \"future\";\n\t\tdefault:\n\t\t\treturn \"draft\";\n\t}\n}\n\n// =============================================================================\n// Collection Mapping\n// =============================================================================\n\n/** Default mappings from WordPress post types to EmDash collections */\nconst POST_TYPE_TO_COLLECTION: Record<string, string> = {\n\tpost: \"posts\",\n\tpage: \"pages\",\n\tattachment: \"media\",\n\tproduct: \"products\",\n\tportfolio: \"portfolio\",\n\ttestimonial: \"testimonials\",\n\tteam: \"team\",\n\tevent: \"events\",\n\tfaq: \"faqs\",\n};\n\nconst INVALID_COLLECTION_SLUG_CHARS = /[^a-z0-9_]/g;\n\n/** Turn a WordPress post type name into a valid, non-reserved collection slug. */\nexport function sanitizeCollectionSlug(slug: string): string {\n\tconst sanitized = slug\n\t\t.toLowerCase()\n\t\t.replace(INVALID_COLLECTION_SLUG_CHARS, \"_\")\n\t\t.replace(LEADING_NON_ALPHA_CHARS, \"\");\n\tif (!sanitized) return \"imported\";\n\tif (RESERVED_COLLECTION_SLUGS.includes(sanitized)) return `wp_${sanitized}`;\n\treturn sanitized;\n}\n\n/**\n * Map WordPress post type to EmDash collection name\n */\nexport function mapPostTypeToCollection(postType: string): string {\n\treturn POST_TYPE_TO_COLLECTION[postType] || sanitizeCollectionSlug(postType);\n}\n\n// =============================================================================\n// Meta Key Mapping\n// =============================================================================\n\n/**\n * Map WordPress meta key to EmDash field slug\n */\nexport function mapMetaKeyToField(key: string): string {\n\t// SEO plugins\n\tif (key === \"_yoast_wpseo_title\") return \"seo_title\";\n\tif (key === \"_yoast_wpseo_metadesc\") return \"seo_description\";\n\tif (key === \"_rank_math_title\") return \"seo_title\";\n\tif (key === \"_rank_math_description\") return \"seo_description\";\n\tif (key === \"_thumbnail_id\") return \"featured_image\";\n\n\t// Remove leading underscore\n\tif (key.startsWith(\"_\")) return key.slice(1);\n\n\treturn key;\n}\n\n/**\n * Infer field type from meta key name and sample value\n */\nexport function inferMetaType(\n\tkey: string,\n\tvalue: string | undefined,\n): \"string\" | \"number\" | \"boolean\" | \"date\" | \"json\" {\n\tif (key.endsWith(\"_id\") || key === \"_thumbnail_id\") return \"string\";\n\tif (key.endsWith(\"_date\") || key.endsWith(\"_time\")) return \"date\";\n\tif (key.endsWith(\"_count\") || key.endsWith(\"_number\")) return \"number\";\n\n\tif (!value) return \"string\";\n\n\t// Serialized PHP or JSON\n\tif (value.startsWith(\"a:\") || value.startsWith(\"{\") || value.startsWith(\"[\")) return \"json\";\n\n\t// Number\n\tif (NUMERIC_PATTERN.test(value)) return \"number\";\n\n\t// Boolean\n\tif ([\"0\", \"1\", \"true\", \"false\"].includes(value)) return \"boolean\";\n\n\treturn \"string\";\n}\n\n// =============================================================================\n// Plugin Bookkeeping Meta\n// =============================================================================\n\n/**\n * Meta prefixes written by well-known WordPress plugins as operational\n * bookkeeping (sync state, counters, cache keys) — not content. Without\n * this filter, a mature site's analysis suggests dozens of junk fields\n * per post type and the real content fields drown in them.\n *\n * ponytail: curated list of the plugins we've seen in the wild, not a\n * taxonomy of the WP ecosystem. Unknown plugins' meta still gets through;\n * extend the list as real sites surface new offenders.\n */\nconst PLUGIN_META_PREFIXES = [\n\t\"aawp_\", // AAWP (Amazon affiliate)\n\t\"algolia_\", // Algolia / WP Search with Algolia\n\t\"amazon_polly_\", // Amazon Polly\n\t\"ampforwp_\", // AMP for WP\n\t\"classifai_\", // ClassifAI\n\t\"essb_\", // Easy Social Share Buttons\n\t\"eg_\", // Essential Grid\n\t\"gnpub_\", // Google News publisher tools\n\t\"jetpack_\", // Jetpack\n\t\"mashsb_\", // MashShare\n\t\"monsterinsights_\", // MonsterInsights\n\t\"onesignal_\", // OneSignal push\n\t\"penci_\", // Penci themes\n\t\"perfmatters_\", // Perfmatters\n\t\"pys_\", // PixelYourSite\n\t\"rank_math_\", // Rank Math internals (title/description go through the SEO pass)\n\t\"rp4wp_\", // Related Posts for WP\n\t\"saswp_\", // Schema & Structured Data for WP\n\t\"sbg_\", // Simple Blog Grid\n\t\"snap_\", // SNAP auto-poster\n\t\"spay_\", // Simple Pay\n\t\"tie_\", // TieLabs themes\n\t\"wl_\", // WordLift\n\t\"wpil_\", // Link Whisper\n\t\"wprm_\", // WP Recipe Maker internals\n\t\"wpswa_\", // WP Search with Algolia\n\t\"wpuf_\", // WP User Frontend\n\t\"yarpp_\", // YARPP\n];\n\n/** Exact meta keys that are plugin/core bookkeeping, not content. */\nconst PLUGIN_META_KEYS = new Set([\n\t\"entity_same_as\", // WordLift\n\t\"exclude_from_search\", // search exclusion plugins\n\t\"footnotes\", // Gutenberg core footnotes store\n\t\"inline_featured_image\", // inline featured image plugin\n\t\"os_meta\", // theme option stores\n\t\"thirstydata\", // ThirstyAffiliates\n]);\n\n/**\n * Check whether a meta key is well-known plugin bookkeeping that should\n * not become a content field. Hyphens are normalized to underscores\n * before matching (e.g. `ampforwp-amp-on-off`).\n */\nexport function isPluginBookkeepingMeta(key: string): boolean {\n\tconst normalized = key.replaceAll(\"-\", \"_\");\n\tif (PLUGIN_META_KEYS.has(normalized)) return true;\n\treturn PLUGIN_META_PREFIXES.some((prefix) => normalized.startsWith(prefix));\n}\n\n// =============================================================================\n// Field Slug Sanitization\n// =============================================================================\n\nconst INVALID_FIELD_SLUG_CHARS = /[^a-z0-9_]+/g;\nconst LEADING_NON_ALPHA_CHARS = /^[^a-z]+/;\n\n/**\n * Sanitize a WordPress meta/ACF key into a valid EmDash field slug\n * (`/^[a-z][a-z0-9_]*$/`, max 63 chars, not reserved).\n *\n * Must be applied consistently on both sides of an import: once when\n * creating fields from the analysis, and again when matching incoming\n * meta keys onto schema fields — otherwise keys like `my-field` create\n * `my_field` but never receive values.\n */\nexport function sanitizeFieldSlug(key: string): string {\n\tconst sanitized = key\n\t\t.toLowerCase()\n\t\t.replace(INVALID_FIELD_SLUG_CHARS, \"_\")\n\t\t.replace(LEADING_NON_ALPHA_CHARS, \"\")\n\t\t.slice(0, 63);\n\tif (!sanitized) return \"field\";\n\tif (RESERVED_FIELD_SLUGS.includes(sanitized)) return `wp_${sanitized}`;\n\treturn sanitized;\n}\n\n// =============================================================================\n// Internal Link Relativization\n// =============================================================================\n\nconst REGEX_SPECIALS = /[.*+?^${}()|[\\]\\\\]/g;\nconst LEADING_WWW = /^www\\./;\n\n/**\n * Turn an absolute URL into a root-relative one when it points at the\n * source site (www-insensitive). Returns null when the URL should be\n * left alone: external links, non-http(s) schemes, and `/wp-content/`\n * media files — those stay absolute so the later media pass can match\n * them against its old-URL -> new-URL map.\n */\nfunction relativizeUrl(url: string, sourceHost: string): string | null {\n\tif (!url.startsWith(\"http://\") && !url.startsWith(\"https://\")) return null;\n\ttry {\n\t\tconst parsed = new URL(url);\n\t\tif (parsed.hostname.replace(LEADING_WWW, \"\") !== sourceHost) return null;\n\t\tif (parsed.pathname.startsWith(\"/wp-content/\")) return null;\n\t\treturn `${parsed.pathname}${parsed.search}${parsed.hash}` || \"/\";\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction relativizeMarkDefs(\n\tmarkDefs: Array<{ _type: string; [key: string]: unknown }> | undefined,\n\tsourceHost: string,\n): void {\n\tfor (const def of markDefs ?? []) {\n\t\tif (def._type === \"link\" && typeof def.href === \"string\") {\n\t\t\tdef.href = relativizeUrl(def.href, sourceHost) ?? def.href;\n\t\t}\n\t}\n}\n\n/**\n * Rewrite internal links in imported content to root-relative URLs, in\n * place. Without this, imported posts keep linking back to the old\n * WordPress domain (e.g. `https://oldsite.com/companies/google/`)\n * instead of staying on the new site.\n *\n * ponytail: path structures are kept as-is (WP permalink /2024/05/slug/\n * stays /2024/05/slug/) — mapping old paths onto the new site's routes\n * is the planned permalink->redirect-map feature.\n */\nexport function relativizeContentLinks(blocks: PortableTextBlock[], siteUrl: string): void {\n\tlet sourceHost: string;\n\ttry {\n\t\tsourceHost = new URL(siteUrl).hostname.replace(LEADING_WWW, \"\");\n\t} catch {\n\t\treturn;\n\t}\n\t// Raw HTML in the wild uses double-quoted, single-quoted, and unquoted\n\t// href values; the backreference \\1 matches the closing quote (or\n\t// nothing, for unquoted). Rewritten links are normalized to href=\"...\".\n\tconst hrefPattern = new RegExp(\n\t\t`href=([\"']?)https?://(?:www\\\\.)?${sourceHost.replace(REGEX_SPECIALS, \"\\\\$&\")}(/[^\"'\\\\s>]*)?\\\\1`,\n\t\t\"gi\",\n\t);\n\n\tfor (const block of blocks) {\n\t\tswitch (block._type) {\n\t\t\tcase \"block\":\n\t\t\t\trelativizeMarkDefs(block.markDefs, sourceHost);\n\t\t\t\tbreak;\n\t\t\tcase \"image\":\n\t\t\t\t// asset.url stays absolute (media pass), only the click-through link\n\t\t\t\tif (typeof block.link === \"string\") {\n\t\t\t\t\tblock.link = relativizeUrl(block.link, sourceHost) ?? block.link;\n\t\t\t\t} else if (block.link?.href) {\n\t\t\t\t\tblock.link = {\n\t\t\t\t\t\t...block.link,\n\t\t\t\t\t\thref: relativizeUrl(block.link.href, sourceHost) ?? block.link.href,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"table\":\n\t\t\t\tfor (const row of block.rows) {\n\t\t\t\t\tfor (const cell of row.cells) relativizeMarkDefs(cell.markDefs, sourceHost);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"columns\":\n\t\t\t\tfor (const column of block.columns) relativizeContentLinks(column.content, siteUrl);\n\t\t\t\tbreak;\n\t\t\tcase \"cover\":\n\t\t\t\trelativizeContentLinks(block.content, siteUrl);\n\t\t\t\tbreak;\n\t\t\tcase \"button\":\n\t\t\t\tif (block.url) block.url = relativizeUrl(block.url, sourceHost) ?? block.url;\n\t\t\t\tbreak;\n\t\t\tcase \"buttons\":\n\t\t\t\tfor (const button of block.buttons) {\n\t\t\t\t\tif (button.url) button.url = relativizeUrl(button.url, sourceHost) ?? button.url;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"htmlBlock\":\n\t\t\t\tblock.html = block.html.replace(\n\t\t\t\t\threfPattern,\n\t\t\t\t\t(match, _quote: string, path: string | undefined) =>\n\t\t\t\t\t\tpath?.startsWith(\"/wp-content/\") ? match : `href=\"${path || \"/\"}\"`,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t// URL-less or media-only blocks: media URLs are the media pass's job\n\t\t\tcase \"code\":\n\t\t\tcase \"embed\":\n\t\t\tcase \"gallery\":\n\t\t\tcase \"break\":\n\t\t\tcase \"file\":\n\t\t\tcase \"pullquote\":\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tblock satisfies never;\n\t\t}\n\t}\n}\n\n// =============================================================================\n// String Utilities\n// =============================================================================\n\nexport { slugify } from \"../utils/slugify.js\";\n\n/**\n * Normalize URL for API requests\n */\nexport function normalizeUrl(url: string): string {\n\tlet normalized = url.trim();\n\n\t// Add protocol if missing\n\tif (!normalized.startsWith(\"http\")) {\n\t\tnormalized = `https://${normalized}`;\n\t}\n\n\t// Remove trailing slash\n\tnormalized = normalized.replace(TRAILING_SLASHES, \"\");\n\n\t// Remove /wp-json if included\n\tnormalized = normalized.replace(WP_JSON_SUFFIX, \"\");\n\n\treturn normalized;\n}\n\n// =============================================================================\n// File Utilities\n// =============================================================================\n\n/**\n * Extract filename from URL\n */\nexport function getFilenameFromUrl(url: string): string | undefined {\n\ttry {\n\t\tconst parsed = new URL(url);\n\t\tconst segments = parsed.pathname.split(\"/\").filter(Boolean);\n\t\treturn segments.pop();\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/**\n * Guess MIME type from filename\n */\nexport function guessMimeType(filename: string): string | undefined {\n\treturn mime.getType(filename) ?? undefined;\n}\n\n// =============================================================================\n// Attachment Map Builder\n// =============================================================================\n\n/**\n * Build a map of attachment IDs to URLs for resolving featured images\n */\nexport function buildAttachmentMap(\n\tattachments: Array<{ id?: number | string; url?: string }>,\n): Map<string, string> {\n\tconst map = new Map<string, string>();\n\tfor (const att of attachments) {\n\t\tif (att.id && att.url) {\n\t\t\tmap.set(String(att.id), att.url);\n\t\t}\n\t}\n\treturn map;\n}\n\n// =============================================================================\n// Schema Compatibility\n// =============================================================================\n\n/**\n * Check if two field types are compatible for import\n */\nexport function isTypeCompatible(requiredType: string, existingType: string): boolean {\n\tif (requiredType === existingType) return true;\n\n\tconst compatibleTypes: Record<string, string[]> = {\n\t\tstring: [\"string\", \"text\", \"slug\"],\n\t\ttext: [\"string\", \"text\"],\n\t\tportableText: [\"portableText\", \"json\"],\n\t\tnumber: [\"number\", \"integer\"],\n\t\tinteger: [\"number\", \"integer\"],\n\t};\n\n\tconst compatible = compatibleTypes[requiredType];\n\treturn compatible?.includes(existingType) ?? false;\n}\n\n// =============================================================================\n// Byline Import Utilities\n// =============================================================================\n\nimport type { BylineRepository } from \"../database/repositories/byline.js\";\nimport { slugify as slugifyFn } from \"../utils/slugify.js\";\n\nconst MAX_SLUG_COLLISION_ATTEMPTS = 1000;\n\n/**\n * Find or create a unique byline slug, capped at MAX_SLUG_COLLISION_ATTEMPTS.\n */\nexport async function ensureUniqueBylineSlug(\n\tbylineRepo: BylineRepository,\n\tbaseSlug: string,\n): Promise<string> {\n\tlet candidate = baseSlug;\n\tlet suffix = 2;\n\twhile (await bylineRepo.findBySlug(candidate)) {\n\t\tif (suffix > MAX_SLUG_COLLISION_ATTEMPTS) {\n\t\t\tthrow new Error(\n\t\t\t\t`Byline slug collision limit exceeded for base slug \"${baseSlug}\". ` +\n\t\t\t\t\t`Tried ${MAX_SLUG_COLLISION_ATTEMPTS} variants.`,\n\t\t\t);\n\t\t}\n\t\tcandidate = `${baseSlug}-${suffix}`;\n\t\tsuffix++;\n\t}\n\treturn candidate;\n}\n\n/**\n * Resolve (find-or-create) a byline for an imported WordPress author.\n * Caches results in `cache` keyed by `authorLogin:mappedUserId`.\n */\nexport async function resolveImportByline(\n\tauthorLogin: string | undefined,\n\tdisplayName: string | undefined,\n\tmappedUserId: string | undefined,\n\tbylineRepo: BylineRepository,\n\tcache: Map<string, string>,\n): Promise<string | undefined> {\n\tif (!authorLogin) return undefined;\n\tconst cacheKey = `${authorLogin}:${mappedUserId ?? \"\"}`;\n\tconst cached = cache.get(cacheKey);\n\tif (cached) return cached;\n\n\tif (mappedUserId) {\n\t\tconst existingForUser = await bylineRepo.findByUserId(mappedUserId);\n\t\tif (existingForUser) {\n\t\t\tcache.set(cacheKey, existingForUser.id);\n\t\t\treturn existingForUser.id;\n\t\t}\n\t}\n\n\tconst name = displayName || authorLogin;\n\tconst slugBase = slugifyFn(authorLogin);\n\tconst slug = await ensureUniqueBylineSlug(bylineRepo, slugBase || \"author\");\n\tconst created = await bylineRepo.create({\n\t\tslug,\n\t\tdisplayName: name,\n\t\tuserId: mappedUserId ?? null,\n\t\tisGuest: !mappedUserId,\n\t});\n\n\tcache.set(cacheKey, created.id);\n\treturn created.id;\n}\n\n// =============================================================================\n// Schema Compatibility\n// =============================================================================\n\n/**\n * Check schema compatibility between required fields and existing collection\n */\nexport function checkSchemaCompatibility(\n\trequiredFields: ImportFieldDef[],\n\texistingCollection: { slug: string; fields: Map<string, { type: string }> } | undefined,\n): CollectionSchemaStatus {\n\tif (!existingCollection) {\n\t\t// Collection doesn't exist - will need to create it\n\t\tconst fieldStatus: CollectionSchemaStatus[\"fieldStatus\"] = {};\n\t\tfor (const field of requiredFields) {\n\t\t\tfieldStatus[field.slug] = {\n\t\t\t\tstatus: \"missing\",\n\t\t\t\trequiredType: field.type,\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\texists: false,\n\t\t\tfieldStatus,\n\t\t\tcanImport: true,\n\t\t};\n\t}\n\n\t// Collection exists - check field compatibility\n\tconst fieldStatus: CollectionSchemaStatus[\"fieldStatus\"] = {};\n\tconst incompatibleFields: string[] = [];\n\n\tfor (const field of requiredFields) {\n\t\tconst existingField = existingCollection.fields.get(field.slug);\n\n\t\tif (!existingField) {\n\t\t\tfieldStatus[field.slug] = {\n\t\t\t\tstatus: \"missing\",\n\t\t\t\trequiredType: field.type,\n\t\t\t};\n\t\t} else if (isTypeCompatible(field.type, existingField.type)) {\n\t\t\tfieldStatus[field.slug] = {\n\t\t\t\tstatus: \"compatible\",\n\t\t\t\texistingType: existingField.type,\n\t\t\t\trequiredType: field.type,\n\t\t\t};\n\t\t} else {\n\t\t\tfieldStatus[field.slug] = {\n\t\t\t\tstatus: \"type_mismatch\",\n\t\t\t\texistingType: existingField.type,\n\t\t\t\trequiredType: field.type,\n\t\t\t};\n\t\t\tincompatibleFields.push(field.slug);\n\t\t}\n\t}\n\n\tconst canImport = incompatibleFields.length === 0;\n\tconst reason = canImport\n\t\t? undefined\n\t\t: `Incompatible field types: ${incompatibleFields.join(\", \")}`;\n\n\treturn {\n\t\texists: true,\n\t\tfieldStatus,\n\t\tcanImport,\n\t\treason,\n\t};\n}\n"],"mappings":"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"}