emdash 0.34.0 → 0.35.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 (508) hide show
  1. package/dist/{adapters-34EN2eXO.d.mts → adapters-Bb1vG41D.d.mts} +8 -1
  2. package/dist/adapters-Bb1vG41D.d.mts.map +1 -0
  3. package/dist/api/route-utils.d.mts +3 -3
  4. package/dist/api/route-utils.mjs +9 -9
  5. package/dist/api/schemas/index.d.mts +1 -1
  6. package/dist/api/schemas/index.mjs +1 -1
  7. package/dist/{api-DdAsirBe.mjs → api-BeBglVxU.mjs} +10 -10
  8. package/dist/{api-DdAsirBe.mjs.map → api-BeBglVxU.mjs.map} +1 -1
  9. package/dist/{api-tokens-CFXu8F_2.mjs → api-tokens-KO24G1Fd.mjs} +2 -2
  10. package/dist/{api-tokens-CFXu8F_2.mjs.map → api-tokens-KO24G1Fd.mjs.map} +1 -1
  11. package/dist/{apply-D5zfeD09.mjs → apply-kUDt80-G.mjs} +16 -16
  12. package/dist/{apply-D5zfeD09.mjs.map → apply-kUDt80-G.mjs.map} +1 -1
  13. package/dist/astro/index.d.mts +12 -12
  14. package/dist/astro/index.d.mts.map +1 -1
  15. package/dist/astro/index.mjs +71 -15
  16. package/dist/astro/index.mjs.map +1 -1
  17. package/dist/astro/middleware/auth.d.mts +10 -10
  18. package/dist/astro/middleware/auth.mjs +4 -4
  19. package/dist/astro/middleware/redirect.mjs +2 -2
  20. package/dist/astro/middleware/request-context.mjs +1 -1
  21. package/dist/astro/middleware/setup.mjs +1 -1
  22. package/dist/astro/middleware.d.mts +10 -10
  23. package/dist/astro/middleware.d.mts.map +1 -1
  24. package/dist/astro/middleware.mjs +143 -74
  25. package/dist/astro/middleware.mjs.map +1 -1
  26. package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +1 -1
  27. package/dist/astro/routes/api/admin/allowed-domains/index.mjs +1 -1
  28. package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +2 -2
  29. package/dist/astro/routes/api/admin/api-tokens/index.mjs +2 -2
  30. package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +2 -2
  31. package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +3 -3
  32. package/dist/astro/routes/api/admin/byline-fields/index.mjs +3 -3
  33. package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +3 -3
  34. package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +7 -7
  35. package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +7 -7
  36. package/dist/astro/routes/api/admin/bylines/index.mjs +7 -7
  37. package/dist/astro/routes/api/admin/comments/_id_/status.mjs +5 -5
  38. package/dist/astro/routes/api/admin/comments/_id_.mjs +2 -2
  39. package/dist/astro/routes/api/admin/comments/bulk.mjs +3 -3
  40. package/dist/astro/routes/api/admin/comments/counts.mjs +2 -2
  41. package/dist/astro/routes/api/admin/comments/index.mjs +3 -3
  42. package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +1 -1
  43. package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +1 -1
  44. package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +7 -7
  45. package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +7 -7
  46. package/dist/astro/routes/api/admin/media-usage/repair.mjs +4 -4
  47. package/dist/astro/routes/api/admin/media-usage/work/index.mjs +7 -7
  48. package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +7 -7
  49. package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +1 -1
  50. package/dist/astro/routes/api/admin/oauth-clients/index.mjs +1 -1
  51. package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +28 -28
  52. package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +28 -28
  53. package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +28 -28
  54. package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +1 -1
  55. package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +28 -28
  56. package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +28 -28
  57. package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +28 -28
  58. package/dist/astro/routes/api/admin/plugins/index.mjs +28 -28
  59. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +1 -1
  60. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +28 -28
  61. package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +28 -28
  62. package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +28 -28
  63. package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +28 -28
  64. package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +29 -29
  65. package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +28 -28
  66. package/dist/astro/routes/api/admin/plugins/registry/install.mjs +29 -29
  67. package/dist/astro/routes/api/admin/plugins/updates.mjs +28 -28
  68. package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +28 -28
  69. package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +1 -1
  70. package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +28 -28
  71. package/dist/astro/routes/api/admin/users/_id_/index.mjs +1 -1
  72. package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +1 -1
  73. package/dist/astro/routes/api/admin/users/index.mjs +1 -1
  74. package/dist/astro/routes/api/auth/dev-bypass.d.mts.map +1 -1
  75. package/dist/astro/routes/api/auth/dev-bypass.mjs +2 -6
  76. package/dist/astro/routes/api/auth/dev-bypass.mjs.map +1 -1
  77. package/dist/astro/routes/api/auth/invite/complete.mjs +3 -3
  78. package/dist/astro/routes/api/auth/invite/index.mjs +2 -2
  79. package/dist/astro/routes/api/auth/invite/register-options.mjs +3 -3
  80. package/dist/astro/routes/api/auth/logout.mjs +1 -1
  81. package/dist/astro/routes/api/auth/magic-link/send.mjs +3 -3
  82. package/dist/astro/routes/api/auth/magic-link/verify.mjs +1 -1
  83. package/dist/astro/routes/api/auth/me.mjs +2 -2
  84. package/dist/astro/routes/api/auth/mode.mjs +1 -1
  85. package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +2 -2
  86. package/dist/astro/routes/api/auth/oauth/_provider_.mjs +1 -1
  87. package/dist/astro/routes/api/auth/passkey/_id_.mjs +1 -1
  88. package/dist/astro/routes/api/auth/passkey/options.mjs +4 -4
  89. package/dist/astro/routes/api/auth/passkey/register/options.mjs +3 -3
  90. package/dist/astro/routes/api/auth/passkey/register/verify.mjs +3 -3
  91. package/dist/astro/routes/api/auth/passkey/verify.mjs +3 -3
  92. package/dist/astro/routes/api/auth/signup/complete.mjs +3 -3
  93. package/dist/astro/routes/api/auth/signup/request.mjs +3 -3
  94. package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +5 -5
  95. package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +4 -4
  96. package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +1 -1
  97. package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +1 -1
  98. package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +1 -1
  99. package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +1 -1
  100. package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +3 -3
  101. package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +2 -2
  102. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +9 -9
  103. package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +9 -9
  104. package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +1 -1
  105. package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +1 -1
  106. package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +2 -2
  107. package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +6 -6
  108. package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +1 -1
  109. package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +1 -1
  110. package/dist/astro/routes/api/content/_collection_/_id_.mjs +2 -2
  111. package/dist/astro/routes/api/content/_collection_/authors.mjs +1 -1
  112. package/dist/astro/routes/api/content/_collection_/index.mjs +2 -2
  113. package/dist/astro/routes/api/content/_collection_/trash.mjs +2 -2
  114. package/dist/astro/routes/api/dashboard.mjs +4 -4
  115. package/dist/astro/routes/api/import/probe.d.mts +3 -3
  116. package/dist/astro/routes/api/import/probe.mjs +5 -5
  117. package/dist/astro/routes/api/import/wordpress/analyze.mjs +1 -1
  118. package/dist/astro/routes/api/import/wordpress/execute.d.mts +11 -11
  119. package/dist/astro/routes/api/import/wordpress/execute.mjs +7 -7
  120. package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -10
  121. package/dist/astro/routes/api/import/wordpress/media.mjs +2 -2
  122. package/dist/astro/routes/api/import/wordpress/prepare.mjs +4 -4
  123. package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +11 -11
  124. package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +4 -4
  125. package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
  126. package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +5 -5
  127. package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +11 -11
  128. package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +11 -11
  129. package/dist/astro/routes/api/manifest.mjs +2 -2
  130. package/dist/astro/routes/api/mcp.mjs +38 -38
  131. package/dist/astro/routes/api/media/_id_/confirm.mjs +2 -2
  132. package/dist/astro/routes/api/media/_id_/upload.mjs +2 -2
  133. package/dist/astro/routes/api/media/_id_/usage.mjs +6 -6
  134. package/dist/astro/routes/api/media/_id_.mjs +5 -5
  135. package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +1 -1
  136. package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +1 -1
  137. package/dist/astro/routes/api/media/providers/index.mjs +1 -1
  138. package/dist/astro/routes/api/media/upload-url.mjs +3 -3
  139. package/dist/astro/routes/api/media.mjs +5 -5
  140. package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +3 -3
  141. package/dist/astro/routes/api/menus/_name_/items.mjs +3 -3
  142. package/dist/astro/routes/api/menus/_name_/reorder.mjs +3 -3
  143. package/dist/astro/routes/api/menus/_name_/translations.mjs +3 -3
  144. package/dist/astro/routes/api/menus/_name_.mjs +3 -3
  145. package/dist/astro/routes/api/menus/index.mjs +3 -3
  146. package/dist/astro/routes/api/oauth/authorize.mjs +5 -5
  147. package/dist/astro/routes/api/oauth/device/authorize.mjs +3 -3
  148. package/dist/astro/routes/api/oauth/device/code.mjs +4 -4
  149. package/dist/astro/routes/api/oauth/device/token.mjs +4 -4
  150. package/dist/astro/routes/api/oauth/register.mjs +1 -1
  151. package/dist/astro/routes/api/oauth/token/refresh.mjs +3 -3
  152. package/dist/astro/routes/api/oauth/token/revoke.mjs +3 -3
  153. package/dist/astro/routes/api/oauth/token.mjs +4 -4
  154. package/dist/astro/routes/api/openapi.json.mjs +1 -1
  155. package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +3 -3
  156. package/dist/astro/routes/api/redirects/404s/index.mjs +3 -3
  157. package/dist/astro/routes/api/redirects/404s/summary.mjs +3 -3
  158. package/dist/astro/routes/api/redirects/_id_.mjs +4 -4
  159. package/dist/astro/routes/api/redirects/index.mjs +4 -4
  160. package/dist/astro/routes/api/relations/_id_/index.mjs +9 -9
  161. package/dist/astro/routes/api/relations/_id_/translations.mjs +8 -8
  162. package/dist/astro/routes/api/relations/index.mjs +9 -9
  163. package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +1 -1
  164. package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +1 -1
  165. package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +28 -28
  166. package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +28 -28
  167. package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +28 -28
  168. package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +28 -28
  169. package/dist/astro/routes/api/schema/collections/index.mjs +28 -28
  170. package/dist/astro/routes/api/schema/collections/reorder.mjs +28 -28
  171. package/dist/astro/routes/api/schema/index.mjs +6 -6
  172. package/dist/astro/routes/api/schema/orphans/_slug_.mjs +28 -28
  173. package/dist/astro/routes/api/schema/orphans/index.mjs +28 -28
  174. package/dist/astro/routes/api/search/enable.mjs +5 -5
  175. package/dist/astro/routes/api/search/index.mjs +4 -4
  176. package/dist/astro/routes/api/search/rebuild.mjs +5 -5
  177. package/dist/astro/routes/api/search/stats.mjs +4 -4
  178. package/dist/astro/routes/api/search/suggest.mjs +4 -4
  179. package/dist/astro/routes/api/sections/_slug_.mjs +4 -4
  180. package/dist/astro/routes/api/sections/index.mjs +4 -4
  181. package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +3 -3
  182. package/dist/astro/routes/api/settings/backups/archives/index.mjs +3 -3
  183. package/dist/astro/routes/api/settings/backups/export.mjs +3 -3
  184. package/dist/astro/routes/api/settings/backups/index.mjs +3 -3
  185. package/dist/astro/routes/api/settings/email.mjs +1 -1
  186. package/dist/astro/routes/api/settings.mjs +5 -5
  187. package/dist/astro/routes/api/setup/admin-verify.mjs +4 -4
  188. package/dist/astro/routes/api/setup/admin.mjs +4 -4
  189. package/dist/astro/routes/api/setup/dev-bypass.d.mts.map +1 -1
  190. package/dist/astro/routes/api/setup/dev-bypass.mjs +18 -21
  191. package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
  192. package/dist/astro/routes/api/setup/index.d.mts.map +1 -1
  193. package/dist/astro/routes/api/setup/index.mjs +15 -21
  194. package/dist/astro/routes/api/setup/index.mjs.map +1 -1
  195. package/dist/astro/routes/api/setup/status.mjs +2 -2
  196. package/dist/astro/routes/api/snapshot.mjs +4 -4
  197. package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +6 -6
  198. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +6 -6
  199. package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +6 -6
  200. package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +6 -6
  201. package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +6 -6
  202. package/dist/astro/routes/api/taxonomies/_name_.mjs +6 -6
  203. package/dist/astro/routes/api/taxonomies/index.mjs +6 -6
  204. package/dist/astro/routes/api/themes/preview.mjs +2 -2
  205. package/dist/astro/routes/api/typegen.mjs +3 -3
  206. package/dist/astro/routes/api/well-known/auth.mjs +1 -1
  207. package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +1 -1
  208. package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +1 -1
  209. package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +2 -2
  210. package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +4 -4
  211. package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +4 -4
  212. package/dist/astro/routes/api/widget-areas/_name_.mjs +3 -3
  213. package/dist/astro/routes/api/widget-areas/index.mjs +4 -4
  214. package/dist/astro/routes/robots.txt.mjs +2 -2
  215. package/dist/astro/routes/sitemap-_collection_.xml.mjs +2 -2
  216. package/dist/astro/routes/sitemap.xml.mjs +2 -2
  217. package/dist/astro/types.d.mts +14 -14
  218. package/dist/auth/providers/github.d.mts +1 -1
  219. package/dist/auth/providers/google.d.mts +1 -1
  220. package/dist/{authorize-1iFJzPaZ.mjs → authorize-DUElxgOQ.mjs} +1 -1
  221. package/dist/{authorize-1iFJzPaZ.mjs.map → authorize-DUElxgOQ.mjs.map} +1 -1
  222. package/dist/{backup-LHjIAVNP.mjs → backup-DWYpJlLj.mjs} +3 -3
  223. package/dist/{backup-LHjIAVNP.mjs.map → backup-DWYpJlLj.mjs.map} +1 -1
  224. package/dist/{bundle-CBEXrBnb.mjs → bundle-vn56sLos.mjs} +5 -5
  225. package/dist/{bundle-CBEXrBnb.mjs.map → bundle-vn56sLos.mjs.map} +1 -1
  226. package/dist/{byline-fields-C5S8wygO.mjs → byline-fields-txaLGoME.mjs} +1 -1
  227. package/dist/{byline-fields-C5S8wygO.mjs.map → byline-fields-txaLGoME.mjs.map} +1 -1
  228. package/dist/{byline-pEcoDps8.mjs → byline-yjvWq4ip.mjs} +4 -4
  229. package/dist/{byline-pEcoDps8.mjs.map → byline-yjvWq4ip.mjs.map} +1 -1
  230. package/dist/{bylines-DJfSfXCL.mjs → bylines-Bu7pchQ4.mjs} +3 -3
  231. package/dist/{bylines-DJfSfXCL.mjs.map → bylines-Bu7pchQ4.mjs.map} +1 -1
  232. package/dist/{bylines-BWemdX2k.mjs → bylines-DjXS5p0P.mjs} +5 -5
  233. package/dist/{bylines-BWemdX2k.mjs.map → bylines-DjXS5p0P.mjs.map} +1 -1
  234. package/dist/{cache-CBJaDy_E.mjs → cache-C46-3Irl.mjs} +2 -2
  235. package/dist/{cache-CBJaDy_E.mjs.map → cache-C46-3Irl.mjs.map} +1 -1
  236. package/dist/{challenge-store-CZyFVaad.mjs → challenge-store-SIL5DsF2.mjs} +1 -1
  237. package/dist/{challenge-store-CZyFVaad.mjs.map → challenge-store-SIL5DsF2.mjs.map} +1 -1
  238. package/dist/{chunks-DfPax1I0.mjs → chunks-fiZ8G9RJ.mjs} +2 -2
  239. package/dist/{chunks-DfPax1I0.mjs.map → chunks-fiZ8G9RJ.mjs.map} +1 -1
  240. package/dist/cli/index.mjs +551 -51
  241. package/dist/cli/index.mjs.map +1 -1
  242. package/dist/client/cf-access.d.mts +1 -1
  243. package/dist/client/index.d.mts +2 -2
  244. package/dist/client/index.mjs +2 -2
  245. package/dist/{collection-deletion-C8BugSGz.mjs → collection-deletion-DQPvMD8R.mjs} +2 -2
  246. package/dist/{collection-deletion-C8BugSGz.mjs.map → collection-deletion-DQPvMD8R.mjs.map} +1 -1
  247. package/dist/{comment-reaction-D6qfHKBc.mjs → comment-reaction-D-2J84UE.mjs} +2 -2
  248. package/dist/{comment-reaction-D6qfHKBc.mjs.map → comment-reaction-D-2J84UE.mjs.map} +1 -1
  249. package/dist/{comments-CTOuhTSX.mjs → comments-CTfZtLmM.mjs} +1 -1
  250. package/dist/{comments-CTOuhTSX.mjs.map → comments-CTfZtLmM.mjs.map} +1 -1
  251. package/dist/config-COQzTe5Q.d.mts +34 -0
  252. package/dist/config-COQzTe5Q.d.mts.map +1 -0
  253. package/dist/{content-BNfwh7xX.mjs → content-ZHCc1ngN.mjs} +3 -3
  254. package/dist/{content-BNfwh7xX.mjs.map → content-ZHCc1ngN.mjs.map} +1 -1
  255. package/dist/{content-list-query-DhQ84eVV.d.mts → content-list-query-wJ2WN8Vp.d.mts} +1 -1
  256. package/dist/{content-list-query-DhQ84eVV.d.mts.map → content-list-query-wJ2WN8Vp.d.mts.map} +1 -1
  257. package/dist/{content-refresh-DNERP4-f.mjs → content-refresh-B_8SJzuU.mjs} +2 -2
  258. package/dist/{content-refresh-DNERP4-f.mjs.map → content-refresh-B_8SJzuU.mjs.map} +1 -1
  259. package/dist/{context-DRgOvSnW.mjs → context-ZldbZcle.mjs} +7 -7
  260. package/dist/{context-DRgOvSnW.mjs.map → context-ZldbZcle.mjs.map} +1 -1
  261. package/dist/{dashboard-CB8J89rJ.mjs → dashboard-DvHbk_cv.mjs} +3 -3
  262. package/dist/{dashboard-CB8J89rJ.mjs.map → dashboard-DvHbk_cv.mjs.map} +1 -1
  263. package/dist/db/index.d.mts +4 -4
  264. package/dist/db/index.mjs +30 -7
  265. package/dist/db/index.mjs.map +1 -1
  266. package/dist/db/libsql-migrations.d.mts +11 -0
  267. package/dist/db/libsql-migrations.d.mts.map +1 -0
  268. package/dist/db/libsql-migrations.mjs +57 -0
  269. package/dist/db/libsql-migrations.mjs.map +1 -0
  270. package/dist/db/libsql.d.mts +1 -1
  271. package/dist/db/postgres-migrations.d.mts +10 -0
  272. package/dist/db/postgres-migrations.d.mts.map +1 -0
  273. package/dist/db/postgres-migrations.mjs +47 -0
  274. package/dist/db/postgres-migrations.mjs.map +1 -0
  275. package/dist/db/postgres.d.mts +1 -1
  276. package/dist/db/sqlite-migrations.d.mts +10 -0
  277. package/dist/db/sqlite-migrations.d.mts.map +1 -0
  278. package/dist/db/sqlite-migrations.mjs +28 -0
  279. package/dist/db/sqlite-migrations.mjs.map +1 -0
  280. package/dist/db/sqlite.d.mts +1 -1
  281. package/dist/{deferred-tasks-BMsa9F64.d.mts → deferred-tasks-SDWxrgzJ.d.mts} +1 -1
  282. package/dist/{deferred-tasks-BMsa9F64.d.mts.map → deferred-tasks-SDWxrgzJ.d.mts.map} +1 -1
  283. package/dist/{device-flow-CaioYGK3.mjs → device-flow-C0GdD_z8.mjs} +4 -4
  284. package/dist/{device-flow-CaioYGK3.mjs.map → device-flow-C0GdD_z8.mjs.map} +1 -1
  285. package/dist/direct-executor-CDXeJCSs.mjs +85 -0
  286. package/dist/direct-executor-CDXeJCSs.mjs.map +1 -0
  287. package/dist/{escape-C_aLKP3H.mjs → escape-DUY2r2Zs.mjs} +1 -1
  288. package/dist/{escape-C_aLKP3H.mjs.map → escape-DUY2r2Zs.mjs.map} +1 -1
  289. package/dist/{field-defs-cache-hg6QkjV9.mjs → field-defs-cache-BzwBlJrR.mjs} +2 -2
  290. package/dist/{field-defs-cache-hg6QkjV9.mjs.map → field-defs-cache-BzwBlJrR.mjs.map} +1 -1
  291. package/dist/{fts-manager-CZ-5dVwJ.mjs → fts-manager-DyZEohZC.mjs} +2 -2
  292. package/dist/{fts-manager-CZ-5dVwJ.mjs.map → fts-manager-DyZEohZC.mjs.map} +1 -1
  293. package/dist/{hreflang-DNswoYsi.mjs → hreflang-BBe83kKa.mjs} +5 -5
  294. package/dist/{hreflang-DNswoYsi.mjs.map → hreflang-BBe83kKa.mjs.map} +1 -1
  295. package/dist/{hreflang-D3Uehfv2.d.mts → hreflang-DwT2E0Sa.d.mts} +2 -2
  296. package/dist/{hreflang-D3Uehfv2.d.mts.map → hreflang-DwT2E0Sa.d.mts.map} +1 -1
  297. package/dist/identity-Ys6Dlc9C.mjs +35 -0
  298. package/dist/identity-Ys6Dlc9C.mjs.map +1 -0
  299. package/dist/{import-B41u8Rot.mjs → import-DPkLmeXO.mjs} +2 -2
  300. package/dist/{import-B41u8Rot.mjs.map → import-DPkLmeXO.mjs.map} +1 -1
  301. package/dist/{index-C3Y-rsyN.d.mts → index-BVBZj4-7.d.mts} +28 -49
  302. package/dist/index-BVBZj4-7.d.mts.map +1 -0
  303. package/dist/{index-Cof4-Fab.d.mts → index-C9KuQyO-.d.mts} +3 -3
  304. package/dist/{index-Cof4-Fab.d.mts.map → index-C9KuQyO-.d.mts.map} +1 -1
  305. package/dist/index.d.mts +21 -20
  306. package/dist/index.mjs +42 -42
  307. package/dist/{load-DmvJrtxS.mjs → load-YJ2xl3ra.mjs} +2 -2
  308. package/dist/{load-DmvJrtxS.mjs.map → load-YJ2xl3ra.mjs.map} +1 -1
  309. package/dist/{loader-DLBqRiGP.mjs → loader-CdG_Ci3H.mjs} +2 -2
  310. package/dist/{loader-DLBqRiGP.mjs.map → loader-CdG_Ci3H.mjs.map} +1 -1
  311. package/dist/manifest-builder-B252yQUf.mjs +189 -0
  312. package/dist/manifest-builder-B252yQUf.mjs.map +1 -0
  313. package/dist/media/index.d.mts +1 -1
  314. package/dist/media/local-runtime.d.mts +12 -12
  315. package/dist/media/local-runtime.mjs +2 -2
  316. package/dist/{media-allowlist-BD6HhgXA.mjs → media-allowlist-D6x-Us02.mjs} +1 -1
  317. package/dist/{media-allowlist-BD6HhgXA.mjs.map → media-allowlist-D6x-Us02.mjs.map} +1 -1
  318. package/dist/{media-upload-9yas9zGH.mjs → media-upload-CHBVn6m-.mjs} +2 -2
  319. package/dist/{media-upload-9yas9zGH.mjs.map → media-upload-CHBVn6m-.mjs.map} +1 -1
  320. package/dist/{media-usage-De3qvwjc.mjs → media-usage-BZCydfvu.mjs} +4 -4
  321. package/dist/{media-usage-De3qvwjc.mjs.map → media-usage-BZCydfvu.mjs.map} +1 -1
  322. package/dist/{media-usage-work-B9Bksh_b.mjs → media-usage-work-CLo_6tct.mjs} +2 -2
  323. package/dist/{media-usage-work-B9Bksh_b.mjs.map → media-usage-work-CLo_6tct.mjs.map} +1 -1
  324. package/dist/{menus-CC-yn1F9.mjs → menus-DSo5QeW0.mjs} +6 -6
  325. package/dist/{menus-CC-yn1F9.mjs.map → menus-DSo5QeW0.mjs.map} +1 -1
  326. package/dist/{menus-fxvEDYE6.mjs → menus-TCNSd2vp.mjs} +2 -2
  327. package/dist/{menus-fxvEDYE6.mjs.map → menus-TCNSd2vp.mjs.map} +1 -1
  328. package/dist/migrations/index.d.mts +22 -0
  329. package/dist/migrations/index.d.mts.map +1 -0
  330. package/dist/migrations/index.mjs +7 -0
  331. package/dist/{mode-Bpe-tNNy.mjs → mode-BDoH_WcF.mjs} +1 -1
  332. package/dist/{mode-Bpe-tNNy.mjs.map → mode-BDoH_WcF.mjs.map} +1 -1
  333. package/dist/{oauth-authorization-BXO1MKej.mjs → oauth-authorization-iOikmrJd.mjs} +4 -4
  334. package/dist/{oauth-authorization-BXO1MKej.mjs.map → oauth-authorization-iOikmrJd.mjs.map} +1 -1
  335. package/dist/{oauth-clients-C_DNqtRu.mjs → oauth-clients-CvI0nHMJ.mjs} +1 -1
  336. package/dist/{oauth-clients-C_DNqtRu.mjs.map → oauth-clients-CvI0nHMJ.mjs.map} +1 -1
  337. package/dist/{oauth-state-store-DwAxMtk4.mjs → oauth-state-store-Ba8KZlwW.mjs} +1 -1
  338. package/dist/{oauth-state-store-DwAxMtk4.mjs.map → oauth-state-store-Ba8KZlwW.mjs.map} +1 -1
  339. package/dist/{oauth-user-lookup-BxfZizdk.mjs → oauth-user-lookup-C5SQwGYC.mjs} +1 -1
  340. package/dist/{oauth-user-lookup-BxfZizdk.mjs.map → oauth-user-lookup-C5SQwGYC.mjs.map} +1 -1
  341. package/dist/object-cache/memory.d.mts +1 -1
  342. package/dist/{options-DRe1pIBL.d.mts → options--hhz-jZ1.d.mts} +3 -3
  343. package/dist/{options-DRe1pIBL.d.mts.map → options--hhz-jZ1.d.mts.map} +1 -1
  344. package/dist/page/index.d.mts +2 -2
  345. package/dist/{passkey-config-_2GOwwK8.mjs → passkey-config-DFAmUyuE.mjs} +1 -1
  346. package/dist/{passkey-config-_2GOwwK8.mjs.map → passkey-config-DFAmUyuE.mjs.map} +1 -1
  347. package/dist/{placeholder-CzW7Lshs.d.mts → placeholder-Dp0K3RkD.d.mts} +1 -1
  348. package/dist/{placeholder-CzW7Lshs.d.mts.map → placeholder-Dp0K3RkD.d.mts.map} +1 -1
  349. package/dist/plugin-types.d.mts +1 -1
  350. package/dist/plugin-utils.d.mts +10 -10
  351. package/dist/plugins/adapt-sandbox-entry.d.mts +10 -10
  352. package/dist/policy-TluUIxuu.mjs +45 -0
  353. package/dist/policy-TluUIxuu.mjs.map +1 -0
  354. package/dist/{portable-text-DhKbDAGr.mjs → portable-text-imBW5cHK.mjs} +1 -1
  355. package/dist/{portable-text-DhKbDAGr.mjs.map → portable-text-imBW5cHK.mjs.map} +1 -1
  356. package/dist/protocol-DjsJHTlK.d.mts +52 -0
  357. package/dist/protocol-DjsJHTlK.d.mts.map +1 -0
  358. package/dist/{query-vgZNwIhh.mjs → query-BWs7O5Il.mjs} +3 -3
  359. package/dist/{query-vgZNwIhh.mjs.map → query-BWs7O5Il.mjs.map} +1 -1
  360. package/dist/{query-BgjfiLUQ.mjs → query-zTVAR1Sl.mjs} +12 -12
  361. package/dist/{query-BgjfiLUQ.mjs.map → query-zTVAR1Sl.mjs.map} +1 -1
  362. package/dist/{rate-limit-L5anykgo.mjs → rate-limit-Bx4g9m3p.mjs} +1 -1
  363. package/dist/{rate-limit-L5anykgo.mjs.map → rate-limit-Bx4g9m3p.mjs.map} +1 -1
  364. package/dist/{redirect-KBNE3UEs.mjs → redirect-BgAOGHDq.mjs} +1 -1
  365. package/dist/{redirect-KBNE3UEs.mjs.map → redirect-BgAOGHDq.mjs.map} +1 -1
  366. package/dist/{redirects-cV9g7V-0.mjs → redirects-DTDHWH31.mjs} +2 -2
  367. package/dist/{redirects-cV9g7V-0.mjs.map → redirects-DTDHWH31.mjs.map} +1 -1
  368. package/dist/{redirects-CufRQt0Q.mjs → redirects-DyChwDkG.mjs} +1 -1
  369. package/dist/{redirects-CufRQt0Q.mjs.map → redirects-DyChwDkG.mjs.map} +1 -1
  370. package/dist/{registry-C581V4TP.mjs → registry-Cqa2I749.mjs} +6 -6
  371. package/dist/{registry-C581V4TP.mjs.map → registry-Cqa2I749.mjs.map} +1 -1
  372. package/dist/{relation-DtmAQH7s.mjs → relation-BnHB0T4J.mjs} +2 -2
  373. package/dist/{relation-DtmAQH7s.mjs.map → relation-BnHB0T4J.mjs.map} +1 -1
  374. package/dist/{relations-DItI3MN9.d.mts → relations-BHo5A8Zf.d.mts} +35 -35
  375. package/dist/{relations-DItI3MN9.d.mts.map → relations-BHo5A8Zf.d.mts.map} +1 -1
  376. package/dist/{relations-DICSyfsh.mjs → relations-D5sM5fW0.mjs} +4 -4
  377. package/dist/{relations-DICSyfsh.mjs.map → relations-D5sM5fW0.mjs.map} +1 -1
  378. package/dist/request-context.d.mts +1 -1
  379. package/dist/{runner-CgQbELYC.d.mts → runner-BYHZn3Jy.d.mts} +16 -3
  380. package/dist/runner-BYHZn3Jy.d.mts.map +1 -0
  381. package/dist/{runner-BiDvq5dv.mjs → runner-C1T11CfC.mjs} +34 -4
  382. package/dist/{runner-BiDvq5dv.mjs.map → runner-C1T11CfC.mjs.map} +1 -1
  383. package/dist/runtime.d.mts +11 -11
  384. package/dist/runtime.mjs +1 -1
  385. package/dist/{schema-CeQSNwB3.mjs → schema-2AOsSn2v.mjs} +4 -4
  386. package/dist/{schema-CeQSNwB3.mjs.map → schema-2AOsSn2v.mjs.map} +1 -1
  387. package/dist/{schema-BFyTg38T.mjs → schema-DZ5YVVZj.mjs} +3 -3
  388. package/dist/{schema-BFyTg38T.mjs.map → schema-DZ5YVVZj.mjs.map} +1 -1
  389. package/dist/{scopes-BVeuhGBE.mjs → scopes-8ClPF2bC.mjs} +2 -2
  390. package/dist/{scopes-BVeuhGBE.mjs.map → scopes-8ClPF2bC.mjs.map} +1 -1
  391. package/dist/{search-BpuPKZb0.mjs → search-u1QYdOCG.mjs} +4 -4
  392. package/dist/{search-BpuPKZb0.mjs.map → search-u1QYdOCG.mjs.map} +1 -1
  393. package/dist/{secrets-dtYs2hDo.mjs → secrets-BEgsAQEU.mjs} +1 -1
  394. package/dist/{secrets-dtYs2hDo.mjs.map → secrets-BEgsAQEU.mjs.map} +1 -1
  395. package/dist/{sections-COctk6hf.mjs → sections-DmHviGyM.mjs} +2 -2
  396. package/dist/{sections-COctk6hf.mjs.map → sections-DmHviGyM.mjs.map} +1 -1
  397. package/dist/seed/index.d.mts +2 -2
  398. package/dist/seed/index.mjs +13 -13
  399. package/dist/seo/index.d.mts +3 -3
  400. package/dist/seo/index.mjs +9 -9
  401. package/dist/{seo-CvDxfvFb.mjs → seo-Dq4G-RrO.mjs} +2 -2
  402. package/dist/{seo-CvDxfvFb.mjs.map → seo-Dq4G-RrO.mjs.map} +1 -1
  403. package/dist/{service-xMiMSTsR.mjs → service-BpArayPr.mjs} +2 -2
  404. package/dist/{service-xMiMSTsR.mjs.map → service-BpArayPr.mjs.map} +1 -1
  405. package/dist/{session-user-BzVemLkw.mjs → session-user-BEorKVT-.mjs} +1 -1
  406. package/dist/{session-user-BzVemLkw.mjs.map → session-user-BEorKVT-.mjs.map} +1 -1
  407. package/dist/{settings-BE9aqn_9.mjs → settings-DE9xtzqd.mjs} +3 -3
  408. package/dist/{settings-BE9aqn_9.mjs.map → settings-DE9xtzqd.mjs.map} +1 -1
  409. package/dist/{settings-B372MV0p.mjs → settings-xRdoUZr0.mjs} +2 -2
  410. package/dist/{settings-B372MV0p.mjs.map → settings-xRdoUZr0.mjs.map} +1 -1
  411. package/dist/{setup-complete-DF7TAfD5.mjs → setup-complete-BnT8pq_C.mjs} +1 -1
  412. package/dist/{setup-complete-DF7TAfD5.mjs.map → setup-complete-BnT8pq_C.mjs.map} +1 -1
  413. package/dist/{setup-nonce-Do-U_cg9.mjs → setup-nonce-CBitf_oQ.mjs} +1 -1
  414. package/dist/{setup-nonce-Do-U_cg9.mjs.map → setup-nonce-CBitf_oQ.mjs.map} +1 -1
  415. package/dist/{site-url-Bowsi9T-.mjs → site-url-DjpIXMXJ.mjs} +1 -1
  416. package/dist/{site-url-Bowsi9T-.mjs.map → site-url-DjpIXMXJ.mjs.map} +1 -1
  417. package/dist/{snapshot-B5h6aPMh.mjs → snapshot-BBlGkb2q.mjs} +1 -1
  418. package/dist/{snapshot-B5h6aPMh.mjs.map → snapshot-BBlGkb2q.mjs.map} +1 -1
  419. package/dist/storage/local.d.mts +1 -1
  420. package/dist/storage/local.mjs +2 -2
  421. package/dist/storage/s3.d.mts +1 -1
  422. package/dist/target-DixqqV5i.mjs +27 -0
  423. package/dist/target-DixqqV5i.mjs.map +1 -0
  424. package/dist/{taxonomies-B0o9ExNV.mjs → taxonomies-BlrncHi9.mjs} +5 -5
  425. package/dist/{taxonomies-B0o9ExNV.mjs.map → taxonomies-BlrncHi9.mjs.map} +1 -1
  426. package/dist/{taxonomies-Dk3MAklL.mjs → taxonomies-OHUIiIpI.mjs} +4 -4
  427. package/dist/{taxonomies-Dk3MAklL.mjs.map → taxonomies-OHUIiIpI.mjs.map} +1 -1
  428. package/dist/{taxonomy-CPeM8d2o.mjs → taxonomy-BqCZ1TdU.mjs} +3 -3
  429. package/dist/{taxonomy-CPeM8d2o.mjs.map → taxonomy-BqCZ1TdU.mjs.map} +1 -1
  430. package/dist/{transport--CfOflrp.mjs → transport-DBJwa-Si.mjs} +1 -1
  431. package/dist/{transport--CfOflrp.mjs.map → transport-DBJwa-Si.mjs.map} +1 -1
  432. package/dist/{transport-B_rfeU-a.d.mts → transport-RQE36APG.d.mts} +1 -1
  433. package/dist/{transport-B_rfeU-a.d.mts.map → transport-RQE36APG.d.mts.map} +1 -1
  434. package/dist/{types-CFUfyt1s.d.mts → types-BcqdcT-r.d.mts} +1 -1
  435. package/dist/{types-CFUfyt1s.d.mts.map → types-BcqdcT-r.d.mts.map} +1 -1
  436. package/dist/{types-CPx2lIGo.d.mts → types-BntycPTF.d.mts} +1 -1
  437. package/dist/{types-CPx2lIGo.d.mts.map → types-BntycPTF.d.mts.map} +1 -1
  438. package/dist/{types-C3_AbkDP.d.mts → types-C2pMvO62.d.mts} +1 -1
  439. package/dist/{types-C3_AbkDP.d.mts.map → types-C2pMvO62.d.mts.map} +1 -1
  440. package/dist/{types-DefV3OiO.d.mts → types-CXnOzDe1.d.mts} +1 -1
  441. package/dist/{types-DefV3OiO.d.mts.map → types-CXnOzDe1.d.mts.map} +1 -1
  442. package/dist/{types-D4_1Ga4L.d.mts → types-DN64_zzZ.d.mts} +3 -3
  443. package/dist/{types-D4_1Ga4L.d.mts.map → types-DN64_zzZ.d.mts.map} +1 -1
  444. package/dist/{types-CAGdePf3.d.mts → types-DQIDRKF2.d.mts} +1 -1
  445. package/dist/{types-CAGdePf3.d.mts.map → types-DQIDRKF2.d.mts.map} +1 -1
  446. package/dist/{types-BPuloofb.d.mts → types-DWRhk9xZ.d.mts} +1 -1
  447. package/dist/{types-BPuloofb.d.mts.map → types-DWRhk9xZ.d.mts.map} +1 -1
  448. package/dist/{types-X0MThr7x.d.mts → types-Dfk8KI5R.d.mts} +1 -1
  449. package/dist/{types-X0MThr7x.d.mts.map → types-Dfk8KI5R.d.mts.map} +1 -1
  450. package/dist/{types-Cs-TFLNf.d.mts → types-DrJrVCT1.d.mts} +3 -3
  451. package/dist/{types-Cs-TFLNf.d.mts.map → types-DrJrVCT1.d.mts.map} +1 -1
  452. package/dist/{upload-attempts-hlne3iA1.mjs → upload-attempts-D4FS8LT6.mjs} +1 -1
  453. package/dist/{upload-attempts-hlne3iA1.mjs.map → upload-attempts-D4FS8LT6.mjs.map} +1 -1
  454. package/dist/{user-sHgJ62SP.mjs → user-DJZfUJVE.mjs} +2 -2
  455. package/dist/{user-sHgJ62SP.mjs.map → user-DJZfUJVE.mjs.map} +1 -1
  456. package/dist/{validate-BkqIG_Uj.mjs → validate-BMLBvxOC.mjs} +2 -2
  457. package/dist/{validate-BkqIG_Uj.mjs.map → validate-BMLBvxOC.mjs.map} +1 -1
  458. package/dist/{validate-DeGtBN84.d.mts → validate-CTqt5nuE.d.mts} +5 -5
  459. package/dist/{validate-DeGtBN84.d.mts.map → validate-CTqt5nuE.d.mts.map} +1 -1
  460. package/dist/{validation-CiJb_X5o.mjs → validation-npvENUCB.mjs} +7 -7
  461. package/dist/{validation-CiJb_X5o.mjs.map → validation-npvENUCB.mjs.map} +1 -1
  462. package/dist/version-DB_fqCSI.mjs +7 -0
  463. package/dist/{version-x0NjTScG.mjs.map → version-DB_fqCSI.mjs.map} +1 -1
  464. package/dist/{widgets-Cwzvww0W.mjs → widgets-BD3ho7Rq.mjs} +2 -2
  465. package/dist/{widgets-Cwzvww0W.mjs.map → widgets-BD3ho7Rq.mjs.map} +1 -1
  466. package/dist/{wxr-taxonomies-QZjWxjyk.mjs → wxr-taxonomies-B1R3vBoD.mjs} +3 -3
  467. package/dist/{wxr-taxonomies-QZjWxjyk.mjs.map → wxr-taxonomies-B1R3vBoD.mjs.map} +1 -1
  468. package/dist/{wxr-taxonomies-CmC0ZsDr.d.mts → wxr-taxonomies-Ca68766D.d.mts} +1 -1
  469. package/dist/{wxr-taxonomies-CmC0ZsDr.d.mts.map → wxr-taxonomies-Ca68766D.d.mts.map} +1 -1
  470. package/dist/{zod-generator-D11MhxG4.mjs → zod-generator-LC-on_Vb.mjs} +2 -2
  471. package/dist/{zod-generator-D11MhxG4.mjs.map → zod-generator-LC-on_Vb.mjs.map} +1 -1
  472. package/package.json +21 -5
  473. package/src/astro/integration/index.ts +46 -14
  474. package/src/astro/integration/runtime.ts +3 -0
  475. package/src/astro/middleware/scoped-db.ts +21 -0
  476. package/src/astro/middleware.ts +67 -10
  477. package/src/astro/routes/api/auth/dev-bypass.ts +0 -4
  478. package/src/astro/routes/api/setup/dev-bypass.ts +2 -7
  479. package/src/astro/routes/api/setup/index.ts +5 -13
  480. package/src/cli/commands/migrate.ts +593 -0
  481. package/src/cli/index.ts +2 -23
  482. package/src/database/index.ts +8 -2
  483. package/src/database/migrations/policy.ts +70 -0
  484. package/src/database/migrations/runner.ts +49 -3
  485. package/src/db/adapters.ts +50 -2
  486. package/src/db/index.ts +3 -1
  487. package/src/db/libsql-migrations.ts +72 -0
  488. package/src/db/postgres-migrations.ts +59 -0
  489. package/src/db/sqlite-migrations.ts +37 -0
  490. package/src/emdash-runtime.ts +44 -15
  491. package/src/i18n/normalize.ts +31 -0
  492. package/src/index.ts +7 -1
  493. package/src/migrations/config-loader.ts +205 -0
  494. package/src/migrations/direct-executor.ts +141 -0
  495. package/src/migrations/identity.ts +46 -0
  496. package/src/migrations/index.ts +19 -0
  497. package/src/migrations/integration-metadata.ts +67 -0
  498. package/src/migrations/manifest-builder.ts +55 -0
  499. package/src/migrations/manifest-writer.ts +63 -0
  500. package/src/migrations/manifest.ts +197 -0
  501. package/src/migrations/protocol.ts +59 -0
  502. package/src/migrations/target.ts +35 -0
  503. package/src/virtual-modules.d.ts +8 -0
  504. package/dist/adapters-34EN2eXO.d.mts.map +0 -1
  505. package/dist/index-C3Y-rsyN.d.mts.map +0 -1
  506. package/dist/runner-CgQbELYC.d.mts.map +0 -1
  507. package/dist/version-x0NjTScG.mjs +0 -7
  508. /package/dist/{api-tokens-CyTsLszZ.mjs → api-tokens-rIXC6LdE.mjs} +0 -0
