dineway 0.2.32 → 0.2.34

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 (457) hide show
  1. package/dist/{activity-CfryM8jO.mjs → activity-CZnq5YlZ.mjs} +2 -2
  2. package/dist/{activity-events-BVo9rMUz.mjs → activity-events-D-yGV7cW.mjs} +1 -1
  3. package/dist/{actor-DrJJsvy6.mjs → actor-DxUAJgQX.mjs} +20 -6
  4. package/dist/{adapters-DHt3f2lu.d.mts → adapters-BQ8CQbBm.d.mts} +5 -7
  5. package/dist/after-BVaUn7bK.mjs +24 -0
  6. package/dist/{allowed-origins-DtBQa4JR.mjs → allowed-origins-DV3LWuWW.mjs} +1 -1
  7. package/dist/api/route-utils.d.mts +10 -10
  8. package/dist/api/route-utils.mjs +23 -19
  9. package/dist/api/schemas/index.d.mts +1 -1
  10. package/dist/api/schemas/index.mjs +5 -5
  11. package/dist/{api-DF92r_un.mjs → api-CL4pG2zf.mjs} +55 -1215
  12. package/dist/api-tokens-D5K_Csub.mjs +3 -0
  13. package/dist/{api-tokens-CSomx-l3.mjs → api-tokens-_6tMD1W4.mjs} +1 -1
  14. package/dist/{apply-Bs2jXsms.mjs → apply-CYLUMiZg.mjs} +109 -93
  15. package/dist/astro/index.d.mts +16 -12
  16. package/dist/astro/index.mjs +50 -9
  17. package/dist/astro/middleware/auth.d.mts +9 -9
  18. package/dist/astro/middleware/auth.mjs +29 -8
  19. package/dist/astro/middleware/redirect.mjs +8 -7
  20. package/dist/astro/middleware/request-context.mjs +17 -10
  21. package/dist/astro/middleware/seed.d.mts +1 -1
  22. package/dist/astro/middleware/seed.mjs +93 -71
  23. package/dist/astro/middleware/setup.mjs +1 -1
  24. package/dist/astro/middleware/workers.d.mts +6 -0
  25. package/dist/astro/middleware/workers.mjs +8 -0
  26. package/dist/astro/middleware.mjs +288 -159
  27. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +7 -7
  28. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +7 -7
  29. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +4 -4
  30. package/dist/astro/routes/api/admin/api-tokens/index.mjs +7 -7
  31. package/dist/astro/routes/api/admin/briefing.mjs +25 -23
  32. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +5 -4
  33. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +11 -10
  34. package/dist/astro/routes/api/admin/byline-fields/index.mjs +11 -10
  35. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +11 -10
  36. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +22 -20
  37. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +22 -20
  38. package/dist/astro/routes/api/admin/bylines/index.mjs +22 -20
  39. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +17 -16
  40. package/dist/astro/routes/api/admin/comments/_id_.mjs +8 -7
  41. package/dist/astro/routes/api/admin/comments/bulk.mjs +14 -13
  42. package/dist/astro/routes/api/admin/comments/counts.mjs +8 -7
  43. package/dist/astro/routes/api/admin/comments/index.mjs +14 -13
  44. package/dist/astro/routes/api/admin/context/_id_/history.mjs +43 -31
  45. package/dist/astro/routes/api/admin/context/_id_/index.mjs +43 -31
  46. package/dist/astro/routes/api/admin/context/_id_/review.mjs +48 -36
  47. package/dist/astro/routes/api/admin/context/_id_/supersede.mjs +48 -36
  48. package/dist/astro/routes/api/admin/context/diff.mjs +47 -35
  49. package/dist/astro/routes/api/admin/context/index.mjs +48 -36
  50. package/dist/astro/routes/api/admin/context/stale.mjs +47 -35
  51. package/dist/astro/routes/api/admin/hitl-requests/_id_/index.mjs +43 -31
  52. package/dist/astro/routes/api/admin/hitl-requests/_id_/resolve.mjs +47 -35
  53. package/dist/astro/routes/api/admin/hitl-requests/index.mjs +47 -35
  54. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +44 -32
  55. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
  56. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +7 -7
  57. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +7 -7
  58. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +72 -66
  59. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +72 -66
  60. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +64 -58
  61. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +71 -65
  62. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +71 -65
  63. package/dist/astro/routes/api/admin/plugins/index.mjs +64 -58
  64. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +2 -2
  65. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +64 -58
  66. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +71 -65
  67. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +64 -58
  68. package/dist/astro/routes/api/admin/plugins/updates.mjs +64 -58
  69. package/dist/astro/routes/api/admin/review-requests/_id_/image.mjs +26 -23
  70. package/dist/astro/routes/api/admin/review-requests/_id_/index.mjs +33 -25
  71. package/dist/astro/routes/api/admin/review-requests/_id_/resolve.mjs +56 -43
  72. package/dist/astro/routes/api/admin/review-requests/_id_/revoke.mjs +10 -9
  73. package/dist/astro/routes/api/admin/review-requests/index.mjs +54 -41
  74. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +64 -58
  75. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +2 -2
  76. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +64 -58
  77. package/dist/astro/routes/api/admin/users/_id_/disable.mjs +20 -12
  78. package/dist/astro/routes/api/admin/users/_id_/enable.mjs +1 -1
  79. package/dist/astro/routes/api/admin/users/_id_/index.mjs +40 -32
  80. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +3 -3
  81. package/dist/astro/routes/api/admin/users/index.mjs +7 -7
  82. package/dist/astro/routes/api/auth/dev-bypass.mjs +6 -5
  83. package/dist/astro/routes/api/auth/invite/accept.mjs +1 -1
  84. package/dist/astro/routes/api/auth/invite/complete.mjs +12 -12
  85. package/dist/astro/routes/api/auth/invite/index.mjs +9 -9
  86. package/dist/astro/routes/api/auth/invite/register-options.mjs +11 -11
  87. package/dist/astro/routes/api/auth/logout.mjs +2 -2
  88. package/dist/astro/routes/api/auth/magic-link/send.mjs +12 -11
  89. package/dist/astro/routes/api/auth/magic-link/verify.mjs +2 -2
  90. package/dist/astro/routes/api/auth/me.mjs +11 -11
  91. package/dist/astro/routes/api/auth/mode.mjs +1 -1
  92. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +5 -4
  93. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +5 -4
  94. package/dist/astro/routes/api/auth/passkey/_id_.mjs +7 -7
  95. package/dist/astro/routes/api/auth/passkey/index.mjs +1 -1
  96. package/dist/astro/routes/api/auth/passkey/options.mjs +14 -13
  97. package/dist/astro/routes/api/auth/passkey/register/options.mjs +11 -11
  98. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +12 -12
  99. package/dist/astro/routes/api/auth/passkey/verify.mjs +12 -12
  100. package/dist/astro/routes/api/auth/setup-token/index.mjs +32 -23
  101. package/dist/astro/routes/api/auth/setup-token/verify.mjs +32 -26
  102. package/dist/astro/routes/api/auth/signup/complete.mjs +12 -12
  103. package/dist/astro/routes/api/auth/signup/request.mjs +12 -11
  104. package/dist/astro/routes/api/auth/signup/verify.mjs +1 -1
  105. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +21 -18
  106. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +19 -16
  107. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +2 -2
  108. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +8 -7
  109. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +8 -7
  110. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +8 -7
  111. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +24 -21
  112. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +35 -22
  113. package/dist/astro/routes/api/content/_collection_/_id_/release-readiness.mjs +9 -9
  114. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +8 -7
  115. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +2 -2
  116. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +35 -22
  117. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +23 -19
  118. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +2 -2
  119. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +8 -7
  120. package/dist/astro/routes/api/content/_collection_/_id_.mjs +14 -13
  121. package/dist/astro/routes/api/content/_collection_/authors.mjs +2 -2
  122. package/dist/astro/routes/api/content/_collection_/index.mjs +14 -13
  123. package/dist/astro/routes/api/content/_collection_/trash.mjs +8 -8
  124. package/dist/astro/routes/api/dashboard.mjs +16 -11
  125. package/dist/astro/routes/api/dev/emails.mjs +2 -2
  126. package/dist/astro/routes/api/health.mjs +1 -1
  127. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  128. package/dist/astro/routes/api/import/probe.mjs +25 -24
  129. package/dist/astro/routes/api/import/wordpress/analyze.mjs +12 -11
  130. package/dist/astro/routes/api/import/wordpress/execute.d.mts +9 -9
  131. package/dist/astro/routes/api/import/wordpress/execute.mjs +51 -42
  132. package/dist/astro/routes/api/import/wordpress/media.d.mts +9 -9
  133. package/dist/astro/routes/api/import/wordpress/media.mjs +14 -14
  134. package/dist/astro/routes/api/import/wordpress/prepare.mjs +52 -40
  135. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +10 -10
  136. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +50 -38
  137. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  138. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +29 -27
  139. package/dist/astro/routes/api/import/wordpress-plugin/callback.mjs +1 -1
  140. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +9 -9
  141. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +56 -47
  142. package/dist/astro/routes/api/integration/artifact.mjs +11 -8
  143. package/dist/astro/routes/api/integration/dispatch.mjs +17 -14
  144. package/dist/astro/routes/api/integrations/_provider_.mjs +11 -8
  145. package/dist/astro/routes/api/integrations/index.mjs +10 -7
  146. package/dist/astro/routes/api/manifest.mjs +5 -5
  147. package/dist/astro/routes/api/mcp.mjs +98 -88
  148. package/dist/astro/routes/api/media/_id_/confirm.mjs +12 -12
  149. package/dist/astro/routes/api/media/_id_.mjs +9 -9
  150. package/dist/astro/routes/api/media/file/_...key_.mjs +1 -1
  151. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +2 -2
  152. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +2 -2
  153. package/dist/astro/routes/api/media/providers/index.mjs +2 -2
  154. package/dist/astro/routes/api/media/upload-url.mjs +13 -13
  155. package/dist/astro/routes/api/media.mjs +16 -16
  156. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +48 -36
  157. package/dist/astro/routes/api/menus/_name_/items.mjs +48 -36
  158. package/dist/astro/routes/api/menus/_name_/reorder.mjs +48 -36
  159. package/dist/astro/routes/api/menus/_name_/translations.mjs +48 -36
  160. package/dist/astro/routes/api/menus/_name_.mjs +48 -36
  161. package/dist/astro/routes/api/menus/index.mjs +48 -36
  162. package/dist/astro/routes/api/oauth/authorize.mjs +9 -7
  163. package/dist/astro/routes/api/oauth/device/authorize.mjs +7 -6
  164. package/dist/astro/routes/api/oauth/device/code.mjs +11 -9
  165. package/dist/astro/routes/api/oauth/device/token.mjs +10 -8
  166. package/dist/astro/routes/api/oauth/register.mjs +4 -4
  167. package/dist/astro/routes/api/oauth/token/refresh.mjs +7 -6
  168. package/dist/astro/routes/api/oauth/token/revoke.mjs +7 -6
  169. package/dist/astro/routes/api/oauth/token.mjs +8 -6
  170. package/dist/astro/routes/api/openapi.json.mjs +5 -5
  171. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +4 -4
  172. package/dist/astro/routes/api/redirects/404s/index.mjs +15 -14
  173. package/dist/astro/routes/api/redirects/404s/summary.mjs +15 -14
  174. package/dist/astro/routes/api/redirects/_id_.mjs +48 -37
  175. package/dist/astro/routes/api/redirects/index.mjs +48 -37
  176. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +2 -2
  177. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +2 -2
  178. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +66 -60
  179. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +66 -60
  180. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +66 -60
  181. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +66 -60
  182. package/dist/astro/routes/api/schema/collections/index.mjs +66 -60
  183. package/dist/astro/routes/api/schema/index.mjs +12 -11
  184. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +64 -58
  185. package/dist/astro/routes/api/schema/orphans/index.mjs +64 -58
  186. package/dist/astro/routes/api/search/enable.mjs +15 -14
  187. package/dist/astro/routes/api/search/index.mjs +14 -13
  188. package/dist/astro/routes/api/search/rebuild.mjs +15 -14
  189. package/dist/astro/routes/api/search/stats.mjs +9 -8
  190. package/dist/astro/routes/api/search/suggest.mjs +14 -13
  191. package/dist/astro/routes/api/sections/_slug_.mjs +48 -36
  192. package/dist/astro/routes/api/sections/index.mjs +48 -36
  193. package/dist/astro/routes/api/settings/email.mjs +5 -5
  194. package/dist/astro/routes/api/settings/reviews.mjs +11 -10
  195. package/dist/astro/routes/api/settings.mjs +48 -36
  196. package/dist/astro/routes/api/setup/admin-verify.mjs +14 -14
  197. package/dist/astro/routes/api/setup/admin.mjs +12 -12
  198. package/dist/astro/routes/api/setup/dev-bypass.mjs +35 -31
  199. package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
  200. package/dist/astro/routes/api/setup/index.mjs +37 -33
  201. package/dist/astro/routes/api/setup/status.mjs +3 -3
  202. package/dist/astro/routes/api/snapshot.mjs +11 -9
  203. package/dist/astro/routes/api/system/heartbeat.mjs +2 -2
  204. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +51 -39
  205. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +51 -39
  206. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +51 -39
  207. package/dist/astro/routes/api/taxonomies/index.mjs +51 -39
  208. package/dist/astro/routes/api/themes/preview.mjs +8 -6
  209. package/dist/astro/routes/api/typegen.mjs +4 -4
  210. package/dist/astro/routes/api/well-known/auth.mjs +3 -3
  211. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +3 -3
  212. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +3 -3
  213. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +47 -35
  214. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +48 -36
  215. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +48 -36
  216. package/dist/astro/routes/api/widget-areas/_name_.mjs +45 -33
  217. package/dist/astro/routes/api/widget-areas/index.mjs +48 -36
  218. package/dist/astro/routes/api/widget-components.mjs +2 -2
  219. package/dist/astro/routes/robots.txt.mjs +11 -10
  220. package/dist/astro/routes/sitemap-_collection_.xml.mjs +20 -18
  221. package/dist/astro/routes/sitemap.xml.mjs +19 -17
  222. package/dist/astro/session-driver.d.mts +1 -1
  223. package/dist/astro/session-driver.mjs +4 -4
  224. package/dist/astro/types.d.mts +13 -13
  225. package/dist/atomic-authority-CnBQJ14T.mjs +33 -0
  226. package/dist/{audit-CYjfxG9i.mjs → audit-F5iWkbcJ.mjs} +11 -4
  227. package/dist/auth/providers/github.d.mts +1 -1
  228. package/dist/auth/providers/google.d.mts +1 -1
  229. package/dist/{auth-control-guard-CITT8ZA_.mjs → auth-control-guard-D4WW-wFF.mjs} +1 -1
  230. package/dist/{authorize-KcI0pAfN.mjs → authorize-EnP57AQl.mjs} +1 -1
  231. package/dist/{briefing-r3hXCDQC.mjs → briefing-BXsVwd4P.mjs} +1 -1
  232. package/dist/{briefing-BgQTljQt.mjs → briefing-CkCi6S-W.mjs} +445 -447
  233. package/dist/{bundle-S6zx-V4D.mjs → bundle-Cgak1zGE.mjs} +3 -3
  234. package/dist/{byline-Ctil4rij.mjs → byline-DEZKlzD9.mjs} +107 -113
  235. package/dist/{byline-fields-QpmruT5r.mjs → byline-fields-BGEIA9dZ.mjs} +3 -3
  236. package/dist/{byline-fields-DNXKWUW9.d.mts → byline-fields-BmkhEDFF.d.mts} +2 -2
  237. package/dist/{byline-fields-DiCyW6eQ.mjs → byline-fields-Qg8TesxL.mjs} +1 -1
  238. package/dist/{byline-registry-rkr73qSE.mjs → byline-registry-CkuVVeJJ.mjs} +46 -76
  239. package/dist/{bylines-BcuBpzVi.mjs → bylines-7BQxRGyG.mjs} +4 -4
  240. package/dist/{bylines-v_ZUQnR-.mjs → bylines-LqNRjma2.mjs} +6 -6
  241. package/dist/{cache-V2BCplaY.mjs → cache-CSTy-R-K.mjs} +2 -2
  242. package/dist/{chunks-CnuL55JE.mjs → chunks-BnG3LPMN.mjs} +1 -1
  243. package/dist/cli/index.mjs +452 -263
  244. package/dist/cli/plugin-kit.d.mts +9 -9
  245. package/dist/cli/plugin-kit.mjs +2 -2
  246. package/dist/client/external-auth-headers.d.mts +1 -1
  247. package/dist/client/index.d.mts +11 -11
  248. package/dist/client/index.mjs +2 -2
  249. package/dist/{client-factory-C-y9VZDX.mjs → client-factory-BLSkgsTg.mjs} +1 -1
  250. package/dist/{comment-_nvJSS-A.mjs → comment-Bi7cJ9SS.mjs} +2 -2
  251. package/dist/{comment-reaction-DhVgJ17S.mjs → comment-reaction-BLqIj5mx.mjs} +1 -1
  252. package/dist/{comments-D4mIDjvA.mjs → comments-Dg_gWBEB.mjs} +1 -1
  253. package/dist/content-De_XeXy_.mjs +1230 -0
  254. package/dist/{content-CVCrcuvD.mjs → content-NobcQti0.mjs} +240 -161
  255. package/dist/{content-refresh-QvBIyb_g.mjs → content-refresh-l4mPoGeX.mjs} +170 -193
  256. package/dist/{context-MftkHbWx.mjs → context-6uqzU-M9.mjs} +95 -77
  257. package/dist/{context-JjKucxBm.mjs → context-B0SG9Xkc.mjs} +2 -2
  258. package/dist/{context-route-helpers-e1APrqSm.mjs → context-route-helpers-C8s26uDT.mjs} +2 -2
  259. package/dist/{cron-mGVPQ5e6.mjs → cron-D7zB6m8i.mjs} +36 -32
  260. package/dist/d1-binding-D6HZa3ks.mjs +8 -0
  261. package/dist/d1-dialect-B1b8cmxX.mjs +48 -0
  262. package/dist/{dashboard-ZJ7sMcBI.mjs → dashboard-B-OybCMw.mjs} +5 -5
  263. package/dist/database/batch.d.mts +20 -0
  264. package/dist/database/batch.mjs +69 -0
  265. package/dist/database/d1/index.d.mts +18 -0
  266. package/dist/database/d1/index.mjs +8 -0
  267. package/dist/db/d1.d.mts +7 -0
  268. package/dist/db/d1.mjs +13 -0
  269. package/dist/db/index.d.mts +4 -4
  270. package/dist/db/index.mjs +10 -7
  271. package/dist/db/libsql.d.mts +1 -1
  272. package/dist/db/libsql.mjs +46 -3
  273. package/dist/db/postgres.d.mts +1 -1
  274. package/dist/db/sqlite.d.mts +1 -1
  275. package/dist/{device-flow-eOcL5m0Q.mjs → device-flow-DhpCzMo0.mjs} +130 -94
  276. package/dist/{dialect-helpers-fk43GbDb.mjs → dialect-helpers-C6xtO-Ui.mjs} +1 -1
  277. package/dist/{discovery-CJkuHGhZ.mjs → discovery-CqXbN0WZ.mjs} +5 -5
  278. package/dist/{enrich-KErvJOuI.mjs → enrich-BjF-J4sF.mjs} +1 -1
  279. package/dist/{evidence-6IUv9ML3.mjs → evidence-xJf8hQgH.mjs} +7 -7
  280. package/dist/{field-defs-cache-CwrIyZFT.mjs → field-defs-cache-BKKFFf_V.mjs} +5 -5
  281. package/dist/{forgeway-account-lYJ8iX3G.mjs → forgeway-account-BeKJlKh1.mjs} +1 -1
  282. package/dist/{fts-manager-DX7ZkrCa.mjs → fts-manager-BeWtB7ZD.mjs} +72 -57
  283. package/dist/{hitl-requests-CmYVunm-.mjs → hitl-requests-evSsel48.mjs} +2 -2
  284. package/dist/{hitl-route-helpers-CRm537zS.mjs → hitl-route-helpers-D2kJSOFX.mjs} +5 -5
  285. package/dist/{import-DqRAgsKr.mjs → import-Jpta-CYE.mjs} +9 -9
  286. package/dist/{index-Co7xtjkd.d.mts → index-CSUSBfdD.d.mts} +7 -4
  287. package/dist/index.d.mts +16 -16
  288. package/dist/index.mjs +104 -96
  289. package/dist/{integration-credentials-qudN6yRr.mjs → integration-credentials-BrQr0fb_.mjs} +2 -2
  290. package/dist/{jsonld-DTd-AVWg.d.mts → jsonld-CqIVIeZK.d.mts} +2 -2
  291. package/dist/{load-fCOciq0Q.mjs → load-Dc5ttyg4.mjs} +1 -1
  292. package/dist/{loader-BDje8ME2.mjs → loader-Cgsx23wU.mjs} +4 -4
  293. package/dist/{manifest-schema-CfKD0thC.mjs → manifest-schema-DG29meRy.mjs} +1 -1
  294. package/dist/{mcp-reviewed-executor-DmhM3Cy6.mjs → mcp-reviewed-executor-DAZL3Ckt.mjs} +7 -7
  295. package/dist/media/image-endpoint.mjs +1 -1
  296. package/dist/media/index.d.mts +1 -1
  297. package/dist/media/index.mjs +2 -2
  298. package/dist/media/local-runtime.d.mts +11 -11
  299. package/dist/media/local-runtime.mjs +3 -3
  300. package/dist/{media-dvRjj4po.mjs → media-3fK0u-bo.mjs} +1 -1
  301. package/dist/{media-allowlist-DaG6lNoy.mjs → media-allowlist-rN4qIF6W.mjs} +1 -1
  302. package/dist/{menus-CpuR4Qkm.mjs → menus-5liJusbp.mjs} +138 -90
  303. package/dist/{menus-CZbz5L_V.mjs → menus-CbR_J8cJ.mjs} +8 -8
  304. package/dist/migrations-CMdxWKx-.mjs +76 -0
  305. package/dist/oauth-authority-CCqo4eBm.mjs +43 -0
  306. package/dist/{oauth-authorization-Jf5e3azH.mjs → oauth-authorization--0UtTZpv.mjs} +89 -98
  307. package/dist/{oauth-clients-tovQ4D4h.mjs → oauth-clients-D4WBYaYW.mjs} +2 -2
  308. package/dist/object-cache/memory.d.mts +1 -1
  309. package/dist/{object-cache-D51qOseS.mjs → object-cache-BGjIlY9s.mjs} +1 -1
  310. package/dist/page/index.d.mts +10 -10
  311. package/dist/page/index.mjs +1 -1
  312. package/dist/{parse-IsGn-5lt.mjs → parse--7nG62_h.mjs} +1 -1
  313. package/dist/plugin-utils.d.mts +9 -9
  314. package/dist/plugins/adapt-sandbox-entry.d.mts +9 -9
  315. package/dist/plugins/adapt-sandbox-entry.mjs +1 -1
  316. package/dist/{plugins-DXyLI3Hb.mjs → plugins-DK1wLuao.mjs} +35 -84
  317. package/dist/{policy-950odoX_.mjs → policy-Dej7NJFD.mjs} +2 -2
  318. package/dist/{preview-BXmS1SXL.mjs → preview-q0pkibNO.mjs} +2 -2
  319. package/dist/{provider-loader-DDq7R_RN.d.mts → provider-loader-C0GaLwKB.d.mts} +1 -1
  320. package/dist/{public-url-CT-T1D_w.d.mts → public-url-B9zEdO8p.d.mts} +1 -1
  321. package/dist/{public-url-BQ9vf0AS.d.mts → public-url-BV-YQ_LF.d.mts} +2 -2
  322. package/dist/{publication-authorization-C-vYPGD8.mjs → publication-authorization-BrEZ2TsE.mjs} +459 -33
  323. package/dist/{query-CrW2yI6G.mjs → query-CEn9HXnf.mjs} +15 -15
  324. package/dist/{query-DcB9uGTW.mjs → query-DAS6VbMS.mjs} +4 -4
  325. package/dist/{rate-limit-DEkoxTsP.mjs → rate-limit-Dd1TnzZP.mjs} +2 -2
  326. package/dist/{redirect-DG-o0CKV.mjs → redirect-HLI3wT5Y.mjs} +26 -14
  327. package/dist/{redirects-Bjp4iKJU.mjs → redirects-DmOdfRjI.mjs} +5 -5
  328. package/dist/{redirects-N8gmWhVM.mjs → redirects-UCXyL0lP.mjs} +3 -3
  329. package/dist/{registry-D-IV_h50.mjs → registry-RD9qTnYL.mjs} +183 -186
  330. package/dist/release-BR08Slqf.mjs +5148 -0
  331. package/dist/request-context.d.mts +8 -0
  332. package/dist/{request-meta-BW0the1R.mjs → request-meta-BOcuHAXD.mjs} +1 -1
  333. package/dist/{resolve-pZ4NQM-X.mjs → resolve-C80Pm2DW.mjs} +1 -1
  334. package/dist/{review-payload-f1L4lzQg.mjs → review-payload-DEylbssM.mjs} +52 -4
  335. package/dist/{review-requests-DICrYH2-.mjs → review-requests-BF2eEKr8.mjs} +93 -37
  336. package/dist/{review-requests-BTKfeWlS.mjs → review-requests-CyfWbJ6W.mjs} +2 -2
  337. package/dist/{review-route-helpers-DaZBBps8.mjs → review-route-helpers-lKA-CXms.mjs} +2 -2
  338. package/dist/{revision-De7OmYVD.mjs → revision-090sZyGc.mjs} +28 -22
  339. package/dist/revocation-B7GL5fMl.mjs +53 -0
  340. package/dist/{runner-DJiRFyLI.mjs → runner-CVeq0266.mjs} +594 -491
  341. package/dist/{runner-Dye73myO.d.mts → runner-JnJSGXEB.d.mts} +1 -1
  342. package/dist/{runs-DEujUDOj.mjs → runs-B5BExdKO.mjs} +5 -5
  343. package/dist/runtime-env-CQVAWHzH.mjs +19 -0
  344. package/dist/runtime.d.mts +10 -10
  345. package/dist/runtime.mjs +5 -5
  346. package/dist/schema-DLMkODQc.mjs +8 -0
  347. package/dist/{search-DxUKN9Zz.mjs → search-CRzWNfxX.mjs} +4 -4
  348. package/dist/{secrets-AdCrGg1c.mjs → secrets-Cg0D2gQW.mjs} +10 -11
  349. package/dist/{sections-BPFOEMK6.mjs → sections-BwUjOGqn.mjs} +2 -2
  350. package/dist/seed/index.d.mts +2 -2
  351. package/dist/seed/index.mjs +29 -25
  352. package/dist/seo/index.d.mts +3 -3
  353. package/dist/seo/index.mjs +11 -10
  354. package/dist/{seo-DWHdo5aW.mjs → seo-BOTuCeh-.mjs} +25 -15
  355. package/dist/{seo-GfovzqpU.mjs → seo-B_tBFyud.mjs} +1 -1
  356. package/dist/{service-DbgjHWyW.mjs → service--bQht6oN.mjs} +2 -2
  357. package/dist/{service-BrNKVCjC.mjs → service-DilVsWGD.mjs} +3 -3
  358. package/dist/{session-user-DyqWGIh4.mjs → session-user-DeqTcAmR.mjs} +1 -1
  359. package/dist/{settings-CAsQLi0N.mjs → settings-DFzevIrU.mjs} +8 -8
  360. package/dist/{settings-BKEHw6Bu.mjs → settings-Deqx3Upy.mjs} +2 -2
  361. package/dist/{setup-complete-C8LTo8cO.mjs → setup-complete-BFqudwbW.mjs} +1 -1
  362. package/dist/{site-activity-7oezuHXK.mjs → site-activity-BrN2NviL.mjs} +11 -4
  363. package/dist/{site-context-CA7rbxux.mjs → site-context-vCiDRr4H.mjs} +50 -37
  364. package/dist/{site-url-DoZf_jVj.mjs → site-url-wXFqbm9c.mjs} +1 -1
  365. package/dist/state-jyNZ6-7L.mjs +30 -0
  366. package/dist/storage/local.d.mts +1 -1
  367. package/dist/storage/local.mjs +1 -1
  368. package/dist/storage/s3.d.mts +1 -1
  369. package/dist/storage/s3.mjs +3 -3
  370. package/dist/{store-c4qx3gVh.mjs → store-C1yDxxfv.mjs} +37 -12
  371. package/dist/submission-BsHNfHc7.mjs +155 -0
  372. package/dist/{taxonomies-ALDiRQ84.mjs → taxonomies-4cnTcbD6.mjs} +3 -3
  373. package/dist/{taxonomies-93DV-1QT.mjs → taxonomies-CllxqaH0.mjs} +7 -7
  374. package/dist/{taxonomy-BOBTJ_aE.mjs → taxonomy-DWxxLpp5.mjs} +3 -3
  375. package/dist/{tokens-c-qxNqzC.mjs → tokens-Bjuf1HID.mjs} +1 -1
  376. package/dist/{trusted-proxy-CdEl6g6B.mjs → trusted-proxy-CAW9o4Dw.mjs} +4 -12
  377. package/dist/{types-BRCUO8NR.d.mts → types-7Th6Mwz3.d.mts} +1 -0
  378. package/dist/{types-BpSTdH1H.mjs → types-BqxIv8Il.mjs} +2 -2
  379. package/dist/{types-6KmeXInJ.d.mts → types-CFgTpfPk.d.mts} +1 -1
  380. package/dist/{types-TpXK8km5.d.mts → types-QjOcidFc.d.mts} +300 -172
  381. package/dist/ui/server-runtime.d.mts +13 -13
  382. package/dist/ui/server-runtime.mjs +28 -26
  383. package/dist/{user-D0NJ7gYf.mjs → user-1-YV30lf.mjs} +2 -2
  384. package/dist/{utils-BK2efsHv.mjs → utils-Cglcqpm2.mjs} +2 -2
  385. package/dist/{validate-CDWVODvc.d.mts → validate-A27peRc4.d.mts} +3 -3
  386. package/dist/{validate-C9g9iX3q.mjs → validate-Wl4MSf3V.mjs} +3 -3
  387. package/dist/version-BWxyC5s4.mjs +6 -0
  388. package/dist/{widgets-Cm5Qx2Np.mjs → widgets-Di-6yDH7.mjs} +3 -3
  389. package/dist/{wordpress-slugs-WdPZaVXf.mjs → wordpress-slugs-vOx7R1dM.mjs} +1 -1
  390. package/dist/{worker-D7OccgB8.mjs → worker-RpaMP71d.mjs} +76 -47
  391. package/dist/workers-build-BaQCrSmf.mjs +36 -0
  392. package/dist/{zod-generator-DS5oZNaL.mjs → zod-generator-Cylvl_SM.mjs} +2 -2
  393. package/package.json +35 -9
  394. package/dist/after-BfniwgIf.mjs +0 -9
  395. package/dist/api-tokens-CmT83Bgj.mjs +0 -3
  396. package/dist/db/libsql-http.d.mts +0 -27
  397. package/dist/db/libsql-http.mjs +0 -29
  398. package/dist/libsql-dialect-CANq6UNI.mjs +0 -47
  399. package/dist/oauth-user-lookup-B451pZmd.mjs +0 -25
  400. package/dist/revocation-CkTOhdlw.mjs +0 -42
  401. package/dist/schema-IjuRxkqq.mjs +0 -8
  402. package/dist/submission-C47cHBIg.mjs +0 -67
  403. package/dist/transaction-BGQgnwUi.mjs +0 -28
  404. package/dist/version-9orir5LL.mjs +0 -6
  405. /package/dist/{base64-F8-DUraK.mjs → base64-Cz-aU0X1.mjs} +0 -0
  406. /package/dist/{challenge-store-CYrg4F4t.mjs → challenge-store-D-_-VavY.mjs} +0 -0
  407. /package/dist/{components-DAq_4iPX.mjs → components-BWQUCJEr.mjs} +0 -0
  408. /package/dist/{config-CVssduLe.mjs → config-XW5tMrH8.mjs} +0 -0
  409. /package/dist/{content-index-names-Bbu1FY1r.mjs → content-index-names-CDc2IQIx.mjs} +0 -0
  410. /package/dist/{context-types-CPWAJRs5.mjs → context-types-DqTo6C79.mjs} +0 -0
  411. /package/dist/{default-BeIzUa1e.mjs → default-D9zxuUU7.mjs} +0 -0
  412. /package/dist/{email-console-Bfi_exVg.mjs → email-console-BONByQiC.mjs} +0 -0
  413. /package/dist/{error-DLg1H2LT.mjs → error-Dd8LtpG5.mjs} +0 -0
  414. /package/dist/{escape-C6lkys0j.mjs → escape-BWC4s5bV.mjs} +0 -0
  415. /package/dist/{experimental-workflows-B9x8delL.mjs → experimental-workflows-M5D3RTFo.mjs} +0 -0
  416. /package/dist/{hash-jhbF98tT.mjs → hash-lNx3KJis.mjs} +0 -0
  417. /package/dist/{media-url-CL3NzgLh.mjs → media-url-B4YtTY6c.mjs} +0 -0
  418. /package/dist/{mime-CDTtL7jE.mjs → mime-D_ae-u_U.mjs} +0 -0
  419. /package/dist/{mode-D554vAgH.mjs → mode-CPf_KZ37.mjs} +0 -0
  420. /package/dist/{normalize-Ev3FiBMx.mjs → normalize-5rct_U0I.mjs} +0 -0
  421. /package/dist/{oauth-state-store-Do1a_o3H.mjs → oauth-state-store-CMgcimzA.mjs} +0 -0
  422. /package/dist/{options-1dBRkoCl.mjs → options-BcqHWpc-.mjs} +0 -0
  423. /package/dist/{output-8j9oltTf.mjs → output-BYpiVUBf.mjs} +0 -0
  424. /package/dist/{parser-C9rzPuSZ.mjs → parser-BV0wzQHo.mjs} +0 -0
  425. /package/dist/{passkey-config-CRN44T04.mjs → passkey-config-BG4GO4OO.mjs} +0 -0
  426. /package/dist/{patterns-3XE9bU4r.mjs → patterns-CZ7D4y_R.mjs} +0 -0
  427. /package/dist/{placeholder-D03pGvqM.d.mts → placeholder-BHTaoCYx.d.mts} +0 -0
  428. /package/dist/{portable-text-tIk9_uz_.mjs → portable-text-B9YuySom.mjs} +0 -0
  429. /package/dist/{portable-text-BdRm4uZq.d.mts → portable-text-FKf3IrPz.d.mts} +0 -0
  430. /package/dist/{process-cache-B-L-A9zg.mjs → process-cache-MHM4Sqzs.mjs} +0 -0
  431. /package/dist/{provider-loader-C4i82ll1.mjs → provider-loader-3MY1SjzA.mjs} +0 -0
  432. /package/dist/{public-discovery-CyDzK1-S.mjs → public-discovery-BAbOvKiR.mjs} +0 -0
  433. /package/dist/{public-url-oudwI7K0.mjs → public-url-C7pbmS_7.mjs} +0 -0
  434. /package/dist/{public-url-BVIjzMo3.mjs → public-url-D5Wjq0sy.mjs} +0 -0
  435. /package/dist/{redirect-Dp5u-8dH.mjs → redirect-Bx96u2nS.mjs} +0 -0
  436. /package/dist/{request-cache-BruBnFAR.mjs → request-cache-DPmV5nk4.mjs} +0 -0
  437. /package/dist/{seo-contributions-BAtRDXEQ.mjs → seo-contributions-Dt57p6Sq.mjs} +0 -0
  438. /package/dist/{service-DeX1PRNt.mjs → service-wYQ_ePZ4.mjs} +0 -0
  439. /package/dist/{setup-nonce-D-CEYlw7.mjs → setup-nonce-CAqDUxxU.mjs} +0 -0
  440. /package/dist/{sidecar-client-Bw2C0XTf.mjs → sidecar-client-CnpGTvYq.mjs} +0 -0
  441. /package/dist/{slugify-KSsVD_D3.mjs → slugify-Di8Q_MFq.mjs} +0 -0
  442. /package/dist/{ssrf-C7tTSD1r.mjs → ssrf-LN16WMip.mjs} +0 -0
  443. /package/dist/{stable-hash-DF7R5eN8.mjs → stable-hash-DEtJgcp7.mjs} +0 -0
  444. /package/dist/{status-Bba6RbkS.mjs → status-Bwkeuz8g.mjs} +0 -0
  445. /package/dist/{transport-BddGhTAI.mjs → transport-472KVGBe.mjs} +0 -0
  446. /package/dist/{transport-ktLL9r2O.d.mts → transport-C0jj-Nc8.d.mts} +0 -0
  447. /package/dist/{types-BQZFeZjd.mjs → types-BDq9t5lG.mjs} +0 -0
  448. /package/dist/{types-CKIt_jmM.d.mts → types-Bs-7Geuh.d.mts} +0 -0
  449. /package/dist/{types-CLMOusxP.d.mts → types-CwkJp6zr.d.mts} +0 -0
  450. /package/dist/{types-C0DPvhR5.mjs → types-CyBH89BS.mjs} +0 -0
  451. /package/dist/{types-BbkkkAb6.mjs → types-D17dJRht.mjs} +0 -0
  452. /package/dist/{types--3oJQ0hs.d.mts → types-DTjrkhKU.d.mts} +0 -0
  453. /package/dist/{types-CPaVj_GC.d.mts → types-DkXuBo8k.d.mts} +0 -0
  454. /package/dist/{types-CU3Wn2HC.d.mts → types-b2sq7ZDk.d.mts} +0 -0
  455. /package/dist/{url-C_pLSrGZ.mjs → url-D375-6LM.mjs} +0 -0
  456. /package/dist/{url-Dumsft7G.mjs → url-bv5i4JN0.mjs} +0 -0
  457. /package/dist/{validate-VPnKoIzW.mjs → validate-Co3j6T_K.mjs} +0 -0
