emdash 0.8.0 → 0.9.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 (286) hide show
  1. package/dist/{adapters-BKSf3T9R.d.mts → adapters-DoNJiveC.d.mts} +1 -1
  2. package/dist/{adapters-BKSf3T9R.d.mts.map → adapters-DoNJiveC.d.mts.map} +1 -1
  3. package/dist/{apply-x0eMK1lX.mjs → apply-BzltprvY.mjs} +85 -135
  4. package/dist/apply-BzltprvY.mjs.map +1 -0
  5. package/dist/astro/index.d.mts +6 -6
  6. package/dist/astro/index.d.mts.map +1 -1
  7. package/dist/astro/index.mjs +110 -4
  8. package/dist/astro/index.mjs.map +1 -1
  9. package/dist/astro/middleware/auth.d.mts +6 -7
  10. package/dist/astro/middleware/auth.d.mts.map +1 -1
  11. package/dist/astro/middleware/auth.mjs +16 -59
  12. package/dist/astro/middleware/auth.mjs.map +1 -1
  13. package/dist/astro/middleware/redirect.d.mts.map +1 -1
  14. package/dist/astro/middleware/redirect.mjs +17 -12
  15. package/dist/astro/middleware/redirect.mjs.map +1 -1
  16. package/dist/astro/middleware/request-context.d.mts.map +1 -1
  17. package/dist/astro/middleware/request-context.mjs +9 -6
  18. package/dist/astro/middleware/request-context.mjs.map +1 -1
  19. package/dist/astro/middleware/setup.mjs +1 -1
  20. package/dist/astro/middleware.d.mts.map +1 -1
  21. package/dist/astro/middleware.mjs +72 -124
  22. package/dist/astro/middleware.mjs.map +1 -1
  23. package/dist/astro/types.d.mts +26 -10
  24. package/dist/astro/types.d.mts.map +1 -1
  25. package/dist/{base64-MBPo9ozB.mjs → base64-BRICGH2l.mjs} +1 -1
  26. package/dist/{base64-MBPo9ozB.mjs.map → base64-BRICGH2l.mjs.map} +1 -1
  27. package/dist/{byline-Chbr2GoP.mjs → byline-BSaNL1w7.mjs} +4 -4
  28. package/dist/{byline-Chbr2GoP.mjs.map → byline-BSaNL1w7.mjs.map} +1 -1
  29. package/dist/bylines-CvJ3PYz2.mjs +113 -0
  30. package/dist/bylines-CvJ3PYz2.mjs.map +1 -0
  31. package/dist/cache-C6N_hhN7.mjs +65 -0
  32. package/dist/cache-C6N_hhN7.mjs.map +1 -0
  33. package/dist/{chunks-HGz06Soa.mjs → chunks-NBQVDOci.mjs} +8 -2
  34. package/dist/{chunks-HGz06Soa.mjs.map → chunks-NBQVDOci.mjs.map} +1 -1
  35. package/dist/cli/index.mjs +224 -30
  36. package/dist/cli/index.mjs.map +1 -1
  37. package/dist/client/cf-access.d.mts +1 -1
  38. package/dist/client/index.d.mts +1 -1
  39. package/dist/client/index.mjs +3 -3
  40. package/dist/client/index.mjs.map +1 -1
  41. package/dist/{config-BXwuX8Bx.mjs → config-BI0V3ICQ.mjs} +1 -1
  42. package/dist/{config-BXwuX8Bx.mjs.map → config-BI0V3ICQ.mjs.map} +1 -1
  43. package/dist/{content-BcQPYxdV.mjs → content-8lOYF0pr.mjs} +32 -15
  44. package/dist/{content-BcQPYxdV.mjs.map → content-8lOYF0pr.mjs.map} +1 -1
  45. package/dist/db/index.d.mts +3 -3
  46. package/dist/db/index.mjs +2 -2
  47. package/dist/db/libsql.d.mts +1 -1
  48. package/dist/db/libsql.d.mts.map +1 -1
  49. package/dist/db/libsql.mjs +7 -2
  50. package/dist/db/libsql.mjs.map +1 -1
  51. package/dist/db/postgres.d.mts +1 -1
  52. package/dist/db/sqlite.d.mts +1 -1
  53. package/dist/db/sqlite.d.mts.map +1 -1
  54. package/dist/db/sqlite.mjs +8 -3
  55. package/dist/db/sqlite.mjs.map +1 -1
  56. package/dist/{db-errors-l1Qh2RPR.mjs → db-errors-WRezodiz.mjs} +1 -1
  57. package/dist/{db-errors-l1Qh2RPR.mjs.map → db-errors-WRezodiz.mjs.map} +1 -1
  58. package/dist/{default-DCVqE5ib.mjs → default-D8ksjWhO.mjs} +1 -1
  59. package/dist/{default-DCVqE5ib.mjs.map → default-D8ksjWhO.mjs.map} +1 -1
  60. package/dist/{dialect-helpers-DhTzaUxP.mjs → dialect-helpers-BKCvISIQ.mjs} +19 -2
  61. package/dist/dialect-helpers-BKCvISIQ.mjs.map +1 -0
  62. package/dist/{error-zG5T1UGA.mjs → error-D_-tqP-I.mjs} +1 -1
  63. package/dist/{error-zG5T1UGA.mjs.map → error-D_-tqP-I.mjs.map} +1 -1
  64. package/dist/{index-DIb-CzNx.d.mts → index-BFRaVcD6.d.mts} +94 -34
  65. package/dist/index-BFRaVcD6.d.mts.map +1 -0
  66. package/dist/index.d.mts +11 -11
  67. package/dist/index.mjs +29 -27
  68. package/dist/{load-CyEoextb.mjs → load-DDqMMvZL.mjs} +2 -2
  69. package/dist/{load-CyEoextb.mjs.map → load-DDqMMvZL.mjs.map} +1 -1
  70. package/dist/{loader-CndGj8kM.mjs → loader-CKLbBnhK.mjs} +27 -7
  71. package/dist/loader-CKLbBnhK.mjs.map +1 -0
  72. package/dist/{manifest-schema-DH9xhc6t.mjs → manifest-schema-DqWNC3lM.mjs} +33 -3
  73. package/dist/manifest-schema-DqWNC3lM.mjs.map +1 -0
  74. package/dist/media/index.d.mts +1 -1
  75. package/dist/media/index.mjs +1 -1
  76. package/dist/media/local-runtime.d.mts +7 -7
  77. package/dist/media/local-runtime.mjs +3 -3
  78. package/dist/{media-D8FbNsl0.mjs → media-BW32b4gi.mjs} +2 -2
  79. package/dist/{media-D8FbNsl0.mjs.map → media-BW32b4gi.mjs.map} +1 -1
  80. package/dist/{mode-BnAOqItE.mjs → mode-ier8jbBk.mjs} +1 -1
  81. package/dist/{mode-BnAOqItE.mjs.map → mode-ier8jbBk.mjs.map} +1 -1
  82. package/dist/options-BVp3UsTS.mjs +117 -0
  83. package/dist/options-BVp3UsTS.mjs.map +1 -0
  84. package/dist/page/index.d.mts +2 -2
  85. package/dist/{placeholder-D29tWZ7o.d.mts → placeholder-BE4o_2dc.d.mts} +1 -1
  86. package/dist/{placeholder-D29tWZ7o.d.mts.map → placeholder-BE4o_2dc.d.mts.map} +1 -1
  87. package/dist/{placeholder-C-fk5hYI.mjs → placeholder-CIJejMlK.mjs} +1 -1
  88. package/dist/{placeholder-C-fk5hYI.mjs.map → placeholder-CIJejMlK.mjs.map} +1 -1
  89. package/dist/plugins/adapt-sandbox-entry.d.mts +5 -5
  90. package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
  91. package/dist/plugins/adapt-sandbox-entry.mjs +6 -5
  92. package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
  93. package/dist/public-url-DByxYjUw.mjs +51 -0
  94. package/dist/public-url-DByxYjUw.mjs.map +1 -0
  95. package/dist/{query-fqEdLFms.mjs → query-Cg9ZKRQ0.mjs} +114 -16
  96. package/dist/query-Cg9ZKRQ0.mjs.map +1 -0
  97. package/dist/{redirect-D_pshWdf.mjs → redirect-BhUBKRc1.mjs} +11 -6
  98. package/dist/redirect-BhUBKRc1.mjs.map +1 -0
  99. package/dist/{registry-C3Mr0ODu.mjs → registry-Dw70ChxB.mjs} +38 -4
  100. package/dist/registry-Dw70ChxB.mjs.map +1 -0
  101. package/dist/{request-cache-Ci7f5pBb.mjs → request-cache-B-bmkipQ.mjs} +1 -1
  102. package/dist/{request-cache-Ci7f5pBb.mjs.map → request-cache-B-bmkipQ.mjs.map} +1 -1
  103. package/dist/runner-Bnoj7vjK.d.mts +44 -0
  104. package/dist/runner-Bnoj7vjK.d.mts.map +1 -0
  105. package/dist/{runner-tQ7BJ4T7.mjs → runner-C7ADox5q.mjs} +185 -55
  106. package/dist/{runner-tQ7BJ4T7.mjs.map → runner-C7ADox5q.mjs.map} +1 -1
  107. package/dist/runtime.d.mts +6 -6
  108. package/dist/runtime.mjs +4 -4
  109. package/dist/{search-BoZYFuUk.mjs → search-dOGEccMa.mjs} +129 -83
  110. package/dist/search-dOGEccMa.mjs.map +1 -0
  111. package/dist/secrets-CW3reAnU.mjs +314 -0
  112. package/dist/secrets-CW3reAnU.mjs.map +1 -0
  113. package/dist/seed/index.d.mts +2 -2
  114. package/dist/seed/index.mjs +15 -14
  115. package/dist/seo/index.d.mts +1 -1
  116. package/dist/storage/local.d.mts +1 -1
  117. package/dist/storage/local.mjs +1 -1
  118. package/dist/storage/s3.d.mts +1 -1
  119. package/dist/storage/s3.mjs +1 -1
  120. package/dist/{taxonomies-B4IAshV8.mjs → taxonomies-ZlRtD6AG.mjs} +14 -7
  121. package/dist/taxonomies-ZlRtD6AG.mjs.map +1 -0
  122. package/dist/{tokens-D9vnZqYS.mjs → tokens-D7zMmWi2.mjs} +2 -2
  123. package/dist/{tokens-D9vnZqYS.mjs.map → tokens-D7zMmWi2.mjs.map} +1 -1
  124. package/dist/{transport-C9ugt2Nr.mjs → transport-BeMCmin1.mjs} +6 -5
  125. package/dist/{transport-C9ugt2Nr.mjs.map → transport-BeMCmin1.mjs.map} +1 -1
  126. package/dist/{transport-CUnEL3Vs.d.mts → transport-DNEfeMaU.d.mts} +1 -1
  127. package/dist/{transport-CUnEL3Vs.d.mts.map → transport-DNEfeMaU.d.mts.map} +1 -1
  128. package/dist/types-4fVtCIm0.mjs +68 -0
  129. package/dist/types-4fVtCIm0.mjs.map +1 -0
  130. package/dist/{types-BmPPSUEx.d.mts → types-BSyXeCFW.d.mts} +24 -2
  131. package/dist/{types-BmPPSUEx.d.mts.map → types-BSyXeCFW.d.mts.map} +1 -1
  132. package/dist/{types-i36XcA_X.d.mts → types-BuBIptGk.d.mts} +65 -134
  133. package/dist/types-BuBIptGk.d.mts.map +1 -0
  134. package/dist/{types-CgqmmMJB.mjs → types-CDbKp7ND.mjs} +1 -1
  135. package/dist/{types-CgqmmMJB.mjs.map → types-CDbKp7ND.mjs.map} +1 -1
  136. package/dist/{types-Bm1dn-q3.mjs → types-CIOg5AR8.mjs} +1 -1
  137. package/dist/{types-Bm1dn-q3.mjs.map → types-CIOg5AR8.mjs.map} +1 -1
  138. package/dist/{types-BrA0xf5I.d.mts → types-CJsYGpco.d.mts} +1 -1
  139. package/dist/{types-BrA0xf5I.d.mts.map → types-CJsYGpco.d.mts.map} +1 -1
  140. package/dist/{types-BIgulNsW.mjs → types-CRxNbK-Z.mjs} +2 -2
  141. package/dist/{types-BIgulNsW.mjs.map → types-CRxNbK-Z.mjs.map} +1 -1
  142. package/dist/{types-CS8FIX7L.d.mts → types-CrtWgIvl.d.mts} +1 -1
  143. package/dist/{types-CS8FIX7L.d.mts.map → types-CrtWgIvl.d.mts.map} +1 -1
  144. package/dist/{types-DIMwPFub.d.mts → types-M78DQ1lx.d.mts} +1 -1
  145. package/dist/{types-DIMwPFub.d.mts.map → types-M78DQ1lx.d.mts.map} +1 -1
  146. package/dist/{validate-CxVsLehf.mjs → validate-Baqf0slj.mjs} +3 -3
  147. package/dist/{validate-CxVsLehf.mjs.map → validate-Baqf0slj.mjs.map} +1 -1
  148. package/dist/{validate-DHxmpFJt.d.mts → validate-BfQh_C_y.d.mts} +4 -4
  149. package/dist/{validate-DHxmpFJt.d.mts.map → validate-BfQh_C_y.d.mts.map} +1 -1
  150. package/dist/{validation-C-ZpN2GI.mjs → validation-BfEI7tNe.mjs} +6 -6
  151. package/dist/{validation-C-ZpN2GI.mjs.map → validation-BfEI7tNe.mjs.map} +1 -1
  152. package/dist/version-DoxrVdYf.mjs +7 -0
  153. package/dist/{version-Bbq8TCrz.mjs.map → version-DoxrVdYf.mjs.map} +1 -1
  154. package/dist/{zod-generator-CpwccCIv.mjs → zod-generator-CC0xNe_K.mjs} +4 -4
  155. package/dist/zod-generator-CC0xNe_K.mjs.map +1 -0
  156. package/locals.d.ts +1 -6
  157. package/package.json +9 -8
  158. package/src/api/handlers/comments.ts +6 -4
  159. package/src/api/handlers/content.ts +29 -1
  160. package/src/api/handlers/device-flow.ts +5 -0
  161. package/src/api/handlers/marketplace.ts +11 -4
  162. package/src/api/handlers/oauth-authorization.ts +72 -33
  163. package/src/api/handlers/revision.ts +23 -14
  164. package/src/api/handlers/taxonomies.ts +3 -6
  165. package/src/api/public-url.ts +48 -2
  166. package/src/api/schemas/comments.ts +2 -2
  167. package/src/api/schemas/content.ts +17 -0
  168. package/src/api/schemas/sections.ts +3 -3
  169. package/src/api/schemas/users.ts +1 -1
  170. package/src/api/types.ts +5 -1
  171. package/src/astro/integration/index.ts +17 -0
  172. package/src/astro/integration/runtime.ts +30 -0
  173. package/src/astro/integration/virtual-modules.ts +32 -2
  174. package/src/astro/integration/vite-config.ts +6 -1
  175. package/src/astro/middleware/auth.ts +13 -6
  176. package/src/astro/middleware/redirect.ts +29 -16
  177. package/src/astro/middleware/request-context.ts +15 -5
  178. package/src/astro/middleware.ts +23 -9
  179. package/src/astro/routes/api/auth/invite/complete.ts +6 -1
  180. package/src/astro/routes/api/auth/passkey/register/verify.ts +6 -1
  181. package/src/astro/routes/api/auth/passkey/verify.ts +6 -1
  182. package/src/astro/routes/api/auth/signup/complete.ts +6 -1
  183. package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +2 -2
  184. package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +4 -2
  185. package/src/astro/routes/api/content/[collection]/[id]/preview-url.ts +34 -12
  186. package/src/astro/routes/api/content/[collection]/[id]/publish.ts +32 -2
  187. package/src/astro/routes/api/content/[collection]/[id]/restore.ts +4 -2
  188. package/src/astro/routes/api/content/[collection]/[id]/revisions.ts +3 -2
  189. package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +8 -4
  190. package/src/astro/routes/api/content/[collection]/[id].ts +12 -0
  191. package/src/astro/routes/api/import/wordpress/execute.ts +3 -1
  192. package/src/astro/routes/api/import/wordpress/prepare.ts +7 -8
  193. package/src/astro/routes/api/import/wordpress-plugin/execute.ts +3 -1
  194. package/src/astro/routes/api/manifest.ts +62 -45
  195. package/src/astro/routes/api/media/[id]/confirm.ts +10 -1
  196. package/src/astro/routes/api/media/providers/[providerId]/index.ts +12 -3
  197. package/src/astro/routes/api/openapi.json.ts +27 -10
  198. package/src/astro/routes/api/redirects/404s/index.ts +10 -4
  199. package/src/astro/routes/api/redirects/404s/summary.ts +4 -2
  200. package/src/astro/routes/api/redirects/[id].ts +10 -4
  201. package/src/astro/routes/api/redirects/index.ts +7 -3
  202. package/src/astro/routes/api/revisions/[revisionId]/index.ts +1 -1
  203. package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +0 -2
  204. package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +0 -1
  205. package/src/astro/routes/api/schema/collections/[slug]/fields/reorder.ts +0 -1
  206. package/src/astro/routes/api/schema/collections/[slug]/index.ts +2 -2
  207. package/src/astro/routes/api/schema/collections/index.ts +1 -1
  208. package/src/astro/routes/api/search/index.ts +10 -2
  209. package/src/astro/routes/api/sections/[slug].ts +10 -4
  210. package/src/astro/routes/api/sections/index.ts +7 -3
  211. package/src/astro/routes/api/setup/admin-verify.ts +6 -1
  212. package/src/astro/routes/api/snapshot.ts +44 -18
  213. package/src/astro/routes/api/taxonomies/index.ts +0 -1
  214. package/src/astro/routes/api/themes/preview.ts +11 -5
  215. package/src/astro/types.ts +23 -3
  216. package/src/auth/allowed-origins.ts +168 -0
  217. package/src/auth/passkey-config.ts +35 -13
  218. package/src/bylines/index.ts +37 -88
  219. package/src/cli/commands/auth.ts +28 -6
  220. package/src/cli/commands/bundle-utils.ts +11 -2
  221. package/src/cli/commands/bundle.ts +28 -8
  222. package/src/cli/commands/content.ts +13 -0
  223. package/src/cli/commands/login.ts +8 -1
  224. package/src/cli/commands/publish.ts +24 -0
  225. package/src/cli/commands/secrets.ts +183 -0
  226. package/src/cli/credentials.ts +1 -1
  227. package/src/cli/index.ts +5 -1
  228. package/src/client/index.ts +4 -4
  229. package/src/client/transport.ts +17 -7
  230. package/src/components/Break.astro +2 -2
  231. package/src/components/EmDashHead.astro +18 -13
  232. package/src/components/Embed.astro +1 -1
  233. package/src/components/Gallery.astro +1 -1
  234. package/src/components/Image.astro +1 -1
  235. package/src/components/InlinePortableTextEditor.tsx +104 -18
  236. package/src/config/secrets.ts +528 -0
  237. package/src/database/dialect-helpers.ts +50 -0
  238. package/src/database/migrations/034_published_at_index.ts +1 -1
  239. package/src/database/migrations/035_bounded_404_log.ts +56 -39
  240. package/src/database/migrations/runner.ts +156 -23
  241. package/src/database/repositories/content.ts +36 -12
  242. package/src/database/repositories/redirect.ts +14 -3
  243. package/src/database/repositories/taxonomy.ts +26 -0
  244. package/src/db/libsql.ts +1 -3
  245. package/src/db/sqlite.ts +2 -5
  246. package/src/emdash-runtime.ts +84 -159
  247. package/src/index.ts +9 -0
  248. package/src/loader.ts +24 -1
  249. package/src/mcp/server.ts +103 -36
  250. package/src/page/site-identity.ts +58 -0
  251. package/src/plugins/adapt-sandbox-entry.ts +22 -10
  252. package/src/plugins/context.ts +13 -10
  253. package/src/plugins/define-plugin.ts +40 -12
  254. package/src/plugins/hooks.ts +23 -19
  255. package/src/plugins/index.ts +9 -0
  256. package/src/plugins/manifest-schema.ts +37 -2
  257. package/src/plugins/types.ts +151 -11
  258. package/src/preview/urls.ts +23 -3
  259. package/src/query.ts +148 -5
  260. package/src/redirects/cache.ts +38 -18
  261. package/src/schema/registry.ts +56 -0
  262. package/src/schema/zod-generator.ts +27 -5
  263. package/src/seed/apply.ts +2 -0
  264. package/src/settings/index.ts +80 -6
  265. package/src/settings/types.ts +23 -1
  266. package/src/taxonomies/index.ts +11 -1
  267. package/dist/apply-x0eMK1lX.mjs.map +0 -1
  268. package/dist/bylines-CRNsVG88.mjs +0 -157
  269. package/dist/bylines-CRNsVG88.mjs.map +0 -1
  270. package/dist/cache-BkKBuIvS.mjs +0 -56
  271. package/dist/cache-BkKBuIvS.mjs.map +0 -1
  272. package/dist/chunk-ClPoSABd.mjs +0 -21
  273. package/dist/dialect-helpers-DhTzaUxP.mjs.map +0 -1
  274. package/dist/index-DIb-CzNx.d.mts.map +0 -1
  275. package/dist/loader-CndGj8kM.mjs.map +0 -1
  276. package/dist/manifest-schema-DH9xhc6t.mjs.map +0 -1
  277. package/dist/query-fqEdLFms.mjs.map +0 -1
  278. package/dist/redirect-D_pshWdf.mjs.map +0 -1
  279. package/dist/registry-C3Mr0ODu.mjs.map +0 -1
  280. package/dist/runner-OURCaApa.d.mts +0 -34
  281. package/dist/runner-OURCaApa.d.mts.map +0 -1
  282. package/dist/search-BoZYFuUk.mjs.map +0 -1
  283. package/dist/taxonomies-B4IAshV8.mjs.map +0 -1
  284. package/dist/types-i36XcA_X.d.mts.map +0 -1
  285. package/dist/version-Bbq8TCrz.mjs +0 -7
  286. package/dist/zod-generator-CpwccCIv.mjs.map +0 -1