@@ -2,6 +2,12 @@
2
2
  // `connection.ts`, which statically imports `better-sqlite3`. See #947.
3
3
  export { EmDashDatabaseError } from "./errors.js";
4
4
  export type { DatabaseConfig } from "./connection.js";
5
- export { runMigrations, getMigrationStatus, rollbackMigration } from "./migrations/runner.js";
6
- export type { MigrationStatus } from "./migrations/runner.js";
5
+ export {
6
+ runMigrations,
7
+ getMigrationStatus,
8
+ getExactMigrationStatus,
9
+ rollbackMigration,
10
+ MIGRATION_NAMES,
11
+ } from "./migrations/runner.js";
12
+ export type { MigrationStatus, ExactMigrationStatus } from "./migrations/runner.js";
7
13
  export type * from "./types.js";
@@ -0,0 +1,70 @@
1
+ import type { Kysely } from "kysely";
2
+
3
+ import type { Database } from "../types.js";
4
+ import { getExactMigrationStatus, runMigrations } from "./runner.js";
5
+
6
+ export type RuntimeMigrationMode = "auto" | "check" | "manual";
7
+
8
+ export interface RuntimeMigrationConfig {
9
+ runtime: RuntimeMigrationMode;
10
+ dev?: RuntimeMigrationMode;
11
+ }
12
+
13
+ function parseMigrationMode(value: unknown, source: string): RuntimeMigrationMode {
14
+ if (value === "auto" || value === "check" || value === "manual") {
15
+ return value;
16
+ }
17
+ throw new Error(
18
+ `Invalid ${source} value ${JSON.stringify(value)}; expected "auto", "check", or "manual"`,
19
+ );
20
+ }
21
+
22
+ export function normalizeMigrationConfig(value: unknown): RuntimeMigrationConfig {
23
+ if (value === undefined) return { runtime: "auto" };
24
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
25
+ throw new Error("Invalid migrations configuration; expected an object");
26
+ }
27
+
28
+ const runtimeValue = Reflect.get(value, "runtime");
29
+ const devValue = Reflect.get(value, "dev");
30
+ const runtime = parseMigrationMode(runtimeValue, "migrations.runtime");
31
+ const dev = devValue === undefined ? undefined : parseMigrationMode(devValue, "migrations.dev");
32
+ return dev === undefined ? { runtime } : { runtime, dev };
33
+ }
34
+
35
+ export function resolveRuntimeMigrationMode(
36
+ config: RuntimeMigrationConfig | undefined,
37
+ options: { dev: boolean; override?: unknown },
38
+ ): RuntimeMigrationMode {
39
+ if (options.override !== undefined) {
40
+ return parseMigrationMode(options.override, "EMDASH_MIGRATIONS_MODE");
41
+ }
42
+ if (options.dev) return config?.dev ?? "auto";
43
+ return config?.runtime ?? "auto";
44
+ }
45
+
46
+ export class PendingMigrationsError extends Error {
47
+ readonly pending: string[];
48
+
49
+ constructor(pending: readonly string[]) {
50
+ super(`Database has pending EmDash migrations: ${pending.join(", ")}`);
51
+ this.name = "PendingMigrationsError";
52
+ this.pending = [...pending];
53
+ }
54
+ }
55
+
56
+ export async function enforceRuntimeMigrationPolicy(
57
+ db: Kysely<Database>,
58
+ mode: RuntimeMigrationMode,
59
+ ): Promise<void> {
60
+ if (mode === "manual") return;
61
+ if (mode === "auto") {
62
+ await runMigrations(db);
63
+ return;
64
+ }
65
+
66
+ const status = await getExactMigrationStatus(db);
67
+ if (status.pending.length > 0) {
68
+ throw new PendingMigrationsError(status.pending);
69
+ }
70
+ }
@@ -146,8 +146,11 @@ const MIGRATIONS: Readonly<Record<string, Migration>> = Object.freeze({
146
146
  "070_collection_routable": m070,
147
147
  });