@@ -1,13 +1,97 @@
1
- import { t as validateIdentifier } from "./validate-VPnKoIzW.mjs";
2
- import { r as isI18nEnabled } from "./config-CVssduLe.mjs";
3
- import { i as encodeCursor, r as decodeCursor } from "./types-BpSTdH1H.mjs";
4
- import { n as chunks, t as SQL_BATCH_SIZE } from "./chunks-CnuL55JE.mjs";
5
- import { t as withTransaction } from "./transaction-BGQgnwUi.mjs";
6
- import { n as normalizeMime } from "./mime-CDTtL7jE.mjs";
7
- import { n as hashString } from "./hash-jhbF98tT.mjs";
1
+ import { AtomicWriteConflict, atomicBatch } from "./database/batch.mjs";
2
+ import { t as validateIdentifier } from "./validate-Co3j6T_K.mjs";
3
+ import { r as isI18nEnabled } from "./config-XW5tMrH8.mjs";
4
+ import { i as encodeCursor, r as decodeCursor } from "./types-BqxIv8Il.mjs";
5
+ import { n as chunks, t as SQL_BATCH_SIZE } from "./chunks-BnG3LPMN.mjs";
6
+ import { n as normalizeMime } from "./mime-D_ae-u_U.mjs";
7
+ import { n as hashString } from "./hash-lNx3KJis.mjs";
8
8
  import { sql } from "kysely";