@@ -1,8 +1,25 @@
1
- import { t as __exportAll } from "./chunk-ClPoSABd.mjs";
2
1
  import { t as validateIdentifier } from "./validate-VPnKoIzW.mjs";
3
- import { a as isSqlite, n as currentTimestamp, r as currentTimestampValue, s as listTablesLike, t as binaryType } from "./dialect-helpers-DhTzaUxP.mjs";
2
+ import { c as listTablesLike, i as currentTimestampValue, n as columnExists, o as isSqlite, r as currentTimestamp, t as binaryType } from "./dialect-helpers-BKCvISIQ.mjs";
3
+ import { createRequire } from "node:module";
4
4
  import { Migrator, sql } from "kysely";
5
5
 
6
+ //#region \0rolldown/runtime.js
7
+ var __defProp = Object.defineProperty;
8
+ var __exportAll = (all, no_symbols) => {
9
+ let target = {};
10
+ for (var name in all) {
11
+ __defProp(target, name, {
12
+ get: all[name],
13
+ enumerable: true
14
+ });
15
+ }
16
+ if (!no_symbols) {
17
+ __defProp(target, Symbol.toStringTag, { value: "Module" });
18
+ }
19
+ return target;
20
+ };
21
+
22
+ //#endregion
6
23
  //#region src/database/migrations/001_initial.ts