148
148
 
149
+ /** Ordered names from the statically registered migration set. */
150
+ export const MIGRATION_NAMES: readonly string[] = Object.freeze(Object.keys(MIGRATIONS));
151
+
149
152
  /** Total number of registered migrations. Exported for use in tests. */
150
- export const MIGRATION_COUNT = Object.keys(MIGRATIONS).length;
153
+ export const MIGRATION_COUNT = MIGRATION_NAMES.length;
151
154
 
152
155
  /**
153
156
  * Migration provider that uses statically imported migrations.
@@ -164,6 +167,12 @@ export interface MigrationStatus {
164
167
  pending: string[];
165
168
  }
166
169
 
170
+ export interface ExactMigrationStatus {
171
+ knownApplied: string[];
172
+ pending: string[];
173
+ unknownApplied: string[];
174
+ }
175
+
167
176
  /**
168
177
  * Thrown when another instance held the migration lock for the whole wait
169
178
  * window. This is NOT a migration failure — the holder may simply be slow
@@ -286,8 +295,8 @@ const MIGRATION_RACE_POLL_MS = 100;
286
295
  * built from `MIGRATION_TABLE` so a rename cannot drift.
287
296
  */
288
297
  const MIGRATION_TABLE_MISSING_PATTERN = new RegExp(
289
- `(?:no such table:\\s*${escapeRegExp(MIGRATION_TABLE)}\\b` +
290
- `|(?:relation|table)\\s+"?${escapeRegExp(MIGRATION_TABLE)}"?\\s+does(?:n't| not) exist\\b)`,
298
+ `(?:no such table:\\s*(?:[a-z][a-z0-9_]*\\.)?${escapeRegExp(MIGRATION_TABLE)}\\b` +
299
+ `|(?:relation|table)\\s+"?(?:[a-z][a-z0-9_]*\\.)?${escapeRegExp(MIGRATION_TABLE)}"?\\s+does(?:n't| not) exist\\b)`,
291
300
  "i",
292
301
  );