9
9
  import { ulid } from "ulidx";
10
10
 
11
+ //#region src/media/usage/content-fields.ts
12
+ var MediaUsageFieldDiscoveryError = class extends Error {
13
+ constructor(message, code) {
14
+ super(message);
15
+ this.code = code;
16
+ this.name = "MediaUsageFieldDiscoveryError";
17
+ }
18
+ };
19
+ const DISPLAY_FIELD_SLUGS = ["title", "name"];
20
+ const SUPPORTED_TOP_LEVEL_TYPES = [
21
+ "file",
22
+ "image",
23
+ "portableText"
24
+ ];
25
+ async function loadContentMediaUsageFields(db, collectionSlug) {
26
+ validateIdentifier(collectionSlug, "collection slug");
27
+ const rows = await db.selectFrom("_dineway_fields").innerJoin("_dineway_collections", "_dineway_collections.id", "_dineway_fields.collection_id").select([
28
+ "_dineway_fields.slug",
29
+ "_dineway_fields.type",
30
+ "_dineway_fields.validation"
31
+ ]).where("_dineway_collections.slug", "=", collectionSlug).execute();
32
+ const extractionFields = [];
33
+ const rowBySlug = /* @__PURE__ */ new Map();
34
+ for (const row of rows) {
35
+ rowBySlug.set(row.slug, row);
36
+ if (isSupportedTopLevelType(row.type)) {
37
+ validateIdentifier(row.slug, "media usage field slug");
38
+ extractionFields.push({
39
+ slug: row.slug,
40
+ type: row.type
41
+ });
42
+ continue;
43
+ }
44
+ if (row.type === "repeater") {
45
+ validateIdentifier(row.slug, "media usage field slug");
46
+ const subFields = normalizeRepeaterImageSubFields(row.validation);
47
+ if (subFields.length > 0) extractionFields.push({
48
+ slug: row.slug,
49
+ type: "repeater",
50
+ validation: { subFields }
51
+ });
52
+ }
53
+ }
54
+ extractionFields.sort((a, b) => a.slug.localeCompare(b.slug));
55
+ return {
56
+ extractionFields,
57
+ displayFieldSlugs: DISPLAY_FIELD_SLUGS.filter((slug) => {
58
+ if (!rowBySlug.has(slug)) return false;
59
+ validateIdentifier(slug, "media usage display field slug");
60
+ return true;
61
+ })
62
+ };
63
+ }
64
+ function normalizeRepeaterImageSubFields(rawValidation) {
65
+ const validation = parseValidation(rawValidation);
66
+ if (!isRecord$2(validation) || !Array.isArray(validation.subFields)) return [];
67
+ const subFields = [];
68
+ for (const subField of validation.subFields) {
69
+ if (!isRecord$2(subField) || subField.type !== "image") continue;
70
+ if (typeof subField.slug !== "string") continue;
71
+ validateIdentifier(subField.slug, "media usage repeater sub-field slug");
72
+ subFields.push({
73
+ slug: subField.slug,
74
+ type: "image"
75
+ });
76
+ }
77
+ return subFields.toSorted((a, b) => a.slug.localeCompare(b.slug));
78
+ }
79
+ function parseValidation(rawValidation) {
80
+ if (!rawValidation) return null;
81
+ try {
82
+ return JSON.parse(rawValidation);
83
+ } catch {
84
+ throw new MediaUsageFieldDiscoveryError("Repeater field validation must be valid JSON before media usage can be discovered", "INVALID_REPEATER_VALIDATION");
85
+ }
86
+ }
87
+ function isSupportedTopLevelType(value) {
88
+ return SUPPORTED_TOP_LEVEL_TYPES.includes(value);
89
+ }
90
+ function isRecord$2(value) {
91
+ return typeof value === "object" && value !== null && !Array.isArray(value);
92
+ }
93
+
94
+ //#endregion
11
95
  //#region src/database/repositories/media-usage.ts