7
24
  var _001_initial_exports = /* @__PURE__ */ __exportAll({
8
25
  down: () => down$33,
@@ -1404,7 +1421,7 @@ async function up$1(db) {
1404
1421
  for (const tableName of tableNames) {
1405
1422
  const table = { name: tableName };
1406
1423
  await sql`
1407
- CREATE INDEX ${sql.ref(`idx_${table.name}_deleted_published_id`)}
1424
+ CREATE INDEX IF NOT EXISTS ${sql.ref(`idx_${table.name}_deleted_published_id`)}
1408
1425
  ON ${sql.ref(table.name)} (deleted_at, published_at DESC, id DESC)
1409
1426
  `.execute(db);
1410
1427
  }
@@ -1440,55 +1457,58 @@ var _035_bounded_404_log_exports = /* @__PURE__ */ __exportAll({
1440
1457
  * - Adds a UNIQUE index on `path` so upsert semantics work
1441
1458
  */
1442
1459
  async function up(db) {
1443
- await db.schema.alterTable("_emdash_404_log").addColumn("hits", "integer", (col) => col.notNull().defaultTo(1)).execute();
1444
- await db.schema.alterTable("_emdash_404_log").addColumn("last_seen_at", "text").execute();
1460
+ const hitsExists = await columnExists(db, "_emdash_404_log", "hits");
1461
+ if (!hitsExists) await db.schema.alterTable("_emdash_404_log").addColumn("hits", "integer", (col) => col.notNull().defaultTo(1)).execute();
1462
+ if (!await columnExists(db, "_emdash_404_log", "last_seen_at")) await db.schema.alterTable("_emdash_404_log").addColumn("last_seen_at", "text").execute();
1445
1463
  await sql`
1446
1464
  UPDATE _emdash_404_log
1447
1465
  SET last_seen_at = created_at
1448
1466
  WHERE last_seen_at IS NULL
1449
1467
  `.execute(db);
1450
- await sql`
1451
- WITH ranked AS (
1452
- SELECT
1453
- id,
1454
- path,
1455
- ROW_NUMBER() OVER (
1456
- PARTITION BY path
1457
- ORDER BY created_at DESC, id DESC
1458
- ) AS rn,
1459
- COUNT(*) OVER (PARTITION BY path) AS path_count,
1460
- MAX(created_at) OVER (PARTITION BY path) AS latest_created_at
1461
- FROM _emdash_404_log
1462
- )
1463
- UPDATE _emdash_404_log
1464
- SET
1465
- hits = (SELECT path_count FROM ranked WHERE ranked.id = _emdash_404_log.id),
1466
- last_seen_at = (SELECT latest_created_at FROM ranked WHERE ranked.id = _emdash_404_log.id)
1467
- WHERE id IN (SELECT id FROM ranked WHERE rn = 1)
1468
- `.execute(db);
1469
- await sql`
1470
- DELETE FROM _emdash_404_log
1471
- WHERE id IN (
1472
- SELECT id FROM (
1468
+ if (!hitsExists) {
1469
+ await sql`
1470
+ WITH ranked AS (
1473
1471
  SELECT
1474
1472
  id,
1473
+ path,
1475
1474
  ROW_NUMBER() OVER (
1476
1475
  PARTITION BY path
1477
1476
  ORDER BY created_at DESC, id DESC
1478
- ) AS rn
1477
+ ) AS rn,
1478
+ COUNT(*) OVER (PARTITION BY path) AS path_count,
1479
+ MAX(created_at) OVER (PARTITION BY path) AS latest_created_at
1479
1480
  FROM _emdash_404_log
1480
- ) AS ranked
1481
- WHERE rn > 1
1482
- )
1483
- `.execute(db);
1484
- await db.schema.createIndex("idx_404_log_path_unique").on("_emdash_404_log").column("path").unique().execute();
1485
- await db.schema.dropIndex("idx_404_log_path").execute();
1486
- await db.schema.createIndex("idx_404_log_last_seen").on("_emdash_404_log").column("last_seen_at").execute();
1481
+ )
1482
+ UPDATE _emdash_404_log
1483
+ SET
1484
+ hits = (SELECT path_count FROM ranked WHERE ranked.id = _emdash_404_log.id),
1485
+ last_seen_at = (SELECT latest_created_at FROM ranked WHERE ranked.id = _emdash_404_log.id)
1486
+ WHERE id IN (SELECT id FROM ranked WHERE rn = 1)
1487
+ `.execute(db);
1488
+ await sql`
1489
+ DELETE FROM _emdash_404_log
1490
+ WHERE id IN (
1491
+ SELECT id FROM (
1492
+ SELECT
1493
+ id,
1494
+ ROW_NUMBER() OVER (
1495
+ PARTITION BY path
1496
+ ORDER BY created_at DESC, id DESC
1497
+ ) AS rn
1498
+ FROM _emdash_404_log
1499
+ ) AS ranked
1500
+ WHERE rn > 1
1501
+ )
1502
+ `.execute(db);
1503
+ }
1504
+ await db.schema.createIndex("idx_404_log_path_unique").ifNotExists().on("_emdash_404_log").column("path").unique().execute();
1505
+ await db.schema.dropIndex("idx_404_log_path").ifExists().execute();
1506
+ await db.schema.createIndex("idx_404_log_last_seen").ifNotExists().on("_emdash_404_log").column("last_seen_at").execute();
1487
1507
  }
1488
1508
  async function down(db) {
1489
- await db.schema.dropIndex("idx_404_log_last_seen").execute();
1490
- await db.schema.dropIndex("idx_404_log_path_unique").execute();
1491
- await db.schema.createIndex("idx_404_log_path").on("_emdash_404_log").column("path").execute();
1509
+ await db.schema.dropIndex("idx_404_log_last_seen").ifExists().execute();
1510
+ await db.schema.dropIndex("idx_404_log_path_unique").ifExists().execute();
1511
+ await db.schema.createIndex("idx_404_log_path").ifNotExists().on("_emdash_404_log").column("path").execute();
1492
1512
  await db.schema.alterTable("_emdash_404_log").dropColumn("last_seen_at").execute();
1493
1513
  await db.schema.alterTable("_emdash_404_log").dropColumn("hits").execute();
1494
1514
  }
@@ -1564,22 +1584,130 @@ async function getMigrationStatus(db) {
1564
1584
  pending
1565
1585
  };
1566
1586
  }
1587
+ /** Pattern for escaping special regex characters. Matches the shared helper in `database/repositories/content.ts`. */
1588
+ const REGEX_ESCAPE_PATTERN = /[.*+?^${}()|[\]\\]/g;
1589
+ /** Escape special regex characters so a string can be embedded literally in `new RegExp()`. */
1590
+ function escapeRegExp(value) {
1591
+ return value.replace(REGEX_ESCAPE_PATTERN, "\\$&");
1592
+ }
1593
+ /**
1594
+ * Pattern used to detect the concurrent-migration race. The Kysely
1595
+ * `SqliteAdapter.acquireMigrationLock` is a no-op (inherited by `kysely-d1`
1596
+ * and our `EmDashD1Dialect`), so two isolates running migrations against the
1597
+ * same database can both attempt `INSERT INTO _emdash_migrations` for the
1598
+ * same migration name. The losing insert fails with a UNIQUE constraint
1599
+ * error, which is benign: the other isolate is applying the same schema.
1600
+ *
1601
+ * We match on the table name (not the full error text) because different
1602
+ * SQLite drivers phrase the message differently
1603
+ * (`UNIQUE constraint failed: _emdash_migrations.name` for better-sqlite3,
1604
+ * `D1_ERROR: UNIQUE constraint failed: _emdash_migrations.name: SQLITE_CONSTRAINT`
1605
+ * for D1, etc.). The pattern is built from `MIGRATION_TABLE` so a rename
1606
+ * cannot silently disable race detection.
1607
+ */
1608
+ const MIGRATION_RACE_PATTERN = new RegExp(`UNIQUE constraint failed: ${escapeRegExp(MIGRATION_TABLE)}\\.name`, "i");
1609
+ /** How long to wait for a concurrent migrator to finish before giving up. */
1610
+ const MIGRATION_RACE_WAIT_MS = 1e4;
1611
+ /** Polling interval while waiting for a concurrent migrator. */
1612
+ const MIGRATION_RACE_POLL_MS = 100;
1613
+ /**
1614
+ * Pattern used to detect "table does not exist" errors across the dialects
1615
+ * EmDash supports. The phrasing differs by driver:
1616
+ *
1617
+ * - better-sqlite3: `no such table: _emdash_migrations`
1618
+ * - D1: `D1_ERROR: no such table: _emdash_migrations: SQLITE_ERROR`
1619
+ * - PostgreSQL: `relation "_emdash_migrations" does not exist`
1620
+ * (also occasionally `table "_emdash_migrations" does not exist`)
1621
+ *
1622
+ * We deliberately match on the migration table name (rather than using the
1623
+ * generic `isMissingTableError` helper) so an unexpected missing-table error
1624
+ * naming a different table — implausible today since
1625
+ * `getAppliedMigrationCount` only references `MIGRATION_TABLE`, but cheap
1626
+ * insurance against future edits — is not silently swallowed. The pattern is
1627
+ * built from `MIGRATION_TABLE` so a rename cannot drift.
1628
+ */
1629
+ const MIGRATION_TABLE_MISSING_PATTERN = new RegExp(`(?:no such table:\\s*${escapeRegExp(MIGRATION_TABLE)}\\b|(?:relation|table)\\s+"?${escapeRegExp(MIGRATION_TABLE)}"?\\s+does(?:n't| not) exist\\b)`, "i");
1630
+ /**
1631
+ * Read the count of applied migrations.
1632
+ *
1633
+ * Returns `null` only when the migration table does not exist yet (which is
1634
+ * the normal state on a fresh database before the first migration runs).
1635
+ * Any other error is rethrown so callers — particularly
1636
+ * `waitForConcurrentMigrator` — don't silently mask connection failures,
1637
+ * permission errors, or other unexpected driver problems behind a 10s wait
1638
+ * and a bogus "we're done" verdict.
1639
+ */
1640
+ async function getAppliedMigrationCount(db) {
1641
+ try {
1642
+ const result = await sql`
1643
+ SELECT COUNT(*) as count FROM ${sql.ref(MIGRATION_TABLE)}
1644
+ `.execute(db);
1645
+ return Number(result.rows[0]?.count ?? 0);
1646
+ } catch (error) {
1647
+ if (MIGRATION_TABLE_MISSING_PATTERN.test(deepErrorMessage(error))) return null;
1648
+ throw error;
1649
+ }
1650
+ }
1651
+ /**
1652
+ * Wait for a concurrent migrator to finish applying all migrations.
1653
+ *
1654
+ * Resolves to `true` once the migration table contains at least
1655
+ * `MIGRATION_COUNT` rows (i.e. every migration this build knows about has
1656
+ * been recorded), `false` if the deadline elapses first. We use `>=` rather
1657
+ * than `===` so that an old isolate observing a database that has already
1658
+ * been migrated by a newer build still treats the wait as settled instead
1659
+ * of timing out.
1660
+ */
1661
+ async function waitForConcurrentMigrator(db) {
1662
+ const deadline = Date.now() + MIGRATION_RACE_WAIT_MS;
1663
+ while (Date.now() < deadline) {
1664
+ const count = await getAppliedMigrationCount(db);
1665
+ if (count !== null && count >= MIGRATION_COUNT) return true;
1666
+ await new Promise((resolve) => setTimeout(resolve, MIGRATION_RACE_POLL_MS));
1667
+ }
1668
+ const finalCount = await getAppliedMigrationCount(db);
1669
+ return finalCount !== null && finalCount >= MIGRATION_COUNT;
1670
+ }
1671
+ /** Extract the deepest error message available from a thrown value. */
1672
+ function deepErrorMessage(error) {
1673
+ if (error instanceof Error) {
1674
+ const own = error.message ?? "";
1675
+ if (error.cause) {
1676
+ const causeMsg = deepErrorMessage(error.cause);
1677
+ return own ? `${own}: ${causeMsg}` : causeMsg;
1678
+ }
1679
+ return own;
1680
+ }
1681
+ if (typeof error === "string") return error;
1682
+ try {
1683
+ return JSON.stringify(error);
1684
+ } catch {
1685
+ return String(error);
1686
+ }
1687
+ }
1567
1688
  /**
1568
1689
  * Run all pending migrations.
1569
1690
  *
1570
1691
  * Includes a fast-path: if the migration table already exists and contains
1571
- * exactly MIGRATION_COUNT rows, all migrations have been applied and we can
1572
- * skip the Kysely Migrator entirely. This avoids the expensive
1573
- * `pragma_table_info` introspection that Kysely runs for every table in the
1574
- * database (twice!) just to check if the migration tables exist.
1575
- * On D1 with ~57 tables, that's ~116 queries saved per init.
1692
+ * at least MIGRATION_COUNT rows, all migrations this build knows about have
1693
+ * been applied and we can skip the Kysely Migrator entirely. This avoids
1694
+ * the expensive `pragma_table_info` introspection that Kysely runs for
1695
+ * every table in the database (twice!) just to check if the migration
1696
+ * tables exist. On D1 with ~57 tables, that's ~116 queries saved per init.
1697
+ *
1698
+ * Concurrent-migration safety: the Kysely Migrator's `acquireMigrationLock`
1699
+ * is a no-op for SQLite (and therefore D1), so two callers running this
1700
+ * concurrently against the same database will both try to apply pending
1701
+ * migrations. SQLite serializes the writes, but the loser still surfaces a
1702
+ * `UNIQUE constraint failed: _emdash_migrations.name` error. We treat that
1703
+ * specific error as benign: another caller is already applying the same
1704
+ * schema. We wait for the concurrent migrator to finish, then return
1705
+ * success. This matches the user-observable expectation that running
1706
+ * migrations twice in a row is a no-op.
1576
1707
  */
1577
1708
  async function runMigrations(db) {
1578
- try {
1579
- if ((await sql`
1580
- SELECT COUNT(*) as count FROM ${sql.ref(MIGRATION_TABLE)}
1581
- `.execute(db)).rows[0]?.count === MIGRATION_COUNT) return { applied: [] };
1582
- } catch {}
1709
+ const initialCount = await getAppliedMigrationCount(db);
1710
+ if (initialCount !== null && initialCount >= MIGRATION_COUNT) return { applied: [] };
1583
1711
  const { error, results } = await new Migrator({
1584
1712
  db,
1585
1713
  provider: new StaticMigrationProvider(),
@@ -1588,11 +1716,13 @@ async function runMigrations(db) {
1588
1716
  }).migrateToLatest();
1589
1717
  const applied = results?.filter((r) => r.status === "Success").map((r) => r.migrationName) ?? [];
1590
1718
  if (error) {
1591
- let msg = error instanceof Error ? error.message : JSON.stringify(error);
1592
- if (!msg && error instanceof Error && error.cause) msg = error.cause instanceof Error ? error.cause.message : JSON.stringify(error.cause);
1719
+ const msg = deepErrorMessage(error);
1593
1720
  const failedMigration = results?.find((r) => r.status === "Error");
1594
- if (failedMigration) msg = `${msg || "unknown error"} (migration: ${failedMigration.migrationName})`;
1595
- throw new Error(`Migration failed: ${msg}`);
1721
+ if (MIGRATION_RACE_PATTERN.test(msg)) {
1722
+ if (await waitForConcurrentMigrator(db)) return { applied };
1723
+ }
1724
+ const failedSuffix = failedMigration ? ` (migration: ${failedMigration.migrationName})` : "";
1725
+ throw new Error(`Migration failed: ${msg || "unknown error"}${failedSuffix}`);
1596
1726
  }
1597
1727
  return { applied };
1598
1728
  }
@@ -1615,5 +1745,5 @@ async function rollbackMigration(db) {
1615
1745
  }
1616
1746
 
1617
1747
  //#endregion
1618
- export { rollbackMigration as n, runMigrations as r, getMigrationStatus as t };
1619
- //# sourceMappingURL=runner-tQ7BJ4T7.mjs.map
1748
+ export { __exportAll as i, rollbackMigration as n, runMigrations as r, getMigrationStatus as t };
1749
+ //# sourceMappingURL=runner-C7ADox5q.mjs.map