293
302
 
@@ -359,6 +368,43 @@ function deepErrorMessage(error: unknown): string {
359
368
  }
360
369
  }
361
370
 
371
+ /**
372
+ * Read exact migration status without invoking Kysely's migration
373
+ * introspection. Registered names retain execution order; unknown database
374
+ * records are sorted so reports remain stable across dialects.
375
+ */
376
+ export async function getExactMigrationStatus(
377
+ db: Kysely<Database>,
378
+ options?: MigrationOptions,
379
+ ): Promise<ExactMigrationStatus> {
380
+ const table = options?.migrationTableSchema
381
+ ? sql`${sql.ref(options.migrationTableSchema)}.${sql.ref(MIGRATION_TABLE)}`
382
+ : sql.ref(MIGRATION_TABLE);
383
+
384
+ let rows: readonly { name: string }[];
385
+ try {
386
+ const result = await sql<{ name: string }>`SELECT name FROM ${table}`.execute(db);
387
+ rows = result.rows;
388
+ } catch (error) {
389
+ if (MIGRATION_TABLE_MISSING_PATTERN.test(deepErrorMessage(error))) {
390
+ return {
391
+ knownApplied: [],
392
+ pending: [...MIGRATION_NAMES],
393
+ unknownApplied: [],
394
+ };
395
+ }
396
+ throw error;
397
+ }
398
+
399
+ const appliedNames = new Set(rows.map((row) => row.name));
400
+ const knownApplied = MIGRATION_NAMES.filter((name) => appliedNames.has(name));
401
+ const pending = MIGRATION_NAMES.filter((name) => !appliedNames.has(name));
402
+ const knownNames = new Set(MIGRATION_NAMES);
403
+ const unknownApplied = [...appliedNames].filter((name) => !knownNames.has(name)).toSorted();
404
+
405
+ return { knownApplied, pending, unknownApplied };
406
+ }
407
+
362
408
  /**
363
409
  * Run all pending migrations.
364
410
  *
@@ -52,6 +52,20 @@ export type ExecuteCollectionDeletionGuard = (
52
52
  input: CollectionDeletionGuardInput,
53
53
  ) => Promise<CollectionDeletionGuardResult>;
54
54
 
55
+ const ENVIRONMENT_VARIABLE_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
56
+
57
+ function migrationEnvironmentVariable(
58
+ value: string | undefined,
59
+ fallback: string,
60
+ optionName: string,
61
+ ): string {
62
+ const name = value ?? fallback;
63
+ if (!ENVIRONMENT_VARIABLE_PATTERN.test(name)) {
64
+ throw new Error(`${optionName} must be a valid environment variable name.`);
65
+ }
66
+ return name;
67
+ }
68
+
55
69
  /**
56
70
  * Database descriptor - serializable config for virtual modules
57
71
  */