12
96
  const OCCURRENCE_INSERT_BATCH_SIZE = Math.max(1, Math.floor(SQL_BATCH_SIZE / 13));
13
97
  /** Persistence-only repository for the internal media usage projection tables. */
@@ -18,31 +102,15 @@ var MediaUsageRepository = class {
18
102
  async replaceSource(source, occurrences) {
19
103
  const generation = ulid();
20
104
  const now = (/* @__PURE__ */ new Date()).toISOString();
21
- await withTransaction(this.db, async (trx) => {
22
- await this.insertOccurrences(trx, source.sourceKey, generation, occurrences, now);
23
- await this.upsertSource(trx, source, generation, now);
24
- });
105
+ await atomicBatch(this.db, { statements: this.prepareReplacement(source, generation, occurrences, now) });
25
106
  const replaced = await this.findSource(source.sourceKey);
26
107
  if (!replaced) throw new Error(`Media usage source ${source.sourceKey} was not persisted`);
27
108
  return replaced;
28
109
  }
29
110
  async replaceSourceIfCurrent(source, occurrences, expectedCurrentGeneration) {
30
- const generation = ulid();
31
- const now = (/* @__PURE__ */ new Date()).toISOString();
32
- const row = this.buildSourceRow(source, generation, now);
33
- let replaced = false;
34
- await withTransaction(this.db, async (trx) => {
35
- await this.insertOccurrences(trx, source.sourceKey, generation, occurrences, now);
36
- if (expectedCurrentGeneration === null) {
37
- replaced = await this.insertSourceIfAbsent(trx, row);
38
- return;
39
- }
40
- replaced = await this.updateSourceIfGeneration(trx, row, expectedCurrentGeneration);
41
- });
42
- return {
43
- replaced,
44
- source: replaced ? null : await this.findSource(source.sourceKey)
45
- };
111
+ const exists = this.db.selectFrom("_dineway_media_usage_sources").select("source_key").where("source_key", "=", source.sourceKey);
112
+ const check = expectedCurrentGeneration === null ? sql`NOT EXISTS ${exists}` : sql`EXISTS ${exists.where("current_generation", "=", expectedCurrentGeneration)}`;
113
+ return this.replaceGuarded(source, occurrences, check);
46
114
  }
47
115
  async findSource(sourceKey) {
48
116
  const row = await this.db.selectFrom("_dineway_media_usage_sources").selectAll().where("source_key", "=", sourceKey).executeTakeFirst();
@@ -62,22 +130,27 @@ var MediaUsageRepository = class {
62
130
  return sources;
63
131
  }
64
132
  async replaceSourceIfMatching(source, occurrences, expectedSource) {
65
- const generation = ulid();
66
- const now = (/* @__PURE__ */ new Date()).toISOString();
67
- const row = this.buildSourceRow(source, generation, now);
68
- let replaced = false;
69
- await withTransaction(this.db, async (trx) => {
70
- await this.insertOccurrences(trx, source.sourceKey, generation, occurrences, now);
71
- if (expectedSource === null) {
72
- replaced = await this.insertSourceIfAbsent(trx, row);
73
- return;
74
- }
75
- replaced = await this.updateSourceIfMatching(trx, row, expectedSource);
76
- });
77
- return {
78
- replaced,
79
- source: replaced ? null : await this.findSource(source.sourceKey)
80
- };
133
+ const exists = this.db.selectFrom("_dineway_media_usage_sources").select("source_key").where("source_key", "=", source.sourceKey);
134
+ const check = expectedSource === null ? sql`NOT EXISTS ${exists}` : sql`EXISTS ${exists.where(this.sourceMatchExpression(expectedSource))}`;
135
+ return this.replaceGuarded(source, occurrences, check);
136
+ }
137
+ async replaceGuarded(source, occurrences, check) {
138
+ try {
139
+ await atomicBatch(this.db, {
140
+ checks: [check],
141
+ statements: this.prepareReplacement(source, ulid(), occurrences, (/* @__PURE__ */ new Date()).toISOString())
142
+ });
143
+ return {
144
+ replaced: true,
145
+ source: null
146
+ };
147
+ } catch (error) {
148
+ if (!(error instanceof AtomicWriteConflict)) throw error;
149
+ return {
150
+ replaced: false,
151
+ source: await this.findSource(source.sourceKey)
152
+ };
153
+ }
81
154
  }
82
155
  async markSourceAttempted(source) {
83
156
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -161,41 +234,24 @@ var MediaUsageRepository = class {
161
234
  return this.deleteSources([sourceKey]);
162
235
  }
163
236
  async deleteSourceIfCurrent(sourceKey, expectedCurrentGeneration) {
164
- let deleted = false;
165
- await withTransaction(this.db, async (trx) => {
166
- const result = await trx.deleteFrom("_dineway_media_usage_sources").where("source_key", "=", sourceKey).where("current_generation", "=", expectedCurrentGeneration).executeTakeFirst();
167
- deleted = Number(result.numDeletedRows ?? 0) > 0;
168
- if (!deleted) return;
169
- await trx.deleteFrom("_dineway_media_usage").where("source_key", "=", sourceKey).execute();
170
- });
237
+ const exists = this.db.selectFrom("_dineway_media_usage_sources").select("source_key").where("source_key", "=", sourceKey).where("current_generation", "=", expectedCurrentGeneration);
171
238
  return {
172
- deleted,
239
+ deleted: await this.deleteGuarded(sourceKey, [sql`EXISTS ${exists}`]),
173
240
  source: await this.findSource(sourceKey)
174
241
  };
175
242
  }
176
243
  async deleteSourceIfMatching(sourceKey, expectedSource) {
177
- let deleted = false;
178
- await withTransaction(this.db, async (trx) => {
179
- const result = await trx.deleteFrom("_dineway_media_usage_sources").where("source_key", "=", sourceKey).where(this.sourceMatchExpression(expectedSource)).executeTakeFirst();
180
- deleted = Number(result.numDeletedRows ?? 0) > 0;
181
- if (!deleted) return;
182
- await trx.deleteFrom("_dineway_media_usage").where("source_key", "=", sourceKey).execute();
183
- });
244
+ const exists = this.db.selectFrom("_dineway_media_usage_sources").select("source_key").where("source_key", "=", sourceKey).where(this.sourceMatchExpression(expectedSource));
184
245
  return {
185
- deleted,
246
+ deleted: await this.deleteGuarded(sourceKey, [sql`EXISTS ${exists}`]),
186
247
  source: await this.findSource(sourceKey)
187
248
  };
188
249
  }
189
250
  async deleteSourceIfMatchingContentAbsent(sourceKey, expectedSource, collectionSlug, contentId) {
190
251
  validateIdentifier(collectionSlug, "collection slug");
191
252
  const tableName = `ec_${collectionSlug}`;
192
- let deleted = false;
193
- await withTransaction(this.db, async (trx) => {
194
- const result = await trx.deleteFrom("_dineway_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();
195
- deleted = Number(result.numDeletedRows ?? 0) > 0;
196
- if (!deleted) return;
197
- await trx.deleteFrom("_dineway_media_usage").where("source_key", "=", sourceKey).execute();
198
- });
253
+ const exists = this.db.selectFrom("_dineway_media_usage_sources").select("source_key").where("source_key", "=", sourceKey).where(this.sourceMatchExpression(expectedSource));
254
+ const deleted = await this.deleteGuarded(sourceKey, [sql`EXISTS ${exists}`, sql`NOT EXISTS (SELECT 1 FROM ${sql.table(tableName)} WHERE id = ${contentId})`]);
199
255
  const contentPresent = deleted ? false : await this.contentRowExists(tableName, contentId);
200
256
  return {
201
257
  deleted,
@@ -203,6 +259,18 @@ var MediaUsageRepository = class {
203
259
  source: deleted || contentPresent ? null : await this.findSource(sourceKey)
204
260
  };
205
261
  }
262
+ async deleteGuarded(sourceKey, checks) {
263
+ try {
264
+ await atomicBatch(this.db, {
265
+ checks,
266
+ statements: [this.db.deleteFrom("_dineway_media_usage_sources").where("source_key", "=", sourceKey).compile(), this.db.deleteFrom("_dineway_media_usage").where("source_key", "=", sourceKey).compile()]
267
+ });
268
+ return true;
269
+ } catch (error) {
270
+ if (!(error instanceof AtomicWriteConflict)) throw error;
271
+ return false;
272
+ }
273
+ }
206
274
  async deleteSources(sourceKeys) {
207
275
  return this.deleteSourceKeys(sourceKeys);
208
276
  }
@@ -354,19 +422,13 @@ var MediaUsageRepository = class {
354
422
  async deleteSourceKeys(sourceKeys) {
355
423
  const uniqueSourceKeys = [...new Set(sourceKeys)];
356
424
  if (uniqueSourceKeys.length === 0) return 0;
357
- return withTransaction(this.db, async (trx) => {
358
- let deleted = 0;
359
- for (const sourceKeyBatch of chunks(uniqueSourceKeys, SQL_BATCH_SIZE)) {
360
- const result = await trx.deleteFrom("_dineway_media_usage_sources").where("source_key", "in", sourceKeyBatch).executeTakeFirst();
361
- deleted += Number(result.numDeletedRows ?? 0);
362
- await trx.deleteFrom("_dineway_media_usage").where("source_key", "in", sourceKeyBatch).execute();
363
- }
364
- return deleted;
365
- });
425
+ const statements = [];
426
+ for (const sourceKeyBatch of chunks(uniqueSourceKeys, SQL_BATCH_SIZE)) statements.push(this.db.deleteFrom("_dineway_media_usage_sources").where("source_key", "in", sourceKeyBatch).compile(), this.db.deleteFrom("_dineway_media_usage").where("source_key", "in", sourceKeyBatch).compile());
427
+ return (await atomicBatch(this.db, { statements })).reduce((total, result, index) => total + (index % 2 === 0 ? Number(result.numAffectedRows ?? 0) : 0), 0);
366
428
  }
367
- async insertOccurrences(db, sourceKey, generation, occurrences, now) {
368
- if (occurrences.length === 0) return;
369
- const rows = occurrences.map((occurrence) => ({
429
+ prepareOccurrences(sourceKey, generation, occurrences, now) {
430
+ if (occurrences.length === 0) return [];
431
+ return chunks(occurrences.map((occurrence) => ({
370
432
  id: ulid(),
371
433
  source_key: sourceKey,
372
434
  generation,
@@ -380,24 +442,15 @@ var MediaUsageRepository = class {
380
442
  media_kind: occurrence.mediaKind ?? null,
381
443
  mime_type: occurrence.mimeType ?? null,
382
444
  created_at: now
383
- }));
384
- for (const rowBatch of chunks(rows, OCCURRENCE_INSERT_BATCH_SIZE)) await db.insertInto("_dineway_media_usage").values(rowBatch).execute();
445
+ })), OCCURRENCE_INSERT_BATCH_SIZE).map((rowBatch) => this.db.insertInto("_dineway_media_usage").values(rowBatch).compile());
385
446
  }
386
- async upsertSource(db, source, generation, now) {
447
+ prepareReplacement(source, generation, occurrences, now) {
387
448
  const row = this.buildSourceRow(source, generation, now);
388
- await db.insertInto("_dineway_media_usage_sources").values(row).onConflict((oc) => oc.column("source_key").doUpdateSet(this.sourceUpdateSet(row))).execute();
449
+ return [...this.prepareOccurrences(source.sourceKey, generation, occurrences, now), this.db.insertInto("_dineway_media_usage_sources").values(row).onConflict((oc) => oc.column("source_key").doUpdateSet(this.sourceUpdateSet(row))).compile()];
389
450
  }
390
451
  async insertSourceIfAbsent(db, row) {
391
452
  return ((await db.insertInto("_dineway_media_usage_sources").values(row).onConflict((oc) => oc.column("source_key").doNothing()).executeTakeFirst()).numInsertedOrUpdatedRows ?? 0n) > 0n;
392
453
  }
393
- async updateSourceIfGeneration(db, row, expectedCurrentGeneration) {
394
- const result = await db.updateTable("_dineway_media_usage_sources").set(this.sourceUpdateSet(row)).where("source_key", "=", row.source_key).where("current_generation", "=", expectedCurrentGeneration).executeTakeFirst();
395
- return Number(result.numUpdatedRows ?? 0) > 0;
396
- }
397
- async updateSourceIfMatching(db, row, expectedSource) {
398
- const result = await db.updateTable("_dineway_media_usage_sources").set(this.sourceUpdateSet(row)).where("source_key", "=", row.source_key).where(this.sourceMatchExpression(expectedSource)).executeTakeFirst();
399
- return Number(result.numUpdatedRows ?? 0) > 0;
400
- }
401
454
  async updateAttemptedSourceIfMatching(db, source, row, expectedSource) {
402
455
  const result = await db.updateTable("_dineway_media_usage_sources").set(this.attemptedSourceUpdateSet(source, row)).where("source_key", "=", row.source_key).where(this.sourceMatchExpression(expectedSource)).executeTakeFirst();
403
456
  return Number(result.numUpdatedRows ?? 0) > 0;
@@ -680,90 +733,6 @@ function rowToIndexStatus(row) {
680
733
  };
681
734
  }
682
735
 
683
- //#endregion
684
- //#region src/media/usage/content-fields.ts
685
- var MediaUsageFieldDiscoveryError = class extends Error {
686
- constructor(message, code) {
687
- super(message);
688
- this.code = code;
689
- this.name = "MediaUsageFieldDiscoveryError";
690
- }
691
- };
692
- const DISPLAY_FIELD_SLUGS = ["title", "name"];
693
- const SUPPORTED_TOP_LEVEL_TYPES = [
694
- "file",
695
- "image",
696
- "portableText"
697
- ];
698
- async function loadContentMediaUsageFields(db, collectionSlug) {
699
- validateIdentifier(collectionSlug, "collection slug");
700
- const rows = await db.selectFrom("_dineway_fields").innerJoin("_dineway_collections", "_dineway_collections.id", "_dineway_fields.collection_id").select([
701
- "_dineway_fields.slug",
702
- "_dineway_fields.type",
703
- "_dineway_fields.validation"
704
- ]).where("_dineway_collections.slug", "=", collectionSlug).execute();
705
- const extractionFields = [];
706
- const rowBySlug = /* @__PURE__ */ new Map();
707
- for (const row of rows) {
708
- rowBySlug.set(row.slug, row);
709
- if (isSupportedTopLevelType(row.type)) {
710
- validateIdentifier(row.slug, "media usage field slug");
711
- extractionFields.push({
712
- slug: row.slug,
713
- type: row.type
714
- });
715
- continue;
716
- }
717
- if (row.type === "repeater") {
718
- validateIdentifier(row.slug, "media usage field slug");
719
- const subFields = normalizeRepeaterImageSubFields(row.validation);
720
- if (subFields.length > 0) extractionFields.push({
721
- slug: row.slug,
722
- type: "repeater",
723
- validation: { subFields }
724
- });
725
- }
726
- }
727
- extractionFields.sort((a, b) => a.slug.localeCompare(b.slug));
728
- return {
729
- extractionFields,
730
- displayFieldSlugs: DISPLAY_FIELD_SLUGS.filter((slug) => {
731
- if (!rowBySlug.has(slug)) return false;
732
- validateIdentifier(slug, "media usage display field slug");
733
- return true;
734
- })
735
- };
736
- }
737
- function normalizeRepeaterImageSubFields(rawValidation) {
738
- const validation = parseValidation(rawValidation);
739
- if (!isRecord$2(validation) || !Array.isArray(validation.subFields)) return [];
740
- const subFields = [];
741
- for (const subField of validation.subFields) {
742
- if (!isRecord$2(subField) || subField.type !== "image") continue;
743
- if (typeof subField.slug !== "string") continue;
744
- validateIdentifier(subField.slug, "media usage repeater sub-field slug");
745
- subFields.push({
746
- slug: subField.slug,
747
- type: "image"
748
- });
749
- }
750
- return subFields.toSorted((a, b) => a.slug.localeCompare(b.slug));
751
- }
752
- function parseValidation(rawValidation) {
753
- if (!rawValidation) return null;
754
- try {
755
- return JSON.parse(rawValidation);
756
- } catch {
757
- throw new MediaUsageFieldDiscoveryError("Repeater field validation must be valid JSON before media usage can be discovered", "INVALID_REPEATER_VALIDATION");
758
- }
759
- }
760
- function isSupportedTopLevelType(value) {
761
- return SUPPORTED_TOP_LEVEL_TYPES.includes(value);
762
- }
763
- function isRecord$2(value) {
764
- return typeof value === "object" && value !== null && !Array.isArray(value);
765
- }
766
-
767
736
  //#endregion
768
737
  //#region src/media/usage/extractor.ts
769
738
  const INTERNAL_MEDIA_PREFIX = "/_dineway/api/media/file/";
@@ -1454,26 +1423,34 @@ async function refreshContentMediaUsageAfterWrite(db, collectionSlug, contentId)
1454
1423
  const result = await refreshContentMediaUsage(db, collectionSlug, contentId);
1455
1424
  if (!result.success) console.error(`[media-usage] Usage refresh for ${collectionSlug}/${contentId} finished with ${result.errorCode}`);
1456
1425
  }
1457
- async function markContentMediaUsageCollectionStale(db, collectionSlug, lastErrorCode) {
1426
+ function prepareContentMediaUsageCollectionStale(db, collectionSlug, lastErrorCode) {
1458
1427
  validateIdentifier(collectionSlug, "collection slug");
1459
- const repo = new MediaUsageRepository(db);
1460
- const identity = {
1461
- adapterId: CONTENT_MEDIA_USAGE_ADAPTER_ID,
1462
- scopeType: CONTENT_MEDIA_USAGE_COLLECTION_SCOPE,
1463
- scopeKey: collectionSlug
1464
- };
1465
- const existing = await repo.findIndexStatus(identity);
1466
- await repo.upsertIndexStatus({
1467
- ...identity,
1428
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1429
+ return db.insertInto("_dineway_media_usage_index_status").values({
1430
+ adapter_id: CONTENT_MEDIA_USAGE_ADAPTER_ID,
1431
+ scope_type: CONTENT_MEDIA_USAGE_COLLECTION_SCOPE,
1432
+ scope_key: collectionSlug,
1468
1433
  status: "stale",
1469
- schemaVersion: existing?.schemaVersion ?? CONTENT_SOURCE_SCHEMA_VERSION,
1470
- startedAt: existing?.startedAt ?? null,
1471
- completedAt: existing?.completedAt ?? null,
1472
- cursor: existing?.cursor ?? null,
1473
- indexedSourceCount: existing?.indexedSourceCount ?? 0,
1474
- failedSourceCount: existing?.failedSourceCount ?? 0,
1475
- lastErrorCode
1476
- });
1434
+ schema_version: CONTENT_SOURCE_SCHEMA_VERSION,
1435
+ started_at: null,
1436
+ completed_at: null,
1437
+ cursor: null,
1438
+ indexed_source_count: 0,
1439
+ failed_source_count: 0,
1440
+ last_error_code: lastErrorCode,
1441
+ updated_at: now
1442
+ }).onConflict((conflict) => conflict.columns([
1443
+ "adapter_id",
1444
+ "scope_type",
1445
+ "scope_key"
1446
+ ]).doUpdateSet({
1447
+ status: "stale",
1448
+ last_error_code: lastErrorCode,
1449
+ updated_at: now
1450
+ })).compile();
1451
+ }
1452
+ async function markContentMediaUsageCollectionStale(db, collectionSlug, lastErrorCode) {
1453
+ await db.executeQuery(prepareContentMediaUsageCollectionStale(db, collectionSlug, lastErrorCode));
1477
1454
  }
1478
1455
  async function markContentMediaUsageCollectionStaleSafely(db, collectionSlug, lastErrorCode) {
1479
1456
  try {
@@ -1573,4 +1550,4 @@ function isContentUsageLockMap(value) {
1573
1550
  }
1574
1551
 
1575
1552
  //#endregion
1576
- export { markContentMediaUsageCollectionStaleSafely as a, markContentMediaUsageCollectionStale as i, deleteContentMediaUsageCollection as n, refreshContentMediaUsageAfterWrite as o, findNonTranslatableSiblingContentIds as r, loadContentMediaUsageFields as s, deleteContentMediaUsage as t };
1553
+ export { markContentMediaUsageCollectionStaleSafely as a, loadContentMediaUsageFields as c, markContentMediaUsageCollectionStale as i, deleteContentMediaUsageCollection as n, prepareContentMediaUsageCollectionStale as o, findNonTranslatableSiblingContentIds as r, refreshContentMediaUsageAfterWrite as s, deleteContentMediaUsage as t };
@@ -1,16 +1,18 @@
1
- import { n as validateJsonFieldName } from "./validate-VPnKoIzW.mjs";
2
- import { c as jsonExtractExpr } from "./dialect-helpers-fk43GbDb.mjs";
3
- import { i as encodeCursor, r as decodeCursor } from "./types-BpSTdH1H.mjs";
4
- import { t as ContentRepository } from "./content-CVCrcuvD.mjs";
5
- import { t as MediaRepository } from "./media-dvRjj4po.mjs";
6
- import { t as UserRepository } from "./user-D0NJ7gYf.mjs";
7
- import { t as OptionsRepository } from "./options-1dBRkoCl.mjs";
8
- import { t as withTransaction } from "./transaction-BGQgnwUi.mjs";
9
- import { t as enrichImageMetadata } from "./enrich-KErvJOuI.mjs";
10
- import { t as SeoRepository } from "./seo-DWHdo5aW.mjs";
11
- import { a as markContentMediaUsageCollectionStaleSafely } from "./content-refresh-QvBIyb_g.mjs";
12
- import { a as validateExternalUrl, i as stripCredentialHeaders, t as SsrfError } from "./ssrf-C7tTSD1r.mjs";
13
- import { t as CronAccessImpl } from "./cron-mGVPQ5e6.mjs";
1
+ import { atomicBatch } from "./database/batch.mjs";
2
+ import { n as validateJsonFieldName } from "./validate-Co3j6T_K.mjs";
3
+ import { c as jsonExtractExpr } from "./dialect-helpers-C6xtO-Ui.mjs";
4
+ import { i as encodeCursor, r as decodeCursor } from "./types-BqxIv8Il.mjs";
5
+ import { t as contentWriteChecks } from "./atomic-authority-CnBQJ14T.mjs";
6
+ import { o as invalidateCollectionCache } from "./object-cache-BGjIlY9s.mjs";
7
+ import { t as ContentRepository } from "./content-NobcQti0.mjs";
8
+ import { t as MediaRepository } from "./media-3fK0u-bo.mjs";
9
+ import { t as UserRepository } from "./user-1-YV30lf.mjs";
10
+ import { t as OptionsRepository } from "./options-BcqHWpc-.mjs";
11
+ import { t as enrichImageMetadata } from "./enrich-BjF-J4sF.mjs";
12
+ import { o as prepareContentMediaUsageCollectionStale } from "./content-refresh-l4mPoGeX.mjs";
13
+ import { a as validateExternalUrl, i as stripCredentialHeaders, t as SsrfError } from "./ssrf-LN16WMip.mjs";
14
+ import { t as SeoRepository } from "./seo-BOTuCeh-.mjs";
15
+ import { t as CronAccessImpl } from "./cron-D7zB6m8i.mjs";
14
16
  import { sql } from "kysely";
15
17
  import { ulid } from "ulidx";
16
18
 
@@ -223,26 +225,24 @@ var PluginStorageRepository = class {
223
225
  async putMany(items) {
224
226
  if (items.length === 0) return;
225
227
  const now = (/* @__PURE__ */ new Date()).toISOString();
226
- await withTransaction(this.db, async (trx) => {
227
- for (const item of items) {
228
- const jsonData = JSON.stringify(item.data);
229
- await trx.insertInto("_plugin_storage").values({
230
- plugin_id: this.pluginId,
231
- collection: this.collection,
232
- id: item.id,
233
- data: jsonData,
234
- created_at: now,
235
- updated_at: now
236
- }).onConflict((oc) => oc.columns([
237
- "plugin_id",
238
- "collection",
239
- "id"
240
- ]).doUpdateSet({
241
- data: jsonData,
242
- updated_at: now
243
- })).execute();
244
- }
245
- });
228
+ await atomicBatch(this.db, { statements: items.map((item) => {
229
+ const jsonData = JSON.stringify(item.data);
230
+ return this.db.insertInto("_plugin_storage").values({
231
+ plugin_id: this.pluginId,
232
+ collection: this.collection,
233
+ id: item.id,
234
+ data: jsonData,
235
+ created_at: now,
236
+ updated_at: now
237
+ }).onConflict((oc) => oc.columns([
238
+ "plugin_id",
239
+ "collection",
240
+ "id"
241
+ ]).doUpdateSet({
242
+ data: jsonData,
243
+ updated_at: now
244
+ })).compile();
245
+ }) });
246
246
  }
247
247
  /**
248
248
  * Delete multiple documents
@@ -330,6 +330,12 @@ var PluginStorageRepository = class {
330
330
  //#endregion
331
331
  //#region src/plugins/context.ts
332
332
  /**
333
+ * Plugin Context v2
334
+ *
335
+ * Creates the unified context object provided to plugins in all hooks and routes.
336
+ *
337
+ */
338
+ /**
333
339
  * Create KV accessor for a plugin
334
340
  * All keys are automatically prefixed with the plugin ID
335
341
  */
@@ -488,58 +494,70 @@ function createContentAccessWithWrite(db) {
488
494
  ...createContentAccess(db),
489
495
  async create(collection, data) {
490
496
  const { fields, seo } = splitSeoFromInput(data);
491
- let contentMutated = false;
492
- try {
493
- const created = await withTransaction(db, async (trx) => {
494
- const trxContentRepo = new ContentRepository(trx);
495
- const trxSeoRepo = new SeoRepository(trx);
496
- const hasSeo = await assertSeoEnabled(trxSeoRepo, collection, seo);
497
- const item = await trxContentRepo.create({
498
- type: collection,
499
- data: fields
500
- });
501
- contentMutated = true;
502
- const result = toPluginContentItem(item);
503
- if (hasSeo) result.seo = seo !== void 0 ? await trxSeoRepo.upsert(collection, item.id, seo) : await trxSeoRepo.get(collection, item.id);
504
- return result;
505
- });
506
- await markContentMediaUsageCollectionStaleSafely(db, collection, "CONTENT_USAGE_STALE");
507
- return created;
508
- } catch (error) {
509
- if (contentMutated) await markContentMediaUsageCollectionStaleSafely(db, collection, "CONTENT_USAGE_STALE");
510
- throw error;
497
+ const repo = new ContentRepository(db);
498
+ const seoRepo = new SeoRepository(db);
499
+ const hasSeo = await assertSeoEnabled(seoRepo, collection, seo);
500
+ const prepared = await repo.prepareCreate({
501
+ type: collection,
502
+ data: fields
503
+ });
504
+ const statements = [...prepared.batch.statements];
505
+ if (hasSeo && seo !== void 0) {
506
+ const write = seoRepo.prepareUpsert(collection, prepared.id, seo);
507
+ if (write) statements.push(write);
511
508
  }
509
+ statements.push(prepareContentMediaUsageCollectionStale(db, collection, "CONTENT_USAGE_STALE"));
510
+ await atomicBatch(db, {
511
+ checks: [...prepared.batch.checks ?? [], sql`COALESCE((SELECT has_seo FROM _dineway_collections WHERE slug = ${collection}), 0) = ${hasSeo ? 1 : 0}`],
512
+ statements
513
+ });
514
+ invalidateCollectionCache(collection);
515
+ const item = await repo.findById(collection, prepared.id);
516
+ if (!item) throw new Error("Content not found");
517
+ const result = toPluginContentItem(item);
518
+ if (hasSeo) result.seo = await seoRepo.get(collection, item.id);
519
+ return result;
512
520
  },
513
521
  async update(collection, id, data) {
514
522
  const { fields, seo } = splitSeoFromInput(data);
515
523
  const hasFieldUpdates = Object.keys(fields).length > 0;
516
- let contentMutated = false;
517
- try {
518
- const updated = await withTransaction(db, async (trx) => {
519
- const trxContentRepo = new ContentRepository(trx);
520
- const trxSeoRepo = new SeoRepository(trx);
521
- const hasSeo = await assertSeoEnabled(trxSeoRepo, collection, seo);
522
- const item = hasFieldUpdates ? await trxContentRepo.update(collection, id, { data: fields }) : await (async () => {
523
- const existing = await trxContentRepo.findById(collection, id);
524
- if (!existing) throw new Error("Content not found");
525
- return existing;
526
- })();
527
- if (hasFieldUpdates) contentMutated = true;
528
- const result = toPluginContentItem(item);
529
- if (hasSeo) result.seo = seo !== void 0 ? await trxSeoRepo.upsert(collection, item.id, seo) : await trxSeoRepo.get(collection, item.id);
530
- return result;
531
- });
532
- if (hasFieldUpdates) await markContentMediaUsageCollectionStaleSafely(db, collection, "CONTENT_USAGE_STALE");
533
- return updated;
534
- } catch (error) {
535
- if (contentMutated) await markContentMediaUsageCollectionStaleSafely(db, collection, "CONTENT_USAGE_STALE");
536
- throw error;
524
+ const repo = new ContentRepository(db);
525
+ const seoRepo = new SeoRepository(db);
526
+ const hasSeo = await assertSeoEnabled(seoRepo, collection, seo);
527
+ const snapshot = await repo.snapshot(collection, id);
528
+ if (!snapshot) throw new Error("Content not found");
529
+ const statements = hasFieldUpdates ? [repo.prepareUpdate(collection, id, { data: fields })] : [];
530
+ if (hasSeo && seo !== void 0) {
531
+ const write = seoRepo.prepareUpsert(collection, id, seo);
532
+ if (write) statements.push(write);
537
533
  }
534
+ if (hasFieldUpdates) statements.push(prepareContentMediaUsageCollectionStale(db, collection, "CONTENT_USAGE_STALE"));
535
+ await atomicBatch(db, {
536
+ checks: [
537
+ snapshot.check,
538
+ ...contentWriteChecks(collection, id, "edit"),
539
+ sql`COALESCE((SELECT has_seo FROM _dineway_collections WHERE slug = ${collection}), 0) = ${hasSeo ? 1 : 0}`
540
+ ],
541
+ statements
542
+ });
543
+ invalidateCollectionCache(collection);
544
+ const item = await repo.findById(collection, id);
545
+ if (!item) throw new Error("Content not found");
546
+ const result = toPluginContentItem(item);
547
+ if (hasSeo) result.seo = await seoRepo.get(collection, id);
548
+ return result;
538
549
  },
539
550
  async delete(collection, id) {
540
- const deleted = await new ContentRepository(db).delete(collection, id);
541
- if (deleted) await markContentMediaUsageCollectionStaleSafely(db, collection, "CONTENT_USAGE_STALE");
542
- return deleted;
551
+ const repo = new ContentRepository(db);
552
+ const snapshot = await repo.snapshot(collection, id);
553
+ if (!snapshot) return false;
554
+ const prepared = repo.prepareDelete(collection, id);
555
+ const [result] = await atomicBatch(db, {
556
+ checks: [snapshot.check, ...prepared.checks ?? []],
557
+ statements: [...prepared.statements, prepareContentMediaUsageCollectionStale(db, collection, "CONTENT_USAGE_STALE")]
558
+ });
559
+ invalidateCollectionCache(collection);
560
+ return (result?.numAffectedRows ?? 0n) > 0n;
543
561
  }
544
562
  };
545
563
  }