emdash 0.27.0 → 0.28.1

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 (537) hide show
  1. package/dist/{adapters-u037EnTR.d.mts → adapters-hUy8vOB-.d.mts} +1 -1
  2. package/dist/{adapters-u037EnTR.d.mts.map → adapters-hUy8vOB-.d.mts.map} +1 -1
  3. package/dist/{allowed-origins-D5FxMUo8.mjs → allowed-origins-CRsJ6BPM.mjs} +2 -2
  4. package/dist/{allowed-origins-D5FxMUo8.mjs.map → allowed-origins-CRsJ6BPM.mjs.map} +1 -1
  5. package/dist/api/route-utils.d.mts +3 -3
  6. package/dist/api/route-utils.mjs +17 -16
  7. package/dist/api/route-utils.mjs.map +1 -1
  8. package/dist/api/schemas/index.d.mts +1 -1
  9. package/dist/api/schemas/index.mjs +3 -3
  10. package/dist/{api-80kycR9o.mjs → api-DxFSorgk.mjs} +33 -23
  11. package/dist/api-DxFSorgk.mjs.map +1 -0
  12. package/dist/{api-tokens-D6ppjIVi.mjs → api-tokens-DvqeZmVq.mjs} +2 -2
  13. package/dist/{api-tokens-D6ppjIVi.mjs.map → api-tokens-DvqeZmVq.mjs.map} +1 -1
  14. package/dist/{apply-DSypk6Iu.mjs → apply-CDJqIjPU.mjs} +111 -74
  15. package/dist/apply-CDJqIjPU.mjs.map +1 -0
  16. package/dist/astro/index.d.mts +12 -12
  17. package/dist/astro/index.mjs +3 -3
  18. package/dist/astro/index.mjs.map +1 -1
  19. package/dist/astro/middleware/auth.d.mts +10 -10
  20. package/dist/astro/middleware/auth.d.mts.map +1 -1
  21. package/dist/astro/middleware/auth.mjs +50 -11
  22. package/dist/astro/middleware/auth.mjs.map +1 -1
  23. package/dist/astro/middleware/redirect.mjs +5 -5
  24. package/dist/astro/middleware/request-context.mjs +2 -2
  25. package/dist/astro/middleware/setup.mjs +1 -1
  26. package/dist/astro/middleware.d.mts +2 -2
  27. package/dist/astro/middleware.mjs +124 -71
  28. package/dist/astro/middleware.mjs.map +1 -1
  29. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +6 -6
  30. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +6 -6
  31. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +4 -4
  32. package/dist/astro/routes/api/admin/api-tokens/index.mjs +5 -5
  33. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +4 -4
  34. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +8 -8
  35. package/dist/astro/routes/api/admin/byline-fields/index.mjs +8 -8
  36. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +8 -8
  37. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +14 -14
  38. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +14 -14
  39. package/dist/astro/routes/api/admin/bylines/index.mjs +14 -14
  40. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +12 -12
  41. package/dist/astro/routes/api/admin/comments/_id_.mjs +6 -6
  42. package/dist/astro/routes/api/admin/comments/bulk.mjs +10 -10
  43. package/dist/astro/routes/api/admin/comments/counts.mjs +6 -6
  44. package/dist/astro/routes/api/admin/comments/index.mjs +10 -10
  45. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +4 -4
  46. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
  47. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +4 -4
  48. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +4 -4
  49. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +37 -36
  50. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  51. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +37 -36
  52. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  53. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +36 -35
  54. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  55. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +36 -35
  56. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  57. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +36 -35
  58. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  59. package/dist/astro/routes/api/admin/plugins/index.mjs +36 -35
  60. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  61. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +3 -3
  62. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +36 -35
  63. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  64. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +36 -35
  65. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  66. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +36 -35
  67. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  68. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +36 -35
  69. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  70. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +37 -36
  71. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  72. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +36 -35
  73. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
  74. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +37 -36
  75. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  76. package/dist/astro/routes/api/admin/plugins/updates.mjs +36 -35
  77. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  78. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +36 -35
  79. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  80. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +3 -3
  81. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +36 -35
  82. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  83. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +2 -2
  84. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +2 -2
  85. package/dist/astro/routes/api/admin/users/_id_/index.mjs +6 -6
  86. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +3 -3
  87. package/dist/astro/routes/api/admin/users/index.mjs +6 -6
  88. package/dist/astro/routes/api/auth/dev-bypass.mjs +5 -5
  89. package/dist/astro/routes/api/auth/invite/accept.mjs +2 -2
  90. package/dist/astro/routes/api/auth/invite/complete.mjs +10 -10
  91. package/dist/astro/routes/api/auth/invite/index.mjs +7 -7
  92. package/dist/astro/routes/api/auth/invite/register-options.mjs +9 -9
  93. package/dist/astro/routes/api/auth/logout.mjs +3 -3
  94. package/dist/astro/routes/api/auth/magic-link/send.mjs +9 -9
  95. package/dist/astro/routes/api/auth/magic-link/verify.mjs +3 -3
  96. package/dist/astro/routes/api/auth/me.mjs +7 -7
  97. package/dist/astro/routes/api/auth/mode.mjs +1 -1
  98. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +3 -3
  99. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  100. package/dist/astro/routes/api/auth/passkey/_id_.mjs +6 -6
  101. package/dist/astro/routes/api/auth/passkey/index.mjs +2 -2
  102. package/dist/astro/routes/api/auth/passkey/options.mjs +11 -11
  103. package/dist/astro/routes/api/auth/passkey/register/options.mjs +9 -9
  104. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +10 -10
  105. package/dist/astro/routes/api/auth/passkey/verify.mjs +10 -10
  106. package/dist/astro/routes/api/auth/signup/complete.mjs +10 -10
  107. package/dist/astro/routes/api/auth/signup/request.mjs +9 -9
  108. package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
  109. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +13 -13
  110. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +12 -12
  111. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +3 -3
  112. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +3 -3
  113. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
  114. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +3 -3
  115. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +10 -10
  116. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +7 -7
  117. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
  118. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +3 -3
  119. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +7 -7
  120. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +13 -13
  121. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +3 -3
  122. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +3 -3
  123. package/dist/astro/routes/api/content/_collection_/_id_.mjs +7 -7
  124. package/dist/astro/routes/api/content/_collection_/authors.mjs +3 -3
  125. package/dist/astro/routes/api/content/_collection_/index.mjs +7 -7
  126. package/dist/astro/routes/api/content/_collection_/trash.mjs +7 -7
  127. package/dist/astro/routes/api/dashboard.mjs +8 -8
  128. package/dist/astro/routes/api/dev/emails.mjs +3 -3
  129. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  130. package/dist/astro/routes/api/import/probe.mjs +19 -11
  131. package/dist/astro/routes/api/import/probe.mjs.map +1 -1
  132. package/dist/astro/routes/api/import/wordpress/analyze.mjs +3 -3
  133. package/dist/astro/routes/api/import/wordpress/execute.d.mts +11 -41
  134. package/dist/astro/routes/api/import/wordpress/execute.d.mts.map +1 -1
  135. package/dist/astro/routes/api/import/wordpress/execute.mjs +12 -407
  136. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  137. package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -10
  138. package/dist/astro/routes/api/import/wordpress/media.mjs +9 -9
  139. package/dist/astro/routes/api/import/wordpress/prepare.mjs +9 -9
  140. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +19 -1
  141. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts.map +1 -1
  142. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +97 -79
  143. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
  144. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  145. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +19 -11
  146. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs.map +1 -1
  147. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +40 -2
  148. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts.map +1 -1
  149. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +519 -39
  150. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  151. package/dist/astro/routes/api/manifest.mjs +4 -4
  152. package/dist/astro/routes/api/mcp.mjs +39 -39
  153. package/dist/astro/routes/api/media/_id_/confirm.mjs +7 -7
  154. package/dist/astro/routes/api/media/_id_.mjs +7 -7
  155. package/dist/astro/routes/api/media/file/_...key_.mjs +2 -2
  156. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +3 -3
  157. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +3 -3
  158. package/dist/astro/routes/api/media/providers/index.mjs +3 -3
  159. package/dist/astro/routes/api/media/upload-url.mjs +8 -8
  160. package/dist/astro/routes/api/media.mjs +9 -9
  161. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +9 -9
  162. package/dist/astro/routes/api/menus/_name_/items.mjs +9 -9
  163. package/dist/astro/routes/api/menus/_name_/reorder.mjs +9 -9
  164. package/dist/astro/routes/api/menus/_name_/translations.mjs +9 -9
  165. package/dist/astro/routes/api/menus/_name_.mjs +9 -9
  166. package/dist/astro/routes/api/menus/index.mjs +9 -9
  167. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  168. package/dist/astro/routes/api/oauth/device/authorize.mjs +6 -6
  169. package/dist/astro/routes/api/oauth/device/code.mjs +9 -9
  170. package/dist/astro/routes/api/oauth/device/token.mjs +8 -8
  171. package/dist/astro/routes/api/oauth/register.mjs +3 -3
  172. package/dist/astro/routes/api/oauth/token/refresh.mjs +6 -6
  173. package/dist/astro/routes/api/oauth/token/revoke.mjs +6 -6
  174. package/dist/astro/routes/api/oauth/token.mjs +6 -6
  175. package/dist/astro/routes/api/openapi.json.mjs +4 -4
  176. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.d.mts.map +1 -1
  177. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +6 -14
  178. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs.map +1 -1
  179. package/dist/astro/routes/api/redirects/404s/index.mjs +9 -9
  180. package/dist/astro/routes/api/redirects/404s/summary.mjs +9 -9
  181. package/dist/astro/routes/api/redirects/_id_.mjs +10 -10
  182. package/dist/astro/routes/api/redirects/index.mjs +10 -10
  183. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +3 -3
  184. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
  185. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +36 -35
  186. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  187. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +36 -35
  188. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  189. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +36 -35
  190. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  191. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +36 -35
  192. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  193. package/dist/astro/routes/api/schema/collections/index.mjs +36 -35
  194. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  195. package/dist/astro/routes/api/schema/index.mjs +7 -6
  196. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  197. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +36 -35
  198. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  199. package/dist/astro/routes/api/schema/orphans/index.mjs +36 -35
  200. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  201. package/dist/astro/routes/api/search/enable.mjs +10 -10
  202. package/dist/astro/routes/api/search/index.mjs +9 -9
  203. package/dist/astro/routes/api/search/rebuild.mjs +10 -10
  204. package/dist/astro/routes/api/search/stats.mjs +6 -6
  205. package/dist/astro/routes/api/search/suggest.mjs +9 -9
  206. package/dist/astro/routes/api/sections/_slug_.mjs +9 -9
  207. package/dist/astro/routes/api/sections/index.mjs +9 -9
  208. package/dist/astro/routes/api/settings/email.mjs +4 -4
  209. package/dist/astro/routes/api/settings.mjs +12 -12
  210. package/dist/astro/routes/api/setup/admin-verify.mjs +11 -11
  211. package/dist/astro/routes/api/setup/admin.mjs +10 -10
  212. package/dist/astro/routes/api/setup/dev-bypass.mjs +25 -24
  213. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  214. package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
  215. package/dist/astro/routes/api/setup/index.mjs +26 -25
  216. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  217. package/dist/astro/routes/api/setup/status.mjs +4 -4
  218. package/dist/astro/routes/api/snapshot.mjs +6 -6
  219. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +13 -13
  220. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +13 -13
  221. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +13 -13
  222. package/dist/astro/routes/api/taxonomies/index.mjs +13 -13
  223. package/dist/astro/routes/api/themes/preview.mjs +5 -5
  224. package/dist/astro/routes/api/typegen.mjs +5 -5
  225. package/dist/astro/routes/api/well-known/auth.mjs +1 -1
  226. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  227. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  228. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +7 -7
  229. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +9 -9
  230. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +9 -9
  231. package/dist/astro/routes/api/widget-areas/_name_.mjs +5 -5
  232. package/dist/astro/routes/api/widget-areas/index.mjs +9 -9
  233. package/dist/astro/routes/api/widget-components.mjs +3 -3
  234. package/dist/astro/routes/robots.txt.mjs +6 -6
  235. package/dist/astro/routes/sitemap-_collection_.xml.mjs +9 -9
  236. package/dist/astro/routes/sitemap.xml.mjs +7 -7
  237. package/dist/astro/types.d.mts +13 -13
  238. package/dist/auth/providers/github.d.mts +1 -1
  239. package/dist/auth/providers/google.d.mts +1 -1
  240. package/dist/{authorize-C3a_zGsM.mjs → authorize-Dz88F_Fw.mjs} +2 -2
  241. package/dist/{authorize-C3a_zGsM.mjs.map → authorize-Dz88F_Fw.mjs.map} +1 -1
  242. package/dist/{byline-DEKSVPTy.mjs → byline-Bm8ZgUP9.mjs} +6 -6
  243. package/dist/{byline-DEKSVPTy.mjs.map → byline-Bm8ZgUP9.mjs.map} +1 -1
  244. package/dist/{byline-fields-eyJMblSr.mjs → byline-fields-2Lp5Hbgf.mjs} +18 -3
  245. package/dist/byline-fields-2Lp5Hbgf.mjs.map +1 -0
  246. package/dist/{byline-fields-CtQ6blXd.d.mts → byline-fields-CHE8UStY.d.mts} +47 -32
  247. package/dist/{byline-fields-CtQ6blXd.d.mts.map → byline-fields-CHE8UStY.d.mts.map} +1 -1
  248. package/dist/{byline-fields-DaMKzkhO.mjs → byline-fields-CIx_GuN4.mjs} +1 -1
  249. package/dist/{byline-fields-DaMKzkhO.mjs.map → byline-fields-CIx_GuN4.mjs.map} +1 -1
  250. package/dist/{bylines-Ds4-otXl.mjs → bylines-6tm9mgQb.mjs} +4 -4
  251. package/dist/{bylines-Ds4-otXl.mjs.map → bylines-6tm9mgQb.mjs.map} +1 -1
  252. package/dist/{bylines-CiqgTHWF.mjs → bylines-CAZxGSrm.mjs} +6 -6
  253. package/dist/{bylines-CiqgTHWF.mjs.map → bylines-CAZxGSrm.mjs.map} +1 -1
  254. package/dist/{cache-Ciu3e3AF.mjs → cache-CEBAZjir.mjs} +2 -2
  255. package/dist/{cache-Ciu3e3AF.mjs.map → cache-CEBAZjir.mjs.map} +1 -1
  256. package/dist/{challenge-store-LhiqMccz.mjs → challenge-store-anhwVER0.mjs} +1 -1
  257. package/dist/{challenge-store-LhiqMccz.mjs.map → challenge-store-anhwVER0.mjs.map} +1 -1
  258. package/dist/{chunks-CZFiauig.mjs → chunks-B2isWQhr.mjs} +2 -2
  259. package/dist/{chunks-CZFiauig.mjs.map → chunks-B2isWQhr.mjs.map} +1 -1
  260. package/dist/cli/index.mjs +22 -21
  261. package/dist/cli/index.mjs.map +1 -1
  262. package/dist/client/cf-access.d.mts +1 -1
  263. package/dist/client/index.d.mts +1 -1
  264. package/dist/client/index.mjs +2 -2
  265. package/dist/{comment-CH1IrFFs.mjs → comment-CzeatwBV.mjs} +3 -3
  266. package/dist/{comment-CH1IrFFs.mjs.map → comment-CzeatwBV.mjs.map} +1 -1
  267. package/dist/{comment-reaction-kruNY-kP.mjs → comment-reaction-Cj9QJY7I.mjs} +2 -2
  268. package/dist/{comment-reaction-kruNY-kP.mjs.map → comment-reaction-Cj9QJY7I.mjs.map} +1 -1
  269. package/dist/{comments-BUJyXbgq.mjs → comments-BLE-jv5k.mjs} +3 -3
  270. package/dist/{comments-BUJyXbgq.mjs.map → comments-BLE-jv5k.mjs.map} +1 -1
  271. package/dist/{components-CYt4uVK9.mjs → components-B_sATNUc.mjs} +1 -1
  272. package/dist/{components-CYt4uVK9.mjs.map → components-B_sATNUc.mjs.map} +1 -1
  273. package/dist/{content-RmfHoWqK.mjs → content-DhgEth4k.mjs} +4 -4
  274. package/dist/{content-RmfHoWqK.mjs.map → content-DhgEth4k.mjs.map} +1 -1
  275. package/dist/content-refresh-Br4gMzh8.mjs +1537 -0
  276. package/dist/content-refresh-Br4gMzh8.mjs.map +1 -0
  277. package/dist/{context-CzUU_WzL.mjs → context-BRIpHARC.mjs} +76 -54
  278. package/dist/context-BRIpHARC.mjs.map +1 -0
  279. package/dist/{cron-C5LVoNmP.mjs → cron-v4FTEFR_.mjs} +1 -1
  280. package/dist/{cron-C5LVoNmP.mjs.map → cron-v4FTEFR_.mjs.map} +1 -1
  281. package/dist/{dashboard-CVyGhift.mjs → dashboard-EvEKF5en.mjs} +4 -4
  282. package/dist/{dashboard-CVyGhift.mjs.map → dashboard-EvEKF5en.mjs.map} +1 -1
  283. package/dist/db/index.d.mts +3 -3
  284. package/dist/db/index.mjs +1 -1
  285. package/dist/db/libsql.d.mts +1 -1
  286. package/dist/db/postgres.d.mts +1 -1
  287. package/dist/db/sqlite.d.mts +1 -1
  288. package/dist/{default-CeRG-Ot4.mjs → default-CM_D83Mg.mjs} +1 -1
  289. package/dist/{default-CeRG-Ot4.mjs.map → default-CM_D83Mg.mjs.map} +1 -1
  290. package/dist/{device-flow-DENDCQ9F.mjs → device-flow-CfGP18Uw.mjs} +4 -4
  291. package/dist/{device-flow-DENDCQ9F.mjs.map → device-flow-CfGP18Uw.mjs.map} +1 -1
  292. package/dist/{email-console-DJP32ucW.mjs → email-console-CIf4Lfvv.mjs} +1 -1
  293. package/dist/{email-console-DJP32ucW.mjs.map → email-console-CIf4Lfvv.mjs.map} +1 -1
  294. package/dist/{error-BHkLZk-w.mjs → error-CkAseSqZ.mjs} +2 -2
  295. package/dist/{error-BHkLZk-w.mjs.map → error-CkAseSqZ.mjs.map} +1 -1
  296. package/dist/{escape-Bjio4ZsM.mjs → escape-DqD0aCKu.mjs} +1 -1
  297. package/dist/{escape-Bjio4ZsM.mjs.map → escape-DqD0aCKu.mjs.map} +1 -1
  298. package/dist/{field-defs-cache-BA-8ZPiT.mjs → field-defs-cache-WUI88LX5.mjs} +2 -2
  299. package/dist/{field-defs-cache-BA-8ZPiT.mjs.map → field-defs-cache-WUI88LX5.mjs.map} +1 -1
  300. package/dist/{fts-manager-Db9jGavf.mjs → fts-manager-BbFaF_V8.mjs} +2 -2
  301. package/dist/{fts-manager-Db9jGavf.mjs.map → fts-manager-BbFaF_V8.mjs.map} +1 -1
  302. package/dist/{import-Bb1T9WJS.mjs → import-fYLf14Co.mjs} +514 -25
  303. package/dist/import-fYLf14Co.mjs.map +1 -0
  304. package/dist/{index-CDZZjrLT.d.mts → index-B9sIxwe4.d.mts} +21 -22
  305. package/dist/{index-CDZZjrLT.d.mts.map → index-B9sIxwe4.d.mts.map} +1 -1
  306. package/dist/{index-DGIjmUXQ.d.mts → index-Bm-Gy8Mh.d.mts} +25 -4
  307. package/dist/index-Bm-Gy8Mh.d.mts.map +1 -0
  308. package/dist/index.d.mts +18 -18
  309. package/dist/index.mjs +54 -53
  310. package/dist/{load-DpHICVPh.mjs → load-Djn3HWQS.mjs} +2 -2
  311. package/dist/{load-DpHICVPh.mjs.map → load-Djn3HWQS.mjs.map} +1 -1
  312. package/dist/{loader-4K37qA-y.mjs → loader-CB6YHeul.mjs} +6 -5
  313. package/dist/loader-CB6YHeul.mjs.map +1 -0
  314. package/dist/{manifest-schema-kPGX7VS-.mjs → manifest-schema-BHlgZM1W.mjs} +1 -1
  315. package/dist/{manifest-schema-kPGX7VS-.mjs.map → manifest-schema-BHlgZM1W.mjs.map} +1 -1
  316. package/dist/media/index.d.mts +1 -1
  317. package/dist/media/local-runtime.d.mts +12 -12
  318. package/dist/media/local-runtime.mjs +5 -5
  319. package/dist/{media-C0nRRfs1.mjs → media-BrXIaMFN.mjs} +2 -2
  320. package/dist/{media-C0nRRfs1.mjs.map → media-BrXIaMFN.mjs.map} +1 -1
  321. package/dist/{media-allowlist-Du8t1u6a.mjs → media-allowlist-CRHEeJ_i.mjs} +1 -1
  322. package/dist/{media-allowlist-Du8t1u6a.mjs.map → media-allowlist-CRHEeJ_i.mjs.map} +1 -1
  323. package/dist/{media-url-O4rm9-SQ.mjs → media-url-CKi5XSw4.mjs} +1 -1
  324. package/dist/{media-url-O4rm9-SQ.mjs.map → media-url-CKi5XSw4.mjs.map} +1 -1
  325. package/dist/{menus-SL2K0xq2.mjs → menus-Cfivc2Ad.mjs} +3 -3
  326. package/dist/{menus-SL2K0xq2.mjs.map → menus-Cfivc2Ad.mjs.map} +1 -1
  327. package/dist/{menus-DzRyC1ID.mjs → menus-b2T4clbO.mjs} +16 -12
  328. package/dist/{menus-DzRyC1ID.mjs.map → menus-b2T4clbO.mjs.map} +1 -1
  329. package/dist/{mode-BB0F8xTC.mjs → mode-BM9QgEmt.mjs} +1 -1
  330. package/dist/{mode-BB0F8xTC.mjs.map → mode-BM9QgEmt.mjs.map} +1 -1
  331. package/dist/{oauth-authorization-CsvzIp_F.mjs → oauth-authorization-CXWkIGT4.mjs} +4 -4
  332. package/dist/{oauth-authorization-CsvzIp_F.mjs.map → oauth-authorization-CXWkIGT4.mjs.map} +1 -1
  333. package/dist/{oauth-clients-C9SYwEbZ.mjs → oauth-clients-BmTI5rsl.mjs} +1 -1
  334. package/dist/{oauth-clients-C9SYwEbZ.mjs.map → oauth-clients-BmTI5rsl.mjs.map} +1 -1
  335. package/dist/{oauth-state-store---zrApfB.mjs → oauth-state-store-YLFLcH5F.mjs} +1 -1
  336. package/dist/{oauth-state-store---zrApfB.mjs.map → oauth-state-store-YLFLcH5F.mjs.map} +1 -1
  337. package/dist/{oauth-user-lookup-SHsWRlG9.mjs → oauth-user-lookup-Bsc_GsX-.mjs} +1 -1
  338. package/dist/{oauth-user-lookup-SHsWRlG9.mjs.map → oauth-user-lookup-Bsc_GsX-.mjs.map} +1 -1
  339. package/dist/object-cache/memory.d.mts +1 -1
  340. package/dist/{object-cache-CHbHv83-.mjs → object-cache-Bok5j2ae.mjs} +43 -3
  341. package/dist/object-cache-Bok5j2ae.mjs.map +1 -0
  342. package/dist/{options-41nCWqi9.d.mts → options-iMpRRxIe.d.mts} +3 -3
  343. package/dist/{options-41nCWqi9.d.mts.map → options-iMpRRxIe.d.mts.map} +1 -1
  344. package/dist/page/index.d.mts +2 -2
  345. package/dist/{parse-CqyZj3Hp.mjs → parse-GmjecGct.mjs} +2 -2
  346. package/dist/{parse-CqyZj3Hp.mjs.map → parse-GmjecGct.mjs.map} +1 -1
  347. package/dist/{passkey-config-C0YfSBko.mjs → passkey-config-De0ahnRg.mjs} +1 -1
  348. package/dist/{passkey-config-C0YfSBko.mjs.map → passkey-config-De0ahnRg.mjs.map} +1 -1
  349. package/dist/{placeholder-Cuce9U-m.d.mts → placeholder-BSKwzRe4.d.mts} +1 -1
  350. package/dist/{placeholder-Cuce9U-m.d.mts.map → placeholder-BSKwzRe4.d.mts.map} +1 -1
  351. package/dist/plugin-types.d.mts +1 -1
  352. package/dist/plugin-utils.d.mts +10 -10
  353. package/dist/plugins/adapt-sandbox-entry.d.mts +10 -10
  354. package/dist/plugins/adapt-sandbox-entry.mjs +2 -2
  355. package/dist/{portable-text-BICg8bTk.mjs → portable-text-cCa0cGV6.mjs} +1 -1
  356. package/dist/{portable-text-BICg8bTk.mjs.map → portable-text-cCa0cGV6.mjs.map} +1 -1
  357. package/dist/{preview-DKGCt2_p.mjs → preview-SSXNVPAC.mjs} +2 -2
  358. package/dist/{preview-DKGCt2_p.mjs.map → preview-SSXNVPAC.mjs.map} +1 -1
  359. package/dist/{public-url-CTVqgMmg.mjs → public-url-Danv47cS.mjs} +1 -1
  360. package/dist/{public-url-CTVqgMmg.mjs.map → public-url-Danv47cS.mjs.map} +1 -1
  361. package/dist/{query-B0M-9LYR.mjs → query-1Cp6U9oo.mjs} +14 -14
  362. package/dist/{query-B0M-9LYR.mjs.map → query-1Cp6U9oo.mjs.map} +1 -1
  363. package/dist/{rate-limit-BwoUdIpC.mjs → rate-limit-C_Lf63Dd.mjs} +2 -2
  364. package/dist/{rate-limit-BwoUdIpC.mjs.map → rate-limit-C_Lf63Dd.mjs.map} +1 -1
  365. package/dist/{redirect-CS-PHtNh.mjs → redirect-CoW3G-0U.mjs} +1 -1
  366. package/dist/{redirect-CS-PHtNh.mjs.map → redirect-CoW3G-0U.mjs.map} +1 -1
  367. package/dist/{redirect-lMOzG04S.mjs → redirect-IyfNirgS.mjs} +2 -2
  368. package/dist/{redirect-lMOzG04S.mjs.map → redirect-IyfNirgS.mjs.map} +1 -1
  369. package/dist/{redirects-9218MmYl.mjs → redirects-Bs1g42Ri.mjs} +4 -4
  370. package/dist/{redirects-9218MmYl.mjs.map → redirects-Bs1g42Ri.mjs.map} +1 -1
  371. package/dist/{redirects-Dcbuisoj.mjs → redirects-DXEXBAII.mjs} +2 -2
  372. package/dist/{redirects-Dcbuisoj.mjs.map → redirects-DXEXBAII.mjs.map} +1 -1
  373. package/dist/{registry-DP-iEtdR.mjs → registry-B57vp_X9.mjs} +122 -79
  374. package/dist/registry-B57vp_X9.mjs.map +1 -0
  375. package/dist/{request-meta-CmS1tDFf.mjs → request-meta-DbvXaAvU.mjs} +2 -2
  376. package/dist/{request-meta-CmS1tDFf.mjs.map → request-meta-DbvXaAvU.mjs.map} +1 -1
  377. package/dist/{resolve-C7I0qiR0.mjs → resolve-DR3wqMTy.mjs} +1 -1
  378. package/dist/{resolve-C7I0qiR0.mjs.map → resolve-DR3wqMTy.mjs.map} +1 -1
  379. package/dist/{runner-BbR3DfrL.d.mts → runner-DvFWoz8-.d.mts} +2 -2
  380. package/dist/{runner-BbR3DfrL.d.mts.map → runner-DvFWoz8-.d.mts.map} +1 -1
  381. package/dist/{runner-CFngB4WZ.mjs → runner-K8XK101B.mjs} +309 -190
  382. package/dist/runner-K8XK101B.mjs.map +1 -0
  383. package/dist/runtime.d.mts +11 -11
  384. package/dist/runtime.mjs +2 -2
  385. package/dist/{scheduled-publish-BMljtY5G.d.mts → scheduled-publish-Drffrf2a.d.mts} +1 -1
  386. package/dist/scheduled-publish-Drffrf2a.d.mts.map +1 -0
  387. package/dist/{schema-BfJ7bIXH.mjs → schema-CX9cfNkZ.mjs} +5 -5
  388. package/dist/{schema-BfJ7bIXH.mjs.map → schema-CX9cfNkZ.mjs.map} +1 -1
  389. package/dist/{search-C7t3PH1J.mjs → search-DZN2HZ-V.mjs} +4 -4
  390. package/dist/{search-C7t3PH1J.mjs.map → search-DZN2HZ-V.mjs.map} +1 -1
  391. package/dist/{secrets-BSf9pRRY.mjs → secrets-kp760LlD.mjs} +2 -2
  392. package/dist/{secrets-BSf9pRRY.mjs.map → secrets-kp760LlD.mjs.map} +1 -1
  393. package/dist/{sections-Dm0CVX23.mjs → sections-CpF5SaGr.mjs} +3 -3
  394. package/dist/{sections-Dm0CVX23.mjs.map → sections-CpF5SaGr.mjs.map} +1 -1
  395. package/dist/seed/index.d.mts +2 -2
  396. package/dist/seed/index.mjs +19 -18
  397. package/dist/seo/index.d.mts +1 -1
  398. package/dist/seo/index.mjs +1 -1
  399. package/dist/{seo-BkhuuaaE.mjs → seo-89-53DDs.mjs} +1 -1
  400. package/dist/{seo-BkhuuaaE.mjs.map → seo-89-53DDs.mjs.map} +1 -1
  401. package/dist/{seo-Dd3tbY_k.mjs → seo-DXu2UQnC.mjs} +3 -3
  402. package/dist/{seo-Dd3tbY_k.mjs.map → seo-DXu2UQnC.mjs.map} +1 -1
  403. package/dist/{service-CTrqp_Jy.mjs → service-DQmiBMzt.mjs} +3 -3
  404. package/dist/{service-CTrqp_Jy.mjs.map → service-DQmiBMzt.mjs.map} +1 -1
  405. package/dist/{session-user-B8aLtKAH.mjs → session-user-Cascbax7.mjs} +1 -1
  406. package/dist/{session-user-B8aLtKAH.mjs.map → session-user-Cascbax7.mjs.map} +1 -1
  407. package/dist/{settings-CZ7ZP9cW.mjs → settings-rZyHEcNT.mjs} +3 -3
  408. package/dist/{settings-CZ7ZP9cW.mjs.map → settings-rZyHEcNT.mjs.map} +1 -1
  409. package/dist/{settings-BX8cWBus.mjs → settings-zhmdKyJQ.mjs} +5 -5
  410. package/dist/{settings-BX8cWBus.mjs.map → settings-zhmdKyJQ.mjs.map} +1 -1
  411. package/dist/{setup-complete-gEiySUc-.mjs → setup-complete-Cb3LRyzy.mjs} +1 -1
  412. package/dist/{setup-complete-gEiySUc-.mjs.map → setup-complete-Cb3LRyzy.mjs.map} +1 -1
  413. package/dist/{setup-nonce-DzS50zme.mjs → setup-nonce-Z8x0tHf8.mjs} +1 -1
  414. package/dist/{setup-nonce-DzS50zme.mjs.map → setup-nonce-Z8x0tHf8.mjs.map} +1 -1
  415. package/dist/{single-flight-cache-Cdfkic3t.mjs → single-flight-cache-BG3B_GhN.mjs} +1 -1
  416. package/dist/{single-flight-cache-Cdfkic3t.mjs.map → single-flight-cache-BG3B_GhN.mjs.map} +1 -1
  417. package/dist/{site-url-BLebyON8.mjs → site-url-BBfDTgZB.mjs} +1 -1
  418. package/dist/{site-url-BLebyON8.mjs.map → site-url-BBfDTgZB.mjs.map} +1 -1
  419. package/dist/{ssrf-BRKb343l.mjs → ssrf-1g7usGBg.mjs} +1 -1
  420. package/dist/{ssrf-BRKb343l.mjs.map → ssrf-1g7usGBg.mjs.map} +1 -1
  421. package/dist/{status-vUK0SA17.mjs → status-CqJQX1QN.mjs} +1 -1
  422. package/dist/{status-vUK0SA17.mjs.map → status-CqJQX1QN.mjs.map} +1 -1
  423. package/dist/storage/local.d.mts +1 -1
  424. package/dist/storage/local.mjs +1 -1
  425. package/dist/storage/s3.d.mts +1 -1
  426. package/dist/storage/s3.mjs +1 -1
  427. package/dist/{taxonomies-DChKcVxf.mjs → taxonomies-Bs13SN-F.mjs} +4 -4
  428. package/dist/{taxonomies-DChKcVxf.mjs.map → taxonomies-Bs13SN-F.mjs.map} +1 -1
  429. package/dist/{taxonomies-ckPjz-6d.mjs → taxonomies-kH9ABDUF.mjs} +7 -7
  430. package/dist/{taxonomies-ckPjz-6d.mjs.map → taxonomies-kH9ABDUF.mjs.map} +1 -1
  431. package/dist/{taxonomy-Cru-he6s.mjs → taxonomy-BxGxZZdu.mjs} +4 -4
  432. package/dist/{taxonomy-Cru-he6s.mjs.map → taxonomy-BxGxZZdu.mjs.map} +1 -1
  433. package/dist/{tokens-LeuXF9gG.mjs → tokens-BGT0TUUo.mjs} +1 -1
  434. package/dist/{tokens-LeuXF9gG.mjs.map → tokens-BGT0TUUo.mjs.map} +1 -1
  435. package/dist/{transport-Blrl2k_o.d.mts → transport-BMDWHSgZ.d.mts} +1 -1
  436. package/dist/{transport-Blrl2k_o.d.mts.map → transport-BMDWHSgZ.d.mts.map} +1 -1
  437. package/dist/{transport-_2nBz7e9.mjs → transport-DPefPMcz.mjs} +1 -1
  438. package/dist/{transport-_2nBz7e9.mjs.map → transport-DPefPMcz.mjs.map} +1 -1
  439. package/dist/{trusted-proxy-DZY5WCn2.mjs → trusted-proxy-VTPRiX2s.mjs} +1 -1
  440. package/dist/{trusted-proxy-DZY5WCn2.mjs.map → trusted-proxy-VTPRiX2s.mjs.map} +1 -1
  441. package/dist/{types-ETmO_jQr.d.mts → types-BcLUUbbR.d.mts} +2 -2
  442. package/dist/{types-ETmO_jQr.d.mts.map → types-BcLUUbbR.d.mts.map} +1 -1
  443. package/dist/{types-BYnDBVwe.d.mts → types-CGbYowGQ.d.mts} +2 -2
  444. package/dist/{types-BYnDBVwe.d.mts.map → types-CGbYowGQ.d.mts.map} +1 -1
  445. package/dist/{types-CvuKO5Pn.d.mts → types-CgvhU-hF.d.mts} +1 -1
  446. package/dist/{types-CvuKO5Pn.d.mts.map → types-CgvhU-hF.d.mts.map} +1 -1
  447. package/dist/{types-Y09-wtyU.d.mts → types-ClUkdbWb.d.mts} +1 -1
  448. package/dist/{types-Y09-wtyU.d.mts.map → types-ClUkdbWb.d.mts.map} +1 -1
  449. package/dist/{types-DU4TSFS5.mjs → types-CuW0zWDA.mjs} +2 -2
  450. package/dist/{types-DU4TSFS5.mjs.map → types-CuW0zWDA.mjs.map} +1 -1
  451. package/dist/{types-BkZ8DUEI.d.mts → types-DmHk7vAt.d.mts} +1 -1
  452. package/dist/{types-BkZ8DUEI.d.mts.map → types-DmHk7vAt.d.mts.map} +1 -1
  453. package/dist/{types-CQAugunJ.mjs → types-Jo3UYd6b.mjs} +1 -1
  454. package/dist/{types-CQAugunJ.mjs.map → types-Jo3UYd6b.mjs.map} +1 -1
  455. package/dist/{types-xIfVRNLp.d.mts → types-_HFLRzTn.d.mts} +22 -1
  456. package/dist/types-_HFLRzTn.d.mts.map +1 -0
  457. package/dist/{types-ByChcBgE.d.mts → types-ea9sAPck.d.mts} +1 -1
  458. package/dist/{types-ByChcBgE.d.mts.map → types-ea9sAPck.d.mts.map} +1 -1
  459. package/dist/{types-CNlaBFzx.d.mts → types-g_aFIdW0.d.mts} +1 -1
  460. package/dist/{types-CNlaBFzx.d.mts.map → types-g_aFIdW0.d.mts.map} +1 -1
  461. package/dist/{types-Dbqff978.d.mts → types-vgEWF18A.d.mts} +19 -1
  462. package/dist/{types-Dbqff978.d.mts.map → types-vgEWF18A.d.mts.map} +1 -1
  463. package/dist/{user-DgGbKL9s.mjs → user-BjAOvU3Z.mjs} +3 -3
  464. package/dist/{user-DgGbKL9s.mjs.map → user-BjAOvU3Z.mjs.map} +1 -1
  465. package/dist/{utils-B7A57fm9.mjs → utils-BJXElxdw.mjs} +156 -7
  466. package/dist/utils-BJXElxdw.mjs.map +1 -0
  467. package/dist/{validate-CRkcYZAR.mjs → validate-CWSnKVIJ.mjs} +2 -2
  468. package/dist/{validate-CRkcYZAR.mjs.map → validate-CWSnKVIJ.mjs.map} +1 -1
  469. package/dist/{validate-9ECmtEpJ.d.mts → validate-Z1b86_3B.d.mts} +5 -5
  470. package/dist/{validate-9ECmtEpJ.d.mts.map → validate-Z1b86_3B.d.mts.map} +1 -1
  471. package/dist/{validation-sR26SOwD.mjs → validation-0l8-RYj4.mjs} +8 -5
  472. package/dist/{validation-sR26SOwD.mjs.map → validation-0l8-RYj4.mjs.map} +1 -1
  473. package/dist/version-qmeO1XZY.mjs +7 -0
  474. package/dist/{version-CrqhKGWn.mjs.map → version-qmeO1XZY.mjs.map} +1 -1
  475. package/dist/{widgets-DRgtn7Cl.mjs → widgets-hWcIicX8.mjs} +3 -3
  476. package/dist/{widgets-DRgtn7Cl.mjs.map → widgets-hWcIicX8.mjs.map} +1 -1
  477. package/dist/wxr-taxonomies-0_uxSrmf.d.mts +34 -0
  478. package/dist/wxr-taxonomies-0_uxSrmf.d.mts.map +1 -0
  479. package/dist/wxr-taxonomies-CNFcsNCr.mjs +425 -0
  480. package/dist/wxr-taxonomies-CNFcsNCr.mjs.map +1 -0
  481. package/dist/{zod-generator-C5JaV--i.mjs → zod-generator-CacrR-i8.mjs} +2 -2
  482. package/dist/{zod-generator-C5JaV--i.mjs.map → zod-generator-CacrR-i8.mjs.map} +1 -1
  483. package/package.json +7 -7
  484. package/src/api/handlers/content.ts +10 -7
  485. package/src/api/schemas/import.ts +19 -0
  486. package/src/astro/integration/runtime.ts +3 -6
  487. package/src/astro/middleware/auth.ts +9 -3
  488. package/src/astro/middleware/csp.ts +54 -3
  489. package/src/astro/routes/admin.astro +9 -0
  490. package/src/astro/routes/api/import/wordpress/rewrite-urls.ts +122 -98
  491. package/src/astro/routes/api/import/wordpress-plugin/execute.ts +794 -44
  492. package/src/astro/routes/api/plugins/[pluginId]/[...path].ts +17 -15
  493. package/src/components/EmDashImage.astro +59 -23
  494. package/src/components/Image.astro +36 -35
  495. package/src/database/migrations/049_taxonomies_name_locale_index.ts +42 -0
  496. package/src/database/migrations/050_media_usage_index_status.ts +142 -0
  497. package/src/database/migrations/runner.ts +4 -0
  498. package/src/database/repositories/media-usage.ts +955 -59
  499. package/src/database/types.ts +22 -0
  500. package/src/emdash-runtime.ts +123 -3
  501. package/src/import/comments.ts +159 -0
  502. package/src/import/index.ts +8 -1
  503. package/src/import/settings.ts +65 -189
  504. package/src/import/sources/wordpress-plugin.ts +338 -42
  505. package/src/import/sources/wxr.ts +4 -1
  506. package/src/import/types.ts +12 -0
  507. package/src/import/utils.ts +207 -0
  508. package/src/import/wxr-taxonomies.ts +39 -0
  509. package/src/loader.ts +13 -2
  510. package/src/media/usage/content-fields.ts +119 -0
  511. package/src/media/usage/content-refresh.ts +524 -0
  512. package/src/media/usage/content-repair.ts +675 -0
  513. package/src/media/usage/content-snapshots.ts +439 -0
  514. package/src/media/usage/extractor.ts +4 -4
  515. package/src/media/usage/source-key.ts +22 -0
  516. package/src/menus/index.ts +17 -1
  517. package/src/object-cache/index.ts +82 -7
  518. package/src/plugins/context.ts +100 -71
  519. package/src/schema/registry.ts +240 -154
  520. package/src/seed/apply.ts +156 -99
  521. package/dist/api-80kycR9o.mjs.map +0 -1
  522. package/dist/apply-DSypk6Iu.mjs.map +0 -1
  523. package/dist/byline-fields-eyJMblSr.mjs.map +0 -1
  524. package/dist/context-CzUU_WzL.mjs.map +0 -1
  525. package/dist/import-Bb1T9WJS.mjs.map +0 -1
  526. package/dist/index-DGIjmUXQ.d.mts.map +0 -1
  527. package/dist/loader-4K37qA-y.mjs.map +0 -1
  528. package/dist/object-cache-CHbHv83-.mjs.map +0 -1
  529. package/dist/registry-DP-iEtdR.mjs.map +0 -1
  530. package/dist/runner-CFngB4WZ.mjs.map +0 -1
  531. package/dist/scheduled-publish-BMljtY5G.d.mts.map +0 -1
  532. package/dist/types-xIfVRNLp.d.mts.map +0 -1
  533. package/dist/utils-B7A57fm9.mjs.map +0 -1
  534. package/dist/version-CrqhKGWn.mjs +0 -7
  535. /package/dist/{api-tokens-B4BQybOp.mjs → api-tokens-DsvvCtdh.mjs} +0 -0
  536. /package/dist/{ssrf-CcX9zvMK.mjs → ssrf-CmuGgCq3.mjs} +0 -0
  537. /package/dist/{types-BvbeGEtr.mjs → types-DROWRxYV.mjs} +0 -0