@@ -59,6 +73,11 @@ export interface DatabaseDescriptor {
59
73
  entrypoint: string;
60
74
  config: unknown;
61
75
  type: DatabaseDialectType;
76
+ /** Deployment migration capability with configuration safe for a build artifact. */
77
+ migrations?: {
78
+ entrypoint: string;
79
+ manifestConfig: unknown;
80
+ };
62
81
  /**
63
82
  * When true, the adapter's runtime entrypoint MUST export a named
64
83
  * `createRequestScopedDb` function matching the signature declared in
@@ -111,6 +130,7 @@ export interface LibsqlConfig {
111
130
  * Auth token for remote libSQL
112
131
  */
113
132
  authToken?: string;
133
+ migrationAuthTokenEnv?: string;
114
134
  }
115
135
 
116
136
  /**
@@ -128,6 +148,10 @@ export function sqlite(config: SqliteConfig): DatabaseDescriptor {
128
148
  entrypoint: "emdash/db/sqlite",
129
149
  config,
130
150
  type: "sqlite",
151
+ migrations: {
152
+ entrypoint: "emdash/db/sqlite-migrations",
153
+ manifestConfig: { url: config.url },
154
+ },
131
155
  };
132
156
  }
133
157
 
@@ -145,10 +169,22 @@ export function sqlite(config: SqliteConfig): DatabaseDescriptor {
145
169
  * ```
146
170
  */
