emdash 0.33.0 → 0.34.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 (860) hide show
  1. package/dist/{adapters-BMyNSSZi.d.mts → adapters-34EN2eXO.d.mts} +26 -2
  2. package/dist/adapters-34EN2eXO.d.mts.map +1 -0
  3. package/dist/{allowed-origins-CG1pACtS.mjs → allowed-origins-DW7sYyqg.mjs} +2 -2
  4. package/dist/{allowed-origins-CG1pACtS.mjs.map → allowed-origins-DW7sYyqg.mjs.map} +1 -1
  5. package/dist/api/route-utils.d.mts +3 -3
  6. package/dist/api/route-utils.mjs +22 -21
  7. package/dist/api/route-utils.mjs.map +1 -1
  8. package/dist/api/schemas/index.d.mts +2 -2
  9. package/dist/api/schemas/index.mjs +6 -5
  10. package/dist/{api-D2hunekQ.mjs → api-DdAsirBe.mjs} +98 -407
  11. package/dist/api-DdAsirBe.mjs.map +1 -0
  12. package/dist/{api-tokens-CSND0i1z.mjs → api-tokens-CFXu8F_2.mjs} +2 -2
  13. package/dist/{api-tokens-CSND0i1z.mjs.map → api-tokens-CFXu8F_2.mjs.map} +1 -1
  14. package/dist/{apply-kwNEJW2l.mjs → apply-D5zfeD09.mjs} +131 -107
  15. package/dist/apply-D5zfeD09.mjs.map +1 -0
  16. package/dist/astro/index.d.mts +12 -12
  17. package/dist/astro/index.d.mts.map +1 -1
  18. package/dist/astro/index.mjs +93 -35
  19. package/dist/astro/index.mjs.map +1 -1
  20. package/dist/astro/middleware/auth.d.mts +10 -10
  21. package/dist/astro/middleware/auth.mjs +8 -8
  22. package/dist/astro/middleware/media-usage-write-fence.d.mts +7 -0
  23. package/dist/astro/middleware/media-usage-write-fence.d.mts.map +1 -0
  24. package/dist/astro/middleware/media-usage-write-fence.mjs +35 -0
  25. package/dist/astro/middleware/media-usage-write-fence.mjs.map +1 -0
  26. package/dist/astro/middleware/redirect.d.mts.map +1 -1
  27. package/dist/astro/middleware/redirect.mjs +10 -7
  28. package/dist/astro/middleware/redirect.mjs.map +1 -1
  29. package/dist/astro/middleware/request-context.mjs +3 -3
  30. package/dist/astro/middleware/setup.mjs +1 -1
  31. package/dist/astro/middleware.d.mts +12 -11
  32. package/dist/astro/middleware.d.mts.map +1 -1
  33. package/dist/astro/middleware.mjs +1677 -156
  34. package/dist/astro/middleware.mjs.map +1 -1
  35. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +9 -8
  36. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs.map +1 -1
  37. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +9 -8
  38. package/dist/astro/routes/api/admin/allowed-domains/index.mjs.map +1 -1
  39. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +5 -5
  40. package/dist/astro/routes/api/admin/api-tokens/index.mjs +6 -6
  41. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +6 -6
  42. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +12 -11
  43. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs.map +1 -1
  44. package/dist/astro/routes/api/admin/byline-fields/index.mjs +12 -11
  45. package/dist/astro/routes/api/admin/byline-fields/index.mjs.map +1 -1
  46. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +12 -11
  47. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs.map +1 -1
  48. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +17 -17
  49. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +17 -17
  50. package/dist/astro/routes/api/admin/bylines/index.mjs +17 -17
  51. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +14 -13
  52. package/dist/astro/routes/api/admin/comments/_id_/status.mjs.map +1 -1
  53. package/dist/astro/routes/api/admin/comments/_id_.mjs +6 -6
  54. package/dist/astro/routes/api/admin/comments/bulk.mjs +12 -11
  55. package/dist/astro/routes/api/admin/comments/bulk.mjs.map +1 -1
  56. package/dist/astro/routes/api/admin/comments/counts.mjs +6 -6
  57. package/dist/astro/routes/api/admin/comments/index.mjs +12 -11
  58. package/dist/astro/routes/api/admin/comments/index.mjs.map +1 -1
  59. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +5 -5
  60. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +4 -4
  61. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.d.mts +8 -0
  62. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.d.mts.map +1 -0
  63. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +36 -0
  64. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs.map +1 -0
  65. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.d.mts +8 -0
  66. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.d.mts.map +1 -0
  67. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +36 -0
  68. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs.map +1 -0
  69. package/dist/astro/routes/api/admin/media-usage/repair.mjs +15 -14
  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.d.mts +8 -0
  72. package/dist/astro/routes/api/admin/media-usage/work/index.d.mts.map +1 -0
  73. package/dist/astro/routes/api/admin/media-usage/work/index.mjs +37 -0
  74. package/dist/astro/routes/api/admin/media-usage/work/index.mjs.map +1 -0
  75. package/dist/astro/routes/api/admin/media-usage/work/retry.d.mts +8 -0
  76. package/dist/astro/routes/api/admin/media-usage/work/retry.d.mts.map +1 -0
  77. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +37 -0
  78. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs.map +1 -0
  79. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +5 -5
  80. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +5 -5
  81. package/dist/astro/routes/api/admin/plugins/_id_/disable.d.mts.map +1 -1
  82. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +51 -43
  83. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
  84. package/dist/astro/routes/api/admin/plugins/_id_/enable.d.mts.map +1 -1
  85. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +51 -43
  86. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
  87. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +47 -42
  88. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
  89. package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +6 -6
  90. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +47 -42
  91. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
  92. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.d.mts.map +1 -1
  93. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +50 -42
  94. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
  95. package/dist/astro/routes/api/admin/plugins/_id_/update.d.mts.map +1 -1
  96. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +50 -42
  97. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
  98. package/dist/astro/routes/api/admin/plugins/index.mjs +47 -42
  99. package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
  100. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +4 -4
  101. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +47 -42
  102. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
  103. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.d.mts.map +1 -1
  104. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +50 -42
  105. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
  106. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +47 -42
  107. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
  108. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.d.mts.map +1 -1
  109. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +50 -42
  110. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
  111. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.d.mts.map +1 -1
  112. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +51 -43
  113. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
  114. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +47 -42
  115. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
  116. package/dist/astro/routes/api/admin/plugins/registry/install.d.mts.map +1 -1
  117. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +51 -43
  118. package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
  119. package/dist/astro/routes/api/admin/plugins/updates.mjs +47 -42
  120. package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
  121. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +47 -42
  122. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
  123. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +4 -4
  124. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +47 -42
  125. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
  126. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +3 -3
  127. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +3 -3
  128. package/dist/astro/routes/api/admin/users/_id_/index.mjs +9 -8
  129. package/dist/astro/routes/api/admin/users/_id_/index.mjs.map +1 -1
  130. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +4 -4
  131. package/dist/astro/routes/api/admin/users/index.mjs +9 -8
  132. package/dist/astro/routes/api/admin/users/index.mjs.map +1 -1
  133. package/dist/astro/routes/api/auth/dev-bypass.mjs +7 -7
  134. package/dist/astro/routes/api/auth/invite/accept.mjs +3 -3
  135. package/dist/astro/routes/api/auth/invite/complete.mjs +13 -12
  136. package/dist/astro/routes/api/auth/invite/complete.mjs.map +1 -1
  137. package/dist/astro/routes/api/auth/invite/index.mjs +10 -9
  138. package/dist/astro/routes/api/auth/invite/index.mjs.map +1 -1
  139. package/dist/astro/routes/api/auth/invite/register-options.mjs +12 -11
  140. package/dist/astro/routes/api/auth/invite/register-options.mjs.map +1 -1
  141. package/dist/astro/routes/api/auth/logout.mjs +4 -4
  142. package/dist/astro/routes/api/auth/magic-link/send.mjs +12 -11
  143. package/dist/astro/routes/api/auth/magic-link/send.mjs.map +1 -1
  144. package/dist/astro/routes/api/auth/magic-link/verify.mjs +4 -4
  145. package/dist/astro/routes/api/auth/me.mjs +10 -9
  146. package/dist/astro/routes/api/auth/me.mjs.map +1 -1
  147. package/dist/astro/routes/api/auth/mode.mjs +4 -4
  148. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +3 -3
  149. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
  150. package/dist/astro/routes/api/auth/passkey/_id_.mjs +9 -8
  151. package/dist/astro/routes/api/auth/passkey/_id_.mjs.map +1 -1
  152. package/dist/astro/routes/api/auth/passkey/index.mjs +3 -3
  153. package/dist/astro/routes/api/auth/passkey/options.mjs +14 -13
  154. package/dist/astro/routes/api/auth/passkey/options.mjs.map +1 -1
  155. package/dist/astro/routes/api/auth/passkey/register/options.mjs +12 -11
  156. package/dist/astro/routes/api/auth/passkey/register/options.mjs.map +1 -1
  157. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +13 -12
  158. package/dist/astro/routes/api/auth/passkey/register/verify.mjs.map +1 -1
  159. package/dist/astro/routes/api/auth/passkey/verify.mjs +13 -12
  160. package/dist/astro/routes/api/auth/passkey/verify.mjs.map +1 -1
  161. package/dist/astro/routes/api/auth/signup/complete.mjs +13 -12
  162. package/dist/astro/routes/api/auth/signup/complete.mjs.map +1 -1
  163. package/dist/astro/routes/api/auth/signup/request.mjs +12 -11
  164. package/dist/astro/routes/api/auth/signup/request.mjs.map +1 -1
  165. package/dist/astro/routes/api/auth/signup/verify.mjs +3 -3
  166. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +15 -14
  167. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs.map +1 -1
  168. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +14 -13
  169. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs.map +1 -1
  170. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +4 -4
  171. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +5 -5
  172. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +5 -5
  173. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +4 -4
  174. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +13 -13
  175. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +11 -10
  176. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
  177. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +18 -17
  178. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
  179. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +18 -17
  180. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
  181. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +5 -5
  182. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +4 -4
  183. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +11 -10
  184. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs.map +1 -1
  185. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.d.mts.map +1 -1
  186. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +44 -31
  187. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
  188. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +4 -4
  189. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +5 -5
  190. package/dist/astro/routes/api/content/_collection_/_id_.mjs +11 -10
  191. package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
  192. package/dist/astro/routes/api/content/_collection_/authors.mjs +4 -4
  193. package/dist/astro/routes/api/content/_collection_/index.mjs +11 -10
  194. package/dist/astro/routes/api/content/_collection_/index.mjs.map +1 -1
  195. package/dist/astro/routes/api/content/_collection_/trash.mjs +10 -9
  196. package/dist/astro/routes/api/content/_collection_/trash.mjs.map +1 -1
  197. package/dist/astro/routes/api/dashboard.mjs +10 -8
  198. package/dist/astro/routes/api/dashboard.mjs.map +1 -1
  199. package/dist/astro/routes/api/dev/emails.mjs +4 -4
  200. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  201. package/dist/astro/routes/api/import/probe.mjs +18 -16
  202. package/dist/astro/routes/api/import/probe.mjs.map +1 -1
  203. package/dist/astro/routes/api/import/wordpress/analyze.mjs +5 -5
  204. package/dist/astro/routes/api/import/wordpress/execute.d.mts +11 -11
  205. package/dist/astro/routes/api/import/wordpress/execute.mjs +15 -15
  206. package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
  207. package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -10
  208. package/dist/astro/routes/api/import/wordpress/media.mjs +14 -12
  209. package/dist/astro/routes/api/import/wordpress/media.mjs.map +1 -1
  210. package/dist/astro/routes/api/import/wordpress/prepare.mjs +13 -12
  211. package/dist/astro/routes/api/import/wordpress/prepare.mjs.map +1 -1
  212. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +11 -11
  213. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +14 -14
  214. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  215. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +18 -16
  216. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs.map +1 -1
  217. package/dist/astro/routes/api/import/wordpress-plugin/callback.mjs +1 -1
  218. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +11 -11
  219. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +28 -27
  220. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
  221. package/dist/astro/routes/api/manifest.mjs +5 -5
  222. package/dist/astro/routes/api/mcp.d.mts.map +1 -1
  223. package/dist/astro/routes/api/mcp.mjs +174 -72
  224. package/dist/astro/routes/api/mcp.mjs.map +1 -1
  225. package/dist/astro/routes/api/media/_id_/confirm.mjs +13 -11
  226. package/dist/astro/routes/api/media/_id_/confirm.mjs.map +1 -1
  227. package/dist/astro/routes/api/media/_id_/upload.mjs +6 -6
  228. package/dist/astro/routes/api/media/_id_/usage.mjs +17 -16
  229. package/dist/astro/routes/api/media/_id_/usage.mjs.map +1 -1
  230. package/dist/astro/routes/api/media/_id_.mjs +16 -15
  231. package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
  232. package/dist/astro/routes/api/media/file/_...key_.mjs +3 -3
  233. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +4 -4
  234. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +4 -4
  235. package/dist/astro/routes/api/media/providers/index.mjs +4 -4
  236. package/dist/astro/routes/api/media/upload-url.mjs +11 -10
  237. package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
  238. package/dist/astro/routes/api/media.mjs +18 -15
  239. package/dist/astro/routes/api/media.mjs.map +1 -1
  240. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +11 -11
  241. package/dist/astro/routes/api/menus/_name_/items.mjs +11 -11
  242. package/dist/astro/routes/api/menus/_name_/reorder.mjs +11 -11
  243. package/dist/astro/routes/api/menus/_name_/translations.mjs +11 -11
  244. package/dist/astro/routes/api/menus/_name_.mjs +11 -11
  245. package/dist/astro/routes/api/menus/index.mjs +11 -11
  246. package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
  247. package/dist/astro/routes/api/oauth/device/authorize.mjs +7 -7
  248. package/dist/astro/routes/api/oauth/device/code.mjs +10 -10
  249. package/dist/astro/routes/api/oauth/device/token.mjs +9 -9
  250. package/dist/astro/routes/api/oauth/register.mjs +4 -4
  251. package/dist/astro/routes/api/oauth/token/refresh.mjs +7 -7
  252. package/dist/astro/routes/api/oauth/token/revoke.mjs +7 -7
  253. package/dist/astro/routes/api/oauth/token.mjs +7 -7
  254. package/dist/astro/routes/api/openapi.json.mjs +152 -6
  255. package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
  256. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.d.mts.map +1 -1
  257. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +8 -7
  258. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs.map +1 -1
  259. package/dist/astro/routes/api/redirects/404s/index.mjs +12 -11
  260. package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
  261. package/dist/astro/routes/api/redirects/404s/summary.mjs +12 -11
  262. package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
  263. package/dist/astro/routes/api/redirects/_id_.mjs +13 -12
  264. package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
  265. package/dist/astro/routes/api/redirects/index.mjs +13 -12
  266. package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
  267. package/dist/astro/routes/api/relations/_id_/index.mjs +18 -17
  268. package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
  269. package/dist/astro/routes/api/relations/_id_/translations.mjs +13 -12
  270. package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -1
  271. package/dist/astro/routes/api/relations/index.mjs +18 -17
  272. package/dist/astro/routes/api/relations/index.mjs.map +1 -1
  273. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +4 -4
  274. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +5 -5
  275. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +47 -42
  276. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
  277. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +47 -42
  278. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
  279. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +47 -42
  280. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
  281. package/dist/astro/routes/api/schema/collections/_slug_/index.d.mts.map +1 -1
  282. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +47 -42
  283. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
  284. package/dist/astro/routes/api/schema/collections/index.mjs +47 -42
  285. package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
  286. package/dist/astro/routes/api/schema/collections/reorder.mjs +47 -42
  287. package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
  288. package/dist/astro/routes/api/schema/index.mjs +10 -9
  289. package/dist/astro/routes/api/schema/index.mjs.map +1 -1
  290. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +47 -42
  291. package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
  292. package/dist/astro/routes/api/schema/orphans/index.mjs +47 -42
  293. package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
  294. package/dist/astro/routes/api/search/enable.mjs +13 -13
  295. package/dist/astro/routes/api/search/index.mjs +12 -12
  296. package/dist/astro/routes/api/search/rebuild.mjs +13 -13
  297. package/dist/astro/routes/api/search/stats.mjs +8 -8
  298. package/dist/astro/routes/api/search/suggest.mjs +12 -12
  299. package/dist/astro/routes/api/sections/_slug_.mjs +12 -11
  300. package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
  301. package/dist/astro/routes/api/sections/index.mjs +12 -11
  302. package/dist/astro/routes/api/sections/index.mjs.map +1 -1
  303. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +7 -7
  304. package/dist/astro/routes/api/settings/backups/archives/index.mjs +6 -6
  305. package/dist/astro/routes/api/settings/backups/export.mjs +7 -7
  306. package/dist/astro/routes/api/settings/backups/index.mjs +8 -8
  307. package/dist/astro/routes/api/settings/email.mjs +5 -5
  308. package/dist/astro/routes/api/settings.mjs +14 -13
  309. package/dist/astro/routes/api/settings.mjs.map +1 -1
  310. package/dist/astro/routes/api/setup/admin-verify.mjs +14 -13
  311. package/dist/astro/routes/api/setup/admin-verify.mjs.map +1 -1
  312. package/dist/astro/routes/api/setup/admin.mjs +13 -12
  313. package/dist/astro/routes/api/setup/admin.mjs.map +1 -1
  314. package/dist/astro/routes/api/setup/dev-bypass.mjs +30 -28
  315. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  316. package/dist/astro/routes/api/setup/dev-reset.mjs +3 -3
  317. package/dist/astro/routes/api/setup/index.mjs +32 -30
  318. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  319. package/dist/astro/routes/api/setup/status.mjs +5 -5
  320. package/dist/astro/routes/api/snapshot.mjs +8 -8
  321. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +16 -15
  322. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs.map +1 -1
  323. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +16 -15
  324. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
  325. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +16 -15
  326. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
  327. package/dist/astro/routes/api/taxonomies/_name_/terms/index.d.mts.map +1 -1
  328. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +18 -16
  329. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
  330. package/dist/astro/routes/api/taxonomies/_name_/translations.d.mts +8 -0
  331. package/dist/astro/routes/api/taxonomies/_name_/translations.d.mts.map +1 -0
  332. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +46 -0
  333. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs.map +1 -0
  334. package/dist/astro/routes/api/taxonomies/_name_.d.mts +19 -0
  335. package/dist/astro/routes/api/taxonomies/_name_.d.mts.map +1 -0
  336. package/dist/astro/routes/api/taxonomies/_name_.mjs +88 -0
  337. package/dist/astro/routes/api/taxonomies/_name_.mjs.map +1 -0
  338. package/dist/astro/routes/api/taxonomies/index.mjs +16 -15
  339. package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
  340. package/dist/astro/routes/api/themes/preview.mjs +6 -6
  341. package/dist/astro/routes/api/typegen.mjs +6 -6
  342. package/dist/astro/routes/api/well-known/auth.mjs +1 -1
  343. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
  344. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
  345. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +10 -9
  346. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs.map +1 -1
  347. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +12 -11
  348. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs.map +1 -1
  349. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +12 -11
  350. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs.map +1 -1
  351. package/dist/astro/routes/api/widget-areas/_name_.mjs +7 -6
  352. package/dist/astro/routes/api/widget-areas/_name_.mjs.map +1 -1
  353. package/dist/astro/routes/api/widget-areas/index.mjs +12 -11
  354. package/dist/astro/routes/api/widget-areas/index.mjs.map +1 -1
  355. package/dist/astro/routes/api/widget-components.mjs +4 -4
  356. package/dist/astro/routes/robots.txt.mjs +7 -6
  357. package/dist/astro/routes/robots.txt.mjs.map +1 -1
  358. package/dist/astro/routes/sitemap-_collection_.xml.mjs +10 -10
  359. package/dist/astro/routes/sitemap.xml.mjs +8 -7
  360. package/dist/astro/routes/sitemap.xml.mjs.map +1 -1
  361. package/dist/astro/types.d.mts +35 -17
  362. package/dist/astro/types.d.mts.map +1 -1
  363. package/dist/auth/providers/github.d.mts +1 -1
  364. package/dist/auth/providers/google.d.mts +1 -1
  365. package/dist/{authorize-qRhWQnel.mjs → authorize-1iFJzPaZ.mjs} +2 -2
  366. package/dist/{authorize-qRhWQnel.mjs.map → authorize-1iFJzPaZ.mjs.map} +1 -1
  367. package/dist/{backup-CtA6LDNw.mjs → backup-LHjIAVNP.mjs} +4 -4
  368. package/dist/{backup-CtA6LDNw.mjs.map → backup-LHjIAVNP.mjs.map} +1 -1
  369. package/dist/{base64-B-PsqheR.mjs → base64-CvLhUKQv.mjs} +1 -1
  370. package/dist/{base64-B-PsqheR.mjs.map → base64-CvLhUKQv.mjs.map} +1 -1
  371. package/dist/bundle-CBEXrBnb.mjs +663 -0
  372. package/dist/bundle-CBEXrBnb.mjs.map +1 -0
  373. package/dist/{byline-fields-CNc0Yq5i.mjs → byline-fields-C5S8wygO.mjs} +2 -2
  374. package/dist/{byline-fields-CNc0Yq5i.mjs.map → byline-fields-C5S8wygO.mjs.map} +1 -1
  375. package/dist/{byline-Cp6csL84.mjs → byline-pEcoDps8.mjs} +5 -5
  376. package/dist/{byline-Cp6csL84.mjs.map → byline-pEcoDps8.mjs.map} +1 -1
  377. package/dist/{byline-registry-ZkPKqEwC.mjs → byline-registry-DDun8sxh.mjs} +2 -2
  378. package/dist/{byline-registry-ZkPKqEwC.mjs.map → byline-registry-DDun8sxh.mjs.map} +1 -1
  379. package/dist/{bylines-CEj5CdT4.mjs → bylines-BWemdX2k.mjs} +7 -7
  380. package/dist/{bylines-CEj5CdT4.mjs.map → bylines-BWemdX2k.mjs.map} +1 -1
  381. package/dist/{bylines-cf-C9lmF.mjs → bylines-DJfSfXCL.mjs} +5 -5
  382. package/dist/{bylines-cf-C9lmF.mjs.map → bylines-DJfSfXCL.mjs.map} +1 -1
  383. package/dist/{cache-C9FptTFR.mjs → cache-CBJaDy_E.mjs} +3 -3
  384. package/dist/{cache-C9FptTFR.mjs.map → cache-CBJaDy_E.mjs.map} +1 -1
  385. package/dist/{challenge-store-D9VNKELo.mjs → challenge-store-CZyFVaad.mjs} +1 -1
  386. package/dist/{challenge-store-D9VNKELo.mjs.map → challenge-store-CZyFVaad.mjs.map} +1 -1
  387. package/dist/{chunks-DbYzib_k.mjs → chunks-DfPax1I0.mjs} +2 -2
  388. package/dist/{chunks-DbYzib_k.mjs.map → chunks-DfPax1I0.mjs.map} +1 -1
  389. package/dist/cli/index.mjs +176 -698
  390. package/dist/cli/index.mjs.map +1 -1
  391. package/dist/client/cf-access.d.mts +1 -1
  392. package/dist/client/index.d.mts +74 -4
  393. package/dist/client/index.d.mts.map +1 -1
  394. package/dist/client/index.mjs +25 -2
  395. package/dist/client/index.mjs.map +1 -1
  396. package/dist/collection-deletion-C8BugSGz.mjs +779 -0
  397. package/dist/collection-deletion-C8BugSGz.mjs.map +1 -0
  398. package/dist/{comment-BIkJ6Fil.mjs → comment-Dxlep6cE.mjs} +2 -2
  399. package/dist/{comment-BIkJ6Fil.mjs.map → comment-Dxlep6cE.mjs.map} +1 -1
  400. package/dist/{comment-reaction-D-laEceb.mjs → comment-reaction-D6qfHKBc.mjs} +2 -2
  401. package/dist/{comment-reaction-D-laEceb.mjs.map → comment-reaction-D6qfHKBc.mjs.map} +1 -1
  402. package/dist/{comments-0_w6KChA.mjs → comments-CTOuhTSX.mjs} +3 -3
  403. package/dist/{comments-0_w6KChA.mjs.map → comments-CTOuhTSX.mjs.map} +1 -1
  404. package/dist/{components-BPxrRjpE.mjs → components-CQy3lh9x.mjs} +1 -1
  405. package/dist/{components-BPxrRjpE.mjs.map → components-CQy3lh9x.mjs.map} +1 -1
  406. package/dist/{config-DyF3OKg_.mjs → config-C3EBstHi.mjs} +18 -2
  407. package/dist/config-C3EBstHi.mjs.map +1 -0
  408. package/dist/{content-CJ94NEx5.mjs → content-BNfwh7xX.mjs} +509 -78
  409. package/dist/content-BNfwh7xX.mjs.map +1 -0
  410. package/dist/content-list-query-DhQ84eVV.d.mts +26 -0
  411. package/dist/content-list-query-DhQ84eVV.d.mts.map +1 -0
  412. package/dist/content-refresh-DNERP4-f.mjs +2560 -0
  413. package/dist/content-refresh-DNERP4-f.mjs.map +1 -0
  414. package/dist/{context-C_1nrqnW.mjs → context-DRgOvSnW.mjs} +25 -17
  415. package/dist/context-DRgOvSnW.mjs.map +1 -0
  416. package/dist/{cron-DRV-UC4K.mjs → cron-Y9aLtgrA.mjs} +1 -1
  417. package/dist/{cron-DRV-UC4K.mjs.map → cron-Y9aLtgrA.mjs.map} +1 -1
  418. package/dist/{dashboard-DINnNVVU.mjs → dashboard-CB8J89rJ.mjs} +44 -10
  419. package/dist/dashboard-CB8J89rJ.mjs.map +1 -0
  420. package/dist/db/index.d.mts +4 -4
  421. package/dist/db/index.mjs +2 -2
  422. package/dist/db/index.mjs.map +1 -1
  423. package/dist/db/libsql.d.mts +1 -1
  424. package/dist/db/postgres.d.mts +1 -1
  425. package/dist/db/sqlite.d.mts +1 -1
  426. package/dist/{db-errors-CcWLaRiR.mjs → db-errors-Cl-sKYTm.mjs} +1 -1
  427. package/dist/{db-errors-CcWLaRiR.mjs.map → db-errors-Cl-sKYTm.mjs.map} +1 -1
  428. package/dist/{default-BD2FG0xV.mjs → default-DdDl3fxv.mjs} +1 -1
  429. package/dist/{default-BD2FG0xV.mjs.map → default-DdDl3fxv.mjs.map} +1 -1
  430. package/dist/{deferred-tasks-C-WRCcKo.d.mts → deferred-tasks-BMsa9F64.d.mts} +1 -1
  431. package/dist/{deferred-tasks-C-WRCcKo.d.mts.map → deferred-tasks-BMsa9F64.d.mts.map} +1 -1
  432. package/dist/{device-flow-CTqd8mud.mjs → device-flow-CaioYGK3.mjs} +4 -4
  433. package/dist/{device-flow-CTqd8mud.mjs.map → device-flow-CaioYGK3.mjs.map} +1 -1
  434. package/dist/dist-D_6CKR8z.mjs +810 -0
  435. package/dist/dist-D_6CKR8z.mjs.map +1 -0
  436. package/dist/{email-console-C6WdcWbL.mjs → email-console-BHNjIwiB.mjs} +1 -1
  437. package/dist/{email-console-C6WdcWbL.mjs.map → email-console-BHNjIwiB.mjs.map} +1 -1
  438. package/dist/{enrich-CFJJgxs_.mjs → enrich-_ySMEvEE.mjs} +2 -2
  439. package/dist/{enrich-CFJJgxs_.mjs.map → enrich-_ySMEvEE.mjs.map} +1 -1
  440. package/dist/{error-oh_9i6bR.mjs → error-DupyJZE2.mjs} +3 -3
  441. package/dist/{error-oh_9i6bR.mjs.map → error-DupyJZE2.mjs.map} +1 -1
  442. package/dist/{errors-BucQ8VYz.mjs → errors-CLUPm7aD.mjs} +14 -2
  443. package/dist/errors-CLUPm7aD.mjs.map +1 -0
  444. package/dist/{escape-CXps5F_v.mjs → escape-C_aLKP3H.mjs} +1 -1
  445. package/dist/{escape-CXps5F_v.mjs.map → escape-C_aLKP3H.mjs.map} +1 -1
  446. package/dist/{field-defs-cache-WD82dMQq.mjs → field-defs-cache-hg6QkjV9.mjs} +4 -4
  447. package/dist/{field-defs-cache-WD82dMQq.mjs.map → field-defs-cache-hg6QkjV9.mjs.map} +1 -1
  448. package/dist/{fts-manager-BITakW_R.mjs → fts-manager-CZ-5dVwJ.mjs} +76 -50
  449. package/dist/fts-manager-CZ-5dVwJ.mjs.map +1 -0
  450. package/dist/{hreflang-BaLCNcDx.d.mts → hreflang-D3Uehfv2.d.mts} +2 -2
  451. package/dist/{hreflang-BaLCNcDx.d.mts.map → hreflang-D3Uehfv2.d.mts.map} +1 -1
  452. package/dist/{hreflang-BdZuVBhL.mjs → hreflang-DNswoYsi.mjs} +7 -7
  453. package/dist/{hreflang-BdZuVBhL.mjs.map → hreflang-DNswoYsi.mjs.map} +1 -1
  454. package/dist/{import-C-9uqyT3.mjs → import-B41u8Rot.mjs} +5 -5
  455. package/dist/{import-C-9uqyT3.mjs.map → import-B41u8Rot.mjs.map} +1 -1
  456. package/dist/{index-M37iz29I.d.mts → index-C3Y-rsyN.d.mts} +226 -73
  457. package/dist/index-C3Y-rsyN.d.mts.map +1 -0
  458. package/dist/{index-MGw47uWq.d.mts → index-Cof4-Fab.d.mts} +5 -10
  459. package/dist/index-Cof4-Fab.d.mts.map +1 -0
  460. package/dist/index.d.mts +20 -19
  461. package/dist/index.mjs +73 -67
  462. package/dist/{init-lock-DJkX6Hto.mjs → init-lock-6b309ZrF.mjs} +1 -1
  463. package/dist/{init-lock-DJkX6Hto.mjs.map → init-lock-6b309ZrF.mjs.map} +1 -1
  464. package/dist/{load-DV1DZuUJ.mjs → load-DmvJrtxS.mjs} +2 -2
  465. package/dist/{load-DV1DZuUJ.mjs.map → load-DmvJrtxS.mjs.map} +1 -1
  466. package/dist/{loader-CGugY7Zl.mjs → loader-DLBqRiGP.mjs} +95 -53
  467. package/dist/loader-DLBqRiGP.mjs.map +1 -0
  468. package/dist/{manifest-schema-Da7kj23y.mjs → manifest-schema-BXbUAHod.mjs} +1 -1
  469. package/dist/{manifest-schema-Da7kj23y.mjs.map → manifest-schema-BXbUAHod.mjs.map} +1 -1
  470. package/dist/media/image-endpoint.mjs +1 -1
  471. package/dist/media/index.d.mts +1 -1
  472. package/dist/media/index.mjs +3 -2
  473. package/dist/media/index.mjs.map +1 -1
  474. package/dist/media/local-runtime.d.mts +12 -12
  475. package/dist/media/local-runtime.mjs +6 -5
  476. package/dist/media/local-runtime.mjs.map +1 -1
  477. package/dist/{media-OhYL-7Io.mjs → media-BWWWb8kg.mjs} +92 -3
  478. package/dist/media-BWWWb8kg.mjs.map +1 -0
  479. package/dist/{media-BP7S-nHT.mjs → media-CzhAn2--.mjs} +2 -2
  480. package/dist/{media-BP7S-nHT.mjs.map → media-CzhAn2--.mjs.map} +1 -1
  481. package/dist/{media-allowlist-D-peH1H5.mjs → media-allowlist-BD6HhgXA.mjs} +14 -3
  482. package/dist/media-allowlist-BD6HhgXA.mjs.map +1 -0
  483. package/dist/{media-upload-DtrwU2B0.mjs → media-upload-9yas9zGH.mjs} +10 -8
  484. package/dist/{media-upload-DtrwU2B0.mjs.map → media-upload-9yas9zGH.mjs.map} +1 -1
  485. package/dist/{media-url-DYs_YLOx.mjs → media-url-BvoX88FA.mjs} +1 -1
  486. package/dist/{media-url-DYs_YLOx.mjs.map → media-url-BvoX88FA.mjs.map} +1 -1
  487. package/dist/{media-usage-BlxfTkN0.mjs → media-usage-De3qvwjc.mjs} +137 -60
  488. package/dist/media-usage-De3qvwjc.mjs.map +1 -0
  489. package/dist/media-usage-work-B9Bksh_b.mjs +152 -0
  490. package/dist/media-usage-work-B9Bksh_b.mjs.map +1 -0
  491. package/dist/media-usage-work-DrCbqBcl.mjs +424 -0
  492. package/dist/media-usage-work-DrCbqBcl.mjs.map +1 -0
  493. package/dist/media-usage-write-fence-aHEgN1zB.mjs +42 -0
  494. package/dist/media-usage-write-fence-aHEgN1zB.mjs.map +1 -0
  495. package/dist/{menus-Y54RDPIN.mjs → menus-CC-yn1F9.mjs} +351 -95
  496. package/dist/menus-CC-yn1F9.mjs.map +1 -0
  497. package/dist/{menus-BcQWxeXu.mjs → menus-fxvEDYE6.mjs} +3 -3
  498. package/dist/{menus-BcQWxeXu.mjs.map → menus-fxvEDYE6.mjs.map} +1 -1
  499. package/dist/{mode-BWyTBe3I.mjs → mode-Bpe-tNNy.mjs} +1 -1
  500. package/dist/{mode-BWyTBe3I.mjs.map → mode-Bpe-tNNy.mjs.map} +1 -1
  501. package/dist/{normalize-C-SHXmra.mjs → normalize-Bc-s_r-a.mjs} +1 -1
  502. package/dist/{normalize-C-SHXmra.mjs.map → normalize-Bc-s_r-a.mjs.map} +1 -1
  503. package/dist/{oauth-authorization-ClvktmrL.mjs → oauth-authorization-BXO1MKej.mjs} +4 -4
  504. package/dist/{oauth-authorization-ClvktmrL.mjs.map → oauth-authorization-BXO1MKej.mjs.map} +1 -1
  505. package/dist/{oauth-clients-8ao-U66l.mjs → oauth-clients-C_DNqtRu.mjs} +1 -1
  506. package/dist/{oauth-clients-8ao-U66l.mjs.map → oauth-clients-C_DNqtRu.mjs.map} +1 -1
  507. package/dist/{oauth-state-store-B1ofdTiQ.mjs → oauth-state-store-DwAxMtk4.mjs} +1 -1
  508. package/dist/{oauth-state-store-B1ofdTiQ.mjs.map → oauth-state-store-DwAxMtk4.mjs.map} +1 -1
  509. package/dist/{oauth-user-lookup-CscEuIiR.mjs → oauth-user-lookup-BxfZizdk.mjs} +1 -1
  510. package/dist/{oauth-user-lookup-CscEuIiR.mjs.map → oauth-user-lookup-BxfZizdk.mjs.map} +1 -1
  511. package/dist/object-cache/memory.d.mts +1 -1
  512. package/dist/{options-CA4eVX6P.d.mts → options-DRe1pIBL.d.mts} +4 -3
  513. package/dist/options-DRe1pIBL.d.mts.map +1 -0
  514. package/dist/page/index.d.mts +2 -2
  515. package/dist/{parse-CJKNuewM.mjs → parse-DFbuc-Fh.mjs} +2 -2
  516. package/dist/{parse-CJKNuewM.mjs.map → parse-DFbuc-Fh.mjs.map} +1 -1
  517. package/dist/{passkey-config-D-zrzMJI.mjs → passkey-config-_2GOwwK8.mjs} +1 -1
  518. package/dist/{passkey-config-D-zrzMJI.mjs.map → passkey-config-_2GOwwK8.mjs.map} +1 -1
  519. package/dist/{placeholder-DaeNS-VG.d.mts → placeholder-CzW7Lshs.d.mts} +1 -1
  520. package/dist/{placeholder-DaeNS-VG.d.mts.map → placeholder-CzW7Lshs.d.mts.map} +1 -1
  521. package/dist/plugin-types.d.mts +8 -1
  522. package/dist/plugin-types.d.mts.map +1 -1
  523. package/dist/plugin-utils.d.mts +10 -10
  524. package/dist/plugins/adapt-sandbox-entry.d.mts +10 -10
  525. package/dist/plugins/adapt-sandbox-entry.mjs +7 -4
  526. package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
  527. package/dist/{portable-text-B_kqBmXB.mjs → portable-text-DhKbDAGr.mjs} +1 -1
  528. package/dist/{portable-text-B_kqBmXB.mjs.map → portable-text-DhKbDAGr.mjs.map} +1 -1
  529. package/dist/{preview-BU6PaLpM.mjs → preview-PW-nOnq4.mjs} +2 -2
  530. package/dist/{preview-BU6PaLpM.mjs.map → preview-PW-nOnq4.mjs.map} +1 -1
  531. package/dist/{public-url-Ox9oOlgp.mjs → public-url-CWoFhQT8.mjs} +1 -1
  532. package/dist/{public-url-Ox9oOlgp.mjs.map → public-url-CWoFhQT8.mjs.map} +1 -1
  533. package/dist/{query-C5w7PsRQ.mjs → query-BgjfiLUQ.mjs} +31 -49
  534. package/dist/query-BgjfiLUQ.mjs.map +1 -0
  535. package/dist/{query-rC9HKv1N.mjs → query-vgZNwIhh.mjs} +3 -3
  536. package/dist/{query-rC9HKv1N.mjs.map → query-vgZNwIhh.mjs.map} +1 -1
  537. package/dist/{rate-limit-kug6q99V.mjs → rate-limit-L5anykgo.mjs} +2 -2
  538. package/dist/{rate-limit-kug6q99V.mjs.map → rate-limit-L5anykgo.mjs.map} +1 -1
  539. package/dist/{redirect-DIJxXKOG.mjs → redirect-COsS6SWJ.mjs} +2 -2
  540. package/dist/{redirect-DIJxXKOG.mjs.map → redirect-COsS6SWJ.mjs.map} +1 -1
  541. package/dist/{redirect-Egf2R9yP.mjs → redirect-KBNE3UEs.mjs} +1 -1
  542. package/dist/{redirect-Egf2R9yP.mjs.map → redirect-KBNE3UEs.mjs.map} +1 -1
  543. package/dist/{redirects-Bzm812bY.mjs → redirects-CufRQt0Q.mjs} +4 -4
  544. package/dist/{redirects-Bzm812bY.mjs.map → redirects-CufRQt0Q.mjs.map} +1 -1
  545. package/dist/{redirects-G8wAhWAf.mjs → redirects-cV9g7V-0.mjs} +133 -14
  546. package/dist/redirects-cV9g7V-0.mjs.map +1 -0
  547. package/dist/registry-C581V4TP.mjs +1275 -0
  548. package/dist/registry-C581V4TP.mjs.map +1 -0
  549. package/dist/{relation-Cbe3Sd3m.mjs → relation-DtmAQH7s.mjs} +3 -3
  550. package/dist/{relation-Cbe3Sd3m.mjs.map → relation-DtmAQH7s.mjs.map} +1 -1
  551. package/dist/{relations-Bw_E1TXo.mjs → relations-BBApI4e2.mjs} +3 -3
  552. package/dist/{relations-Bw_E1TXo.mjs.map → relations-BBApI4e2.mjs.map} +1 -1
  553. package/dist/{relations-qHwpUe66.mjs → relations-DICSyfsh.mjs} +6 -6
  554. package/dist/{relations-qHwpUe66.mjs.map → relations-DICSyfsh.mjs.map} +1 -1
  555. package/dist/{relations-G2ta7GIl.d.mts → relations-DItI3MN9.d.mts} +369 -35
  556. package/dist/relations-DItI3MN9.d.mts.map +1 -0
  557. package/dist/request-context.d.mts +1 -1
  558. package/dist/{request-meta-Df-jFbAd.mjs → request-meta-DgZJh3zG.mjs} +2 -2
  559. package/dist/{request-meta-Df-jFbAd.mjs.map → request-meta-DgZJh3zG.mjs.map} +1 -1
  560. package/dist/{resolve-DZzG4HqM.mjs → resolve-DOhVEvty.mjs} +2 -2
  561. package/dist/{resolve-DZzG4HqM.mjs.map → resolve-DOhVEvty.mjs.map} +1 -1
  562. package/dist/{runner-BFTrkYhu.mjs → runner-BiDvq5dv.mjs} +1157 -254
  563. package/dist/runner-BiDvq5dv.mjs.map +1 -0
  564. package/dist/{runner-BaADli8l.d.mts → runner-CgQbELYC.d.mts} +2 -2
  565. package/dist/{runner-BaADli8l.d.mts.map → runner-CgQbELYC.d.mts.map} +1 -1
  566. package/dist/runtime.d.mts +11 -11
  567. package/dist/runtime.mjs +4 -3
  568. package/dist/runtime.mjs.map +1 -1
  569. package/dist/{schema-CiQXr6_F.mjs → schema-BFyTg38T.mjs} +3 -3
  570. package/dist/{schema-CiQXr6_F.mjs.map → schema-BFyTg38T.mjs.map} +1 -1
  571. package/dist/schema-CeQSNwB3.mjs +390 -0
  572. package/dist/schema-CeQSNwB3.mjs.map +1 -0
  573. package/dist/{scopes-CNJVT5i5.mjs → scopes-BVeuhGBE.mjs} +3 -3
  574. package/dist/{scopes-CNJVT5i5.mjs.map → scopes-BVeuhGBE.mjs.map} +1 -1
  575. package/dist/{search-FZhx5dDU.mjs → search-BpuPKZb0.mjs} +25 -15
  576. package/dist/search-BpuPKZb0.mjs.map +1 -0
  577. package/dist/{secrets-DLd8RXee.mjs → secrets-dtYs2hDo.mjs} +3 -3
  578. package/dist/{secrets-DLd8RXee.mjs.map → secrets-dtYs2hDo.mjs.map} +1 -1
  579. package/dist/{sections-BrIrMUCn.mjs → sections-COctk6hf.mjs} +3 -3
  580. package/dist/{sections-BrIrMUCn.mjs.map → sections-COctk6hf.mjs.map} +1 -1
  581. package/dist/seed/index.d.mts +2 -2
  582. package/dist/seed/index.mjs +24 -22
  583. package/dist/seo/index.d.mts +3 -3
  584. package/dist/seo/index.mjs +16 -15
  585. package/dist/seo/index.mjs.map +1 -1
  586. package/dist/{seo-CobNfOvb.mjs → seo-AFpVvTqr.mjs} +5 -3
  587. package/dist/seo-AFpVvTqr.mjs.map +1 -0
  588. package/dist/{seo-DTHRntNC.mjs → seo-CvDxfvFb.mjs} +2 -2
  589. package/dist/{seo-DTHRntNC.mjs.map → seo-CvDxfvFb.mjs.map} +1 -1
  590. package/dist/{service-B-pYGPgR.mjs → service-xMiMSTsR.mjs} +3 -3
  591. package/dist/{service-B-pYGPgR.mjs.map → service-xMiMSTsR.mjs.map} +1 -1
  592. package/dist/{session-user-BvM9-zNl.mjs → session-user-BzVemLkw.mjs} +1 -1
  593. package/dist/{session-user-BvM9-zNl.mjs.map → session-user-BzVemLkw.mjs.map} +1 -1
  594. package/dist/{settings-kJhGiQ4z.mjs → settings-B372MV0p.mjs} +4 -4
  595. package/dist/{settings-kJhGiQ4z.mjs.map → settings-B372MV0p.mjs.map} +1 -1
  596. package/dist/{settings-DPHau-WH.mjs → settings-BE9aqn_9.mjs} +3 -3
  597. package/dist/{settings-DPHau-WH.mjs.map → settings-BE9aqn_9.mjs.map} +1 -1
  598. package/dist/{setup-complete-u50Qm8rY.mjs → setup-complete-DF7TAfD5.mjs} +1 -1
  599. package/dist/{setup-complete-u50Qm8rY.mjs.map → setup-complete-DF7TAfD5.mjs.map} +1 -1
  600. package/dist/{setup-nonce-DCjiiOD2.mjs → setup-nonce-Do-U_cg9.mjs} +1 -1
  601. package/dist/{setup-nonce-DCjiiOD2.mjs.map → setup-nonce-Do-U_cg9.mjs.map} +1 -1
  602. package/dist/{single-flight-cache-DW3w11Pu.mjs → single-flight-cache-B0eLKS6K.mjs} +2 -2
  603. package/dist/{single-flight-cache-DW3w11Pu.mjs.map → single-flight-cache-B0eLKS6K.mjs.map} +1 -1
  604. package/dist/{site-url-I-lJ5kma.mjs → site-url-Bowsi9T-.mjs} +2 -2
  605. package/dist/{site-url-I-lJ5kma.mjs.map → site-url-Bowsi9T-.mjs.map} +1 -1
  606. package/dist/slugify-B994zkXC.mjs +17 -0
  607. package/dist/slugify-B994zkXC.mjs.map +1 -0
  608. package/dist/{snapshot-I_fjLDaD.mjs → snapshot-B5h6aPMh.mjs} +1 -1
  609. package/dist/{snapshot-I_fjLDaD.mjs.map → snapshot-B5h6aPMh.mjs.map} +1 -1
  610. package/dist/{ssrf-CTa6v21i.mjs → ssrf-Cpvg_n3A.mjs} +1 -1
  611. package/dist/{ssrf-CTa6v21i.mjs.map → ssrf-Cpvg_n3A.mjs.map} +1 -1
  612. package/dist/{state-CQvoefYP.mjs → state-DYwPue40.mjs} +1 -1
  613. package/dist/{state-CQvoefYP.mjs.map → state-DYwPue40.mjs.map} +1 -1
  614. package/dist/{status-CIsmlC1E.mjs → status-CWVYpbD8.mjs} +1 -1
  615. package/dist/{status-CIsmlC1E.mjs.map → status-CWVYpbD8.mjs.map} +1 -1
  616. package/dist/storage/local.d.mts +1 -1
  617. package/dist/storage/local.mjs +1 -1
  618. package/dist/storage/s3.d.mts +1 -1
  619. package/dist/storage/s3.mjs +1 -1
  620. package/dist/{taxonomies-CLN1N92E.mjs → taxonomies-B0o9ExNV.mjs} +75 -64
  621. package/dist/taxonomies-B0o9ExNV.mjs.map +1 -0
  622. package/dist/{taxonomies-CKuaZER5.mjs → taxonomies-Dk3MAklL.mjs} +280 -56
  623. package/dist/taxonomies-Dk3MAklL.mjs.map +1 -0
  624. package/dist/{taxonomy-pOrB2kZe.mjs → taxonomy-CPeM8d2o.mjs} +131 -78
  625. package/dist/taxonomy-CPeM8d2o.mjs.map +1 -0
  626. package/dist/{tokens-DagaJGK8.mjs → tokens-C39klX8R.mjs} +2 -2
  627. package/dist/{tokens-DagaJGK8.mjs.map → tokens-C39klX8R.mjs.map} +1 -1
  628. package/dist/{transport-DVsa5YYo.mjs → transport--CfOflrp.mjs} +1 -1
  629. package/dist/{transport-DVsa5YYo.mjs.map → transport--CfOflrp.mjs.map} +1 -1
  630. package/dist/{transport-CAwTaTp_.d.mts → transport-B_rfeU-a.d.mts} +1 -1
  631. package/dist/{transport-CAwTaTp_.d.mts.map → transport-B_rfeU-a.d.mts.map} +1 -1
  632. package/dist/{trusted-proxy-D20_7fyX.mjs → trusted-proxy-CEVekpby.mjs} +1 -1
  633. package/dist/{trusted-proxy-D20_7fyX.mjs.map → trusted-proxy-CEVekpby.mjs.map} +1 -1
  634. package/dist/{types-NBI3rF-_.mjs → types-75KIqzL9.mjs} +18 -2
  635. package/dist/types-75KIqzL9.mjs.map +1 -0
  636. package/dist/{types-CbUcuxxc.d.mts → types-BPuloofb.d.mts} +1 -1
  637. package/dist/{types-CbUcuxxc.d.mts.map → types-BPuloofb.d.mts.map} +1 -1
  638. package/dist/{types-BjxTKxrZ.mjs → types-BW1syrlw.mjs} +1 -1
  639. package/dist/{types-BjxTKxrZ.mjs.map → types-BW1syrlw.mjs.map} +1 -1
  640. package/dist/{types-BnFP1M3J.d.mts → types-C3_AbkDP.d.mts} +32 -10
  641. package/dist/types-C3_AbkDP.d.mts.map +1 -0
  642. package/dist/{types-Dc4ntQjQ.d.mts → types-CAGdePf3.d.mts} +124 -1
  643. package/dist/types-CAGdePf3.d.mts.map +1 -0
  644. package/dist/{types-DLG4IFEQ.d.mts → types-CFUfyt1s.d.mts} +1 -1
  645. package/dist/{types-DLG4IFEQ.d.mts.map → types-CFUfyt1s.d.mts.map} +1 -1
  646. package/dist/{types-LoagAGzH.d.mts → types-CPx2lIGo.d.mts} +1 -1
  647. package/dist/{types-LoagAGzH.d.mts.map → types-CPx2lIGo.d.mts.map} +1 -1
  648. package/dist/{types-Cd8iuS1J.mjs → types-CQPWhPxE.mjs} +9 -12
  649. package/dist/types-CQPWhPxE.mjs.map +1 -0
  650. package/dist/{types-Cz8hNch2.d.mts → types-Cs-TFLNf.d.mts} +25 -5
  651. package/dist/types-Cs-TFLNf.d.mts.map +1 -0
  652. package/dist/types-CtzytVXn.mjs.map +1 -1
  653. package/dist/{types-BGWPMiBO.d.mts → types-D4_1Ga4L.d.mts} +44 -5
  654. package/dist/types-D4_1Ga4L.d.mts.map +1 -0
  655. package/dist/{types-C8oz_ayJ.d.mts → types-DefV3OiO.d.mts} +1 -1
  656. package/dist/{types-C8oz_ayJ.d.mts.map → types-DefV3OiO.d.mts.map} +1 -1
  657. package/dist/{types-BK6U01Ro.d.mts → types-X0MThr7x.d.mts} +1 -1
  658. package/dist/{types-BK6U01Ro.d.mts.map → types-X0MThr7x.d.mts.map} +1 -1
  659. package/dist/{upload-attempts-D8QAFLUJ.mjs → upload-attempts-hlne3iA1.mjs} +1 -1
  660. package/dist/{upload-attempts-D8QAFLUJ.mjs.map → upload-attempts-hlne3iA1.mjs.map} +1 -1
  661. package/dist/url-pattern-BHS0V5Ng.mjs +33 -0
  662. package/dist/url-pattern-BHS0V5Ng.mjs.map +1 -0
  663. package/dist/{user-DBrq4UVq.mjs → user-sHgJ62SP.mjs} +3 -3
  664. package/dist/{user-DBrq4UVq.mjs.map → user-sHgJ62SP.mjs.map} +1 -1
  665. package/dist/{utils-hLzi_2Fn.mjs → utils-D4vD_Y98.mjs} +3 -3
  666. package/dist/{utils-hLzi_2Fn.mjs.map → utils-D4vD_Y98.mjs.map} +1 -1
  667. package/dist/{validate-mKo3RxBM.mjs → validate-BkqIG_Uj.mjs} +24 -5
  668. package/dist/validate-BkqIG_Uj.mjs.map +1 -0
  669. package/dist/{validate-C3oSmA7F.d.mts → validate-DeGtBN84.d.mts} +15 -7
  670. package/dist/validate-DeGtBN84.d.mts.map +1 -0
  671. package/dist/{validation-BgpucsvF.mjs → validation-CiJb_X5o.mjs} +11 -10
  672. package/dist/{validation-BgpucsvF.mjs.map → validation-CiJb_X5o.mjs.map} +1 -1
  673. package/dist/version-x0NjTScG.mjs +7 -0
  674. package/dist/{version-C4PnpmoV.mjs.map → version-x0NjTScG.mjs.map} +1 -1
  675. package/dist/{widgets-CJJtkiKh.mjs → widgets-Cwzvww0W.mjs} +3 -3
  676. package/dist/{widgets-CJJtkiKh.mjs.map → widgets-Cwzvww0W.mjs.map} +1 -1
  677. package/dist/{wxr-taxonomies-Bkpp_2tK.d.mts → wxr-taxonomies-CmC0ZsDr.d.mts} +1 -1
  678. package/dist/{wxr-taxonomies-Bkpp_2tK.d.mts.map → wxr-taxonomies-CmC0ZsDr.d.mts.map} +1 -1
  679. package/dist/{wxr-taxonomies-9PPSy8X6.mjs → wxr-taxonomies-QZjWxjyk.mjs} +13 -32
  680. package/dist/{wxr-taxonomies-9PPSy8X6.mjs.map → wxr-taxonomies-QZjWxjyk.mjs.map} +1 -1
  681. package/dist/{zod-generator-CG64Hnbh.mjs → zod-generator-D11MhxG4.mjs} +52 -5
  682. package/dist/zod-generator-D11MhxG4.mjs.map +1 -0
  683. package/package.json +16 -8
  684. package/src/api/errors.ts +12 -0
  685. package/src/api/handlers/content.ts +127 -29
  686. package/src/api/handlers/dashboard.ts +12 -2
  687. package/src/api/handlers/index.ts +16 -0
  688. package/src/api/handlers/manifest.ts +2 -0
  689. package/src/api/handlers/media-allowlist.ts +13 -2
  690. package/src/api/handlers/media-usage-work.ts +188 -0
  691. package/src/api/handlers/media-usage.ts +5 -3
  692. package/src/api/handlers/schema.ts +9 -3
  693. package/src/api/handlers/seo.ts +5 -2
  694. package/src/api/handlers/taxonomies.ts +345 -82
  695. package/src/api/media-usage-write-fence.ts +64 -0
  696. package/src/api/openapi/document.ts +199 -0
  697. package/src/api/schemas/common.ts +3 -1
  698. package/src/api/schemas/content.ts +122 -1
  699. package/src/api/schemas/media-usage.ts +133 -0
  700. package/src/api/schemas/schema.ts +78 -3
  701. package/src/api/schemas/taxonomies.ts +40 -8
  702. package/src/api/types.ts +1 -0
  703. package/src/astro/integration/index.ts +55 -42
  704. package/src/astro/integration/routes.ts +34 -4
  705. package/src/astro/integration/runtime.ts +15 -0
  706. package/src/astro/integration/virtual-modules.ts +25 -1
  707. package/src/astro/integration/vite-config.ts +16 -1
  708. package/src/astro/middleware/media-usage-write-fence.ts +30 -0
  709. package/src/astro/middleware/redirect.ts +12 -2
  710. package/src/astro/middleware.ts +75 -8
  711. package/src/astro/routes/api/admin/media-usage/collection-deletions/index.ts +22 -0
  712. package/src/astro/routes/api/admin/media-usage/collection-deletions/retry.ts +22 -0
  713. package/src/astro/routes/api/admin/media-usage/work/index.ts +26 -0
  714. package/src/astro/routes/api/admin/media-usage/work/retry.ts +26 -0
  715. package/src/astro/routes/api/admin/plugins/[id]/disable.ts +4 -0
  716. package/src/astro/routes/api/admin/plugins/[id]/enable.ts +4 -0
  717. package/src/astro/routes/api/admin/plugins/[id]/uninstall.ts +4 -0
  718. package/src/astro/routes/api/admin/plugins/[id]/update.ts +4 -0
  719. package/src/astro/routes/api/admin/plugins/marketplace/[id]/install.ts +4 -0
  720. package/src/astro/routes/api/admin/plugins/registry/[id]/uninstall.ts +4 -0
  721. package/src/astro/routes/api/admin/plugins/registry/[id]/update.ts +4 -0
  722. package/src/astro/routes/api/admin/plugins/registry/install.ts +4 -0
  723. package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +67 -31
  724. package/src/astro/routes/api/import/wordpress/execute.ts +3 -10
  725. package/src/astro/routes/api/mcp.ts +1 -0
  726. package/src/astro/routes/api/plugins/[pluginId]/[...path].ts +7 -1
  727. package/src/astro/routes/api/schema/collections/[slug]/index.ts +1 -7
  728. package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +1 -0
  729. package/src/astro/routes/api/taxonomies/[name]/translations.ts +48 -0
  730. package/src/astro/routes/api/taxonomies/[name].ts +102 -0
  731. package/src/astro/types.ts +25 -4
  732. package/src/cleanup.ts +6 -12
  733. package/src/cli/commands/doctor.ts +193 -6
  734. package/src/cli/commands/export-seed.ts +4 -1
  735. package/src/client/index.ts +119 -0
  736. package/src/components/Block.astro +12 -0
  737. package/src/components/InlinePortableTextEditor.tsx +89 -1
  738. package/src/content/converters/mark-safety.ts +120 -0
  739. package/src/content/converters/portable-text-to-prosemirror.ts +25 -16
  740. package/src/content/converters/prosemirror-to-portable-text.ts +12 -2
  741. package/src/content-list-query.ts +29 -0
  742. package/src/database/migrations/060_collection_admin_config.ts +16 -0
  743. package/src/database/migrations/061_media_usage_cleanup.ts +77 -0
  744. package/src/database/migrations/062_media_usage_cleanup_fence.ts +295 -0
  745. package/src/database/migrations/063_media_usage_incremental_work.ts +397 -0
  746. package/src/database/migrations/064_fts_plain_text.ts +253 -0
  747. package/src/database/migrations/065_media_usage_collection_deletion.ts +85 -0
  748. package/src/database/migrations/066_media_usage_reconciliation.ts +115 -0
  749. package/src/database/migrations/067_indexed_content_fields.ts +39 -0
  750. package/src/database/migrations/068_content_taxonomy_entry_groups.ts +61 -0
  751. package/src/database/migrations/069_collection_title_date_fields.ts +45 -0
  752. package/src/database/migrations/070_collection_routable.ts +18 -0
  753. package/src/database/migrations/runner.ts +22 -0
  754. package/src/database/repositories/content.ts +861 -96
  755. package/src/database/repositories/media-usage-work.ts +848 -0
  756. package/src/database/repositories/media-usage.ts +1502 -138
  757. package/src/database/repositories/revision.ts +17 -6
  758. package/src/database/repositories/taxonomy.ts +234 -103
  759. package/src/database/repositories/types.ts +51 -2
  760. package/src/database/types.ts +134 -16
  761. package/src/db/adapters.ts +28 -0
  762. package/src/db/index.ts +3 -0
  763. package/src/emdash-runtime.ts +227 -20
  764. package/src/fields/file.ts +7 -4
  765. package/src/fields/image.ts +8 -1
  766. package/src/fields/types.ts +18 -5
  767. package/src/i18n/config.ts +32 -0
  768. package/src/i18n/repair-locale-casing.ts +0 -14
  769. package/src/i18n/taxonomy-locale-diagnostic.ts +47 -0
  770. package/src/import/wxr-taxonomies.ts +7 -47
  771. package/src/index.ts +25 -2
  772. package/src/loader.ts +119 -65
  773. package/src/mcp/server.ts +242 -34
  774. package/src/media/usage/activation.ts +626 -0
  775. package/src/media/usage/capture-triggers.ts +543 -0
  776. package/src/media/usage/cleanup.ts +305 -0
  777. package/src/media/usage/collection-deletion-processor.ts +356 -0
  778. package/src/media/usage/collection-deletion.ts +836 -0
  779. package/src/media/usage/content-fields.ts +40 -3
  780. package/src/media/usage/content-refresh.ts +356 -47
  781. package/src/media/usage/content-repair.ts +180 -61
  782. package/src/media/usage/content-snapshots.ts +85 -105
  783. package/src/media/usage/projection-fingerprint.ts +129 -0
  784. package/src/media/usage/reconciliation-processor.ts +372 -0
  785. package/src/media/usage/reconciliation.ts +1117 -0
  786. package/src/media/usage/source-key.ts +4 -0
  787. package/src/media/usage/types.ts +2 -0
  788. package/src/media/usage/work-processor.ts +248 -0
  789. package/src/menus/index.ts +246 -141
  790. package/src/plugin-types.ts +8 -0
  791. package/src/plugins/adapt-sandbox-entry.ts +24 -5
  792. package/src/plugins/context.ts +24 -7
  793. package/src/plugins/index.ts +9 -0
  794. package/src/plugins/routes.ts +43 -1
  795. package/src/plugins/sandbox/index.ts +10 -1
  796. package/src/plugins/sandbox/types.ts +78 -1
  797. package/src/plugins/scheduler/node.ts +13 -1
  798. package/src/plugins/scheduler/types.ts +2 -0
  799. package/src/plugins/types.ts +39 -2
  800. package/src/query.ts +29 -37
  801. package/src/scheduler-health.ts +46 -0
  802. package/src/schema/registry.ts +777 -255
  803. package/src/schema/types.ts +50 -8
  804. package/src/schema/url-pattern.ts +33 -0
  805. package/src/schema/zod-generator.ts +77 -5
  806. package/src/search/fts-manager.ts +117 -76
  807. package/src/search/query.ts +32 -11
  808. package/src/search/types.ts +2 -0
  809. package/src/seed/apply.ts +68 -15
  810. package/src/seed/types.ts +11 -3
  811. package/src/seed/validate.ts +52 -2
  812. package/src/taxonomies/index.ts +77 -75
  813. package/src/taxonomies/term-counts.ts +21 -8
  814. package/src/utils/slugify.ts +1 -29
  815. package/src/virtual-modules.d.ts +16 -0
  816. package/dist/adapters-BMyNSSZi.d.mts.map +0 -1
  817. package/dist/api-D2hunekQ.mjs.map +0 -1
  818. package/dist/apply-kwNEJW2l.mjs.map +0 -1
  819. package/dist/config-DyF3OKg_.mjs.map +0 -1
  820. package/dist/content-CJ94NEx5.mjs.map +0 -1
  821. package/dist/content-refresh-Xw7aKmou.mjs +0 -1629
  822. package/dist/content-refresh-Xw7aKmou.mjs.map +0 -1
  823. package/dist/context-C_1nrqnW.mjs.map +0 -1
  824. package/dist/dashboard-DINnNVVU.mjs.map +0 -1
  825. package/dist/errors-BucQ8VYz.mjs.map +0 -1
  826. package/dist/fts-manager-BITakW_R.mjs.map +0 -1
  827. package/dist/index-M37iz29I.d.mts.map +0 -1
  828. package/dist/index-MGw47uWq.d.mts.map +0 -1
  829. package/dist/loader-CGugY7Zl.mjs.map +0 -1
  830. package/dist/media-OhYL-7Io.mjs.map +0 -1
  831. package/dist/media-allowlist-D-peH1H5.mjs.map +0 -1
  832. package/dist/media-usage-BlxfTkN0.mjs.map +0 -1
  833. package/dist/menus-Y54RDPIN.mjs.map +0 -1
  834. package/dist/options-CA4eVX6P.d.mts.map +0 -1
  835. package/dist/query-C5w7PsRQ.mjs.map +0 -1
  836. package/dist/redirects-G8wAhWAf.mjs.map +0 -1
  837. package/dist/registry-Dbodb4Uo.mjs +0 -840
  838. package/dist/registry-Dbodb4Uo.mjs.map +0 -1
  839. package/dist/relations-G2ta7GIl.d.mts.map +0 -1
  840. package/dist/runner-BFTrkYhu.mjs.map +0 -1
  841. package/dist/search-FZhx5dDU.mjs.map +0 -1
  842. package/dist/seo-CobNfOvb.mjs.map +0 -1
  843. package/dist/slugify-C_tqlU4G.mjs +0 -30
  844. package/dist/slugify-C_tqlU4G.mjs.map +0 -1
  845. package/dist/taxonomies-CKuaZER5.mjs.map +0 -1
  846. package/dist/taxonomies-CLN1N92E.mjs.map +0 -1
  847. package/dist/taxonomy-pOrB2kZe.mjs.map +0 -1
  848. package/dist/types-BGWPMiBO.d.mts.map +0 -1
  849. package/dist/types-BnFP1M3J.d.mts.map +0 -1
  850. package/dist/types-Cd8iuS1J.mjs.map +0 -1
  851. package/dist/types-Cz8hNch2.d.mts.map +0 -1
  852. package/dist/types-Dc4ntQjQ.d.mts.map +0 -1
  853. package/dist/types-NBI3rF-_.mjs.map +0 -1
  854. package/dist/validate-C3oSmA7F.d.mts.map +0 -1
  855. package/dist/validate-mKo3RxBM.mjs.map +0 -1
  856. package/dist/version-C4PnpmoV.mjs +0 -7
  857. package/dist/zod-generator-CG64Hnbh.mjs.map +0 -1
  858. /package/dist/{api-tokens-Dai9dND0.mjs → api-tokens-CyTsLszZ.mjs} +0 -0
  859. /package/dist/{ssrf-Cj568Dgs.mjs → ssrf-DpXgKsna.mjs} +0 -0
  860. /package/dist/{types-DKuWPYV5.mjs → types-CP1CflWf.mjs} +0 -0