@@ -0,0 +1,675 @@
1
+ import { sql, type Kysely } from "kysely";
2
+ import { ulid } from "ulidx";
3
+
4
+ import {
5
+ MediaUsageRepository,
6
+ type MediaUsageSource,
7
+ } from "../../database/repositories/media-usage.js";
8
+ import type { Database } from "../../database/types.js";
9
+ import { validateIdentifier } from "../../database/validate.js";
10
+ import { chunks, SQL_BATCH_SIZE } from "../../utils/chunks.js";
11
+ import {
12
+ loadContentMediaUsageFields,
13
+ MediaUsageFieldDiscoveryError,
14
+ type ContentMediaUsageFieldDiscovery,
15
+ } from "./content-fields.js";
16
+ import {
17
+ CONTENT_MEDIA_USAGE_ADAPTER_ID,
18
+ CONTENT_MEDIA_USAGE_COLLECTION_SCOPE,
19
+ withContentUsageCollectionLock,
20
+ } from "./content-refresh.js";
21
+ import {
22
+ CONTENT_SOURCE_SCHEMA_VERSION,
23
+ type ContentMediaUsageSnapshot,
24
+ loadContentMediaUsageSnapshots,
25
+ } from "./content-snapshots.js";
26
+ import {
27
+ buildContentMediaUsageSourceKey,
28
+ MEDIA_USAGE_CONTENT_SOURCE_VARIANTS,
29
+ } from "./source-key.js";
30
+
31
+ export type ContentMediaUsageRepairStatus = "complete" | "partial" | "failed" | "stale";
32
+
33
+ export const CONTENT_MEDIA_USAGE_REPAIR_ERROR = {
34
+ COLLECTION_NOT_FOUND: "COLLECTION_NOT_FOUND",
35
+ CONTENT_NOT_FOUND: "CONTENT_NOT_FOUND",
36
+ DRAFT_REVISION_NOT_FOUND: "DRAFT_REVISION_NOT_FOUND",
37
+ DRAFT_REVISION_MISMATCH: "DRAFT_REVISION_MISMATCH",
38
+ DRAFT_REVISION_INVALID: "DRAFT_REVISION_INVALID",
39
+ CONTENT_USAGE_REPAIR_ERROR: "CONTENT_USAGE_REPAIR_ERROR",
40
+ CONTENT_USAGE_REPAIR_CONFLICT: "CONTENT_USAGE_REPAIR_CONFLICT",
41
+ INVALID_REPEATER_VALIDATION: "INVALID_REPEATER_VALIDATION",
42
+ } as const;
43
+
44
+ export type ContentMediaUsageRepairErrorCode =
45
+ (typeof CONTENT_MEDIA_USAGE_REPAIR_ERROR)[keyof typeof CONTENT_MEDIA_USAGE_REPAIR_ERROR];
46
+
47
+ export interface ContentMediaUsageRepairCollectionInput {
48
+ collectionSlug: string;
49
+ }
50
+
51
+ export interface ContentMediaUsageRepairScope {
52
+ adapterId: typeof CONTENT_MEDIA_USAGE_ADAPTER_ID;
53
+ scopeType: typeof CONTENT_MEDIA_USAGE_COLLECTION_SCOPE;
54
+ scopeKey: string;
55
+ }
56
+
57
+ export interface ContentMediaUsageRepairCollectionResult {
58
+ scope: ContentMediaUsageRepairScope;
59
+ status: ContentMediaUsageRepairStatus;
60
+ indexedSourceCount: number;
61
+ failedSourceCount: number;
62
+ skippedSourceCount: number;
63
+ deletedSourceCount: number;
64
+ lastErrorCode: string | null;
65
+ startedAt: string;
66
+ completedAt: string | null;
67
+ }
68
+
69
+ export interface ContentMediaUsageRepairAllResult {
70
+ status: ContentMediaUsageRepairStatus;
71
+ collections: ContentMediaUsageRepairCollectionResult[];
72
+ indexedSourceCount: number;
73
+ failedSourceCount: number;
74
+ skippedSourceCount: number;
75
+ deletedSourceCount: number;
76
+ }
77
+
78
+ export interface ContentMediaUsageCollectionScan {
79
+ collectionSlug: string;
80
+ contentIds: string[];
81
+ }
82
+
83
+ interface ContentMediaUsageCollectionRecord {
84
+ id: string;
85
+ slug: string;
86
+ }
87
+
88
+ interface ContentMediaUsageInitialCollectionResult {
89
+ collection: ContentMediaUsageCollectionRecord;
90
+ result: ContentMediaUsageRepairCollectionResult;
91
+ }
92
+
93
+ export async function repairContentMediaUsageAll(
94
+ db: Kysely<Database>,
95
+ ): Promise<ContentMediaUsageRepairAllResult> {
96
+ const collections = await loadContentMediaUsageCollectionRecords(db);
97
+ const results: ContentMediaUsageInitialCollectionResult[] = [];
98
+
99
+ for (const collection of collections) {
100
+ results.push({
101
+ collection,
102
+ result: await repairContentMediaUsageCollectionSafely(db, collection.slug),
103
+ });
104
+ }
105
+
106
+ return aggregateContentMediaUsageRepairAll(
107
+ await filterExistingContentMediaUsageCollectionResults(db, results),
108
+ );
109
+ }
110
+
111
+ export async function scanContentMediaUsageCollection(
112
+ db: Kysely<Database>,
113
+ collectionSlug: string,
114
+ ): Promise<ContentMediaUsageCollectionScan | null> {
115
+ validateIdentifier(collectionSlug, "collection slug");
116
+ const collection = await db
117
+ .selectFrom("_emdash_collections")
118
+ .select("id")
119
+ .where("slug", "=", collectionSlug)
120
+ .executeTakeFirst();
121
+ if (!collection) return null;
122
+
123
+ const tableName = getContentTableName(collectionSlug);
124
+ const rows = await sql<{ id: string }>`
125
+ SELECT id
126
+ FROM ${sql.ref(tableName)}
127
+ ORDER BY id ASC
128
+ `.execute(db);
129
+
130
+ return {
131
+ collectionSlug,
132
+ contentIds: rows.rows.map((row) => row.id),
133
+ };
134
+ }
135
+
136
+ export async function repairContentMediaUsageCollection(
137
+ db: Kysely<Database>,
138
+ input: ContentMediaUsageRepairCollectionInput,
139
+ ): Promise<ContentMediaUsageRepairCollectionResult> {
140
+ validateIdentifier(input.collectionSlug, "collection slug");
141
+ return withContentUsageCollectionLock(input.collectionSlug, () =>
142
+ repairContentMediaUsageCollectionUnlocked(db, input.collectionSlug),
143
+ );
144
+ }
145
+
146
+ async function loadContentMediaUsageCollectionRecords(
147
+ db: Kysely<Database>,
148
+ ): Promise<ContentMediaUsageCollectionRecord[]> {
149
+ return db
150
+ .selectFrom("_emdash_collections")
151
+ .select(["id", "slug"])
152
+ .orderBy("slug", "asc")
153
+ .execute();
154
+ }
155
+
156
+ async function repairContentMediaUsageCollectionSafely(
157
+ db: Kysely<Database>,
158
+ collectionSlug: string,
159
+ ): Promise<ContentMediaUsageRepairCollectionResult> {
160
+ try {
161
+ return await repairContentMediaUsageCollection(db, { collectionSlug });
162
+ } catch (error) {
163
+ console.error(`[media-usage] Failed to repair collection ${collectionSlug}:`, error);
164
+ const now = new Date().toISOString();
165
+ return {
166
+ scope: contentMediaUsageCollectionScope(collectionSlug),
167
+ status: "failed",
168
+ indexedSourceCount: 0,
169
+ failedSourceCount: 0,
170
+ skippedSourceCount: 0,
171
+ deletedSourceCount: 0,
172
+ lastErrorCode: CONTENT_MEDIA_USAGE_REPAIR_ERROR.CONTENT_USAGE_REPAIR_ERROR,
173
+ startedAt: now,
174
+ completedAt: now,
175
+ };
176
+ }
177
+ }
178
+
179
+ async function filterExistingContentMediaUsageCollectionResults(
180
+ db: Kysely<Database>,
181
+ results: readonly ContentMediaUsageInitialCollectionResult[],
182
+ ): Promise<ContentMediaUsageRepairCollectionResult[]> {
183
+ const currentCollections = await loadContentMediaUsageCollectionRecordsSafely(db);
184
+ const currentIdsBySlug = new Map(
185
+ currentCollections.map((collection) => [collection.slug, collection.id]),
186
+ );
187
+ const includedResults: ContentMediaUsageRepairCollectionResult[] = [];
188
+ const excludedResults: ContentMediaUsageRepairCollectionResult[] = [];
189
+
190
+ for (const { collection, result } of results) {
191
+ if (currentIdsBySlug.get(collection.slug) === collection.id) {
192
+ includedResults.push(result);
193
+ } else {
194
+ excludedResults.push(result);
195
+ }
196
+ }
197
+
198
+ if (excludedResults.length > 0) {
199
+ const repo = new MediaUsageRepository(db);
200
+ for (const result of excludedResults) {
201
+ await repo.deleteIndexStatus(result.scope);
202
+ }
203
+ }
204
+
205
+ return includedResults;
206
+ }
207
+
208
+ async function loadContentMediaUsageCollectionRecordsSafely(
209
+ db: Kysely<Database>,
210
+ ): Promise<ContentMediaUsageCollectionRecord[]> {
211
+ try {
212
+ return await loadContentMediaUsageCollectionRecords(db);
213
+ } catch {
214
+ // Retry once before failing; returning unpruned results can over-report deleted collections.
215
+ }
216
+
217
+ try {
218
+ return await loadContentMediaUsageCollectionRecords(db);
219
+ } catch (error) {
220
+ console.error("[media-usage] Failed to reconcile all-content repair collections:", error);
221
+ throw error;
222
+ }
223
+ }
224
+
225
+ function aggregateContentMediaUsageRepairAll(
226
+ collections: readonly ContentMediaUsageRepairCollectionResult[],
227
+ ): ContentMediaUsageRepairAllResult {
228
+ return {
229
+ status: determineRepairAllStatus(collections),
230
+ collections: [...collections],
231
+ indexedSourceCount: sumCollectionRepairCount(collections, "indexedSourceCount"),
232
+ failedSourceCount: sumCollectionRepairCount(collections, "failedSourceCount"),
233
+ skippedSourceCount: sumCollectionRepairCount(collections, "skippedSourceCount"),
234
+ deletedSourceCount: sumCollectionRepairCount(collections, "deletedSourceCount"),
235
+ };
236
+ }
237
+
238
+ function determineRepairAllStatus(
239
+ collections: readonly ContentMediaUsageRepairCollectionResult[],
240
+ ): ContentMediaUsageRepairStatus {
241
+ if (collections.length === 0) return "complete";
242
+ if (collections.every((collection) => collection.status === "complete")) return "complete";
243
+ if (collections.some((collection) => collection.status === "stale")) return "stale";
244
+ if (collections.some((collection) => collection.status === "partial")) return "partial";
245
+ if (collections.every((collection) => collection.status === "failed")) return "failed";
246
+ return "partial";
247
+ }
248
+
249
+ function sumCollectionRepairCount(
250
+ collections: readonly ContentMediaUsageRepairCollectionResult[],
251
+ key: "indexedSourceCount" | "failedSourceCount" | "skippedSourceCount" | "deletedSourceCount",
252
+ ): number {
253
+ return collections.reduce((sum, collection) => sum + collection[key], 0);
254
+ }
255
+
256
+ async function repairContentMediaUsageCollectionUnlocked(
257
+ db: Kysely<Database>,
258
+ collectionSlug: string,
259
+ ): Promise<ContentMediaUsageRepairCollectionResult> {
260
+ const startedAt = new Date().toISOString();
261
+ const scope = contentMediaUsageCollectionScope(collectionSlug);
262
+ if (!(await contentCollectionExists(db, collectionSlug))) {
263
+ return {
264
+ scope,
265
+ status: "failed",
266
+ indexedSourceCount: 0,
267
+ failedSourceCount: 0,
268
+ skippedSourceCount: 0,
269
+ deletedSourceCount: 0,
270
+ lastErrorCode: CONTENT_MEDIA_USAGE_REPAIR_ERROR.COLLECTION_NOT_FOUND,
271
+ startedAt,
272
+ completedAt: startedAt,
273
+ };
274
+ }
275
+
276
+ const repo = new MediaUsageRepository(db);
277
+ const runToken = ulid();
278
+ await repo.beginIndexStatusRepair({
279
+ ...scope,
280
+ runToken,
281
+ schemaVersion: CONTENT_SOURCE_SCHEMA_VERSION,
282
+ startedAt,
283
+ });
284
+
285
+ try {
286
+ const scan = await scanContentMediaUsageCollection(db, collectionSlug);
287
+ if (!scan) {
288
+ const completedAt = new Date().toISOString();
289
+ return await finalizeRepairStatus(repo, {
290
+ ...scope,
291
+ runToken,
292
+ counts: {
293
+ indexedSourceCount: 0,
294
+ failedSourceCount: 0,
295
+ skippedSourceCount: 0,
296
+ deletedSourceCount: 0,
297
+ lastErrorCode: CONTENT_MEDIA_USAGE_REPAIR_ERROR.COLLECTION_NOT_FOUND,
298
+ missingContentIds: new Set(),
299
+ },
300
+ status: "failed",
301
+ startedAt,
302
+ completedAt,
303
+ });
304
+ }
305
+ const counts = await repairScannedContentSources(db, repo, scan);
306
+ const finalScan = await scanContentMediaUsageCollection(db, collectionSlug);
307
+ if (!finalScan) {
308
+ counts.failedSourceCount++;
309
+ counts.lastErrorCode = CONTENT_MEDIA_USAGE_REPAIR_ERROR.COLLECTION_NOT_FOUND;
310
+ } else if (!sameContentIds(repairedContentIds(scan.contentIds, counts), finalScan.contentIds)) {
311
+ markRepairConflict(counts);
312
+ }
313
+ const completedAt = new Date().toISOString();
314
+ const status = determineRepairStatus(counts);
315
+ return await finalizeRepairStatus(repo, {
316
+ ...scope,
317
+ runToken,
318
+ counts,
319
+ status,
320
+ startedAt,
321
+ completedAt,
322
+ });
323
+ } catch (error) {
324
+ if (!(error instanceof MediaUsageFieldDiscoveryError)) {
325
+ console.error(`[media-usage] Failed to repair collection ${collectionSlug}:`, error);
326
+ }
327
+ const completedAt = new Date().toISOString();
328
+ const lastErrorCode =
329
+ error instanceof MediaUsageFieldDiscoveryError
330
+ ? error.code
331
+ : CONTENT_MEDIA_USAGE_REPAIR_ERROR.CONTENT_USAGE_REPAIR_ERROR;
332
+ return finalizeRepairStatus(repo, {
333
+ ...scope,
334
+ runToken,
335
+ counts: {
336
+ indexedSourceCount: 0,
337
+ failedSourceCount: 0,
338
+ skippedSourceCount: 0,
339
+ deletedSourceCount: 0,
340
+ lastErrorCode,
341
+ missingContentIds: new Set(),
342
+ },
343
+ status: "failed",
344
+ startedAt,
345
+ completedAt,
346
+ });
347
+ }
348
+ }
349
+
350
+ interface RepairCounts {
351
+ indexedSourceCount: number;
352
+ failedSourceCount: number;
353
+ skippedSourceCount: number;
354
+ deletedSourceCount: number;
355
+ lastErrorCode: ContentMediaUsageRepairErrorCode | null;
356
+ missingContentIds: Set<string>;
357
+ }
358
+
359
+ async function repairScannedContentSources(
360
+ db: Kysely<Database>,
361
+ repo: MediaUsageRepository,
362
+ scan: ContentMediaUsageCollectionScan,
363
+ ): Promise<RepairCounts> {
364
+ const counts: RepairCounts = {
365
+ indexedSourceCount: 0,
366
+ failedSourceCount: 0,
367
+ skippedSourceCount: 0,
368
+ deletedSourceCount: 0,
369
+ lastErrorCode: null,
370
+ missingContentIds: new Set(),
371
+ };
372
+
373
+ const fieldDiscovery = await loadContentMediaUsageFields(db, scan.collectionSlug);
374
+ const observedSources = await repo.findSources(buildContentSourceKeysForScan(scan));
375
+
376
+ for (const contentId of scan.contentIds) {
377
+ await repairContentSource(
378
+ db,
379
+ repo,
380
+ scan.collectionSlug,
381
+ contentId,
382
+ fieldDiscovery,
383
+ observedSources,
384
+ counts,
385
+ );
386
+ }
387
+
388
+ await reconcileOrphanedContentSources(db, repo, scan.collectionSlug, counts);
389
+ return counts;
390
+ }
391
+
392
+ async function repairContentSource(
393
+ db: Kysely<Database>,
394
+ repo: MediaUsageRepository,
395
+ collectionSlug: string,
396
+ contentId: string,
397
+ fieldDiscovery: ContentMediaUsageFieldDiscovery,
398
+ observedSources: Map<string, MediaUsageSource>,
399
+ counts: RepairCounts,
400
+ ): Promise<void> {
401
+ const sourceKeys = buildContentSourceKeys(collectionSlug, contentId);
402
+ const snapshotsResult = await loadContentMediaUsageSnapshots(
403
+ db,
404
+ collectionSlug,
405
+ contentId,
406
+ fieldDiscovery,
407
+ );
408
+ if (!snapshotsResult.success) {
409
+ if (snapshotsResult.error === CONTENT_MEDIA_USAGE_REPAIR_ERROR.CONTENT_NOT_FOUND) {
410
+ markRepairConflict(counts);
411
+ counts.missingContentIds.add(contentId);
412
+ return;
413
+ }
414
+ counts.lastErrorCode = snapshotsResult.error;
415
+ if (snapshotsResult.snapshots) {
416
+ // Partial snapshot failures keep absent variants in place; the attempted source is marked below.
417
+ await repairSnapshotSources(repo, snapshotsResult.snapshots, observedSources, counts);
418
+ }
419
+ if (snapshotsResult.source) {
420
+ const result = await repo.markSourceAttemptedIfMatching(
421
+ {
422
+ ...snapshotsResult.source,
423
+ sourceCompleteness: "failed",
424
+ lastErrorCode: snapshotsResult.error,
425
+ },
426
+ observedSources.get(snapshotsResult.source.sourceKey) ?? null,
427
+ );
428
+ if (result.attempted) {
429
+ counts.failedSourceCount++;
430
+ } else {
431
+ markRepairConflict(counts);
432
+ }
433
+ return;
434
+ }
435
+
436
+ counts.failedSourceCount++;
437
+ return;
438
+ }
439
+
440
+ const expectedSourceKeys = await repairSnapshotSources(
441
+ repo,
442
+ snapshotsResult.snapshots,
443
+ observedSources,
444
+ counts,
445
+ );
446
+
447
+ for (const sourceKey of sourceKeys) {
448
+ if (expectedSourceKeys.has(sourceKey)) continue;
449
+ const observedSource = observedSources.get(sourceKey);
450
+ if (!observedSource) continue;
451
+ await deleteObservedSource(repo, sourceKey, observedSource, counts);
452
+ }
453
+ }
454
+
455
+ async function repairSnapshotSources(
456
+ repo: MediaUsageRepository,
457
+ snapshots: readonly ContentMediaUsageSnapshot[],
458
+ observedSources: Map<string, MediaUsageSource>,
459
+ counts: RepairCounts,
460
+ ): Promise<Set<string>> {
461
+ const expectedSourceKeys = new Set<string>();
462
+ for (const snapshot of snapshots) {
463
+ expectedSourceKeys.add(snapshot.source.sourceKey);
464
+ const result = await repo.replaceSourceIfMatching(
465
+ snapshot.source,
466
+ snapshot.occurrences,
467
+ observedSources.get(snapshot.source.sourceKey) ?? null,
468
+ );
469
+ if (result.replaced) {
470
+ counts.indexedSourceCount++;
471
+ } else {
472
+ markRepairConflict(counts);
473
+ }
474
+ }
475
+ return expectedSourceKeys;
476
+ }
477
+
478
+ function markRepairConflict(counts: RepairCounts): void {
479
+ counts.skippedSourceCount++;
480
+ counts.lastErrorCode ??= CONTENT_MEDIA_USAGE_REPAIR_ERROR.CONTENT_USAGE_REPAIR_CONFLICT;
481
+ }
482
+
483
+ async function reconcileOrphanedContentSources(
484
+ db: Kysely<Database>,
485
+ repo: MediaUsageRepository,
486
+ collectionSlug: string,
487
+ counts: RepairCounts,
488
+ ): Promise<void> {
489
+ const sources = await repo.findCollectionContentSources(collectionSlug);
490
+ const existingContentIds = await findExistingContentIds(
491
+ db,
492
+ collectionSlug,
493
+ sources.flatMap((source) => (source.contentId ? [source.contentId] : [])),
494
+ );
495
+
496
+ for (const source of sources) {
497
+ if (!source.contentId) {
498
+ await deleteObservedSource(repo, source.sourceKey, source, counts);
499
+ continue;
500
+ }
501
+ if (existingContentIds.has(source.contentId)) continue;
502
+ await deleteObservedSourceIfContentAbsent(repo, collectionSlug, source, counts);
503
+ }
504
+ }
505
+
506
+ async function findExistingContentIds(
507
+ db: Kysely<Database>,
508
+ collectionSlug: string,
509
+ contentIds: readonly string[],
510
+ ): Promise<Set<string>> {
511
+ validateIdentifier(collectionSlug, "collection slug");
512
+ const existingContentIds = new Set<string>();
513
+ const uniqueContentIds = [...new Set(contentIds)];
514
+ if (uniqueContentIds.length === 0) return existingContentIds;
515
+
516
+ const tableName = getContentTableName(collectionSlug);
517
+ for (const contentIdBatch of chunks(uniqueContentIds, SQL_BATCH_SIZE)) {
518
+ const result = await sql<{ id: string }>`
519
+ SELECT id
520
+ FROM ${sql.ref(tableName)}
521
+ WHERE id IN (${sql.join(contentIdBatch)})
522
+ `.execute(db);
523
+ for (const row of result.rows) {
524
+ existingContentIds.add(row.id);
525
+ }
526
+ }
527
+
528
+ return existingContentIds;
529
+ }
530
+
531
+ async function deleteObservedSourceIfContentAbsent(
532
+ repo: MediaUsageRepository,
533
+ collectionSlug: string,
534
+ observedSource: MediaUsageSource,
535
+ counts: RepairCounts,
536
+ ): Promise<void> {
537
+ if (!observedSource.contentId) return;
538
+ const result = await repo.deleteSourceIfMatchingContentAbsent(
539
+ observedSource.sourceKey,
540
+ observedSource,
541
+ collectionSlug,
542
+ observedSource.contentId,
543
+ );
544
+ if (result.deleted) {
545
+ counts.deletedSourceCount++;
546
+ return;
547
+ }
548
+ if (result.contentPresent) return;
549
+ if (result.source) {
550
+ markRepairConflict(counts);
551
+ }
552
+ }
553
+
554
+ async function deleteObservedSource(
555
+ repo: MediaUsageRepository,
556
+ sourceKey: string,
557
+ observedSource: MediaUsageSource,
558
+ counts: RepairCounts,
559
+ ): Promise<void> {
560
+ const result = await repo.deleteSourceIfMatching(sourceKey, observedSource);
561
+ if (result.deleted) {
562
+ counts.deletedSourceCount++;
563
+ return;
564
+ }
565
+ if (result.source) {
566
+ markRepairConflict(counts);
567
+ }
568
+ }
569
+
570
+ interface FinalizeInput extends ContentMediaUsageRepairScope {
571
+ runToken: string;
572
+ counts: RepairCounts;
573
+ status: Exclude<ContentMediaUsageRepairStatus, "stale">;
574
+ startedAt: string;
575
+ completedAt: string;
576
+ }
577
+
578
+ async function finalizeRepairStatus(
579
+ repo: MediaUsageRepository,
580
+ input: FinalizeInput,
581
+ ): Promise<ContentMediaUsageRepairCollectionResult> {
582
+ const result = await repo.finalizeIndexStatusRepairIfRunning({
583
+ adapterId: input.adapterId,
584
+ scopeType: input.scopeType,
585
+ scopeKey: input.scopeKey,
586
+ runToken: input.runToken,
587
+ status: input.status,
588
+ schemaVersion: CONTENT_SOURCE_SCHEMA_VERSION,
589
+ completedAt: input.completedAt,
590
+ indexedSourceCount: input.counts.indexedSourceCount,
591
+ failedSourceCount: input.counts.failedSourceCount,
592
+ lastErrorCode: input.counts.lastErrorCode,
593
+ });
594
+
595
+ return {
596
+ scope: {
597
+ adapterId: input.adapterId,
598
+ scopeType: input.scopeType,
599
+ scopeKey: input.scopeKey,
600
+ },
601
+ status: result.finalized ? input.status : "stale",
602
+ indexedSourceCount: input.counts.indexedSourceCount,
603
+ failedSourceCount: input.counts.failedSourceCount,
604
+ skippedSourceCount: input.counts.skippedSourceCount,
605
+ deletedSourceCount: input.counts.deletedSourceCount,
606
+ lastErrorCode: result.finalized
607
+ ? input.counts.lastErrorCode
608
+ : (result.status?.lastErrorCode ??
609
+ CONTENT_MEDIA_USAGE_REPAIR_ERROR.CONTENT_USAGE_REPAIR_CONFLICT),
610
+ startedAt: input.startedAt,
611
+ completedAt: result.finalized ? input.completedAt : null,
612
+ };
613
+ }
614
+
615
+ function determineRepairStatus(
616
+ counts: RepairCounts,
617
+ ): Exclude<ContentMediaUsageRepairStatus, "stale"> {
618
+ if (counts.failedSourceCount === 0 && counts.skippedSourceCount === 0) return "complete";
619
+ const trustedProgress = counts.indexedSourceCount + counts.deletedSourceCount;
620
+ if (counts.failedSourceCount > 0 && trustedProgress === 0) {
621
+ return "failed";
622
+ }
623
+ return "partial";
624
+ }
625
+
626
+ function buildContentSourceKeys(collectionSlug: string, contentId: string): string[] {
627
+ return MEDIA_USAGE_CONTENT_SOURCE_VARIANTS.map((sourceVariant) =>
628
+ buildContentMediaUsageSourceKey({ collectionSlug, contentId, sourceVariant }),
629
+ );
630
+ }
631
+
632
+ function buildContentSourceKeysForScan(scan: ContentMediaUsageCollectionScan): string[] {
633
+ return scan.contentIds.flatMap((contentId) =>
634
+ buildContentSourceKeys(scan.collectionSlug, contentId),
635
+ );
636
+ }
637
+
638
+ async function contentCollectionExists(
639
+ db: Kysely<Database>,
640
+ collectionSlug: string,
641
+ ): Promise<boolean> {
642
+ const row = await db
643
+ .selectFrom("_emdash_collections")
644
+ .select("id")
645
+ .where("slug", "=", collectionSlug)
646
+ .executeTakeFirst();
647
+ return row !== undefined;
648
+ }
649
+
650
+ function sameContentIds(left: readonly string[], right: readonly string[]): boolean {
651
+ if (left.length !== right.length) return false;
652
+ const rightIds = new Set(right);
653
+ return left.every((id) => rightIds.has(id));
654
+ }
655
+
656
+ function repairedContentIds(
657
+ contentIds: readonly string[],
658
+ counts: Pick<RepairCounts, "missingContentIds">,
659
+ ): string[] {
660
+ if (counts.missingContentIds.size === 0) return [...contentIds];
661
+ return contentIds.filter((contentId) => !counts.missingContentIds.has(contentId));
662
+ }
663
+
664
+ function contentMediaUsageCollectionScope(collectionSlug: string): ContentMediaUsageRepairScope {
665
+ return {
666
+ adapterId: CONTENT_MEDIA_USAGE_ADAPTER_ID,
667
+ scopeType: CONTENT_MEDIA_USAGE_COLLECTION_SCOPE,
668
+ scopeKey: collectionSlug,
669
+ };
670
+ }
671
+
672
+ function getContentTableName(collectionSlug: string): string {
673
+ validateIdentifier(collectionSlug, "collection slug");
674
+ return `ec_${collectionSlug}`;
675
+ }