147
171
  export function libsql(config: LibsqlConfig): DatabaseDescriptor {
172
+ const { migrationAuthTokenEnv, ...runtimeConfig } = config;
148
173
  return {
149
174
  entrypoint: "emdash/db/libsql",
150
- config,
175
+ config: runtimeConfig,
151
176
  type: "sqlite",
177
+ migrations: {
178
+ entrypoint: "emdash/db/libsql-migrations",
179
+ manifestConfig: {
180
+ url: config.url,
181
+ authTokenEnv: migrationEnvironmentVariable(
182
+ migrationAuthTokenEnv,
183
+ "TURSO_AUTH_TOKEN",
184
+ "migrationAuthTokenEnv",
185
+ ),
186
+ },
187
+ },
152
188
  };
153
189
  }
154
190
 
@@ -164,6 +200,7 @@ export interface PostgresConfig {
164
200
  password?: string;
165
201
  ssl?: boolean;
166
202
  pool?: { min?: number; max?: number };
203
+ migrationConnectionStringEnv?: string;
167
204
  }
168
205
 
169
206
  /**
@@ -177,9 +214,20 @@ export interface PostgresConfig {
177
214
  * ```
178
215
  */
179
216
  export function postgres(config: PostgresConfig): DatabaseDescriptor {
217
+ const { migrationConnectionStringEnv, ...runtimeConfig } = config;
180
218
  return {
181
219
  entrypoint: "emdash/db/postgres",
182
- config,
220
+ config: runtimeConfig,
183
221
  type: "postgres",
222
+ migrations: {
223
+ entrypoint: "emdash/db/postgres-migrations",
224
+ manifestConfig: {
225
+ connectionStringEnv: migrationEnvironmentVariable(
226
+ migrationConnectionStringEnv,
227
+ "DATABASE_URL",
228
+ "migrationConnectionStringEnv",
229
+ ),
230
+ },
231
+ },
184
232
  };
185
233
  }