@@ -1,1629 +0,0 @@
1
- import { t as validateIdentifier } from "./validate-BpwoDOgt.mjs";
2
- import { r as isI18nEnabled } from "./config-DyF3OKg_.mjs";
3
- import { n as chunks, t as SQL_BATCH_SIZE } from "./chunks-DbYzib_k.mjs";
4
- import { a as decodeCursor, o as encodeCursor, r as InvalidCursorError } from "./types-Cd8iuS1J.mjs";
5
- import { t as withTransaction } from "./transaction-NQj4VJ7Z.mjs";
6
- import { t as INTERNAL_MEDIA_PREFIX } from "./normalize-C-SHXmra.mjs";
7
- import { n as normalizeMime } from "./mime-DfIVjNkr.mjs";
8
- import { r as hashString } from "./hash-Cg0TXJPV.mjs";
9
- import { sql } from "kysely";
10
- import { ulid } from "ulidx";
11
-
12
- //#region src/database/repositories/media-usage.ts
13
- const OCCURRENCE_INSERT_BATCH_SIZE = Math.max(1, Math.floor(SQL_BATCH_SIZE / 13));
14
- const CONTENT_SOURCE_ELIGIBILITY = sql`(
15
- s.source_variant = 'draft_overlay'
16
- OR (
17
- s.source_variant = 'columns'
18
- AND (
19
- s.content_status = 'published'
20
- OR NOT EXISTS (
21
- SELECT 1
22
- FROM _emdash_media_usage_sources AS overlay
23
- WHERE overlay.source_type = 'content'
24
- AND overlay.collection_slug = s.collection_slug
25
- AND overlay.content_id = s.content_id
26
- AND overlay.source_variant = 'draft_overlay'
27
- )
28
- )
29
- )
30
- )`;
31
- /** Persistence-only repository for the internal media usage projection tables. */
32
- var MediaUsageRepository = class {
33
- constructor(db) {
34
- this.db = db;
35
- }
36
- async replaceSource(source, occurrences) {
37
- const generation = ulid();
38
- const now = (/* @__PURE__ */ new Date()).toISOString();
39
- await withTransaction(this.db, async (trx) => {
40
- await this.insertOccurrences(trx, source.sourceKey, generation, occurrences, now);
41
- await this.upsertSource(trx, source, generation, now);
42
- });
43
- const replaced = await this.findSource(source.sourceKey);
44
- if (!replaced) throw new Error(`Media usage source ${source.sourceKey} was not persisted`);
45
- return replaced;
46
- }
47
- async replaceSourceIfCurrent(source, occurrences, expectedCurrentGeneration) {
48
- const generation = ulid();
49
- const now = (/* @__PURE__ */ new Date()).toISOString();
50
- const row = this.buildSourceRow(source, generation, now);
51
- let replaced = false;
52
- await withTransaction(this.db, async (trx) => {
53
- await this.insertOccurrences(trx, source.sourceKey, generation, occurrences, now);
54
- if (expectedCurrentGeneration === null) {
55
- replaced = await this.insertSourceIfAbsent(trx, row);
56
- return;
57
- }
58
- replaced = await this.updateSourceIfGeneration(trx, row, expectedCurrentGeneration);
59
- });
60
- return {
61
- replaced,
62
- source: replaced ? null : await this.findSource(source.sourceKey)
63
- };
64
- }
65
- async findSource(sourceKey) {
66
- const row = await this.db.selectFrom("_emdash_media_usage_sources").selectAll().where("source_key", "=", sourceKey).executeTakeFirst();
67
- return row ? rowToSource(row) : null;
68
- }
69
- async findSources(sourceKeys) {
70
- const uniqueSourceKeys = [...new Set(sourceKeys)];
71
- const sources = /* @__PURE__ */ new Map();
72
- if (uniqueSourceKeys.length === 0) return sources;
73
- for (const sourceKeyBatch of chunks(uniqueSourceKeys, SQL_BATCH_SIZE)) {
74
- const rows = await this.db.selectFrom("_emdash_media_usage_sources").selectAll().where("source_key", "in", sourceKeyBatch).execute();
75
- for (const row of rows) {
76
- const source = rowToSource(row);
77
- sources.set(source.sourceKey, source);
78
- }
79
- }
80
- return sources;
81
- }
82
- async replaceSourceIfMatching(source, occurrences, expectedSource) {
83
- const generation = ulid();
84
- const now = (/* @__PURE__ */ new Date()).toISOString();
85
- const row = this.buildSourceRow(source, generation, now);
86
- let replaced = false;
87
- await withTransaction(this.db, async (trx) => {
88
- await this.insertOccurrences(trx, source.sourceKey, generation, occurrences, now);
89
- if (expectedSource === null) {
90
- replaced = await this.insertSourceIfAbsent(trx, row);
91
- return;
92
- }
93
- replaced = await this.updateSourceIfMatching(trx, row, expectedSource);
94
- });
95
- return {
96
- replaced,
97
- source: replaced ? null : await this.findSource(source.sourceKey)
98
- };
99
- }
100
- async markSourceAttempted(source) {
101
- const now = (/* @__PURE__ */ new Date()).toISOString();
102
- const row = this.buildAttemptedSourceRow(source, now);
103
- const updates = this.attemptedSourceUpdateSet(source, row);
104
- await this.db.insertInto("_emdash_media_usage_sources").values(row).onConflict((oc) => oc.column("source_key").doUpdateSet(updates)).execute();
105
- const attempted = await this.findSource(source.sourceKey);
106
- if (!attempted) throw new Error(`Media usage source ${source.sourceKey} was not persisted`);
107
- return attempted;
108
- }
109
- async markSourceAttemptedIfMatching(source, expectedSource) {
110
- const now = (/* @__PURE__ */ new Date()).toISOString();
111
- const row = this.buildAttemptedSourceRow(source, now);
112
- let attempted = false;
113
- if (expectedSource === null) attempted = await this.insertSourceIfAbsent(this.db, row);
114
- else attempted = await this.updateAttemptedSourceIfMatching(this.db, source, row, expectedSource);
115
- return {
116
- attempted,
117
- source: attempted ? null : await this.findSource(source.sourceKey)
118
- };
119
- }
120
- async findActiveEntryCountsByMediaIds(mediaIds) {
121
- const uniqueMediaIds = [...new Set(mediaIds)];
122
- const counts = new Map(uniqueMediaIds.map((mediaId) => [mediaId, 0]));
123
- for (const mediaIdBatch of chunks(uniqueMediaIds, SQL_BATCH_SIZE)) {
124
- const visibleEntries = this.currentContentMediaUsageBaseQuery().select([
125
- "u.media_id as media_id",
126
- "s.collection_slug as collection_slug",
127
- "s.content_id as content_id"
128
- ]).where("u.media_id", "in", mediaIdBatch).where((eb) => eb.not(eb.exists(eb.selectFrom("_emdash_media_usage_sources as deleted_source").select("deleted_source.source_key").where("deleted_source.source_type", "=", "content").whereRef("deleted_source.collection_slug", "=", "s.collection_slug").whereRef("deleted_source.content_id", "=", "s.content_id").where("deleted_source.source_variant", "in", ["columns", "draft_overlay"]).where("deleted_source.content_deleted_at", "is not", null)))).distinct().as("visible_entries");
129
- const rows = await this.db.selectFrom(visibleEntries).select("media_id").select((eb) => eb.fn.countAll().as("usage_count")).groupBy("media_id").execute();
130
- for (const row of rows) if (row.media_id !== null) counts.set(row.media_id, Number(row.usage_count));
131
- }
132
- return counts;
133
- }
134
- async findCollectionIndexStatusScopes(identity) {
135
- return (await this.db.selectFrom("_emdash_collections as collection").leftJoin("_emdash_media_usage_index_status as status", (join) => join.on("status.adapter_id", "=", identity.adapterId).on("status.scope_type", "=", identity.scopeType).onRef("status.scope_key", "=", "collection.slug")).select([
136
- "collection.slug as collection_slug",
137
- "status.status as status",
138
- "status.schema_version as schema_version"
139
- ]).orderBy("collection.slug", "asc").execute()).map((row) => ({
140
- collectionSlug: row.collection_slug,
141
- status: row.status,
142
- schemaVersion: row.schema_version === null ? null : Number(row.schema_version)
143
- }));
144
- }
145
- async findCurrentEntryUsagePageByMediaId(mediaId, options = {}) {
146
- const requestedLimit = Math.floor(options.limit ?? 50);
147
- const limit = Number.isFinite(requestedLimit) ? Math.min(Math.max(1, requestedLimit), 100) : 50;
148
- const cursor = options.cursor ? decodeCursor(options.cursor) : null;
149
- if (cursor && (cursor.orderValue.length === 0 || cursor.id.length === 0)) throw new InvalidCursorError(options.cursor ?? "");
150
- let matchedGroups = this.currentContentMediaUsageBaseQuery().select(["s.collection_slug as collection_slug", "s.content_id as content_id"]).where("u.media_id", "=", mediaId).distinct();
151
- if (cursor) matchedGroups = matchedGroups.where((eb) => eb.or([eb("s.collection_slug", ">", cursor.orderValue), eb.and([eb("s.collection_slug", "=", cursor.orderValue), eb("s.content_id", ">", cursor.id)])]));
152
- matchedGroups = matchedGroups.orderBy("s.collection_slug", "asc").orderBy("s.content_id", "asc").limit(limit + 1);
153
- const rows = await this.db.with("matched_groups", () => matchedGroups).with("page_groups", (db) => db.selectFrom("matched_groups").selectAll().orderBy("collection_slug", "asc").orderBy("content_id", "asc").limit(limit)).with("entry_state", (db) => db.selectFrom("page_groups as page").crossJoin("_emdash_media_usage_sources as state").select(["page.collection_slug", "page.content_id"]).select((eb) => eb.fn.max("state.content_deleted_at").as("entry_deleted_at")).whereRef("page.collection_slug", "=", "state.collection_slug").whereRef("page.content_id", "=", "state.content_id").where("state.source_type", "=", "content").where("state.source_variant", "in", ["columns", "draft_overlay"]).groupBy(["page.collection_slug", "page.content_id"])).selectFrom("entry_state as page").crossJoin("_emdash_media_usage_sources as s").crossJoin("_emdash_media_usage as u").whereRef("page.collection_slug", "=", "s.collection_slug").whereRef("page.content_id", "=", "s.content_id").whereRef("s.source_key", "=", "u.source_key").whereRef("s.current_generation", "=", "u.generation").select(currentUsageSelect).select("page.entry_deleted_at").select(sql`CASE
154
- WHEN (SELECT COUNT(*) FROM matched_groups) > ${limit} THEN 1
155
- ELSE 0
156
- END`.as("has_more")).where("u.media_id", "=", mediaId).where("s.source_type", "=", "content").where("s.collection_slug", "is not", null).where("s.content_id", "is not", null).where("s.source_variant", "in", ["columns", "draft_overlay"]).where(CONTENT_SOURCE_ELIGIBILITY).orderBy("s.collection_slug", "asc").orderBy("s.content_id", "asc").orderBy("s.source_variant", "asc").orderBy("s.source_key", "asc").orderBy("u.field_path", "asc").orderBy("u.occurrence_index", "asc").orderBy("u.id", "asc").execute();
157
- const items = groupUsageRows(rows);
158
- const result = { items };
159
- if (Number(rows[0]?.has_more ?? 0) === 1 && items.length > 0) {
160
- const last = items.at(-1);
161
- result.nextCursor = encodeCursor(last.collectionSlug, last.contentId);
162
- }
163
- return result;
164
- }
165
- async findCurrentUsageByMediaId(mediaId) {
166
- return (await this.db.selectFrom("_emdash_media_usage_sources as s").innerJoin("_emdash_media_usage as u", (join) => join.onRef("u.source_key", "=", "s.source_key").onRef("u.generation", "=", "s.current_generation")).select(currentUsageSelect).where("u.media_id", "=", mediaId).orderBy("s.source_key", "asc").orderBy("u.field_path", "asc").orderBy("u.occurrence_index", "asc").execute()).map(rowToUsageRecord);
167
- }
168
- async findCurrentUsageByProviderAsset(provider, providerAssetId) {
169
- return (await this.db.selectFrom("_emdash_media_usage_sources as s").innerJoin("_emdash_media_usage as u", (join) => join.onRef("u.source_key", "=", "s.source_key").onRef("u.generation", "=", "s.current_generation")).select(currentUsageSelect).where("u.provider", "=", provider).where("u.provider_asset_id", "=", providerAssetId).orderBy("s.source_key", "asc").orderBy("u.field_path", "asc").orderBy("u.occurrence_index", "asc").execute()).map(rowToUsageRecord);
170
- }
171
- async findCurrentUsagePageByMediaId(mediaId, options = {}) {
172
- return this.findCurrentUsagePage((query) => query.where("u.media_id", "=", mediaId), options);
173
- }
174
- async findCurrentUsagePageByProviderAsset(provider, providerAssetId, options = {}) {
175
- return this.findCurrentUsagePage((query) => query.where("u.provider", "=", provider).where("u.provider_asset_id", "=", providerAssetId), options);
176
- }
177
- async deleteSource(sourceKey) {
178
- return this.deleteSources([sourceKey]);
179
- }
180
- async deleteSourceIfCurrent(sourceKey, expectedCurrentGeneration) {
181
- let deleted = false;
182
- await withTransaction(this.db, async (trx) => {
183
- const result = await trx.deleteFrom("_emdash_media_usage_sources").where("source_key", "=", sourceKey).where("current_generation", "=", expectedCurrentGeneration).executeTakeFirst();
184
- deleted = Number(result.numDeletedRows ?? 0) > 0;
185
- if (!deleted) return;
186
- await this.deleteSourceGenerationOccurrences(trx, sourceKey, expectedCurrentGeneration);
187
- });
188
- return {
189
- deleted,
190
- source: await this.findSource(sourceKey)
191
- };
192
- }
193
- async deleteSourceIfMatching(sourceKey, expectedSource) {
194
- let deleted = false;
195
- await withTransaction(this.db, async (trx) => {
196
- const result = await trx.deleteFrom("_emdash_media_usage_sources").where("source_key", "=", sourceKey).where(this.sourceMatchExpression(expectedSource)).executeTakeFirst();
197
- deleted = Number(result.numDeletedRows ?? 0) > 0;
198
- if (!deleted) return;
199
- await this.deleteSourceGenerationOccurrences(trx, sourceKey, expectedSource.currentGeneration);
200
- });
201
- return {
202
- deleted,
203
- source: await this.findSource(sourceKey)
204
- };
205
- }
206
- async deleteSourceIfMatchingContentAbsent(sourceKey, expectedSource, collectionSlug, contentId) {
207
- validateIdentifier(collectionSlug, "collection slug");
208
- const tableName = `ec_${collectionSlug}`;
209
- let deleted = false;
210
- await withTransaction(this.db, async (trx) => {
211
- const result = await trx.deleteFrom("_emdash_media_usage_sources").where("source_key", "=", sourceKey).where(this.sourceMatchExpression(expectedSource)).where(sql`NOT EXISTS (SELECT 1 FROM ${sql.ref(tableName)} WHERE id = ${contentId})`).executeTakeFirst();
212
- deleted = Number(result.numDeletedRows ?? 0) > 0;
213
- if (!deleted) return;
214
- await this.deleteSourceGenerationOccurrences(trx, sourceKey, expectedSource.currentGeneration);
215
- });
216
- const contentPresent = deleted ? false : await this.contentRowExists(tableName, contentId);
217
- return {
218
- deleted,
219
- contentPresent,
220
- source: deleted || contentPresent ? null : await this.findSource(sourceKey)
221
- };
222
- }
223
- async deleteSources(sourceKeys) {
224
- return this.deleteSourceKeys(sourceKeys);
225
- }
226
- async deleteContentSources(collectionSlug, contentId) {
227
- const sourceKeys = (await this.db.selectFrom("_emdash_media_usage_sources").select("source_key").where("source_type", "=", "content").where("collection_slug", "=", collectionSlug).where("content_id", "=", contentId).execute()).map((row) => row.source_key);
228
- return this.deleteSourceKeys(sourceKeys);
229
- }
230
- async deleteCollectionSources(collectionSlug) {
231
- let deleted = 0;
232
- while (true) {
233
- const sourceRows = await this.db.selectFrom("_emdash_media_usage_sources").select("source_key").where("source_type", "=", "content").where("collection_slug", "=", collectionSlug).orderBy("source_key", "asc").limit(SQL_BATCH_SIZE).execute();
234
- if (sourceRows.length === 0) break;
235
- deleted += await this.deleteSourceKeys(sourceRows.map((row) => row.source_key));
236
- }
237
- return deleted;
238
- }
239
- async findCollectionContentSources(collectionSlug) {
240
- return (await this.db.selectFrom("_emdash_media_usage_sources").selectAll().where("source_type", "=", "content").where("collection_slug", "=", collectionSlug).orderBy("source_key", "asc").execute()).map((row) => rowToSource(row));
241
- }
242
- async deleteOrphanOccurrencesOlderThan(cutoff, limit) {
243
- const batchLimit = Math.floor(limit);
244
- if (batchLimit <= 0) return 0;
245
- const rows = await this.db.selectFrom("_emdash_media_usage as u").leftJoin("_emdash_media_usage_sources as s", (join) => join.onRef("s.source_key", "=", "u.source_key")).select("u.id").where("s.source_key", "is", null).where("u.created_at", "<", cutoff).orderBy("u.created_at", "asc").orderBy("u.id", "asc").limit(batchLimit).execute();
246
- let deleted = 0;
247
- for (const idBatch of chunks(rows.map((row) => row.id), SQL_BATCH_SIZE)) {
248
- const result = await this.db.deleteFrom("_emdash_media_usage").where("id", "in", idBatch).where("created_at", "<", cutoff).where(sql`NOT EXISTS (SELECT 1 FROM _emdash_media_usage_sources s WHERE s.source_key = _emdash_media_usage.source_key)`).executeTakeFirst();
249
- deleted += Number(result.numDeletedRows ?? 0);
250
- }
251
- return deleted;
252
- }
253
- async deleteStaleGenerationsOlderThan(cutoff, limit) {
254
- const batchLimit = Math.floor(limit);
255
- if (batchLimit <= 0) return 0;
256
- const ids = (await this.db.selectFrom("_emdash_media_usage as u").innerJoin("_emdash_media_usage_sources as s", (join) => join.onRef("s.source_key", "=", "u.source_key")).select("u.id").where("u.created_at", "<", cutoff).whereRef("u.generation", "!=", "s.current_generation").whereRef("u.created_at", "<", "s.indexed_at").orderBy("u.created_at", "asc").orderBy("u.id", "asc").limit(batchLimit).execute()).map((row) => row.id);
257
- if (ids.length === 0) return 0;
258
- let deleted = 0;
259
- for (const idBatch of chunks(ids, SQL_BATCH_SIZE)) {
260
- const result = await this.db.deleteFrom("_emdash_media_usage").where("id", "in", idBatch).where("created_at", "<", cutoff).where((eb) => eb.exists(eb.selectFrom("_emdash_media_usage_sources as s").select("s.source_key").whereRef("s.source_key", "=", "_emdash_media_usage.source_key").whereRef("s.current_generation", "!=", "_emdash_media_usage.generation").whereRef("_emdash_media_usage.created_at", "<", "s.indexed_at"))).executeTakeFirst();
261
- deleted += Number(result.numDeletedRows ?? 0);
262
- }
263
- return deleted;
264
- }
265
- async deleteAbandonedGenerationsOlderThan(cutoff, limit) {
266
- const batchLimit = Math.floor(limit);
267
- if (batchLimit <= 0) return 0;
268
- const rows = await this.db.selectFrom("_emdash_media_usage as u").innerJoin("_emdash_media_usage_sources as s", (join) => join.onRef("s.source_key", "=", "u.source_key")).select("u.id").where("u.created_at", "<", cutoff).whereRef("u.generation", "!=", "s.current_generation").whereRef("u.created_at", ">=", "s.indexed_at").orderBy("u.created_at", "asc").orderBy("u.id", "asc").limit(batchLimit).execute();
269
- let deleted = 0;
270
- for (const idBatch of chunks(rows.map((row) => row.id), SQL_BATCH_SIZE)) {
271
- const result = await this.db.deleteFrom("_emdash_media_usage").where("id", "in", idBatch).where("created_at", "<", cutoff).where((eb) => eb.exists(eb.selectFrom("_emdash_media_usage_sources as s").select("s.source_key").whereRef("s.source_key", "=", "_emdash_media_usage.source_key").whereRef("s.current_generation", "!=", "_emdash_media_usage.generation").whereRef("_emdash_media_usage.created_at", ">=", "s.indexed_at"))).executeTakeFirst();
272
- deleted += Number(result.numDeletedRows ?? 0);
273
- }
274
- return deleted;
275
- }
276
- async upsertIndexStatus(input) {
277
- const now = input.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
278
- const row = {
279
- adapter_id: input.adapterId,
280
- scope_type: input.scopeType,
281
- scope_key: input.scopeKey,
282
- status: input.status,
283
- schema_version: input.schemaVersion ?? 1,
284
- started_at: input.startedAt ?? null,
285
- completed_at: input.completedAt ?? null,
286
- cursor: input.cursor ?? null,
287
- indexed_source_count: input.indexedSourceCount ?? 0,
288
- failed_source_count: input.failedSourceCount ?? 0,
289
- last_error_code: input.lastErrorCode ?? null,
290
- updated_at: now
291
- };
292
- await this.db.insertInto("_emdash_media_usage_index_status").values(row).onConflict((oc) => oc.columns([
293
- "adapter_id",
294
- "scope_type",
295
- "scope_key"
296
- ]).doUpdateSet({
297
- status: row.status,
298
- schema_version: row.schema_version,
299
- started_at: row.started_at,
300
- completed_at: row.completed_at,
301
- cursor: row.cursor,
302
- indexed_source_count: row.indexed_source_count,
303
- failed_source_count: row.failed_source_count,
304
- last_error_code: row.last_error_code,
305
- updated_at: row.updated_at
306
- })).execute();
307
- const status = await this.findIndexStatus(input);
308
- if (!status) throw new Error(`Media usage index status ${input.adapterId}:${input.scopeType}:${input.scopeKey} was not persisted`);
309
- return status;
310
- }
311
- async beginIndexStatusRepair(input) {
312
- return this.upsertIndexStatus({
313
- adapterId: input.adapterId,
314
- scopeType: input.scopeType,
315
- scopeKey: input.scopeKey,
316
- status: "running",
317
- schemaVersion: input.schemaVersion,
318
- startedAt: input.startedAt,
319
- completedAt: null,
320
- cursor: input.runToken,
321
- indexedSourceCount: 0,
322
- failedSourceCount: 0,
323
- lastErrorCode: null,
324
- updatedAt: input.updatedAt
325
- });
326
- }
327
- async finalizeIndexStatusRepairIfRunning(input) {
328
- const updates = {
329
- status: input.status,
330
- completed_at: input.completedAt,
331
- cursor: null,
332
- indexed_source_count: input.indexedSourceCount ?? 0,
333
- failed_source_count: input.failedSourceCount ?? 0,
334
- last_error_code: input.lastErrorCode ?? null,
335
- updated_at: input.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString()
336
- };
337
- if (input.schemaVersion !== void 0) updates.schema_version = input.schemaVersion;
338
- const result = await this.db.updateTable("_emdash_media_usage_index_status").set(updates).where("adapter_id", "=", input.adapterId).where("scope_type", "=", input.scopeType).where("scope_key", "=", input.scopeKey).where("status", "=", "running").where("cursor", "=", input.runToken).executeTakeFirst();
339
- return {
340
- finalized: Number(result.numUpdatedRows ?? 0) > 0,
341
- status: await this.findIndexStatus(input)
342
- };
343
- }
344
- async findIndexStatus(identity) {
345
- const row = await this.db.selectFrom("_emdash_media_usage_index_status").selectAll().where("adapter_id", "=", identity.adapterId).where("scope_type", "=", identity.scopeType).where("scope_key", "=", identity.scopeKey).executeTakeFirst();
346
- return row ? rowToIndexStatus(row) : null;
347
- }
348
- async deleteIndexStatus(identity) {
349
- const result = await this.db.deleteFrom("_emdash_media_usage_index_status").where("adapter_id", "=", identity.adapterId).where("scope_type", "=", identity.scopeType).where("scope_key", "=", identity.scopeKey).executeTakeFirst();
350
- return Number(result.numDeletedRows ?? 0);
351
- }
352
- async findCurrentUsagePage(applyFilter, options) {
353
- const limit = Math.min(Math.max(1, options.limit ?? 50), 100);
354
- let query = applyFilter(this.currentUsageBaseQuery()).orderBy("u.id", "asc").limit(limit + 1);
355
- if (options.cursor) {
356
- const { id } = decodeCursor(options.cursor);
357
- query = query.where("u.id", ">", id);
358
- }
359
- const rows = await query.execute();
360
- const items = rows.slice(0, limit).map(rowToUsageRecord);
361
- const result = { items };
362
- if (rows.length > limit && items.length > 0) {
363
- const last = items.at(-1);
364
- result.nextCursor = encodeCursor(last.occurrence.id, last.occurrence.id);
365
- }
366
- return result;
367
- }
368
- currentUsageBaseQuery() {
369
- return this.db.selectFrom("_emdash_media_usage_sources as s").innerJoin("_emdash_media_usage as u", (join) => join.onRef("u.source_key", "=", "s.source_key").onRef("u.generation", "=", "s.current_generation")).select(currentUsageSelect);
370
- }
371
- currentContentMediaUsageBaseQuery() {
372
- return this.db.selectFrom("_emdash_media_usage as u").crossJoin("_emdash_media_usage_sources as s").innerJoin("_emdash_collections as collection", "collection.slug", "s.collection_slug").whereRef("s.source_key", "=", "u.source_key").whereRef("s.current_generation", "=", "u.generation").where("s.source_type", "=", "content").where("s.collection_slug", "is not", null).where("s.content_id", "is not", null).where("s.source_variant", "in", ["columns", "draft_overlay"]).where(CONTENT_SOURCE_ELIGIBILITY);
373
- }
374
- async deleteSourceKeys(sourceKeys) {
375
- const uniqueSourceKeys = [...new Set(sourceKeys)];
376
- if (uniqueSourceKeys.length === 0) return 0;
377
- return withTransaction(this.db, async (trx) => {
378
- let deleted = 0;
379
- for (const sourceKeyBatch of chunks(uniqueSourceKeys, SQL_BATCH_SIZE)) {
380
- const result = await trx.deleteFrom("_emdash_media_usage_sources").where("source_key", "in", sourceKeyBatch).executeTakeFirst();
381
- deleted += Number(result.numDeletedRows ?? 0);
382
- await trx.deleteFrom("_emdash_media_usage").where("source_key", "in", sourceKeyBatch).execute();
383
- }
384
- return deleted;
385
- });
386
- }
387
- async deleteSourceGenerationOccurrences(db, sourceKey, generation) {
388
- await db.deleteFrom("_emdash_media_usage").where("source_key", "=", sourceKey).where("generation", "=", generation).execute();
389
- }
390
- async insertOccurrences(db, sourceKey, generation, occurrences, now) {
391
- if (occurrences.length === 0) return;
392
- const rows = occurrences.map((occurrence) => ({
393
- id: ulid(),
394
- source_key: sourceKey,
395
- generation,
396
- field_slug: occurrence.fieldSlug,
397
- field_path: occurrence.fieldPath,
398
- occurrence_index: occurrence.occurrenceIndex ?? 0,
399
- reference_type: occurrence.referenceType,
400
- media_id: occurrence.mediaId,
401
- provider: occurrence.provider,
402
- provider_asset_id: occurrence.providerAssetId,
403
- media_kind: occurrence.mediaKind ?? null,
404
- mime_type: occurrence.mimeType ?? null,
405
- created_at: now
406
- }));
407
- for (const rowBatch of chunks(rows, OCCURRENCE_INSERT_BATCH_SIZE)) await db.insertInto("_emdash_media_usage").values(rowBatch).execute();
408
- }
409
- async upsertSource(db, source, generation, now) {
410
- const row = this.buildSourceRow(source, generation, now);
411
- await db.insertInto("_emdash_media_usage_sources").values(row).onConflict((oc) => oc.column("source_key").doUpdateSet(this.sourceUpdateSet(row))).execute();
412
- }
413
- async insertSourceIfAbsent(db, row) {
414
- return ((await db.insertInto("_emdash_media_usage_sources").values(row).onConflict((oc) => oc.column("source_key").doNothing()).executeTakeFirst()).numInsertedOrUpdatedRows ?? 0n) > 0n;
415
- }
416
- async updateSourceIfGeneration(db, row, expectedCurrentGeneration) {
417
- const result = await db.updateTable("_emdash_media_usage_sources").set(this.sourceUpdateSet(row)).where("source_key", "=", row.source_key).where("current_generation", "=", expectedCurrentGeneration).executeTakeFirst();
418
- return Number(result.numUpdatedRows ?? 0) > 0;
419
- }
420
- async updateSourceIfMatching(db, row, expectedSource) {
421
- const result = await db.updateTable("_emdash_media_usage_sources").set(this.sourceUpdateSet(row)).where("source_key", "=", row.source_key).where(this.sourceMatchExpression(expectedSource)).executeTakeFirst();
422
- return Number(result.numUpdatedRows ?? 0) > 0;
423
- }
424
- async updateAttemptedSourceIfMatching(db, source, row, expectedSource) {
425
- const result = await db.updateTable("_emdash_media_usage_sources").set(this.attemptedSourceUpdateSet(source, row)).where("source_key", "=", row.source_key).where(this.sourceMatchExpression(expectedSource)).executeTakeFirst();
426
- return Number(result.numUpdatedRows ?? 0) > 0;
427
- }
428
- sourceMatchExpression(expectedSource) {
429
- return (eb) => eb.and([
430
- eb("current_generation", "=", expectedSource.currentGeneration),
431
- eb("source_completeness", "=", expectedSource.sourceCompleteness),
432
- this.nullableStringExpression(eb, "updated_at", expectedSource.updatedAt),
433
- this.nullableStringExpression(eb, "source_fingerprint", expectedSource.sourceFingerprint),
434
- this.nullableStringExpression(eb, "source_updated_at", expectedSource.sourceUpdatedAt),
435
- this.nullableNumberExpression(eb, "source_version", expectedSource.sourceVersion),
436
- this.nullableStringExpression(eb, "revision_id", expectedSource.revisionId),
437
- this.nullableStringExpression(eb, "last_attempted_at", expectedSource.lastAttemptedAt),
438
- this.nullableStringExpression(eb, "last_error_code", expectedSource.lastErrorCode)
439
- ]);
440
- }
441
- nullableStringExpression(eb, column, value) {
442
- return value === null ? eb(column, "is", null) : eb(column, "=", value);
443
- }
444
- nullableNumberExpression(eb, column, value) {
445
- return value === null ? eb(column, "is", null) : eb(column, "=", value);
446
- }
447
- async contentRowExists(tableName, contentId) {
448
- return (await sql`
449
- SELECT id
450
- FROM ${sql.ref(tableName)}
451
- WHERE id = ${contentId}
452
- LIMIT 1
453
- `.execute(this.db)).rows.length > 0;
454
- }
455
- buildSourceRow(source, generation, now) {
456
- return {
457
- source_key: source.sourceKey,
458
- source_type: source.sourceType,
459
- collection_slug: source.collectionSlug ?? null,
460
- content_id: source.contentId ?? null,
461
- source_variant: source.sourceVariant,
462
- locale: source.locale ?? null,
463
- translation_group: source.translationGroup ?? null,
464
- content_slug: source.contentSlug ?? null,
465
- content_title: source.contentTitle ?? null,
466
- content_status: source.contentStatus ?? null,
467
- content_scheduled_at: source.contentScheduledAt ?? null,
468
- content_deleted_at: source.contentDeletedAt ?? null,
469
- revision_id: source.revisionId ?? null,
470
- current_generation: generation,
471
- schema_version: source.schemaVersion ?? 1,
472
- source_updated_at: source.sourceUpdatedAt ?? null,
473
- source_version: source.sourceVersion ?? null,
474
- source_fingerprint: source.sourceFingerprint ?? null,
475
- source_completeness: source.sourceCompleteness ?? "complete",
476
- last_attempted_at: source.lastAttemptedAt ?? now,
477
- last_error_code: null,
478
- indexed_at: now,
479
- updated_at: now
480
- };
481
- }
482
- buildAttemptedSourceRow(source, now) {
483
- return {
484
- source_key: source.sourceKey,
485
- source_type: source.sourceType,
486
- collection_slug: source.collectionSlug ?? null,
487
- content_id: source.contentId ?? null,
488
- source_variant: source.sourceVariant,
489
- locale: source.locale ?? null,
490
- translation_group: source.translationGroup ?? null,
491
- content_slug: source.contentSlug ?? null,
492
- content_title: source.contentTitle ?? null,
493
- content_status: source.contentStatus ?? null,
494
- content_scheduled_at: source.contentScheduledAt ?? null,
495
- content_deleted_at: source.contentDeletedAt ?? null,
496
- revision_id: source.revisionId ?? null,
497
- current_generation: ulid(),
498
- schema_version: source.schemaVersion ?? 1,
499
- source_updated_at: source.sourceUpdatedAt ?? null,
500
- source_version: source.sourceVersion ?? null,
501
- source_fingerprint: source.sourceFingerprint ?? null,
502
- source_completeness: source.sourceCompleteness ?? (source.lastErrorCode ? "failed" : "unknown"),
503
- last_attempted_at: source.lastAttemptedAt ?? now,
504
- last_error_code: source.lastErrorCode ?? null,
505
- indexed_at: now,
506
- updated_at: now
507
- };
508
- }
509
- attemptedSourceUpdateSet(source, row) {
510
- const updates = {
511
- source_type: row.source_type,
512
- source_variant: row.source_variant,
513
- source_completeness: row.source_completeness,
514
- last_attempted_at: row.last_attempted_at,
515
- last_error_code: row.last_error_code,
516
- updated_at: row.updated_at
517
- };
518
- if (source.collectionSlug !== void 0) updates.collection_slug = row.collection_slug;
519
- if (source.contentId !== void 0) updates.content_id = row.content_id;
520
- if (source.locale !== void 0) updates.locale = row.locale;
521
- if (source.translationGroup !== void 0) updates.translation_group = row.translation_group;
522
- if (source.contentSlug !== void 0) updates.content_slug = row.content_slug;
523
- if (source.contentTitle !== void 0) updates.content_title = row.content_title;
524
- if (source.contentStatus !== void 0) updates.content_status = row.content_status;
525
- if (source.contentScheduledAt !== void 0) updates.content_scheduled_at = row.content_scheduled_at;
526
- if (source.contentDeletedAt !== void 0) updates.content_deleted_at = row.content_deleted_at;
527
- if (source.revisionId !== void 0) updates.revision_id = row.revision_id;
528
- if (source.schemaVersion !== void 0) updates.schema_version = row.schema_version;
529
- if (source.sourceUpdatedAt !== void 0) updates.source_updated_at = row.source_updated_at;
530
- if (source.sourceVersion !== void 0) updates.source_version = row.source_version;
531
- if (source.sourceFingerprint !== void 0) updates.source_fingerprint = row.source_fingerprint;
532
- return updates;
533
- }
534
- sourceUpdateSet(row) {
535
- return {
536
- source_type: row.source_type,
537
- collection_slug: row.collection_slug,
538
- content_id: row.content_id,
539
- source_variant: row.source_variant,
540
- locale: row.locale,
541
- translation_group: row.translation_group,
542
- content_slug: row.content_slug,
543
- content_title: row.content_title,
544
- content_status: row.content_status,
545
- content_scheduled_at: row.content_scheduled_at,
546
- content_deleted_at: row.content_deleted_at,
547
- revision_id: row.revision_id,
548
- current_generation: row.current_generation,
549
- schema_version: row.schema_version,
550
- source_updated_at: row.source_updated_at,
551
- source_version: row.source_version,
552
- source_fingerprint: row.source_fingerprint,
553
- source_completeness: row.source_completeness,
554
- last_attempted_at: row.last_attempted_at,
555
- last_error_code: row.last_error_code,
556
- indexed_at: row.indexed_at,
557
- updated_at: row.updated_at
558
- };
559
- }
560
- };
561
- const currentUsageSelect = [
562
- "s.source_key as source_key",
563
- "s.source_type as source_type",
564
- "s.collection_slug as collection_slug",
565
- "s.content_id as content_id",
566
- "s.source_variant as source_variant",
567
- "s.locale as locale",
568
- "s.translation_group as translation_group",
569
- "s.content_slug as content_slug",
570
- "s.content_title as content_title",
571
- "s.content_status as content_status",
572
- "s.content_scheduled_at as content_scheduled_at",
573
- "s.content_deleted_at as content_deleted_at",
574
- "s.revision_id as revision_id",
575
- "s.current_generation as current_generation",
576
- "s.schema_version as schema_version",
577
- "s.source_updated_at as source_updated_at",
578
- "s.source_version as source_version",
579
- "s.source_fingerprint as source_fingerprint",
580
- "s.source_completeness as source_completeness",
581
- "s.last_attempted_at as last_attempted_at",
582
- "s.last_error_code as last_error_code",
583
- "s.indexed_at as indexed_at",
584
- "s.created_at as source_created_at",
585
- "s.updated_at as source_row_updated_at",
586
- "u.id as occurrence_id",
587
- "u.generation as generation",
588
- "u.field_slug as field_slug",
589
- "u.field_path as field_path",
590
- "u.occurrence_index as occurrence_index",
591
- "u.reference_type as reference_type",
592
- "u.media_id as media_id",
593
- "u.provider as provider",
594
- "u.provider_asset_id as provider_asset_id",
595
- "u.media_kind as media_kind",
596
- "u.mime_type as mime_type",
597
- "u.created_at as occurrence_created_at"
598
- ];
599
- function groupUsageRows(rows) {
600
- const groups = [];
601
- for (const row of rows) {
602
- if (row.collection_slug === null || row.content_id === null) continue;
603
- const record = rowToUsageRecord(row);
604
- let group = groups.at(-1);
605
- if (!group || group.collectionSlug !== row.collection_slug || group.contentId !== row.content_id) {
606
- group = {
607
- collectionSlug: row.collection_slug,
608
- contentId: row.content_id,
609
- contentDeletedAt: row.entry_deleted_at,
610
- sources: []
611
- };
612
- groups.push(group);
613
- }
614
- let source = group.sources.at(-1);
615
- if (!source || source.source.sourceKey !== record.source.sourceKey) {
616
- source = {
617
- source: record.source,
618
- occurrences: []
619
- };
620
- group.sources.push(source);
621
- }
622
- source.occurrences.push(record.occurrence);
623
- }
624
- return groups;
625
- }
626
- function rowToSource(row) {
627
- return {
628
- sourceKey: row.source_key,
629
- sourceType: row.source_type,
630
- collectionSlug: row.collection_slug,
631
- contentId: row.content_id,
632
- sourceVariant: row.source_variant,
633
- locale: row.locale,
634
- translationGroup: row.translation_group,
635
- contentSlug: row.content_slug,
636
- contentTitle: row.content_title,
637
- contentStatus: row.content_status,
638
- contentScheduledAt: row.content_scheduled_at,
639
- contentDeletedAt: row.content_deleted_at,
640
- revisionId: row.revision_id,
641
- currentGeneration: row.current_generation,
642
- schemaVersion: Number(row.schema_version),
643
- sourceUpdatedAt: row.source_updated_at,
644
- sourceVersion: row.source_version === null ? null : Number(row.source_version),
645
- sourceFingerprint: row.source_fingerprint,
646
- sourceCompleteness: row.source_completeness,
647
- lastAttemptedAt: row.last_attempted_at,
648
- lastErrorCode: row.last_error_code,
649
- indexedAt: row.indexed_at,
650
- createdAt: row.created_at,
651
- updatedAt: row.updated_at
652
- };
653
- }
654
- function rowToOccurrence(row) {
655
- return {
656
- id: row.id,
657
- sourceKey: row.source_key,
658
- generation: row.generation,
659
- fieldSlug: row.field_slug,
660
- fieldPath: row.field_path,
661
- occurrenceIndex: Number(row.occurrence_index),
662
- referenceType: row.reference_type,
663
- mediaId: row.media_id,
664
- provider: row.provider,
665
- providerAssetId: row.provider_asset_id,
666
- mediaKind: row.media_kind,
667
- mimeType: row.mime_type,
668
- createdAt: row.created_at
669
- };
670
- }
671
- function rowToUsageRecord(row) {
672
- return {
673
- source: rowToSource({
674
- source_key: row.source_key,
675
- source_type: row.source_type,
676
- collection_slug: row.collection_slug,
677
- content_id: row.content_id,
678
- source_variant: row.source_variant,
679
- locale: row.locale,
680
- translation_group: row.translation_group,
681
- content_slug: row.content_slug,
682
- content_title: row.content_title,
683
- content_status: row.content_status,
684
- content_scheduled_at: row.content_scheduled_at,
685
- content_deleted_at: row.content_deleted_at,
686
- revision_id: row.revision_id,
687
- current_generation: row.current_generation,
688
- schema_version: row.schema_version,
689
- source_updated_at: row.source_updated_at,
690
- source_version: row.source_version,
691
- source_fingerprint: row.source_fingerprint,
692
- source_completeness: row.source_completeness,
693
- last_attempted_at: row.last_attempted_at,
694
- last_error_code: row.last_error_code,
695
- indexed_at: row.indexed_at,
696
- created_at: row.source_created_at,
697
- updated_at: row.source_row_updated_at
698
- }),
699
- occurrence: rowToOccurrence({
700
- id: row.occurrence_id,
701
- source_key: row.source_key,
702
- generation: row.generation,
703
- field_slug: row.field_slug,
704
- field_path: row.field_path,
705
- occurrence_index: row.occurrence_index,
706
- reference_type: row.reference_type,
707
- media_id: row.media_id,
708
- provider: row.provider,
709
- provider_asset_id: row.provider_asset_id,
710
- media_kind: row.media_kind,
711
- mime_type: row.mime_type,
712
- created_at: row.occurrence_created_at
713
- })
714
- };
715
- }
716
- function rowToIndexStatus(row) {
717
- return {
718
- adapterId: row.adapter_id,
719
- scopeType: row.scope_type,
720
- scopeKey: row.scope_key,
721
- status: row.status,
722
- schemaVersion: Number(row.schema_version),
723
- startedAt: row.started_at,
724
- completedAt: row.completed_at,
725
- cursor: row.cursor,
726
- indexedSourceCount: Number(row.indexed_source_count),
727
- failedSourceCount: Number(row.failed_source_count),
728
- lastErrorCode: row.last_error_code,
729
- updatedAt: row.updated_at
730
- };
731
- }
732
-
733
- //#endregion
734
- //#region src/media/usage/content-fields.ts
735
- var MediaUsageFieldDiscoveryError = class extends Error {
736
- constructor(message, code) {
737
- super(message);
738
- this.code = code;
739
- this.name = "MediaUsageFieldDiscoveryError";
740
- }
741
- };
742
- const DISPLAY_FIELD_SLUGS = ["title", "name"];
743
- const SUPPORTED_TOP_LEVEL_TYPES = [
744
- "file",
745
- "image",
746
- "portableText"
747
- ];
748
- async function loadContentMediaUsageFields(db, collectionSlug) {
749
- validateIdentifier(collectionSlug, "collection slug");
750
- const rows = await db.selectFrom("_emdash_fields").innerJoin("_emdash_collections", "_emdash_collections.id", "_emdash_fields.collection_id").select([
751
- "_emdash_fields.slug",
752
- "_emdash_fields.type",
753
- "_emdash_fields.validation"
754
- ]).where("_emdash_collections.slug", "=", collectionSlug).execute();
755
- const extractionFields = [];
756
- const rowBySlug = /* @__PURE__ */ new Map();
757
- for (const row of rows) {
758
- rowBySlug.set(row.slug, row);
759
- if (isSupportedTopLevelType(row.type)) {
760
- validateIdentifier(row.slug, "media usage field slug");
761
- extractionFields.push({
762
- slug: row.slug,
763
- type: row.type
764
- });
765
- continue;
766
- }
767
- if (row.type === "repeater") {
768
- validateIdentifier(row.slug, "media usage field slug");
769
- const subFields = normalizeRepeaterImageSubFields(row.validation);
770
- if (subFields.length > 0) extractionFields.push({
771
- slug: row.slug,
772
- type: "repeater",
773
- validation: { subFields }
774
- });
775
- }
776
- }
777
- extractionFields.sort((a, b) => a.slug.localeCompare(b.slug));
778
- return {
779
- extractionFields,
780
- displayFieldSlugs: DISPLAY_FIELD_SLUGS.filter((slug) => {
781
- if (!rowBySlug.has(slug)) return false;
782
- validateIdentifier(slug, "media usage display field slug");
783
- return true;
784
- })
785
- };
786
- }
787
- function normalizeRepeaterImageSubFields(rawValidation) {
788
- const validation = parseValidation(rawValidation);
789
- if (!isRecord$2(validation) || !Array.isArray(validation.subFields)) return [];
790
- const subFields = [];
791
- for (const subField of validation.subFields) {
792
- if (!isRecord$2(subField) || subField.type !== "image") continue;
793
- if (typeof subField.slug !== "string") continue;
794
- validateIdentifier(subField.slug, "media usage repeater sub-field slug");
795
- subFields.push({
796
- slug: subField.slug,
797
- type: "image"
798
- });
799
- }
800
- return subFields.toSorted((a, b) => a.slug.localeCompare(b.slug));
801
- }
802
- function parseValidation(rawValidation) {
803
- if (!rawValidation) return null;
804
- try {
805
- return JSON.parse(rawValidation);
806
- } catch {
807
- throw new MediaUsageFieldDiscoveryError("Repeater field validation must be valid JSON before media usage can be discovered", "INVALID_REPEATER_VALIDATION");
808
- }
809
- }
810
- function isSupportedTopLevelType(value) {
811
- return SUPPORTED_TOP_LEVEL_TYPES.includes(value);
812
- }
813
- function isRecord$2(value) {
814
- return typeof value === "object" && value !== null && !Array.isArray(value);
815
- }
816
-
817
- //#endregion
818
- //#region src/media/usage/extractor.ts
819
- const URL_LIKE_RE = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
820
- function extractMediaUsageOccurrences({ fields, data }) {
821
- const occurrences = [];
822
- const seen = /* @__PURE__ */ new Set();
823
- for (const field of fields) {
824
- const value = data[field.slug];
825
- if (field.type === "image") {
826
- addOccurrence(occurrences, seen, {
827
- fieldSlug: field.slug,
828
- fieldPath: field.slug,
829
- referenceType: "image_field",
830
- value,
831
- fallbackKind: "image"
832
- });
833
- continue;
834
- }
835
- if (field.type === "file") {
836
- addOccurrence(occurrences, seen, {
837
- fieldSlug: field.slug,
838
- fieldPath: field.slug,
839
- referenceType: "file_field",
840
- value,
841
- fallbackKind: null
842
- });
843
- continue;
844
- }
845
- if (field.type === "repeater") {
846
- extractRepeaterOccurrences(occurrences, seen, field.slug, value, field.validation?.subFields);
847
- continue;
848
- }
849
- if (field.type === "portableText") extractPortableTextOccurrences(occurrences, seen, field.slug, value);
850
- }
851
- return occurrences;
852
- }
853
- function extractRepeaterOccurrences(occurrences, seen, fieldSlug, value, subFields) {
854
- if (!Array.isArray(value) || !Array.isArray(subFields)) return;
855
- for (const [itemIndex, item] of value.entries()) {
856
- if (!isRecord$1(item)) continue;
857
- for (const subField of subFields) {
858
- if (subField.type !== "image") continue;
859
- addOccurrence(occurrences, seen, {
860
- fieldSlug,
861
- fieldPath: `${fieldSlug}[${itemIndex}].${subField.slug}`,
862
- referenceType: "image_field",
863
- value: item[subField.slug],
864
- fallbackKind: "image"
865
- });
866
- }
867
- }
868
- }
869
- function extractPortableTextOccurrences(occurrences, seen, fieldSlug, value) {
870
- if (!Array.isArray(value)) return;
871
- for (const [blockIndex, block] of value.entries()) {
872
- if (!isRecord$1(block) || block._type !== "image" || !isRecord$1(block.asset)) continue;
873
- const provider = normalizeProvider(block.asset.provider);
874
- const ref = readPortableTextAssetRef(block.asset, provider);
875
- if (!ref) continue;
876
- addRefOccurrence(occurrences, seen, {
877
- fieldSlug,
878
- fieldPath: `${fieldSlug}[${blockIndex}].asset.${ref.key}`,
879
- referenceType: "portable_text_image",
880
- ref: buildMediaRef({
881
- id: ref.id,
882
- provider,
883
- mimeType: normalizeMimeValue(block.asset.mimeType),
884
- fallbackKind: "image"
885
- })
886
- });
887
- }
888
- }
889
- function addOccurrence(occurrences, seen, input) {
890
- const ref = readMediaRef(input.value, input.fallbackKind);
891
- if (!ref) return;
892
- addRefOccurrence(occurrences, seen, {
893
- fieldSlug: input.fieldSlug,
894
- fieldPath: input.fieldPath,
895
- referenceType: input.referenceType,
896
- ref
897
- });
898
- }
899
- function addRefOccurrence(occurrences, seen, input) {
900
- if (!input.ref) return;
901
- const occurrence = {
902
- fieldSlug: input.fieldSlug,
903
- fieldPath: input.fieldPath,
904
- occurrenceIndex: 0,
905
- referenceType: input.referenceType,
906
- mediaId: input.ref.mediaId,
907
- provider: input.ref.provider,
908
- providerAssetId: input.ref.providerAssetId,
909
- mediaKind: input.ref.mediaKind,
910
- mimeType: input.ref.mimeType
911
- };
912
- const key = [
913
- occurrence.fieldSlug,
914
- occurrence.fieldPath,
915
- occurrence.occurrenceIndex,
916
- occurrence.referenceType,
917
- occurrence.provider,
918
- occurrence.providerAssetId,
919
- occurrence.mediaId ?? ""
920
- ].join("\0");
921
- if (seen.has(key)) return;
922
- seen.add(key);
923
- occurrences.push(occurrence);
924
- }
925
- function readMediaRef(value, fallbackKind) {
926
- if (typeof value === "string") {
927
- const id = normalizeLocalMediaId(value);
928
- return id ? buildMediaRef({
929
- id,
930
- provider: "local",
931
- mimeType: null,
932
- fallbackKind
933
- }) : null;
934
- }
935
- if (!isRecord$1(value)) return null;
936
- const provider = normalizeProvider(value.provider);
937
- const id = provider === "local" ? normalizeLocalMediaId(value.id) : normalizeStableId(value.id);
938
- if (!id) return null;
939
- return buildMediaRef({
940
- id,
941
- provider,
942
- mimeType: normalizeMimeValue(value.mimeType),
943
- fallbackKind
944
- });
945
- }
946
- function buildMediaRef(input) {
947
- const provider = normalizeProvider(input.provider);
948
- if (provider === "external") return null;
949
- return {
950
- mediaId: provider === "local" ? input.id : null,
951
- provider,
952
- providerAssetId: input.id,
953
- mediaKind: mediaKindFromMime(input.mimeType) ?? input.fallbackKind,
954
- mimeType: input.mimeType
955
- };
956
- }
957
- function readPortableTextAssetRef(asset, provider) {
958
- const normalizeId = provider === "local" ? normalizeLocalMediaId : normalizeStableId;
959
- const ref = normalizeId(asset._ref);
960
- if (ref) return {
961
- key: "_ref",
962
- id: ref
963
- };
964
- const id = normalizeId(asset.id);
965
- if (id) return {
966
- key: "id",
967
- id
968
- };
969
- return null;
970
- }
971
- function normalizeProvider(value) {
972
- return readString$1(value)?.trim() || "local";
973
- }
974
- function normalizeLocalMediaId(value) {
975
- const id = normalizeStableId(value);
976
- if (!id) return null;
977
- return id.includes("/") ? null : id;
978
- }
979
- function normalizeStableId(value) {
980
- if (typeof value !== "string") return null;
981
- const trimmed = value.trim();
982
- if (!trimmed) return null;
983
- if (URL_LIKE_RE.test(trimmed)) return null;
984
- if (trimmed.startsWith(INTERNAL_MEDIA_PREFIX)) return null;
985
- return trimmed;
986
- }
987
- function normalizeMimeValue(value) {
988
- if (typeof value !== "string") return null;
989
- const normalized = normalizeMime(value);
990
- return normalized.includes("/") ? normalized : null;
991
- }
992
- function mediaKindFromMime(mimeType) {
993
- if (!mimeType) return null;
994
- if (mimeType.startsWith("image/")) return "image";
995
- if (mimeType.startsWith("video/")) return "video";
996
- if (mimeType.startsWith("audio/")) return "audio";
997
- if (mimeType.startsWith("font/") || mimeType.startsWith("application/font-")) return "font";
998
- if (mimeType.startsWith("text/")) return "text";
999
- if (isDocumentMime(mimeType)) return "document";
1000
- if (isArchiveMime(mimeType)) return "archive";
1001
- return "other";
1002
- }
1003
- function isDocumentMime(mimeType) {
1004
- return mimeType === "application/pdf" || mimeType === "application/msword" || mimeType === "application/rtf" || mimeType === "application/vnd.ms-excel" || mimeType === "application/vnd.ms-powerpoint" || mimeType.startsWith("application/vnd.openxmlformats-officedocument.");
1005
- }
1006
- function isArchiveMime(mimeType) {
1007
- return mimeType === "application/zip" || mimeType === "application/gzip" || mimeType === "application/x-tar" || mimeType === "application/x-7z-compressed" || mimeType === "application/x-rar-compressed" || mimeType === "application/vnd.rar";
1008
- }
1009
- function readString$1(value) {
1010
- return typeof value === "string" ? value : null;
1011
- }
1012
- function isRecord$1(value) {
1013
- return typeof value === "object" && value !== null && !Array.isArray(value);
1014
- }
1015
-
1016
- //#endregion
1017
- //#region src/media/usage/source-key.ts
1018
- const MEDIA_USAGE_CONTENT_SOURCE_VARIANTS = ["columns", "draft_overlay"];
1019
- function buildContentMediaUsageSourceKey(input) {
1020
- return `content:${input.collectionSlug}:${input.contentId}:${input.sourceVariant}`;
1021
- }
1022
-
1023
- //#endregion
1024
- //#region src/media/usage/content-snapshots.ts
1025
- const CONTENT_SOURCE_SCHEMA_VERSION = 1;
1026
- const CONTENT_SYSTEM_COLUMNS = [
1027
- "id",
1028
- "slug",
1029
- "status",
1030
- "created_at",
1031
- "updated_at",
1032
- "published_at",
1033
- "scheduled_at",
1034
- "deleted_at",
1035
- "version",
1036
- "live_revision_id",
1037
- "draft_revision_id",
1038
- "locale",
1039
- "translation_group"
1040
- ];
1041
- async function loadContentMediaUsageSnapshots(db, collectionSlug, contentId, fieldDiscovery) {
1042
- validateIdentifier(collectionSlug, "collection slug");
1043
- const discovery = fieldDiscovery ?? await loadContentMediaUsageFields(db, collectionSlug);
1044
- const row = await loadContentRow(db, collectionSlug, contentId, [...discovery.extractionFields.map((field) => field.slug), ...discovery.displayFieldSlugs]);
1045
- if (!row) return {
1046
- success: false,
1047
- error: "CONTENT_NOT_FOUND"
1048
- };
1049
- const columnsData = projectData(row, discovery.extractionFields.map((field) => field.slug));
1050
- const displayData = projectRawData(row, discovery.displayFieldSlugs);
1051
- const occurrences = extractMediaUsageOccurrences({
1052
- fields: discovery.extractionFields,
1053
- data: columnsData
1054
- });
1055
- const columnsRevisionId = readNullableString(row.live_revision_id);
1056
- const snapshots = [{
1057
- source: buildContentSource({
1058
- collectionSlug,
1059
- row,
1060
- displayData,
1061
- sourceVariant: "columns",
1062
- revisionId: columnsRevisionId,
1063
- sourceFingerprint: await buildSourceFingerprint({
1064
- collectionSlug,
1065
- sourceVariant: "columns",
1066
- revisionId: columnsRevisionId,
1067
- fields: discovery.extractionFields,
1068
- data: columnsData
1069
- })
1070
- }),
1071
- occurrences,
1072
- fields: discovery.extractionFields
1073
- }];
1074
- const draftRevisionId = readNullableString(row.draft_revision_id);
1075
- if (draftRevisionId) {
1076
- const attemptedDraftSource = buildContentSource({
1077
- collectionSlug,
1078
- row,
1079
- displayData,
1080
- sourceVariant: "draft_overlay",
1081
- revisionId: draftRevisionId
1082
- });
1083
- const revisionResult = await loadRevisionRow(db, draftRevisionId);
1084
- if (!revisionResult) return {
1085
- success: false,
1086
- error: "DRAFT_REVISION_NOT_FOUND",
1087
- source: attemptedDraftSource,
1088
- snapshots
1089
- };
1090
- if (!revisionResult.success) return {
1091
- success: false,
1092
- error: "DRAFT_REVISION_INVALID",
1093
- source: attemptedDraftSource,
1094
- snapshots
1095
- };
1096
- const revision = revisionResult.revision;
1097
- if (revision.collection !== collectionSlug || revision.entryId !== row.id) return {
1098
- success: false,
1099
- error: "DRAFT_REVISION_MISMATCH",
1100
- source: attemptedDraftSource,
1101
- snapshots
1102
- };
1103
- const revisionData = stripRevisionMetadata(revision.data);
1104
- const draftOverlayData = {
1105
- ...columnsData,
1106
- ...revisionData
1107
- };
1108
- const draftDisplayData = {
1109
- ...displayData,
1110
- ...projectPresentData(revisionData, discovery.displayFieldSlugs)
1111
- };
1112
- const draftContentSlug = readNullableString(revision.data._slug) ?? readNullableString(row.slug);
1113
- const draftFingerprint = await buildSourceFingerprint({
1114
- collectionSlug,
1115
- sourceVariant: "draft_overlay",
1116
- revisionId: draftRevisionId,
1117
- fields: discovery.extractionFields,
1118
- data: draftOverlayData
1119
- });
1120
- snapshots.push({
1121
- source: buildContentSource({
1122
- collectionSlug,
1123
- row,
1124
- displayData: draftDisplayData,
1125
- sourceVariant: "draft_overlay",
1126
- revisionId: draftRevisionId,
1127
- contentSlug: draftContentSlug,
1128
- sourceFingerprint: draftFingerprint
1129
- }),
1130
- occurrences: extractMediaUsageOccurrences({
1131
- fields: discovery.extractionFields,
1132
- data: draftOverlayData
1133
- }),
1134
- fields: discovery.extractionFields
1135
- });
1136
- }
1137
- return {
1138
- success: true,
1139
- snapshots
1140
- };
1141
- }
1142
- async function loadContentRow(db, collectionSlug, contentId, fieldSlugs) {
1143
- const tableName = getContentTableName(collectionSlug);
1144
- const columnRefs = uniqueColumns([...CONTENT_SYSTEM_COLUMNS, ...fieldSlugs]).map((column) => sql.ref(column));
1145
- return (await sql`
1146
- SELECT ${sql.join(columnRefs, sql`, `)}
1147
- FROM ${sql.ref(tableName)}
1148
- WHERE id = ${contentId}
1149
- LIMIT 1
1150
- `.execute(db)).rows[0] ?? null;
1151
- }
1152
- async function loadRevisionRow(db, revisionId) {
1153
- const row = await db.selectFrom("revisions").select([
1154
- "id",
1155
- "collection",
1156
- "entry_id",
1157
- "data"
1158
- ]).where("id", "=", revisionId).executeTakeFirst();
1159
- if (!row) return null;
1160
- const data = parseRevisionData(row.data);
1161
- if (!data) return { success: false };
1162
- return {
1163
- success: true,
1164
- revision: {
1165
- id: row.id,
1166
- collection: row.collection,
1167
- entryId: row.entry_id,
1168
- data
1169
- }
1170
- };
1171
- }
1172
- function buildContentSource(input) {
1173
- const { collectionSlug, row, displayData, sourceVariant, revisionId } = input;
1174
- const contentId = readString(row.id) ?? "";
1175
- const contentSlug = input.contentSlug ?? readNullableString(row.slug);
1176
- const source = {
1177
- sourceKey: buildContentMediaUsageSourceKey({
1178
- collectionSlug,
1179
- contentId,
1180
- sourceVariant
1181
- }),
1182
- sourceType: "content",
1183
- collectionSlug,
1184
- contentId,
1185
- sourceVariant,
1186
- locale: readNullableString(row.locale),
1187
- translationGroup: readNullableString(row.translation_group),
1188
- contentSlug,
1189
- contentTitle: deriveContentTitle(displayData, contentSlug, contentId),
1190
- contentStatus: readNullableString(row.status),
1191
- contentScheduledAt: readNullableString(row.scheduled_at),
1192
- contentDeletedAt: readNullableString(row.deleted_at),
1193
- revisionId,
1194
- schemaVersion: CONTENT_SOURCE_SCHEMA_VERSION,
1195
- sourceUpdatedAt: readNullableString(row.updated_at),
1196
- sourceVersion: readNumber(row.version)
1197
- };
1198
- if (input.sourceFingerprint !== void 0) source.sourceFingerprint = input.sourceFingerprint;
1199
- return source;
1200
- }
1201
- async function buildSourceFingerprint(input) {
1202
- return hashString(canonicalJson({
1203
- schemaVersion: CONTENT_SOURCE_SCHEMA_VERSION,
1204
- collectionSlug: input.collectionSlug,
1205
- sourceVariant: input.sourceVariant,
1206
- fields: normalizeFingerprintFields(input.fields),
1207
- values: projectFingerprintData(input.data, input.fields),
1208
- revisionId: input.sourceVariant === "draft_overlay" ? input.revisionId : null
1209
- }));
1210
- }
1211
- function normalizeFingerprintFields(fields) {
1212
- return fields.map((field) => {
1213
- if (field.type !== "repeater") return {
1214
- slug: field.slug,
1215
- type: field.type
1216
- };
1217
- return {
1218
- slug: field.slug,
1219
- type: field.type,
1220
- subFields: (field.validation?.subFields ?? []).map((subField) => ({
1221
- slug: subField.slug,
1222
- type: subField.type
1223
- })).toSorted((a, b) => a.slug.localeCompare(b.slug))
1224
- };
1225
- }).toSorted((a, b) => String(a.slug).localeCompare(String(b.slug)));
1226
- }
1227
- function projectFingerprintData(data, fields) {
1228
- const projected = {};
1229
- for (const field of fields) projected[field.slug] = Object.hasOwn(data, field.slug) ? data[field.slug] : null;
1230
- return projected;
1231
- }
1232
- function canonicalJson(value) {
1233
- return JSON.stringify(canonicalize(value));
1234
- }
1235
- function canonicalize(value) {
1236
- if (value === void 0) return null;
1237
- if (typeof value === "bigint") return value.toString();
1238
- if (typeof value === "number") return Number.isFinite(value) ? value : null;
1239
- if (Array.isArray(value)) return value.map((item) => canonicalize(item));
1240
- if (!isRecord(value)) return value;
1241
- const canonical = {};
1242
- for (const key of Object.keys(value).toSorted()) canonical[key] = canonicalize(value[key]);
1243
- return canonical;
1244
- }
1245
- function projectData(row, fieldSlugs) {
1246
- const data = {};
1247
- for (const fieldSlug of fieldSlugs) data[fieldSlug] = deserializeValue(row[fieldSlug] ?? null);
1248
- return data;
1249
- }
1250
- function projectRawData(row, fieldSlugs) {
1251
- const data = {};
1252
- for (const fieldSlug of fieldSlugs) data[fieldSlug] = row[fieldSlug] ?? null;
1253
- return data;
1254
- }
1255
- function projectPresentData(row, fieldSlugs) {
1256
- const data = {};
1257
- for (const fieldSlug of fieldSlugs) if (Object.hasOwn(row, fieldSlug)) data[fieldSlug] = row[fieldSlug];
1258
- return data;
1259
- }
1260
- function uniqueColumns(columns) {
1261
- const unique = [...new Set(columns)];
1262
- for (const column of unique) validateIdentifier(column, "content media usage column");
1263
- return unique;
1264
- }
1265
- function getContentTableName(collectionSlug) {
1266
- validateIdentifier(collectionSlug, "collection slug");
1267
- return `ec_${collectionSlug}`;
1268
- }
1269
- function deserializeValue(value) {
1270
- if (typeof value === "string" && (value.startsWith("{") || value.startsWith("["))) try {
1271
- return JSON.parse(value);
1272
- } catch {
1273
- return value;
1274
- }
1275
- return value;
1276
- }
1277
- function parseRevisionData(value) {
1278
- if (typeof value === "string") try {
1279
- const parsed = JSON.parse(value);
1280
- return isRecord(parsed) ? parsed : null;
1281
- } catch {
1282
- return null;
1283
- }
1284
- return isRecord(value) ? value : null;
1285
- }
1286
- function stripRevisionMetadata(data) {
1287
- const stripped = {};
1288
- for (const [key, value] of Object.entries(data)) if (!key.startsWith("_")) stripped[key] = value;
1289
- return stripped;
1290
- }
1291
- function deriveContentTitle(displayData, contentSlug, contentId) {
1292
- for (const fieldSlug of ["title", "name"]) {
1293
- const value = displayData[fieldSlug];
1294
- if (typeof value === "string" && value.trim()) return value;
1295
- }
1296
- return contentSlug ?? contentId;
1297
- }
1298
- function readString(value) {
1299
- return typeof value === "string" ? value : null;
1300
- }
1301
- function readNullableString(value) {
1302
- return value === null || value === void 0 ? null : readString(value);
1303
- }
1304
- function readNumber(value) {
1305
- if (typeof value === "number" && Number.isFinite(value)) return value;
1306
- if (typeof value === "bigint") return Number(value);
1307
- if (typeof value === "string" && value) {
1308
- const parsed = Number(value);
1309
- return Number.isFinite(parsed) ? parsed : null;
1310
- }
1311
- return null;
1312
- }
1313
- function isRecord(value) {
1314
- return typeof value === "object" && value !== null && !Array.isArray(value);
1315
- }
1316
-
1317
- //#endregion
1318
- //#region src/media/usage/content-refresh.ts
1319
- const CONTENT_MEDIA_USAGE_ADAPTER_ID = "content-media";
1320
- const CONTENT_MEDIA_USAGE_COLLECTION_SCOPE = "collection";
1321
- const CONTENT_USAGE_LOCKS_KEY = Symbol.for("emdash.mediaUsage.contentLocks");
1322
- const CONTENT_USAGE_COLLECTION_LOCKS_KEY = Symbol.for("emdash.mediaUsage.collectionLocks");
1323
- const CONTENT_USAGE_REFRESH_MAX_ATTEMPTS = 2;
1324
- const ZERO_RESULT = {
1325
- success: true,
1326
- refreshedSourceCount: 0,
1327
- deletedSourceCount: 0,
1328
- failedSourceCount: 0
1329
- };
1330
- async function refreshContentMediaUsage(db, collectionSlug, contentId) {
1331
- validateIdentifier(collectionSlug, "collection slug");
1332
- return withContentUsageCollectionLock(collectionSlug, () => withContentUsageLock(collectionSlug, contentId, () => refreshContentMediaUsageUnlocked(db, collectionSlug, contentId)));
1333
- }
1334
- async function refreshContentMediaUsageUnlocked(db, collectionSlug, contentId) {
1335
- try {
1336
- let conflictResult = null;
1337
- for (let attempt = 0; attempt < CONTENT_USAGE_REFRESH_MAX_ATTEMPTS; attempt++) {
1338
- const result = await refreshContentMediaUsageAttempt(db, collectionSlug, contentId);
1339
- if (result.errorCode !== "CONTENT_USAGE_GENERATION_CONFLICT") return result;
1340
- conflictResult = result;
1341
- }
1342
- return markGenerationConflict(db, collectionSlug, {
1343
- refreshedSourceCount: conflictResult?.refreshedSourceCount ?? 0,
1344
- deletedSourceCount: conflictResult?.deletedSourceCount ?? 0
1345
- });
1346
- } catch (error) {
1347
- console.error(`[media-usage] Failed to refresh ${collectionSlug}/${contentId}:`, error);
1348
- await markContentMediaUsageCollectionStaleSafely(db, collectionSlug, "CONTENT_USAGE_REFRESH_ERROR");
1349
- return {
1350
- success: false,
1351
- refreshedSourceCount: 0,
1352
- deletedSourceCount: 0,
1353
- failedSourceCount: 0,
1354
- errorCode: "CONTENT_USAGE_REFRESH_ERROR"
1355
- };
1356
- }
1357
- }
1358
- async function refreshContentMediaUsageAttempt(db, collectionSlug, contentId) {
1359
- const repo = new MediaUsageRepository(db);
1360
- const observedGenerations = await loadObservedContentSourceGenerations(db, collectionSlug, contentId);
1361
- const snapshotsResult = await loadContentMediaUsageSnapshots(db, collectionSlug, contentId);
1362
- if (!snapshotsResult.success) return markSnapshotFailure(db, collectionSlug, snapshotsResult);
1363
- if (!await contentCollectionExists(db, collectionSlug)) {
1364
- const deletedSourceCount = await repo.deleteContentSources(collectionSlug, contentId);
1365
- return {
1366
- ...ZERO_RESULT,
1367
- deletedSourceCount
1368
- };
1369
- }
1370
- let refreshedSourceCount = 0;
1371
- for (const snapshot of snapshotsResult.snapshots) {
1372
- if (!(await repo.replaceSourceIfCurrent(snapshot.source, snapshot.occurrences, observedGenerations.get(snapshot.source.sourceKey) ?? null)).replaced) return generationConflictResult({
1373
- refreshedSourceCount,
1374
- deletedSourceCount: 0
1375
- });
1376
- refreshedSourceCount++;
1377
- }
1378
- if (!await contentCollectionExists(db, collectionSlug)) {
1379
- const deletedSourceCount = await repo.deleteContentSources(collectionSlug, contentId);
1380
- return {
1381
- ...ZERO_RESULT,
1382
- deletedSourceCount
1383
- };
1384
- }
1385
- const expectedSourceKeys = new Set(snapshotsResult.snapshots.map((snapshot) => snapshot.source.sourceKey));
1386
- const absentSourceKeys = MEDIA_USAGE_CONTENT_SOURCE_VARIANTS.map((sourceVariant) => buildContentMediaUsageSourceKey({
1387
- collectionSlug,
1388
- contentId,
1389
- sourceVariant
1390
- })).filter((sourceKey) => !expectedSourceKeys.has(sourceKey));
1391
- let deletedSourceCount = 0;
1392
- for (const sourceKey of absentSourceKeys) {
1393
- const expectedGeneration = observedGenerations.get(sourceKey) ?? null;
1394
- if (expectedGeneration === null) continue;
1395
- const result = await repo.deleteSourceIfCurrent(sourceKey, expectedGeneration);
1396
- if (result.deleted) {
1397
- deletedSourceCount++;
1398
- continue;
1399
- }
1400
- if (result.source) return generationConflictResult({
1401
- refreshedSourceCount,
1402
- deletedSourceCount
1403
- });
1404
- }
1405
- return {
1406
- success: true,
1407
- refreshedSourceCount,
1408
- deletedSourceCount,
1409
- failedSourceCount: 0
1410
- };
1411
- }
1412
- async function loadObservedContentSourceGenerations(db, collectionSlug, contentId) {
1413
- const generations = /* @__PURE__ */ new Map();
1414
- const sourceKeys = MEDIA_USAGE_CONTENT_SOURCE_VARIANTS.map((sourceVariant) => buildContentMediaUsageSourceKey({
1415
- collectionSlug,
1416
- contentId,
1417
- sourceVariant
1418
- }));
1419
- for (const sourceKey of sourceKeys) generations.set(sourceKey, null);
1420
- const rows = await db.selectFrom("_emdash_media_usage_sources").select(["source_key", "current_generation"]).where("source_key", "in", sourceKeys).execute();
1421
- for (const row of rows) generations.set(row.source_key, row.current_generation);
1422
- return generations;
1423
- }
1424
- async function markGenerationConflict(db, collectionSlug, counts) {
1425
- await markContentMediaUsageCollectionStaleSafely(db, collectionSlug, "CONTENT_USAGE_GENERATION_CONFLICT");
1426
- return {
1427
- success: false,
1428
- refreshedSourceCount: counts.refreshedSourceCount,
1429
- deletedSourceCount: counts.deletedSourceCount,
1430
- failedSourceCount: 0,
1431
- errorCode: "CONTENT_USAGE_GENERATION_CONFLICT"
1432
- };
1433
- }
1434
- function generationConflictResult(counts) {
1435
- return {
1436
- success: false,
1437
- refreshedSourceCount: counts.refreshedSourceCount,
1438
- deletedSourceCount: counts.deletedSourceCount,
1439
- failedSourceCount: 0,
1440
- errorCode: "CONTENT_USAGE_GENERATION_CONFLICT"
1441
- };
1442
- }
1443
- async function contentCollectionExists(db, collectionSlug) {
1444
- return await db.selectFrom("_emdash_collections").select("id").where("slug", "=", collectionSlug).executeTakeFirst() !== void 0;
1445
- }
1446
- async function deleteContentMediaUsage(db, collectionSlug, contentId) {
1447
- validateIdentifier(collectionSlug, "collection slug");
1448
- return withContentUsageCollectionLock(collectionSlug, () => withContentUsageLock(collectionSlug, contentId, () => deleteContentMediaUsageUnlocked(db, collectionSlug, contentId)));
1449
- }
1450
- async function deleteContentMediaUsageUnlocked(db, collectionSlug, contentId) {
1451
- try {
1452
- const deletedSourceCount = await new MediaUsageRepository(db).deleteContentSources(collectionSlug, contentId);
1453
- return {
1454
- ...ZERO_RESULT,
1455
- deletedSourceCount
1456
- };
1457
- } catch (error) {
1458
- console.error(`[media-usage] Failed to delete usage for ${collectionSlug}/${contentId}:`, error);
1459
- await markContentMediaUsageCollectionStaleSafely(db, collectionSlug, "CONTENT_USAGE_DELETE_ERROR");
1460
- return {
1461
- success: false,
1462
- refreshedSourceCount: 0,
1463
- deletedSourceCount: 0,
1464
- failedSourceCount: 0,
1465
- errorCode: "CONTENT_USAGE_DELETE_ERROR"
1466
- };
1467
- }
1468
- }
1469
- async function deleteContentMediaUsageCollection(db, collectionSlug) {
1470
- validateIdentifier(collectionSlug, "collection slug");
1471
- return withContentUsageCollectionLock(collectionSlug, () => deleteContentMediaUsageCollectionUnlocked(db, collectionSlug));
1472
- }
1473
- async function deleteContentMediaUsageCollectionUnlocked(db, collectionSlug) {
1474
- try {
1475
- const repo = new MediaUsageRepository(db);
1476
- const deletedSourceCount = await repo.deleteCollectionSources(collectionSlug);
1477
- await repo.deleteIndexStatus({
1478
- adapterId: CONTENT_MEDIA_USAGE_ADAPTER_ID,
1479
- scopeType: CONTENT_MEDIA_USAGE_COLLECTION_SCOPE,
1480
- scopeKey: collectionSlug
1481
- });
1482
- return {
1483
- ...ZERO_RESULT,
1484
- deletedSourceCount
1485
- };
1486
- } catch (error) {
1487
- console.error(`[media-usage] Failed to delete usage for collection ${collectionSlug}:`, error);
1488
- try {
1489
- await new MediaUsageRepository(db).deleteIndexStatus({
1490
- adapterId: CONTENT_MEDIA_USAGE_ADAPTER_ID,
1491
- scopeType: CONTENT_MEDIA_USAGE_COLLECTION_SCOPE,
1492
- scopeKey: collectionSlug
1493
- });
1494
- } catch (statusError) {
1495
- console.error(`[media-usage] Failed to clear usage status for deleted collection ${collectionSlug}:`, statusError);
1496
- }
1497
- return {
1498
- success: false,
1499
- refreshedSourceCount: 0,
1500
- deletedSourceCount: 0,
1501
- failedSourceCount: 0,
1502
- errorCode: "CONTENT_USAGE_DELETE_ERROR"
1503
- };
1504
- }
1505
- }
1506
- async function refreshContentMediaUsageAfterWrite(db, collectionSlug, contentId) {
1507
- const result = await refreshContentMediaUsage(db, collectionSlug, contentId);
1508
- if (!result.success) console.error(`[media-usage] Usage refresh for ${collectionSlug}/${contentId} finished with ${result.errorCode}`);
1509
- }
1510
- async function markContentMediaUsageCollectionStale(db, collectionSlug, lastErrorCode) {
1511
- validateIdentifier(collectionSlug, "collection slug");
1512
- const repo = new MediaUsageRepository(db);
1513
- const identity = {
1514
- adapterId: CONTENT_MEDIA_USAGE_ADAPTER_ID,
1515
- scopeType: CONTENT_MEDIA_USAGE_COLLECTION_SCOPE,
1516
- scopeKey: collectionSlug
1517
- };
1518
- const existing = await repo.findIndexStatus(identity);
1519
- await repo.upsertIndexStatus({
1520
- ...identity,
1521
- status: "stale",
1522
- schemaVersion: existing?.schemaVersion ?? CONTENT_SOURCE_SCHEMA_VERSION,
1523
- startedAt: existing?.startedAt ?? null,
1524
- completedAt: existing?.completedAt ?? null,
1525
- cursor: existing?.cursor ?? null,
1526
- indexedSourceCount: existing?.indexedSourceCount ?? 0,
1527
- failedSourceCount: existing?.failedSourceCount ?? 0,
1528
- lastErrorCode
1529
- });
1530
- }
1531
- async function findNonTranslatableSiblingContentIds(db, collectionSlug, updatedContentId, translationGroup, updatedData) {
1532
- if (!isI18nEnabled() || !updatedData || !translationGroup) return [];
1533
- validateIdentifier(collectionSlug, "collection slug");
1534
- const collection = await db.selectFrom("_emdash_collections").select("id").where("slug", "=", collectionSlug).executeTakeFirst();
1535
- if (!collection) return [];
1536
- const touchedNonTranslatableSlugs = (await db.selectFrom("_emdash_fields").select("slug").where("collection_id", "=", collection.id).where("translatable", "=", 0).execute()).filter((field) => field.slug in updatedData).map((field) => field.slug);
1537
- if (touchedNonTranslatableSlugs.length === 0) return [];
1538
- const usageFields = await loadContentMediaUsageFields(db, collectionSlug);
1539
- const usageRelevantSlugs = new Set([...usageFields.extractionFields.map((field) => field.slug), ...usageFields.displayFieldSlugs]);
1540
- if (!touchedNonTranslatableSlugs.some((slug) => usageRelevantSlugs.has(slug))) return [];
1541
- const tableName = `ec_${collectionSlug}`;
1542
- return (await sql`
1543
- SELECT id
1544
- FROM ${sql.ref(tableName)}
1545
- WHERE translation_group = ${translationGroup}
1546
- AND id != ${updatedContentId}
1547
- ORDER BY id ASC
1548
- `.execute(db)).rows.map((row) => row.id);
1549
- }
1550
- async function markSnapshotFailure(db, collectionSlug, result) {
1551
- const repo = new MediaUsageRepository(db);
1552
- if (result.source) await repo.markSourceAttempted({
1553
- ...result.source,
1554
- sourceCompleteness: "failed",
1555
- lastErrorCode: result.error
1556
- });
1557
- await markContentMediaUsageCollectionStale(db, collectionSlug, result.error);
1558
- return {
1559
- success: false,
1560
- refreshedSourceCount: 0,
1561
- deletedSourceCount: 0,
1562
- failedSourceCount: result.source ? 1 : 0,
1563
- errorCode: result.error
1564
- };
1565
- }
1566
- async function markContentMediaUsageCollectionStaleSafely(db, collectionSlug, lastErrorCode) {
1567
- try {
1568
- await markContentMediaUsageCollectionStale(db, collectionSlug, lastErrorCode);
1569
- return true;
1570
- } catch (error) {
1571
- console.error(`[media-usage] Failed to mark ${collectionSlug} stale:`, error);
1572
- return false;
1573
- }
1574
- }
1575
- async function withContentUsageLock(collectionSlug, contentId, fn) {
1576
- const locks = getContentUsageLocks();
1577
- const lockKey = `${collectionSlug}\0${contentId}`;
1578
- const previous = locks.get(lockKey) ?? Promise.resolve();
1579
- let releaseCurrent;
1580
- const current = new Promise((resolve) => {
1581
- releaseCurrent = resolve;
1582
- });
1583
- const next = previous.catch(() => {}).then(() => current);
1584
- locks.set(lockKey, next);
1585
- try {
1586
- await previous.catch(() => {});
1587
- return await fn();
1588
- } finally {
1589
- releaseCurrent();
1590
- if (locks.get(lockKey) === next) locks.delete(lockKey);
1591
- }
1592
- }
1593
- async function withContentUsageCollectionLock(collectionSlug, fn) {
1594
- const locks = getContentUsageCollectionLocks();
1595
- const previous = locks.get(collectionSlug) ?? Promise.resolve();
1596
- let releaseCurrent;
1597
- const current = new Promise((resolve) => {
1598
- releaseCurrent = resolve;
1599
- });
1600
- const next = previous.catch(() => {}).then(() => current);
1601
- locks.set(collectionSlug, next);
1602
- try {
1603
- await previous.catch(() => {});
1604
- return await fn();
1605
- } finally {
1606
- releaseCurrent();
1607
- if (locks.get(collectionSlug) === next) locks.delete(collectionSlug);
1608
- }
1609
- }
1610
- function getContentUsageLocks() {
1611
- const global = globalThis;
1612
- const existing = global[CONTENT_USAGE_LOCKS_KEY];
1613
- if (existing instanceof Map) return existing;
1614
- const locks = /* @__PURE__ */ new Map();
1615
- global[CONTENT_USAGE_LOCKS_KEY] = locks;
1616
- return locks;
1617
- }
1618
- function getContentUsageCollectionLocks() {
1619
- const global = globalThis;
1620
- const existing = global[CONTENT_USAGE_COLLECTION_LOCKS_KEY];
1621
- if (existing instanceof Map) return existing;
1622
- const locks = /* @__PURE__ */ new Map();
1623
- global[CONTENT_USAGE_COLLECTION_LOCKS_KEY] = locks;
1624
- return locks;
1625
- }
1626
-
1627
- //#endregion
1628
- export { findNonTranslatableSiblingContentIds as a, refreshContentMediaUsageAfterWrite as c, loadContentMediaUsageSnapshots as d, MEDIA_USAGE_CONTENT_SOURCE_VARIANTS as f, MediaUsageRepository as g, loadContentMediaUsageFields as h, deleteContentMediaUsageCollection as i, withContentUsageCollectionLock as l, MediaUsageFieldDiscoveryError as m, CONTENT_MEDIA_USAGE_COLLECTION_SCOPE as n, markContentMediaUsageCollectionStale as o, buildContentMediaUsageSourceKey as p, deleteContentMediaUsage as r, markContentMediaUsageCollectionStaleSafely as s, CONTENT_MEDIA_USAGE_ADAPTER_ID as t, CONTENT_SOURCE_SCHEMA_VERSION as u };
1629
- //# sourceMappingURL=content-refresh-Xw7aKmou.mjs.map