package/src/db/index.ts CHANGED
@@ -35,6 +35,8 @@ export type {
35
35
  export {
36
36
  runMigrations,
37
37
  getMigrationStatus,
38
+ getExactMigrationStatus,
38
39
  rollbackMigration,
40
+ MIGRATION_NAMES,
39
41
  } from "../database/migrations/runner.js";
40
- export type { MigrationStatus } from "../database/migrations/runner.js";
42
+ export type { MigrationStatus, ExactMigrationStatus } from "../database/migrations/runner.js";
@@ -0,0 +1,72 @@
1
+ import { resolve } from "node:path";
2
+ import { pathToFileURL } from "node:url";
3
+
4
+ import { createDirectMigrationExecutor } from "../migrations/direct-executor.js";
5
+ import type { MigrationExecutor, MigrationExecutorFactoryContext } from "../migrations/protocol.js";
6
+ import { createMigrationTarget, requireMigrationEnvironment } from "../migrations/target.js";
7
+ import { createDialect } from "./libsql.js";
8
+
9
+ export interface LibsqlMigrationManifestConfig {
10
+ url: string;
11
+ authTokenEnv: string;
12
+ }
13
+
14
+ interface ResolvedLibsqlUrl {
15
+ connectionUrl: string;
16
+ label: string;
17
+ identity: string[];
18
+ requiresAuthToken: boolean;
19
+ }
20
+
21
+ function resolveLibsqlUrl(url: unknown, projectRoot: string): ResolvedLibsqlUrl {
22
+ if (typeof url !== "string" || url.length === 0) {
23
+ throw new Error("libSQL migration URL is missing.");
24
+ }
25
+ if (url.startsWith("file:")) {
26
+ const configuredPath = url.slice(5);
27
+ if (configuredPath.length === 0) throw new Error("libSQL migration URL is invalid.");
28
+ const fileUrl = pathToFileURL(resolve(projectRoot, configuredPath));
29
+ return {
30
+ connectionUrl: fileUrl.href,
31
+ label: fileUrl.href,
32
+ identity: [fileUrl.protocol, fileUrl.pathname],
33
+ requiresAuthToken: false,
34
+ };
35
+ }
36
+
37
+ let parsed: URL;
38
+ try {
39
+ parsed = new URL(url);
40
+ } catch {
41
+ throw new Error("libSQL migration URL is invalid.");
42
+ }
43
+ if (parsed.username || parsed.password) {
44
+ throw new Error("libSQL migration URL must not contain credentials.");
45
+ }
46
+ const label = `${parsed.protocol}//${parsed.host}${parsed.pathname}`;
47
+ return {
48
+ connectionUrl: url,
49
+ label,
50
+ identity: [parsed.protocol, parsed.host, parsed.pathname],
51
+ requiresAuthToken: true,
52
+ };
53
+ }
54
+
55
+ export async function createMigrationExecutor(
56
+ manifestConfig: LibsqlMigrationManifestConfig,
57
+ context: MigrationExecutorFactoryContext,
58
+ ): Promise<MigrationExecutor> {
59
+ const resolvedUrl = resolveLibsqlUrl(manifestConfig.url, context.projectRoot);
60
+ const authToken = resolvedUrl.requiresAuthToken
61
+ ? requireMigrationEnvironment(manifestConfig.authTokenEnv, context.env)
62
+ : undefined;
63
+ const target = await createMigrationTarget("libsql", resolvedUrl.label, resolvedUrl.identity);
64
+ return createDirectMigrationExecutor({
65
+ target,
66
+ createDialect: () =>
67
+ createDialect({
68
+ url: resolvedUrl.connectionUrl,
69
+ authToken,
70
+ }),
71
+ });
72
+ }
@@ -0,0 +1,59 @@
1
+ import { createDirectMigrationExecutor } from "../migrations/direct-executor.js";
2
+ import type { MigrationExecutor, MigrationExecutorFactoryContext } from "../migrations/protocol.js";
3
+ import { createMigrationTarget, requireMigrationEnvironment } from "../migrations/target.js";
4
+ import { createDialect } from "./postgres.js";
5
+
6
+ export interface PostgresMigrationManifestConfig {
7
+ connectionStringEnv: string;
8
+ }
9
+
10
+ interface PostgresTargetIdentity {
11
+ host: string;
12
+ port: string;
13
+ database: string;
14
+ }
15
+
16
+ function parseTargetIdentity(connectionString: string): PostgresTargetIdentity {
17
+ let parsed: URL;
18
+ try {
19
+ parsed = new URL(connectionString);
20
+ } catch {
21
+ throw new Error("PostgreSQL migration connection string is invalid.");
22
+ }
23
+ if (parsed.protocol !== "postgres:" && parsed.protocol !== "postgresql:") {
24
+ throw new Error("PostgreSQL migration connection string is invalid.");
25
+ }
26
+ const database = parsed.pathname.slice(1);
27
+ if (!parsed.hostname || !database) {
28
+ throw new Error("PostgreSQL migration connection string must identify a host and database.");
29
+ }
30
+ return {
31
+ host: parsed.hostname,
32
+ port: parsed.port || "5432",
33
+ database,
34
+ };
35
+ }
36
+
37
+ export async function createMigrationExecutor(
38
+ manifestConfig: PostgresMigrationManifestConfig,
39
+ context: MigrationExecutorFactoryContext,
40
+ ): Promise<MigrationExecutor> {
41
+ const connectionStringEnv =
42
+ context.overrides?.databaseUrlEnv ?? manifestConfig.connectionStringEnv;
43
+ const connectionString = requireMigrationEnvironment(connectionStringEnv, context.env);
44
+ const identity = parseTargetIdentity(connectionString);
45
+ const label = `${identity.host}:${identity.port}/${identity.database}`;
46
+ const target = await createMigrationTarget("postgres", label, [
47
+ identity.host,
48
+ identity.port,
49
+ identity.database,
50
+ ]);
51
+ return createDirectMigrationExecutor({
52
+ target,
53
+ createDialect: () =>
54
+ createDialect({
55
+ connectionString,
56
+ pool: { min: 0, max: 1 },
57
+ }),
58
+ });
59
+ }
@@ -0,0 +1,37 @@
1
+ import { isAbsolute, resolve } from "node:path";
2
+
3
+ import { createDirectMigrationExecutor } from "../migrations/direct-executor.js";
4
+ import type { MigrationExecutor, MigrationExecutorFactoryContext } from "../migrations/protocol.js";
5
+ import { createMigrationTarget } from "../migrations/target.js";
6
+ import { createDialect } from "./sqlite.js";
7
+
8
+ export interface SqliteMigrationManifestConfig {
9
+ url: string;
10
+ }
11
+
12
+ function resolveDatabasePath(
13
+ manifestConfig: SqliteMigrationManifestConfig,
14
+ context: MigrationExecutorFactoryContext,
15
+ ): string {
16
+ const configuredUrl = context.overrides?.database ?? manifestConfig.url;
17
+ if (typeof configuredUrl !== "string" || configuredUrl.length === 0) {
18
+ throw new Error("SQLite migration database path is missing.");
19
+ }
20
+ const path = configuredUrl.startsWith("file:") ? configuredUrl.slice(5) : configuredUrl;
21
+ if (path.length === 0) {
22
+ throw new Error("SQLite migration database path is missing.");
23
+ }
24
+ return isAbsolute(path) ? resolve(path) : resolve(context.projectRoot, path);
25
+ }
26
+
27
+ export async function createMigrationExecutor(
28
+ manifestConfig: SqliteMigrationManifestConfig,
29
+ context: MigrationExecutorFactoryContext,
30
+ ): Promise<MigrationExecutor> {
31
+ const databasePath = resolveDatabasePath(manifestConfig, context);
32
+ const target = await createMigrationTarget("sqlite", databasePath, [databasePath]);
33
+ return createDirectMigrationExecutor({
34
+ target,
35
+ createDialect: () => createDialect({ url: databasePath }),
36
+ });
37
+ }
@@ -26,10 +26,14 @@ import { getTrustedProxyHeaders } from "./auth/trusted-proxy.js";
26
26
  import type { ContentFieldFilters } from "./content-list-query.js";
27
27
  import { isSqlite } from "./database/dialect-helpers.js";
28
28
  import { kyselyLogOption } from "./database/instrumentation.js";
29
+ import {
30
+ enforceRuntimeMigrationPolicy,
31
+ PendingMigrationsError,
32
+ type RuntimeMigrationMode,
33
+ } from "./database/migrations/policy.js";
29
34
  import {
30
35
  ConcurrentMigrationTimeoutError,
31
36
  MIGRATION_RACE_WAIT_MS,
32
- runMigrations,
33
37
  } from "./database/migrations/runner.js";
34
38
  import { AuditRepository } from "./database/repositories/audit.js";
35
39
  import { ContentRepository } from "./database/repositories/content.js";
@@ -87,6 +91,7 @@ import type {
87
91
  } from "./plugins/types.js";
88
92
  import { recordSchedulerHeartbeatSafely } from "./scheduler-health.js";
89
93
  import { MAX_COLLECTION_LIST_COLUMNS, type FieldType } from "./schema/types.js";
94
+ import { isMissingTableError } from "./utils/db-errors.js";
90
95
  import { hashString } from "./utils/hash.js";
91
96
  import { createInitLock, type InitLock, initWithLock } from "./utils/init-lock.js";
92
97
  import { createSingleFlightCache, singleFlightCached } from "./utils/single-flight-cache.js";
@@ -347,6 +352,8 @@ export type CreateSchedulerFn = (executor: CronExecutor) => CronScheduler;
347
352
  */
348
353
  export interface RuntimeDependencies {
349
354
  config: EmDashConfig;
355
+ /** Effective migration mode, resolved once by the runtime entrypoint. */
356
+ migrationMode?: RuntimeMigrationMode;
350
357
  plugins: ResolvedPlugin[];
351
358
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
352
359
  createDialect: (config: any) => Dialect;
@@ -1247,8 +1254,10 @@ export class EmDashRuntime {
1247
1254
  }
1248
1255
  };
1249
1256
 
1250
- // Initialize database (connects, runs migrations if needed)
1251
- const db = await phase("rt.db", "DB init + migrations", () => EmDashRuntime.getDatabase(deps));
1257
+ // Initialize the database and enforce its configured migration policy.
1258
+ const db = await phase("rt.db", "DB init + migration policy", () =>
1259
+ EmDashRuntime.getDatabase(deps),
1260
+ );
1252
1261
 
1253
1262
  // Resolver for the live connection, mirroring the `get db()` getter
1254
1263
  // below (which can't be used here — the runtime instance doesn't exist
@@ -1311,6 +1320,16 @@ export class EmDashRuntime {
1311
1320
  // fall back to the singleton, where serialization costs nothing.
1312
1321
  let readDb = db;
1313
1322
  let readDbDisposable: Kysely<Database> | undefined;
1323
+ const disposeReadDb = async () => {
1324
+ const disposable = readDbDisposable;
1325
+ readDbDisposable = undefined;
1326
+ if (!disposable) return;
1327
+ try {
1328
+ await disposable.destroy();
1329
+ } catch {
1330
+ // Non-fatal — the underlying binding is shared and needs no teardown.
1331
+ }
1332
+ };
1314
1333
  if (ownsConfiguredDb && deps.createCoalescingDialect && deps.config.database) {
1315
1334
  try {
1316
1335
  const dialect = deps.createCoalescingDialect(deps.config.database.config);
@@ -1323,6 +1342,12 @@ export class EmDashRuntime {
1323
1342
  }
1324
1343
  }
1325
1344
  const optionsRepo = new OptionsRepository(readDb);
1345
+ let missingManualSchemaError: unknown;
1346
+ const captureMissingManualSchema = (error: unknown) => {
1347
+ if ((deps.migrationMode ?? "auto") === "manual" && isMissingTableError(error)) {
1348
+ missingManualSchemaError ??= error;
1349
+ }
1350
+ };
1326
1351
 
1327
1352
  const readSiteInfo = async () => {
1328
1353
  const siteOpts = await optionsRepo.getMany<string>([
@@ -1351,14 +1376,16 @@ export class EmDashRuntime {
1351
1376
  .select(["plugin_id", "status"])
1352
1377
  .execute();
1353
1378
  pluginStates = new Map(states.map((s) => [s.plugin_id, s.status]));
1354
- } catch {
1379
+ } catch (error) {
1380
+ captureMissingManualSchema(error);
1355
1381
  // _plugin_state may not exist yet on a pre-migration db.
1356
1382
  }
1357
1383
  }),
1358
1384
  phase("rt.site", "Site info options", async () => {
1359
1385
  try {
1360
1386
  siteInfo = await readSiteInfo();
1361
- } catch {
1387
+ } catch (error) {
1388
+ captureMissingManualSchema(error);
1362
1389
  // options may not exist yet on a pre-migration db.
1363
1390
  }
1364
1391
  }),
@@ -1387,7 +1414,8 @@ export class EmDashRuntime {
1387
1414
  }
1388
1415
  })();
1389
1416
  seedGate = { collectionCount: collectionCount.count, setupDone };
1390
- } catch {
1417
+ } catch (error) {
1418
+ captureMissingManualSchema(error);
1391
1419
  // Leave the "already set up" default so a read failure never
1392
1420
  // triggers a seed onto a half-built db.
1393
1421
  }
@@ -1396,6 +1424,10 @@ export class EmDashRuntime {
1396
1424
  }
1397
1425
 
1398
1426
  await Promise.all(coldStartReads);
1427
+ if (missingManualSchemaError) {
1428
+ await disposeReadDb();
1429
+ throw missingManualSchemaError;
1430
+ }
1399
1431
 
1400
1432
  if (
1401
1433
  localeCasingRepairVersion &&
@@ -1452,13 +1484,7 @@ export class EmDashRuntime {
1452
1484
  }
1453
1485
 
1454
1486
  // The read connection is single-use; everything below uses the singleton.
1455
- if (readDbDisposable) {
1456
- try {
1457
- await readDbDisposable.destroy();
1458
- } catch {
1459
- // Non-fatal — the underlying binding is shared and needs no teardown.
1460
- }
1461
- }
1487
+ await disposeReadDb();
1462
1488
 
1463
1489
  const enabledPlugins = new Set<string>();
1464
1490
  for (const plugin of deps.plugins) {
@@ -1911,13 +1937,16 @@ export class EmDashRuntime {
1911
1937
  const db = new Kysely<Database>({ dialect, log: kyselyLogOption() });
1912
1938
 
1913
1939
  try {
1914
- await runMigrations(db);
1940
+ await enforceRuntimeMigrationPolicy(db, deps.migrationMode ?? "auto");
1915
1941
  } catch (error) {
1916
1942
  // Timing out behind another instance's in-flight migrations
1917
1943
  // is not a failure of OUR migration — the holder may just be
1918
1944
  // slow. Don't back off for it: the next request waits again
1919
1945
  // and init recovers the moment the holder finishes.
1920
- if (!(error instanceof ConcurrentMigrationTimeoutError)) {
1946
+ if (
1947
+ !(error instanceof ConcurrentMigrationTimeoutError) &&
1948
+ !(error instanceof PendingMigrationsError)
1949
+ ) {
1921
1950
  holder.failures.set(cacheKey, {
1922
1951
  at: Date.now(),
1923
1952
  message: error instanceof Error ? error.message : String(error),
@@ -0,0 +1,31 @@
1
+ import type { I18nConfig } from "./config.js";
2
+
3
+ export interface AstroLocaleObject {
4
+ path: string;
5
+ codes: readonly string[];
6
+ }
7
+
8
+ export interface AstroI18nInput {
9
+ defaultLocale: string;
10
+ locales: readonly (string | AstroLocaleObject)[];
11
+ fallback?: Readonly<Record<string, string | undefined>>;
12
+ routing?: string | { prefixDefaultLocale?: boolean };
13
+ }
14
+
15
+ export function normalizeAstroI18n(config: AstroI18nInput | null | undefined): I18nConfig | null {
16
+ if (!config) return null;
17
+
18
+ return {
19
+ defaultLocale: config.defaultLocale,
20
+ locales: config.locales.map((locale) => (typeof locale === "string" ? locale : locale.path)),
21
+ fallback: config.fallback
22
+ ? Object.fromEntries(
23
+ Object.entries(config.fallback).filter(
24
+ (entry): entry is [string, string] => entry[1] !== undefined,
25
+ ),
26
+ )
27
+ : undefined,
28
+ prefixDefaultLocale:
29
+ typeof config.routing === "object" ? (config.routing.prefixDefaultLocale ?? false) : false,
30
+ };
31
+ }
package/src/index.ts CHANGED
@@ -1,8 +1,14 @@
1
1
  // Database (only types and utilities - internal functions not exported)
2
- export { EmDashDatabaseError, getMigrationStatus } from "./database/index.js";
2
+ export {
3
+ EmDashDatabaseError,
4
+ getMigrationStatus,
5
+ getExactMigrationStatus,
6
+ MIGRATION_NAMES,
7
+ } from "./database/index.js";
3
8
  export type {
4
9
  DatabaseConfig,
5
10
  MigrationStatus,
11
+ ExactMigrationStatus,
6
12
  Database,
7
13
  UserTable,
8
14
  MediaTable,