emdash 0.7.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 (354) hide show
  1. package/dist/{adapters-Di31kZ28.d.mts → adapters-DoNJiveC.d.mts} +1 -1
  2. package/dist/{adapters-Di31kZ28.d.mts.map → adapters-DoNJiveC.d.mts.map} +1 -1
  3. package/dist/{apply-5uslYdUu.mjs → apply-BzltprvY.mjs} +90 -139
  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 +194 -17
  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 +34 -57
  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 +301 -165
  22. package/dist/astro/middleware.mjs.map +1 -1
  23. package/dist/astro/types.d.mts +34 -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-C4OVd8b3.mjs → byline-BSaNL1w7.mjs} +5 -5
  28. package/dist/byline-BSaNL1w7.mjs.map +1 -0
  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 +229 -31
  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-D7J5y73J.mjs → content-8lOYF0pr.mjs} +43 -28
  44. package/dist/content-8lOYF0pr.mjs.map +1 -0
  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-D0UT85nC.mjs → db-errors-WRezodiz.mjs} +1 -1
  57. package/dist/{db-errors-D0UT85nC.mjs.map → db-errors-WRezodiz.mjs.map} +1 -1
  58. package/dist/{default-CME5YdZ3.mjs → default-D8ksjWhO.mjs} +1 -1
  59. package/dist/{default-CME5YdZ3.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-CiYn9yDu.mjs → error-D_-tqP-I.mjs} +1 -1
  63. package/dist/error-D_-tqP-I.mjs.map +1 -0
  64. package/dist/{index-De6_Xv3v.d.mts → index-BFRaVcD6.d.mts} +243 -40
  65. package/dist/index-BFRaVcD6.d.mts.map +1 -0
  66. package/dist/index.d.mts +11 -11
  67. package/dist/index.mjs +29 -25
  68. package/dist/{load-CBcmDIot.mjs → load-DDqMMvZL.mjs} +2 -2
  69. package/dist/{load-CBcmDIot.mjs.map → load-DDqMMvZL.mjs.map} +1 -1
  70. package/dist/{loader-DeiBJEMe.mjs → loader-CKLbBnhK.mjs} +32 -10
  71. package/dist/loader-CKLbBnhK.mjs.map +1 -0
  72. package/dist/{manifest-schema-V30qsMft.mjs → manifest-schema-DqWNC3lM.mjs} +45 -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-DqHVh136.mjs → media-BW32b4gi.mjs} +4 -7
  79. package/dist/media-BW32b4gi.mjs.map +1 -0
  80. package/dist/{mode-CpNnGkPz.mjs → mode-ier8jbBk.mjs} +1 -1
  81. package/dist/mode-ier8jbBk.mjs.map +1 -0
  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-tzpqGWII.d.mts → placeholder-BE4o_2dc.d.mts} +1 -1
  86. package/dist/{placeholder-tzpqGWII.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-CIJejMlK.mjs.map +1 -0
  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-g4Ug-9j9.mjs → query-Cg9ZKRQ0.mjs} +114 -16
  96. package/dist/query-Cg9ZKRQ0.mjs.map +1 -0
  97. package/dist/{redirect-CN0Rt9Ob.mjs → redirect-BhUBKRc1.mjs} +13 -8
  98. package/dist/redirect-BhUBKRc1.mjs.map +1 -0
  99. package/dist/{registry-Ci3WxVAr.mjs → registry-Dw70ChxB.mjs} +69 -11
  100. package/dist/registry-Dw70ChxB.mjs.map +1 -0
  101. package/dist/{request-cache-DiR961CV.mjs → request-cache-B-bmkipQ.mjs} +1 -1
  102. package/dist/request-cache-B-bmkipQ.mjs.map +1 -0
  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-B0effn3j.mjs → search-dOGEccMa.mjs} +341 -152
  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.d.mts.map +1 -1
  120. package/dist/storage/s3.mjs +4 -4
  121. package/dist/storage/s3.mjs.map +1 -1
  122. package/dist/{taxonomies-K2z0Uhnj.mjs → taxonomies-ZlRtD6AG.mjs} +14 -7
  123. package/dist/taxonomies-ZlRtD6AG.mjs.map +1 -0
  124. package/dist/{tokens-BFPFx3CA.mjs → tokens-D7zMmWi2.mjs} +2 -2
  125. package/dist/{tokens-BFPFx3CA.mjs.map → tokens-D7zMmWi2.mjs.map} +1 -1
  126. package/dist/{transport-BykRfpyy.mjs → transport-BeMCmin1.mjs} +6 -5
  127. package/dist/{transport-BykRfpyy.mjs.map → transport-BeMCmin1.mjs.map} +1 -1
  128. package/dist/{transport-H4Iwx7tC.d.mts → transport-DNEfeMaU.d.mts} +1 -1
  129. package/dist/{transport-H4Iwx7tC.d.mts.map → transport-DNEfeMaU.d.mts.map} +1 -1
  130. package/dist/types-4fVtCIm0.mjs +68 -0
  131. package/dist/types-4fVtCIm0.mjs.map +1 -0
  132. package/dist/{types-CnZYHyLW.d.mts → types-BSyXeCFW.d.mts} +24 -2
  133. package/dist/{types-CnZYHyLW.d.mts.map → types-BSyXeCFW.d.mts.map} +1 -1
  134. package/dist/{types-DgrIP0tF.d.mts → types-BuBIptGk.d.mts} +80 -106
  135. package/dist/types-BuBIptGk.d.mts.map +1 -0
  136. package/dist/{types-BH2L167P.mjs → types-CDbKp7ND.mjs} +1 -1
  137. package/dist/{types-BH2L167P.mjs.map → types-CDbKp7ND.mjs.map} +1 -1
  138. package/dist/{types-DDS4MxsT.mjs → types-CIOg5AR8.mjs} +1 -1
  139. package/dist/{types-DDS4MxsT.mjs.map → types-CIOg5AR8.mjs.map} +1 -1
  140. package/dist/{types-6CUZRrZP.d.mts → types-CJsYGpco.d.mts} +24 -2
  141. package/dist/{types-6CUZRrZP.d.mts.map → types-CJsYGpco.d.mts.map} +1 -1
  142. package/dist/types-CRxNbK-Z.mjs +68 -0
  143. package/dist/types-CRxNbK-Z.mjs.map +1 -0
  144. package/dist/{types-C2v0c34j.d.mts → types-CrtWgIvl.d.mts} +1 -1
  145. package/dist/{types-C2v0c34j.d.mts.map → types-CrtWgIvl.d.mts.map} +1 -1
  146. package/dist/{types-CFWjXmus.d.mts → types-M78DQ1lx.d.mts} +1 -1
  147. package/dist/{types-CFWjXmus.d.mts.map → types-M78DQ1lx.d.mts.map} +1 -1
  148. package/dist/{validate-CqsNItbt.mjs → validate-Baqf0slj.mjs} +3 -3
  149. package/dist/{validate-CqsNItbt.mjs.map → validate-Baqf0slj.mjs.map} +1 -1
  150. package/dist/{validate-kM8Pjuf7.d.mts → validate-BfQh_C_y.d.mts} +4 -4
  151. package/dist/{validate-kM8Pjuf7.d.mts.map → validate-BfQh_C_y.d.mts.map} +1 -1
  152. package/dist/validation-BfEI7tNe.mjs +144 -0
  153. package/dist/validation-BfEI7tNe.mjs.map +1 -0
  154. package/dist/version-DoxrVdYf.mjs +7 -0
  155. package/dist/{version-BnTKdfam.mjs.map → version-DoxrVdYf.mjs.map} +1 -1
  156. package/dist/zod-generator-CC0xNe_K.mjs +132 -0
  157. package/dist/zod-generator-CC0xNe_K.mjs.map +1 -0
  158. package/locals.d.ts +1 -6
  159. package/package.json +21 -7
  160. package/src/api/auth-storage.ts +37 -0
  161. package/src/api/error.ts +6 -0
  162. package/src/api/errors.ts +8 -0
  163. package/src/api/handlers/comments.ts +19 -4
  164. package/src/api/handlers/content.ts +151 -4
  165. package/src/api/handlers/device-flow.ts +5 -0
  166. package/src/api/handlers/index.ts +2 -0
  167. package/src/api/handlers/marketplace.ts +11 -4
  168. package/src/api/handlers/media.ts +8 -1
  169. package/src/api/handlers/menus.ts +160 -21
  170. package/src/api/handlers/oauth-authorization.ts +72 -33
  171. package/src/api/handlers/redirects.ts +16 -3
  172. package/src/api/handlers/revision.ts +23 -14
  173. package/src/api/handlers/sections.ts +8 -1
  174. package/src/api/handlers/taxonomies.ts +131 -22
  175. package/src/api/handlers/validation.ts +212 -0
  176. package/src/api/openapi/document.ts +4 -1
  177. package/src/api/public-url.ts +54 -5
  178. package/src/api/route-utils.ts +14 -0
  179. package/src/api/schemas/comments.ts +2 -2
  180. package/src/api/schemas/common.ts +1 -1
  181. package/src/api/schemas/content.ts +17 -0
  182. package/src/api/schemas/sections.ts +3 -3
  183. package/src/api/schemas/setup.ts +8 -0
  184. package/src/api/schemas/users.ts +1 -1
  185. package/src/api/schemas/widgets.ts +12 -10
  186. package/src/api/setup-complete.ts +40 -0
  187. package/src/api/types.ts +5 -1
  188. package/src/astro/integration/index.ts +30 -2
  189. package/src/astro/integration/routes.ts +28 -0
  190. package/src/astro/integration/runtime.ts +49 -1
  191. package/src/astro/integration/virtual-modules.ts +73 -2
  192. package/src/astro/integration/vite-config.ts +49 -13
  193. package/src/astro/middleware/auth.ts +34 -6
  194. package/src/astro/middleware/redirect.ts +29 -16
  195. package/src/astro/middleware/request-context.ts +15 -5
  196. package/src/astro/middleware.ts +41 -10
  197. package/src/astro/routes/PluginRegistry.tsx +10 -1
  198. package/src/astro/routes/api/auth/invite/complete.ts +6 -1
  199. package/src/astro/routes/api/auth/mode.ts +57 -0
  200. package/src/astro/routes/api/auth/oauth/[provider]/callback.ts +23 -3
  201. package/src/astro/routes/api/auth/oauth/[provider].ts +10 -4
  202. package/src/astro/routes/api/auth/passkey/register/verify.ts +6 -1
  203. package/src/astro/routes/api/auth/passkey/verify.ts +6 -1
  204. package/src/astro/routes/api/auth/signup/complete.ts +6 -1
  205. package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +2 -2
  206. package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +4 -2
  207. package/src/astro/routes/api/content/[collection]/[id]/preview-url.ts +34 -12
  208. package/src/astro/routes/api/content/[collection]/[id]/publish.ts +32 -2
  209. package/src/astro/routes/api/content/[collection]/[id]/restore.ts +4 -2
  210. package/src/astro/routes/api/content/[collection]/[id]/revisions.ts +3 -2
  211. package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +8 -4
  212. package/src/astro/routes/api/content/[collection]/[id]/translations.ts +1 -1
  213. package/src/astro/routes/api/content/[collection]/[id].ts +12 -0
  214. package/src/astro/routes/api/content/[collection]/index.ts +1 -9
  215. package/src/astro/routes/api/import/wordpress/execute.ts +3 -1
  216. package/src/astro/routes/api/import/wordpress/media.ts +2 -7
  217. package/src/astro/routes/api/import/wordpress/prepare.ts +9 -0
  218. package/src/astro/routes/api/import/wordpress-plugin/execute.ts +3 -1
  219. package/src/astro/routes/api/manifest.ts +62 -45
  220. package/src/astro/routes/api/media/[id]/confirm.ts +10 -1
  221. package/src/astro/routes/api/media/providers/[providerId]/index.ts +12 -3
  222. package/src/astro/routes/api/openapi.json.ts +27 -10
  223. package/src/astro/routes/api/redirects/404s/index.ts +10 -4
  224. package/src/astro/routes/api/redirects/404s/summary.ts +4 -2
  225. package/src/astro/routes/api/redirects/[id].ts +10 -4
  226. package/src/astro/routes/api/redirects/index.ts +7 -3
  227. package/src/astro/routes/api/revisions/[revisionId]/index.ts +1 -1
  228. package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +0 -2
  229. package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +0 -1
  230. package/src/astro/routes/api/schema/collections/[slug]/fields/reorder.ts +0 -1
  231. package/src/astro/routes/api/schema/collections/[slug]/index.ts +2 -2
  232. package/src/astro/routes/api/schema/collections/index.ts +1 -1
  233. package/src/astro/routes/api/search/index.ts +10 -2
  234. package/src/astro/routes/api/sections/[slug].ts +10 -4
  235. package/src/astro/routes/api/sections/index.ts +7 -3
  236. package/src/astro/routes/api/settings/email.ts +4 -9
  237. package/src/astro/routes/api/setup/admin-verify.ts +6 -1
  238. package/src/astro/routes/api/setup/admin.ts +8 -2
  239. package/src/astro/routes/api/setup/index.ts +2 -2
  240. package/src/astro/routes/api/setup/status.ts +3 -1
  241. package/src/astro/routes/api/snapshot.ts +44 -18
  242. package/src/astro/routes/api/taxonomies/index.ts +0 -1
  243. package/src/astro/routes/api/themes/preview.ts +11 -5
  244. package/src/astro/routes/api/widget-areas/[name]/widgets/[id].ts +4 -1
  245. package/src/astro/routes/api/widget-areas/[name]/widgets.ts +4 -1
  246. package/src/astro/routes/api/widget-areas/[name].ts +4 -1
  247. package/src/astro/routes/api/widget-areas/index.ts +4 -1
  248. package/src/astro/types.ts +32 -3
  249. package/src/auth/allowed-origins.ts +168 -0
  250. package/src/auth/mode.ts +15 -3
  251. package/src/auth/passkey-config.ts +35 -13
  252. package/src/auth/providers/github-admin.tsx +29 -0
  253. package/src/auth/providers/github.ts +31 -0
  254. package/src/auth/providers/google-admin.tsx +44 -0
  255. package/src/auth/providers/google.ts +31 -0
  256. package/src/auth/types.ts +114 -4
  257. package/src/bylines/index.ts +37 -88
  258. package/src/cli/commands/auth.ts +28 -6
  259. package/src/cli/commands/bundle-utils.ts +11 -2
  260. package/src/cli/commands/bundle.ts +31 -9
  261. package/src/cli/commands/content.ts +13 -0
  262. package/src/cli/commands/login.ts +8 -1
  263. package/src/cli/commands/publish.ts +24 -0
  264. package/src/cli/commands/secrets.ts +183 -0
  265. package/src/cli/credentials.ts +1 -1
  266. package/src/cli/index.ts +5 -1
  267. package/src/client/index.ts +4 -4
  268. package/src/client/transport.ts +17 -7
  269. package/src/components/Break.astro +2 -2
  270. package/src/components/EmDashHead.astro +18 -13
  271. package/src/components/EmDashImage.astro +7 -6
  272. package/src/components/Embed.astro +1 -1
  273. package/src/components/Gallery.astro +6 -4
  274. package/src/components/Image.astro +9 -4
  275. package/src/components/InlinePortableTextEditor.tsx +106 -19
  276. package/src/components/LiveSearch.astro +5 -14
  277. package/src/config/secrets.ts +528 -0
  278. package/src/database/dialect-helpers.ts +50 -0
  279. package/src/database/migrations/034_published_at_index.ts +1 -1
  280. package/src/database/migrations/035_bounded_404_log.ts +56 -39
  281. package/src/database/migrations/runner.ts +156 -23
  282. package/src/database/repositories/audit.ts +6 -8
  283. package/src/database/repositories/byline.ts +6 -8
  284. package/src/database/repositories/comment.ts +12 -16
  285. package/src/database/repositories/content.ts +76 -52
  286. package/src/database/repositories/index.ts +1 -1
  287. package/src/database/repositories/media.ts +10 -13
  288. package/src/database/repositories/plugin-storage.ts +4 -6
  289. package/src/database/repositories/redirect.ts +26 -19
  290. package/src/database/repositories/taxonomy.ts +40 -3
  291. package/src/database/repositories/types.ts +57 -8
  292. package/src/database/repositories/user.ts +6 -8
  293. package/src/db/libsql.ts +1 -3
  294. package/src/db/sqlite.ts +2 -5
  295. package/src/emdash-runtime.ts +388 -247
  296. package/src/index.ts +14 -1
  297. package/src/loader.ts +30 -6
  298. package/src/mcp/server.ts +781 -141
  299. package/src/media/normalize.ts +1 -1
  300. package/src/media/url.ts +78 -0
  301. package/src/page/site-identity.ts +58 -0
  302. package/src/plugins/adapt-sandbox-entry.ts +22 -10
  303. package/src/plugins/context.ts +13 -10
  304. package/src/plugins/define-plugin.ts +40 -12
  305. package/src/plugins/email-console.ts +10 -3
  306. package/src/plugins/hooks.ts +34 -19
  307. package/src/plugins/index.ts +9 -0
  308. package/src/plugins/manifest-schema.ts +49 -2
  309. package/src/plugins/types.ts +174 -13
  310. package/src/preview/urls.ts +23 -3
  311. package/src/query.ts +149 -6
  312. package/src/redirects/cache.ts +38 -18
  313. package/src/request-cache.ts +3 -0
  314. package/src/schema/registry.ts +97 -5
  315. package/src/schema/zod-generator.ts +27 -5
  316. package/src/search/fts-manager.ts +0 -2
  317. package/src/search/query.ts +111 -26
  318. package/src/search/types.ts +8 -1
  319. package/src/sections/index.ts +7 -9
  320. package/src/seed/apply.ts +2 -0
  321. package/src/settings/index.ts +80 -6
  322. package/src/settings/types.ts +23 -1
  323. package/src/storage/s3.ts +12 -6
  324. package/src/taxonomies/index.ts +11 -1
  325. package/src/virtual-modules.d.ts +21 -1
  326. package/src/widgets/index.ts +1 -1
  327. package/dist/apply-5uslYdUu.mjs.map +0 -1
  328. package/dist/byline-C4OVd8b3.mjs.map +0 -1
  329. package/dist/bylines-hPTW79hw.mjs +0 -157
  330. package/dist/bylines-hPTW79hw.mjs.map +0 -1
  331. package/dist/cache-BkKBuIvS.mjs +0 -56
  332. package/dist/cache-BkKBuIvS.mjs.map +0 -1
  333. package/dist/chunk-ClPoSABd.mjs +0 -21
  334. package/dist/content-D7J5y73J.mjs.map +0 -1
  335. package/dist/dialect-helpers-DhTzaUxP.mjs.map +0 -1
  336. package/dist/error-CiYn9yDu.mjs.map +0 -1
  337. package/dist/index-De6_Xv3v.d.mts.map +0 -1
  338. package/dist/loader-DeiBJEMe.mjs.map +0 -1
  339. package/dist/manifest-schema-V30qsMft.mjs.map +0 -1
  340. package/dist/media-DqHVh136.mjs.map +0 -1
  341. package/dist/mode-CpNnGkPz.mjs.map +0 -1
  342. package/dist/placeholder-C-fk5hYI.mjs.map +0 -1
  343. package/dist/query-g4Ug-9j9.mjs.map +0 -1
  344. package/dist/redirect-CN0Rt9Ob.mjs.map +0 -1
  345. package/dist/registry-Ci3WxVAr.mjs.map +0 -1
  346. package/dist/request-cache-DiR961CV.mjs.map +0 -1
  347. package/dist/runner-BR2xKwhn.d.mts +0 -34
  348. package/dist/runner-BR2xKwhn.d.mts.map +0 -1
  349. package/dist/search-B0effn3j.mjs.map +0 -1
  350. package/dist/taxonomies-K2z0Uhnj.mjs.map +0 -1
  351. package/dist/types-CMMN0pNg.mjs +0 -31
  352. package/dist/types-CMMN0pNg.mjs.map +0 -1
  353. package/dist/types-DgrIP0tF.d.mts.map +0 -1
  354. package/dist/version-BnTKdfam.mjs +0 -7
@@ -1,12 +1,17 @@
1
- import { n as __require } from "../chunk-ClPoSABd.mjs";
1
+ import BetterSqlite3 from "better-sqlite3";
2
+ import { SqliteDialect } from "kysely";
2
3
 
3
4
  //#region src/db/sqlite.ts
4
5
  /**
6
+ * SQLite runtime adapter
7
+ *
8
+ * Creates a Kysely dialect for better-sqlite3.
9
+ * Loaded at runtime via virtual module.
10
+ */
11
+ /**
5
12
  * Create a SQLite dialect from config
6
13
  */
7
14
  function createDialect(config) {
8
- const BetterSqlite3 = __require("better-sqlite3");
9
- const { SqliteDialect } = __require("kysely");
10
15
  const url = config.url;
11
16
  return new SqliteDialect({ database: new BetterSqlite3(url.startsWith("file:") ? url.slice(5) : url) });
12
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite.mjs","names":[],"sources":["../../src/db/sqlite.ts"],"sourcesContent":["/**\n * SQLite runtime adapter\n *\n * Creates a Kysely dialect for better-sqlite3.\n * Loaded at runtime via virtual module.\n */\n\nimport type { Dialect } from \"kysely\";\n\nimport type { SqliteConfig } from \"./adapters.js\";\n\n/**\n * Create a SQLite dialect from config\n */\nexport function createDialect(config: SqliteConfig): Dialect {\n\t// Dynamic import to avoid loading better-sqlite3 at config time\n\tconst BetterSqlite3 = require(\"better-sqlite3\");\n\tconst { SqliteDialect } = require(\"kysely\");\n\n\t// Parse URL to get file path\n\tconst url = config.url;\n\tconst filePath = url.startsWith(\"file:\") ? url.slice(5) : url;\n\n\tconst database = new BetterSqlite3(filePath);\n\n\treturn new SqliteDialect({ database });\n}\n"],"mappings":";;;;;;AAcA,SAAgB,cAAc,QAA+B;CAE5D,MAAM,0BAAwB,iBAAiB;CAC/C,MAAM,EAAE,4BAA0B,SAAS;CAG3C,MAAM,MAAM,OAAO;AAKnB,QAAO,IAAI,cAAc,EAAE,UAFV,IAAI,cAFJ,IAAI,WAAW,QAAQ,GAAG,IAAI,MAAM,EAAE,GAAG,IAEd,EAEP,CAAC"}
1
+ {"version":3,"file":"sqlite.mjs","names":[],"sources":["../../src/db/sqlite.ts"],"sourcesContent":["/**\n * SQLite runtime adapter\n *\n * Creates a Kysely dialect for better-sqlite3.\n * Loaded at runtime via virtual module.\n */\n\nimport BetterSqlite3 from \"better-sqlite3\";\nimport { type Dialect, SqliteDialect } from \"kysely\";\n\nimport type { SqliteConfig } from \"./adapters.js\";\n\n/**\n * Create a SQLite dialect from config\n */\nexport function createDialect(config: SqliteConfig): Dialect {\n\t// Parse URL to get file path\n\tconst url = config.url;\n\tconst filePath = url.startsWith(\"file:\") ? url.slice(5) : url;\n\n\tconst database = new BetterSqlite3(filePath);\n\n\treturn new SqliteDialect({ database });\n}\n"],"mappings":";;;;;;;;;;;;;AAeA,SAAgB,cAAc,QAA+B;CAE5D,MAAM,MAAM,OAAO;AAKnB,QAAO,IAAI,cAAc,EAAE,UAFV,IAAI,cAFJ,IAAI,WAAW,QAAQ,GAAG,IAAI,MAAM,EAAE,GAAG,IAEd,EAEP,CAAC"}
@@ -38,4 +38,4 @@ function isMissingTableError(error) {
38
38
 
39
39
  //#endregion
40
40
  export { isMissingTableError as t };
41
- //# sourceMappingURL=db-errors-D0UT85nC.mjs.map
41
+ //# sourceMappingURL=db-errors-WRezodiz.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"db-errors-D0UT85nC.mjs","names":[],"sources":["../src/utils/db-errors.ts"],"sourcesContent":["/**\n * Shared detection helpers for database-layer error messages.\n *\n * Different SQL dialects phrase \"table or relation does not exist\" differently:\n *\n * - SQLite / D1: \"no such table: foo\"\n * - PostgreSQL: 'relation \"foo\" does not exist'\n * 'table \"foo\" does not exist'\n * - MySQL (future): \"Table 'db.foo' doesn't exist\"\n *\n * Runtime code paths that short-circuit on missing tables (pre-migration\n * probes, optional feature tables, etc.) should use these helpers rather\n * than hand-rolling string matches per call-site.\n */\n\n/**\n * Extract a lowercase error message from any unknown value, safely.\n */\nfunction messageOf(error: unknown): string {\n\tif (error instanceof Error) return error.message.toLowerCase();\n\tif (typeof error === \"string\") return error.toLowerCase();\n\treturn \"\";\n}\n\n/**\n * Returns true when `error` is a \"table does not exist\" error across the\n * dialects EmDash supports (D1/SQLite and PostgreSQL). Used by runtime\n * probes to treat pre-migration databases as empty without logging a scary\n * warning, while still propagating unrelated errors (permissions, connection\n * loss, syntax issues) to callers.\n */\nexport function isMissingTableError(error: unknown): boolean {\n\tconst message = messageOf(error);\n\tif (!message) return false;\n\n\t// SQLite / D1\n\tif (message.includes(\"no such table\")) return true;\n\n\t// PostgreSQL (and some MySQL variants): \"relation ... does not exist\" /\n\t// \"table ... does not exist\" / \"doesn't exist\".\n\tif (message.includes(\"does not exist\") || message.includes(\"doesn't exist\")) {\n\t\treturn message.includes(\"relation\") || message.includes(\"table\");\n\t}\n\n\treturn false;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAkBA,SAAS,UAAU,OAAwB;AAC1C,KAAI,iBAAiB,MAAO,QAAO,MAAM,QAAQ,aAAa;AAC9D,KAAI,OAAO,UAAU,SAAU,QAAO,MAAM,aAAa;AACzD,QAAO;;;;;;;;;AAUR,SAAgB,oBAAoB,OAAyB;CAC5D,MAAM,UAAU,UAAU,MAAM;AAChC,KAAI,CAAC,QAAS,QAAO;AAGrB,KAAI,QAAQ,SAAS,gBAAgB,CAAE,QAAO;AAI9C,KAAI,QAAQ,SAAS,iBAAiB,IAAI,QAAQ,SAAS,gBAAgB,CAC1E,QAAO,QAAQ,SAAS,WAAW,IAAI,QAAQ,SAAS,QAAQ;AAGjE,QAAO"}
1
+ {"version":3,"file":"db-errors-WRezodiz.mjs","names":[],"sources":["../src/utils/db-errors.ts"],"sourcesContent":["/**\n * Shared detection helpers for database-layer error messages.\n *\n * Different SQL dialects phrase \"table or relation does not exist\" differently:\n *\n * - SQLite / D1: \"no such table: foo\"\n * - PostgreSQL: 'relation \"foo\" does not exist'\n * 'table \"foo\" does not exist'\n * - MySQL (future): \"Table 'db.foo' doesn't exist\"\n *\n * Runtime code paths that short-circuit on missing tables (pre-migration\n * probes, optional feature tables, etc.) should use these helpers rather\n * than hand-rolling string matches per call-site.\n */\n\n/**\n * Extract a lowercase error message from any unknown value, safely.\n */\nfunction messageOf(error: unknown): string {\n\tif (error instanceof Error) return error.message.toLowerCase();\n\tif (typeof error === \"string\") return error.toLowerCase();\n\treturn \"\";\n}\n\n/**\n * Returns true when `error` is a \"table does not exist\" error across the\n * dialects EmDash supports (D1/SQLite and PostgreSQL). Used by runtime\n * probes to treat pre-migration databases as empty without logging a scary\n * warning, while still propagating unrelated errors (permissions, connection\n * loss, syntax issues) to callers.\n */\nexport function isMissingTableError(error: unknown): boolean {\n\tconst message = messageOf(error);\n\tif (!message) return false;\n\n\t// SQLite / D1\n\tif (message.includes(\"no such table\")) return true;\n\n\t// PostgreSQL (and some MySQL variants): \"relation ... does not exist\" /\n\t// \"table ... does not exist\" / \"doesn't exist\".\n\tif (message.includes(\"does not exist\") || message.includes(\"doesn't exist\")) {\n\t\treturn message.includes(\"relation\") || message.includes(\"table\");\n\t}\n\n\treturn false;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAkBA,SAAS,UAAU,OAAwB;AAC1C,KAAI,iBAAiB,MAAO,QAAO,MAAM,QAAQ,aAAa;AAC9D,KAAI,OAAO,UAAU,SAAU,QAAO,MAAM,aAAa;AACzD,QAAO;;;;;;;;;AAUR,SAAgB,oBAAoB,OAAyB;CAC5D,MAAM,UAAU,UAAU,MAAM;AAChC,KAAI,CAAC,QAAS,QAAO;AAGrB,KAAI,QAAQ,SAAS,gBAAgB,CAAE,QAAO;AAI9C,KAAI,QAAQ,SAAS,iBAAiB,IAAI,QAAQ,SAAS,gBAAgB,CAC1E,QAAO,QAAQ,SAAS,WAAW,IAAI,QAAQ,SAAS,QAAQ;AAGjE,QAAO"}
@@ -78,4 +78,4 @@ const defaultSeed = {
78
78
 
79
79
  //#endregion
80
80
  export { defaultSeed as t };
81
- //# sourceMappingURL=default-CME5YdZ3.mjs.map
81
+ //# sourceMappingURL=default-D8ksjWhO.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"default-CME5YdZ3.mjs","names":[],"sources":["../src/seed/default.ts"],"sourcesContent":["/**\n * Default seed applied when no user seed file exists.\n *\n * Provides the baseline schema every EmDash site needs:\n * posts, pages, categories, and tags.\n */\n\nimport type { SeedFile } from \"./types.js\";\n\nexport const defaultSeed: SeedFile = {\n\tversion: \"1\",\n\tmeta: {\n\t\tname: \"Default\",\n\t\tdescription: \"Posts and pages with categories and tags\",\n\t},\n\tcollections: [\n\t\t{\n\t\t\tslug: \"posts\",\n\t\t\tlabel: \"Posts\",\n\t\t\tlabelSingular: \"Post\",\n\t\t\tsupports: [\"drafts\", \"revisions\", \"search\"],\n\t\t\tfields: [\n\t\t\t\t{\n\t\t\t\t\tslug: \"title\",\n\t\t\t\t\tlabel: \"Title\",\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\trequired: true,\n\t\t\t\t\tsearchable: true,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tslug: \"featured_image\",\n\t\t\t\t\tlabel: \"Featured Image\",\n\t\t\t\t\ttype: \"image\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tslug: \"content\",\n\t\t\t\t\tlabel: \"Content\",\n\t\t\t\t\ttype: \"portableText\",\n\t\t\t\t\tsearchable: true,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tslug: \"excerpt\",\n\t\t\t\t\tlabel: \"Excerpt\",\n\t\t\t\t\ttype: \"text\",\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\t{\n\t\t\tslug: \"pages\",\n\t\t\tlabel: \"Pages\",\n\t\t\tlabelSingular: \"Page\",\n\t\t\tsupports: [\"drafts\", \"revisions\", \"search\"],\n\t\t\tfields: [\n\t\t\t\t{\n\t\t\t\t\tslug: \"title\",\n\t\t\t\t\tlabel: \"Title\",\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\trequired: true,\n\t\t\t\t\tsearchable: true,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tslug: \"content\",\n\t\t\t\t\tlabel: \"Content\",\n\t\t\t\t\ttype: \"portableText\",\n\t\t\t\t\tsearchable: true,\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t],\n\ttaxonomies: [\n\t\t{\n\t\t\tname: \"category\",\n\t\t\tlabel: \"Categories\",\n\t\t\tlabelSingular: \"Category\",\n\t\t\thierarchical: true,\n\t\t\tcollections: [\"posts\"],\n\t\t},\n\t\t{\n\t\t\tname: \"tag\",\n\t\t\tlabel: \"Tags\",\n\t\t\tlabelSingular: \"Tag\",\n\t\t\thierarchical: false,\n\t\t\tcollections: [\"posts\"],\n\t\t},\n\t],\n};\n"],"mappings":";AASA,MAAa,cAAwB;CACpC,SAAS;CACT,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,aAAa,CACZ;EACC,MAAM;EACN,OAAO;EACP,eAAe;EACf,UAAU;GAAC;GAAU;GAAa;GAAS;EAC3C,QAAQ;GACP;IACC,MAAM;IACN,OAAO;IACP,MAAM;IACN,UAAU;IACV,YAAY;IACZ;GACD;IACC,MAAM;IACN,OAAO;IACP,MAAM;IACN;GACD;IACC,MAAM;IACN,OAAO;IACP,MAAM;IACN,YAAY;IACZ;GACD;IACC,MAAM;IACN,OAAO;IACP,MAAM;IACN;GACD;EACD,EACD;EACC,MAAM;EACN,OAAO;EACP,eAAe;EACf,UAAU;GAAC;GAAU;GAAa;GAAS;EAC3C,QAAQ,CACP;GACC,MAAM;GACN,OAAO;GACP,MAAM;GACN,UAAU;GACV,YAAY;GACZ,EACD;GACC,MAAM;GACN,OAAO;GACP,MAAM;GACN,YAAY;GACZ,CACD;EACD,CACD;CACD,YAAY,CACX;EACC,MAAM;EACN,OAAO;EACP,eAAe;EACf,cAAc;EACd,aAAa,CAAC,QAAQ;EACtB,EACD;EACC,MAAM;EACN,OAAO;EACP,eAAe;EACf,cAAc;EACd,aAAa,CAAC,QAAQ;EACtB,CACD;CACD"}
1
+ {"version":3,"file":"default-D8ksjWhO.mjs","names":[],"sources":["../src/seed/default.ts"],"sourcesContent":["/**\n * Default seed applied when no user seed file exists.\n *\n * Provides the baseline schema every EmDash site needs:\n * posts, pages, categories, and tags.\n */\n\nimport type { SeedFile } from \"./types.js\";\n\nexport const defaultSeed: SeedFile = {\n\tversion: \"1\",\n\tmeta: {\n\t\tname: \"Default\",\n\t\tdescription: \"Posts and pages with categories and tags\",\n\t},\n\tcollections: [\n\t\t{\n\t\t\tslug: \"posts\",\n\t\t\tlabel: \"Posts\",\n\t\t\tlabelSingular: \"Post\",\n\t\t\tsupports: [\"drafts\", \"revisions\", \"search\"],\n\t\t\tfields: [\n\t\t\t\t{\n\t\t\t\t\tslug: \"title\",\n\t\t\t\t\tlabel: \"Title\",\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\trequired: true,\n\t\t\t\t\tsearchable: true,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tslug: \"featured_image\",\n\t\t\t\t\tlabel: \"Featured Image\",\n\t\t\t\t\ttype: \"image\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tslug: \"content\",\n\t\t\t\t\tlabel: \"Content\",\n\t\t\t\t\ttype: \"portableText\",\n\t\t\t\t\tsearchable: true,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tslug: \"excerpt\",\n\t\t\t\t\tlabel: \"Excerpt\",\n\t\t\t\t\ttype: \"text\",\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\t{\n\t\t\tslug: \"pages\",\n\t\t\tlabel: \"Pages\",\n\t\t\tlabelSingular: \"Page\",\n\t\t\tsupports: [\"drafts\", \"revisions\", \"search\"],\n\t\t\tfields: [\n\t\t\t\t{\n\t\t\t\t\tslug: \"title\",\n\t\t\t\t\tlabel: \"Title\",\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\trequired: true,\n\t\t\t\t\tsearchable: true,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tslug: \"content\",\n\t\t\t\t\tlabel: \"Content\",\n\t\t\t\t\ttype: \"portableText\",\n\t\t\t\t\tsearchable: true,\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t],\n\ttaxonomies: [\n\t\t{\n\t\t\tname: \"category\",\n\t\t\tlabel: \"Categories\",\n\t\t\tlabelSingular: \"Category\",\n\t\t\thierarchical: true,\n\t\t\tcollections: [\"posts\"],\n\t\t},\n\t\t{\n\t\t\tname: \"tag\",\n\t\t\tlabel: \"Tags\",\n\t\t\tlabelSingular: \"Tag\",\n\t\t\thierarchical: false,\n\t\t\tcollections: [\"posts\"],\n\t\t},\n\t],\n};\n"],"mappings":";AASA,MAAa,cAAwB;CACpC,SAAS;CACT,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,aAAa,CACZ;EACC,MAAM;EACN,OAAO;EACP,eAAe;EACf,UAAU;GAAC;GAAU;GAAa;GAAS;EAC3C,QAAQ;GACP;IACC,MAAM;IACN,OAAO;IACP,MAAM;IACN,UAAU;IACV,YAAY;IACZ;GACD;IACC,MAAM;IACN,OAAO;IACP,MAAM;IACN;GACD;IACC,MAAM;IACN,OAAO;IACP,MAAM;IACN,YAAY;IACZ;GACD;IACC,MAAM;IACN,OAAO;IACP,MAAM;IACN;GACD;EACD,EACD;EACC,MAAM;EACN,OAAO;EACP,eAAe;EACf,UAAU;GAAC;GAAU;GAAa;GAAS;EAC3C,QAAQ,CACP;GACC,MAAM;GACN,OAAO;GACP,MAAM;GACN,UAAU;GACV,YAAY;GACZ,EACD;GACC,MAAM;GACN,OAAO;GACP,MAAM;GACN,YAAY;GACZ,CACD;EACD,CACD;CACD,YAAY,CACX;EACC,MAAM;EACN,OAAO;EACP,eAAe;EACf,cAAc;EACd,aAAa,CAAC,QAAQ;EACtB,EACD;EACC,MAAM;EACN,OAAO;EACP,eAAe;EACf,cAAc;EACd,aAAa,CAAC,QAAQ;EACtB,CACD;CACD"}
@@ -53,6 +53,23 @@ async function tableExists(db, tableName) {
53
53
  `.execute(db)).rows.length > 0;
54
54
  }
55
55
  /**
56
+ * Check if a column exists in the database.
57
+ */
58
+ async function columnExists(db, tableName, columnName) {
59
+ if (isPostgres(db)) return (await sql`
60
+ SELECT EXISTS(
61
+ SELECT 1 FROM information_schema.columns
62
+ WHERE table_schema = current_schema()
63
+ AND table_name = ${tableName}
64
+ AND column_name = ${columnName}
65
+ ) as exists
66
+ `.execute(db)).rows[0]?.exists === true;
67
+ return (await sql`
68
+ SELECT name FROM pragma_table_info(${tableName})
69
+ WHERE name = ${columnName}
70
+ `.execute(db)).rows.length > 0;
71
+ }
72
+ /**
56
73
  * List tables matching a LIKE pattern.
57
74
  */
58
75
  async function listTablesLike(db, pattern) {
@@ -89,5 +106,5 @@ function jsonExtractExpr(db, column, path) {
89
106
  }
90
107
 
91
108
  //#endregion
92
- export { isSqlite as a, tableExists as c, isPostgres as i, currentTimestamp as n, jsonExtractExpr as o, currentTimestampValue as r, listTablesLike as s, binaryType as t };
93
- //# sourceMappingURL=dialect-helpers-DhTzaUxP.mjs.map
109
+ export { isPostgres as a, listTablesLike as c, currentTimestampValue as i, tableExists as l, columnExists as n, isSqlite as o, currentTimestamp as r, jsonExtractExpr as s, binaryType as t };
110
+ //# sourceMappingURL=dialect-helpers-BKCvISIQ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dialect-helpers-BKCvISIQ.mjs","names":[],"sources":["../src/database/dialect-helpers.ts"],"sourcesContent":["/**\n * Dialect-specific SQL helpers\n *\n * Every function takes a Kysely `db` instance and detects the dialect from\n * the adapter class. No module-level state, no globals, no heuristics —\n * the adapter is the source of truth.\n *\n * This is NOT an ORM abstraction — just targeted helpers for the ~15 places\n * that use raw dialect-specific SQL. Most Kysely schema builder code already\n * works cross-dialect.\n */\n\nimport type { ColumnDataType, Kysely, RawBuilder } from \"kysely\";\nimport { sql } from \"kysely\";\n\nimport type { DatabaseDialectType } from \"../db/adapters.js\";\nimport { validateIdentifier, validateJsonFieldName } from \"./validate.js\";\n\nexport type { DatabaseDialectType };\n\n/**\n * Detect dialect type from a Kysely instance via the adapter class name.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport function detectDialect(db: Kysely<any>): DatabaseDialectType {\n\tconst name = db.getExecutor().adapter.constructor.name;\n\tif (name === \"PostgresAdapter\") return \"postgres\";\n\treturn \"sqlite\";\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport function isSqlite(db: Kysely<any>): boolean {\n\treturn detectDialect(db) === \"sqlite\";\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport function isPostgres(db: Kysely<any>): boolean {\n\treturn detectDialect(db) === \"postgres\";\n}\n\n/**\n * Default timestamp expression for column defaults.\n * Wrapped in parens for use in CREATE TABLE ... DEFAULT (...).\n *\n * sqlite: (datetime('now'))\n * postgres: CURRENT_TIMESTAMP\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport function currentTimestamp(db: Kysely<any>): RawBuilder<string> {\n\tif (isPostgres(db)) {\n\t\treturn sql`CURRENT_TIMESTAMP`;\n\t}\n\treturn sql`(datetime('now'))`;\n}\n\n/**\n * Timestamp expression for use in WHERE clauses and SET expressions.\n * No wrapping parens.\n *\n * sqlite: datetime('now')\n * postgres: CURRENT_TIMESTAMP\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport function currentTimestampValue(db: Kysely<any>): RawBuilder<string> {\n\tif (isPostgres(db)) {\n\t\treturn sql`CURRENT_TIMESTAMP`;\n\t}\n\treturn sql`datetime('now')`;\n}\n\n/**\n * Check if a table exists in the database.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport async function tableExists(db: Kysely<any>, tableName: string): Promise<boolean> {\n\tif (isPostgres(db)) {\n\t\tconst result = await sql<{ exists: boolean }>`\n\t\t\tSELECT EXISTS(\n\t\t\t\tSELECT 1 FROM information_schema.tables\n\t\t\t\tWHERE table_schema = 'public' AND table_name = ${tableName}\n\t\t\t) as exists\n\t\t`.execute(db);\n\t\treturn result.rows[0]?.exists === true;\n\t}\n\n\tconst result = await sql<{ name: string }>`\n\t\tSELECT name FROM sqlite_master\n\t\tWHERE type = 'table' AND name = ${tableName}\n\t`.execute(db);\n\treturn result.rows.length > 0;\n}\n\n/**\n * Check if an index exists in the database.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport async function indexExists(db: Kysely<any>, indexName: string): Promise<boolean> {\n\tif (isPostgres(db)) {\n\t\tconst result = await sql<{ exists: boolean }>`\n\t\t\tSELECT EXISTS(\n\t\t\t\tSELECT 1 FROM pg_indexes\n\t\t\t\tWHERE schemaname = current_schema() AND indexname = ${indexName}\n\t\t\t) as exists\n\t\t`.execute(db);\n\t\treturn result.rows[0]?.exists === true;\n\t}\n\n\tconst result = await sql<{ name: string }>`\n\t\tSELECT name FROM sqlite_master\n\t\tWHERE type = 'index' AND name = ${indexName}\n\t`.execute(db);\n\treturn result.rows.length > 0;\n}\n\n/**\n * Check if a column exists in the database.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport async function columnExists(\n\tdb: Kysely<any>,\n\ttableName: string,\n\tcolumnName: string,\n): Promise<boolean> {\n\tif (isPostgres(db)) {\n\t\tconst result = await sql<{ exists: boolean }>`\n\t\t\tSELECT EXISTS(\n\t\t\t\tSELECT 1 FROM information_schema.columns\n\t\t\t\tWHERE table_schema = current_schema()\n\t\t\t\t\tAND table_name = ${tableName}\n\t\t\t\t\tAND column_name = ${columnName}\n\t\t\t) as exists\n\t\t`.execute(db);\n\t\treturn result.rows[0]?.exists === true;\n\t}\n\n\tconst result = await sql<{ name: string }>`\n\t\tSELECT name FROM pragma_table_info(${tableName})\n\t\tWHERE name = ${columnName}\n\t`.execute(db);\n\treturn result.rows.length > 0;\n}\n\n/**\n * List tables matching a LIKE pattern.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport async function listTablesLike(db: Kysely<any>, pattern: string): Promise<string[]> {\n\tif (isPostgres(db)) {\n\t\tconst result = await sql<{ table_name: string }>`\n\t\t\tSELECT table_name FROM information_schema.tables\n\t\t\tWHERE table_schema = 'public' AND table_name LIKE ${pattern}\n\t\t`.execute(db);\n\t\treturn result.rows.map((r) => r.table_name);\n\t}\n\n\tconst result = await sql<{ name: string }>`\n\t\tSELECT name FROM sqlite_master\n\t\tWHERE type = 'table' AND name LIKE ${pattern}\n\t`.execute(db);\n\treturn result.rows.map((r) => r.name);\n}\n\n/**\n * Column type for binary data.\n *\n * sqlite: blob\n * postgres: bytea\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport function binaryType(db: Kysely<any>): ColumnDataType {\n\tif (isPostgres(db)) {\n\t\treturn \"bytea\";\n\t}\n\treturn \"blob\";\n}\n\n/**\n * SQL expression for extracting a field from a JSON/JSONB column.\n *\n * sqlite: json_extract(column, '$.path')\n * postgres: column->>'path'\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport function jsonExtractExpr(db: Kysely<any>, column: string, path: string): string {\n\tvalidateIdentifier(column, \"JSON column name\");\n\tvalidateJsonFieldName(path, \"JSON path\");\n\tif (isPostgres(db)) {\n\t\treturn `${column}->>'${path}'`;\n\t}\n\treturn `json_extract(${column}, '$.${path}')`;\n}\n"],"mappings":";;;;;;;AAwBA,SAAgB,cAAc,IAAsC;AAEnE,KADa,GAAG,aAAa,CAAC,QAAQ,YAAY,SACrC,kBAAmB,QAAO;AACvC,QAAO;;AAIR,SAAgB,SAAS,IAA0B;AAClD,QAAO,cAAc,GAAG,KAAK;;AAI9B,SAAgB,WAAW,IAA0B;AACpD,QAAO,cAAc,GAAG,KAAK;;;;;;;;;AAW9B,SAAgB,iBAAiB,IAAqC;AACrE,KAAI,WAAW,GAAG,CACjB,QAAO,GAAG;AAEX,QAAO,GAAG;;;;;;;;;AAWX,SAAgB,sBAAsB,IAAqC;AAC1E,KAAI,WAAW,GAAG,CACjB,QAAO,GAAG;AAEX,QAAO,GAAG;;;;;AAOX,eAAsB,YAAY,IAAiB,WAAqC;AACvF,KAAI,WAAW,GAAG,CAOjB,SANe,MAAM,GAAwB;;;qDAGM,UAAU;;IAE3D,QAAQ,GAAG,EACC,KAAK,IAAI,WAAW;AAOnC,SAJe,MAAM,GAAqB;;oCAEP,UAAU;GAC3C,QAAQ,GAAG,EACC,KAAK,SAAS;;;;;AA6B7B,eAAsB,aACrB,IACA,WACA,YACmB;AACnB,KAAI,WAAW,GAAG,CASjB,SARe,MAAM,GAAwB;;;;wBAIvB,UAAU;yBACT,WAAW;;IAEhC,QAAQ,GAAG,EACC,KAAK,IAAI,WAAW;AAOnC,SAJe,MAAM,GAAqB;uCACJ,UAAU;iBAChC,WAAW;GACzB,QAAQ,GAAG,EACC,KAAK,SAAS;;;;;AAO7B,eAAsB,eAAe,IAAiB,SAAoC;AACzF,KAAI,WAAW,GAAG,CAKjB,SAJe,MAAM,GAA2B;;uDAEK,QAAQ;IAC3D,QAAQ,GAAG,EACC,KAAK,KAAK,MAAM,EAAE,WAAW;AAO5C,SAJe,MAAM,GAAqB;;uCAEJ,QAAQ;GAC5C,QAAQ,GAAG,EACC,KAAK,KAAK,MAAM,EAAE,KAAK;;;;;;;;AAUtC,SAAgB,WAAW,IAAiC;AAC3D,KAAI,WAAW,GAAG,CACjB,QAAO;AAER,QAAO;;;;;;;;AAUR,SAAgB,gBAAgB,IAAiB,QAAgB,MAAsB;AACtF,oBAAmB,QAAQ,mBAAmB;AAC9C,uBAAsB,MAAM,YAAY;AACxC,KAAI,WAAW,GAAG,CACjB,QAAO,GAAG,OAAO,MAAM,KAAK;AAE7B,QAAO,gBAAgB,OAAO,OAAO,KAAK"}
@@ -24,4 +24,4 @@ function apiError(code, message, status) {
24
24
 
25
25
  //#endregion
26
26
  export { apiError as t };
27
- //# sourceMappingURL=error-CiYn9yDu.mjs.map
27
+ //# sourceMappingURL=error-D_-tqP-I.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-D_-tqP-I.mjs","names":[],"sources":["../src/api/error.ts"],"sourcesContent":["/**\n * Standardized API error responses.\n *\n * All API routes should use these utilities instead of inline\n * `new Response(JSON.stringify({ error: ... }), ...)` patterns.\n */\n\nimport { InvalidCursorError } from \"../database/repositories/types.js\";\nimport { mapErrorStatus } from \"./errors.js\";\nimport type { ApiResult } from \"./types.js\";\n\n// Re-export everything from errors.ts so existing `import { mapErrorStatus } from \"./error.js\"` still works\nexport * from \"./errors.js\";\n\n/**\n * Standard cache headers for all API responses.\n *\n * Cache-Control: private, no-store -- prevents CDN/proxy caching of authenticated data.\n * no-store already tells caches not to store the response, so Vary is unnecessary.\n */\nconst API_CACHE_HEADERS: HeadersInit = {\n\t\"Cache-Control\": \"private, no-store\",\n};\n\n/**\n * Create a standardized error response.\n *\n * Always returns `{ error: { code, message } }` with correct Content-Type.\n * Use this for all error responses in API routes.\n */\nexport function apiError(code: string, message: string, status: number): Response {\n\treturn Response.json({ error: { code, message } }, { status, headers: API_CACHE_HEADERS });\n}\n\n/**\n * Create a standardized success response.\n *\n * Always returns `{ data: T }` with correct status code.\n * Use this for all success responses in API routes.\n */\nexport function apiSuccess<T>(data: T, status = 200): Response {\n\treturn Response.json({ data }, { status, headers: API_CACHE_HEADERS });\n}\n\n/**\n * Handle an unknown error in a catch block.\n *\n * - Logs the full error server-side\n * - Returns a generic message to the client (never leaks error.message)\n * - Use `fallbackMessage` for the public-facing message\n * - Use `fallbackCode` for the error code\n */\nexport function handleError(\n\terror: unknown,\n\tfallbackMessage: string,\n\tfallbackCode: string,\n): Response {\n\t// Bubble malformed-cursor errors as a structured 400 instead of a\n\t// generic 500.\n\tif (error instanceof InvalidCursorError) {\n\t\treturn apiError(\"INVALID_CURSOR\", error.message, 400);\n\t}\n\tconsole.error(`[${fallbackCode}]`, error);\n\treturn apiError(fallbackCode, fallbackMessage, 500);\n}\n\n/**\n * Standard initialization check.\n *\n * Returns an error response if EmDash is not initialized, or null if OK.\n * Usage: `const err = requireInit(emdash); if (err) return err;`\n */\nexport function requireInit(emdash: unknown): Response | null {\n\tif (!emdash || typeof emdash !== \"object\") {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\treturn null;\n}\n\n/**\n * Standard database check.\n *\n * Returns an error response if the database is not available, or null if OK.\n * Usage: `const err = requireDb(emdash?.db); if (err) return err;`\n */\nexport function requireDb(db: unknown): Response | null {\n\tif (!db) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\treturn null;\n}\n\n/**\n * Convert an ApiResult into an HTTP Response.\n *\n * Collapses the handler-to-response boilerplate:\n * - Success: returns `apiSuccess(result.data, successStatus)`\n * - Error: returns `apiError(code, message, mapErrorStatus(code))`\n */\nexport function unwrapResult<T>(result: ApiResult<T>, successStatus = 200): Response {\n\tif (!result.success) {\n\t\treturn apiError(result.error.code, result.error.message, mapErrorStatus(result.error.code));\n\t}\n\treturn apiSuccess(result.data, successStatus);\n}\n"],"mappings":";;;;;;;AAoBA,MAAM,oBAAiC,EACtC,iBAAiB,qBACjB;;;;;;;AAQD,SAAgB,SAAS,MAAc,SAAiB,QAA0B;AACjF,QAAO,SAAS,KAAK,EAAE,OAAO;EAAE;EAAM;EAAS,EAAE,EAAE;EAAE;EAAQ,SAAS;EAAmB,CAAC"}
@@ -1,16 +1,17 @@
1
- import { _ as MediaValue, m as MediaProviderDescriptor } from "./placeholder-tzpqGWII.mjs";
2
- import { t as Database } from "./types-C2v0c34j.mjs";
3
- import { a as ContentSeoInput, c as FindManyOptions, l as FindManyResult, o as CreateContentInput, r as ContentItem, t as BylineSummary, u as UpdateContentInput } from "./types-6CUZRrZP.mjs";
4
- import { A as PageMetadataContribution, B as PluginDefinition, D as PageFragmentContribution, H as PluginManifest, J as RequestMeta, O as PageFragmentEvent, W as PluginStorageConfig, X as ResolvedPlugin, a as CommentAfterModerateEvent, g as EmailMessage, h as CronEvent, j as PageMetadataEvent, r as CommentAfterCreateEvent, s as CommentBeforeCreateEvent, tt as StandardPluginDefinition, w as MediaItem$1 } from "./types-DgrIP0tF.mjs";
5
- import { a as Collection, b as UpdateFieldInput, c as CollectionWithFields, d as CreateFieldInput, i as SiteSettings, p as Field, r as SiteSettingKey, u as CreateCollectionInput, y as UpdateCollectionInput } from "./types-CnZYHyLW.mjs";
6
- import { d as Storage } from "./types-CFWjXmus.mjs";
7
- import { t as DatabaseDescriptor } from "./adapters-Di31kZ28.mjs";
1
+ import { _ as MediaValue, m as MediaProviderDescriptor } from "./placeholder-BE4o_2dc.mjs";
2
+ import { t as Database } from "./types-CrtWgIvl.mjs";
3
+ import { a as ContentSeoInput, c as FindManyOptions, d as UpdateContentInput, l as FindManyResult, o as CreateContentInput, r as ContentItem, t as BylineSummary } from "./types-CJsYGpco.mjs";
4
+ import { a as Collection, b as UpdateFieldInput, c as CollectionWithFields, d as CreateFieldInput, i as SiteSettings, p as Field, r as SiteSettingKey, u as CreateCollectionInput, y as UpdateCollectionInput } from "./types-BSyXeCFW.mjs";
5
+ import { $ as ResolvedPlugin, A as PageFragmentContribution, D as MediaItem$1, G as PluginManifest, N as PageMetadataContribution, P as PageMetadataEvent, U as PluginDefinition, Z as RequestMeta, c as CommentBeforeCreateEvent, g as CronEvent, i as CommentAfterCreateEvent, it as StandardPluginDefinition, j as PageFragmentEvent, o as CommentAfterModerateEvent, q as PluginStorageConfig, y as EmailMessage } from "./types-BuBIptGk.mjs";
6
+ import { d as Storage } from "./types-M78DQ1lx.mjs";
7
+ import { t as DatabaseDescriptor } from "./adapters-DoNJiveC.mjs";
8
8
  import { Kysely } from "kysely";
9
9
  import { z } from "astro/zod";
10
10
  import { z as z$1 } from "zod";
11
11
  import { PortableTextBlock } from "@emdash-cms/gutenberg-to-portable-text";
12
12
  import { Readable } from "node:stream";
13
13
  import { LiveLoader } from "astro/loaders";
14
+ import * as react from "react";
14
15
 
15
16
  //#region src/database/connection.d.ts
16
17
  interface DatabaseConfig {
@@ -157,8 +158,14 @@ declare class ContentRepository {
157
158
  * Syncs the draft revision's data into the content table columns so the
158
159
  * content table always reflects the published version.
159
160
  * If no draft revision exists, creates one from current data and publishes it.
161
+ *
162
+ * `publishedAt` (optional) overrides the publication timestamp. If omitted,
163
+ * the existing `published_at` is preserved (idempotent re-publish keeps the
164
+ * original date) and falls back to the current time on first publish. Pass
165
+ * an explicit value to backdate a publish (e.g. when migrating content from
166
+ * another CMS).
160
167
  */
161
- publish(type: string, id: string): Promise<ContentItem>;
168
+ publish(type: string, id: string, publishedAt?: string): Promise<ContentItem>;
162
169
  /**
163
170
  * Unpublish content
164
171
  *
@@ -483,10 +490,14 @@ interface FieldDescriptor {
483
490
  kind: string;
484
491
  label?: string;
485
492
  required?: boolean;
493
+ /**
494
+ * For `select` / `multiSelect`: the list of enum choices.
495
+ * For `json` fields driven by a plugin `widget`: arbitrary widget config.
496
+ */
486
497
  options?: Array<{
487
498
  value: string;
488
499
  label: string;
489
- }>;
500
+ }> | Record<string, unknown>;
490
501
  }
491
502
  /**
492
503
  * Discriminated union for handler results.
@@ -650,7 +661,9 @@ declare function handleContentUnschedule(db: Kysely<Database>, collection: strin
650
661
  * (syncDataColumns, slug sync, status/revision update) that must
651
662
  * be atomic to prevent FTS shadow table corruption on crash.
652
663
  */
653
- declare function handleContentPublish(db: Kysely<Database>, collection: string, id: string): Promise<ApiResult<ContentResponse>>;
664
+ declare function handleContentPublish(db: Kysely<Database>, collection: string, id: string, options?: {
665
+ publishedAt?: string;
666
+ }): Promise<ApiResult<ContentResponse>>;
654
667
  /**
655
668
  * Unpublish content (revert to draft).
656
669
  *
@@ -822,6 +835,23 @@ declare class SchemaRegistry {
822
835
  * Get a collection with all its fields
823
836
  */
824
837
  getCollectionWithFields(slug: string): Promise<CollectionWithFields | null>;
838
+ /**
839
+ * List every collection together with its fields in O(1) query shapes
840
+ * — one for collections, then one batched query for the fields of every
841
+ * returned collection — instead of the N+1 pattern of `listCollections`
842
+ * + per-collection `listFields`. The fields query is chunked at
843
+ * `SQL_BATCH_SIZE` to stay under D1's bound-parameter limit, so on
844
+ * sites with more than `SQL_BATCH_SIZE` collections the field fetch
845
+ * becomes `ceil(collectionCount / SQL_BATCH_SIZE)` queries — still
846
+ * a constant factor, not N+1. Typical sites have well under
847
+ * `SQL_BATCH_SIZE` collections, so this is two queries in practice.
848
+ *
849
+ * Used by the manifest build, which previously paid N+1 round-trips on
850
+ * every admin request. Each round-trip costs ~80–150ms against the D1
851
+ * primary on a busy link, so a 10-collection site spent ~1 s rebuilding
852
+ * a manifest that is now built fresh per admin request (no cache).
853
+ */
854
+ listCollectionsWithFields(): Promise<CollectionWithFields[]>;
825
855
  /**
826
856
  * Create a new collection
827
857
  */
@@ -2017,7 +2047,7 @@ declare function parseWxrString(xml: string): Promise<WxrData>;
2017
2047
  * export default definePlugin({
2018
2048
  * id: "my-plugin",
2019
2049
  * version: "1.0.0",
2020
- * capabilities: ["read:content"],
2050
+ * capabilities: ["content:read"],
2021
2051
  * hooks: {
2022
2052
  * "content:beforeSave": async (event, ctx) => {
2023
2053
  * ctx.log.info("Saving content", { collection: event.collection });
@@ -2042,7 +2072,13 @@ declare function definePlugin(definition: StandardPluginDefinition): StandardPlu
2042
2072
  * Auth Provider Types
2043
2073
  *
2044
2074
  * Defines the interfaces for pluggable authentication providers.
2045
- * Providers like Cloudflare Access implement these interfaces.
2075
+ *
2076
+ * Two systems coexist:
2077
+ * - `AuthDescriptor` — transparent auth (Cloudflare Access) that authenticates
2078
+ * every request via headers/cookies. No login UI needed.
2079
+ * - `AuthProviderDescriptor` — pluggable login methods (GitHub, Google,
2080
+ * AT Protocol, etc.) that appear as options on the login page and setup
2081
+ * wizard. Passkey is built-in; providers are additive.
2046
2082
  */
2047
2083
  /**
2048
2084
  * Result of authenticating a request via an external auth provider
@@ -2060,10 +2096,10 @@ interface AuthResult {
2060
2096
  metadata?: Record<string, unknown>;
2061
2097
  }
2062
2098
  /**
2063
- * Auth descriptor - returned by auth adapter functions (e.g., access())
2099
+ * Auth descriptor transparent auth providers (e.g., Cloudflare Access).
2064
2100
  *
2065
- * Similar to DatabaseDescriptor and StorageDescriptor, this allows
2066
- * auth providers to be configured at build time and loaded at runtime.
2101
+ * These authenticate every request via headers/cookies. No login UI needed.
2102
+ * The module's `authenticate()` function is called by middleware on each request.
2067
2103
  */
2068
2104
  interface AuthDescriptor {
2069
2105
  /**
@@ -2098,6 +2134,97 @@ interface AuthProviderModule {
2098
2134
  */
2099
2135
  authenticate(request: Request, config: unknown): Promise<AuthResult>;
2100
2136
  }
2137
+ /**
2138
+ * Descriptor for a pluggable auth provider.
2139
+ *
2140
+ * Auth providers appear as login options on the login page and setup wizard.
2141
+ * They coexist with passkey (which is built-in) and with each other.
2142
+ * Any provider can be used to create the initial admin account.
2143
+ *
2144
+ * @example
2145
+ * ```ts
2146
+ * // astro.config.ts
2147
+ * import { atproto } from "@emdash-cms/auth-atproto";
2148
+ *
2149
+ * emdash({
2150
+ * authProviders: [atproto(), github(), google()],
2151
+ * })
2152
+ * ```
2153
+ */
2154
+ interface AuthProviderDescriptor {
2155
+ /** Unique provider ID (e.g., "github", "atproto") */
2156
+ id: string;
2157
+ /** Human-readable label for UI (e.g., "GitHub", "AT Protocol") */
2158
+ label: string;
2159
+ /** Provider-specific config (JSON-serializable) */
2160
+ config?: unknown;
2161
+ /**
2162
+ * Module exporting React components for the admin UI.
2163
+ * Statically imported at build time via virtual module.
2164
+ *
2165
+ * The module should export components matching `AuthProviderAdminExports`.
2166
+ */
2167
+ adminEntry?: string;
2168
+ /**
2169
+ * Astro route handlers this provider needs injected at build time.
2170
+ * Used for login initiation, OAuth callbacks, well-known endpoints, etc.
2171
+ */
2172
+ routes?: AuthRouteDescriptor[];
2173
+ /**
2174
+ * URL prefixes/paths that should bypass auth middleware.
2175
+ * Added to the public routes set so login/callback endpoints work
2176
+ * for unauthenticated users.
2177
+ */
2178
+ publicRoutes?: string[];
2179
+ /**
2180
+ * Storage collections for persistent auth state (e.g., OAuth sessions).
2181
+ * Same format as plugin storage — collections are stored in the shared
2182
+ * `_plugin_storage` table namespaced under `auth:<providerId>`.
2183
+ *
2184
+ * Access via `getAuthProviderStorage()` from `emdash/api/route-utils`.
2185
+ */
2186
+ storage?: Record<string, {
2187
+ indexes?: Array<string | string[]>;
2188
+ uniqueIndexes?: Array<string | string[]>;
2189
+ }>;
2190
+ }
2191
+ /**
2192
+ * A route that an auth provider needs injected into the Astro app.
2193
+ */
2194
+ interface AuthRouteDescriptor {
2195
+ /** URL pattern (e.g., "/_emdash/api/auth/atproto/login") */
2196
+ pattern: string;
2197
+ /** Module specifier for the Astro route handler */
2198
+ entrypoint: string;
2199
+ }
2200
+ /**
2201
+ * Expected exports from an auth provider's `adminEntry` module.
2202
+ *
2203
+ * All exports are optional. Providers export whichever components
2204
+ * make sense for their auth flow.
2205
+ */
2206
+ interface AuthProviderAdminExports {
2207
+ /**
2208
+ * Compact button for the login page (icon + label).
2209
+ * Used for providers with a simple redirect flow (GitHub, Google).
2210
+ * Rendered in the "Or continue with" section.
2211
+ */
2212
+ LoginButton?: react.ComponentType;
2213
+ /**
2214
+ * Full login form for providers that need custom input.
2215
+ * Used for providers like AT Protocol that need a handle field.
2216
+ * Rendered as an expandable section on the login page.
2217
+ */
2218
+ LoginForm?: react.ComponentType;
2219
+ /**
2220
+ * Setup wizard step for creating the admin account via this provider.
2221
+ * When present, this provider appears as an option in the setup wizard's
2222
+ * "Create admin account" step.
2223
+ */
2224
+ SetupStep?: react.ComponentType<{
2225
+ onComplete: () => void;
2226
+ }>;
2227
+ }
2101
2228
  /**
2102
2229
  * Configuration options common to external auth providers
2103
2230
  */
@@ -2375,6 +2502,23 @@ interface EmDashConfig {
2375
2502
  * ```
2376
2503
  */
2377
2504
  auth?: AuthDescriptor;
2505
+ /**
2506
+ * Pluggable auth providers (login methods on the login page).
2507
+ *
2508
+ * Auth providers appear as options alongside passkey on the login page
2509
+ * and setup wizard. Any provider can be used to create the initial
2510
+ * admin account. Passkey is built-in; providers listed here are additive.
2511
+ *
2512
+ * @example
2513
+ * ```ts
2514
+ * import { atproto } from "@emdash-cms/auth-atproto";
2515
+ *
2516
+ * emdash({
2517
+ * authProviders: [atproto()],
2518
+ * })
2519
+ * ```
2520
+ */
2521
+ authProviders?: AuthProviderDescriptor[];
2378
2522
  /**
2379
2523
  * MCP (Model Context Protocol) server endpoint.
2380
2524
  *
@@ -2434,29 +2578,35 @@ interface EmDashConfig {
2434
2578
  */
2435
2579
  siteUrl?: string;
2436
2580
  /**
2437
- * Headers to trust for client IP resolution when running behind a reverse
2438
- * proxy. The first header in this list that is present on the request
2439
- * wins. Applies to rate limiting for auth endpoints and comment
2440
- * submission.
2581
+ * Additional origins accepted by passkey verification.
2441
2582
  *
2442
- * Common values:
2443
- * - `x-real-ip` nginx, Caddy, Traefik
2444
- * - `fly-client-ip` Fly.io
2445
- * - `x-forwarded-for` generic (first entry is used)
2583
+ * When the same EmDash deployment is reachable under several hostnames sharing
2584
+ * a registrable parent (e.g. `https://example.com` plus
2585
+ * `https://preview.example.com`), the canonical `siteUrl` defines the `rpId`
2586
+ * and the entries here are the *additional* origins from which assertions
2587
+ * are accepted. Each entry must be the same hostname as `siteUrl` or a
2588
+ * subdomain of it — WebAuthn requires `rpId` to be a registrable suffix of
2589
+ * every origin.
2446
2590
  *
2447
- * Only set this when you **control the reverse proxy**. Untrusted
2448
- * clients can set any header they like; trusting headers from an open
2449
- * network is an IP-spoofing vulnerability that defeats rate limiting.
2591
+ * Merged at runtime with the `EMDASH_ALLOWED_ORIGINS` env var (comma-separated).
2592
+ * Validation:
2593
+ * - Config-declared entries are shape-checked at Astro startup.
2594
+ * - Subdomain relationship to `siteUrl` is checked at startup when
2595
+ * `siteUrl` is also config-declared, otherwise at first passkey
2596
+ * verification (since `siteUrl` may come from `EMDASH_SITE_URL`).
2450
2597
  *
2451
- * On Cloudflare the `cf` object on the request is used automatically —
2452
- * you normally don't need to set this. Leave unset (or empty) to
2453
- * preserve the default: IP is resolved only when the request came
2454
- * through Cloudflare's edge.
2598
+ * Mismatches throw with a source-attributed message naming
2599
+ * `config.allowedOrigins` or `EMDASH_ALLOWED_ORIGINS`.
2455
2600
  *
2456
- * Falls back to `EMDASH_TRUSTED_PROXY_HEADERS` env var (comma-separated)
2457
- * when this option is not set, so operators can configure at deploy
2458
- * time without touching the Astro config.
2601
+ * @example
2602
+ * ```ts
2603
+ * emdash({
2604
+ * siteUrl: "https://example.com",
2605
+ * allowedOrigins: ["https://preview.example.com"],
2606
+ * })
2607
+ * ```
2459
2608
  */
2609
+ allowedOrigins?: string[];
2460
2610
  trustedProxyHeaders?: string[];
2461
2611
  /**
2462
2612
  * Enable playground mode for ephemeral "try EmDash" sites.
@@ -2605,10 +2755,20 @@ declare const pluginManifestSchema: z$1.ZodObject<{
2605
2755
  "read:media": "read:media";
2606
2756
  "write:media": "write:media";
2607
2757
  "read:users": "read:users";
2608
- "email:send": "email:send";
2609
2758
  "email:provide": "email:provide";
2610
2759
  "email:intercept": "email:intercept";
2611
2760
  "page:inject": "page:inject";
2761
+ "network:request": "network:request";
2762
+ "network:request:unrestricted": "network:request:unrestricted";
2763
+ "content:read": "content:read";
2764
+ "content:write": "content:write";
2765
+ "media:read": "media:read";
2766
+ "media:write": "media:write";
2767
+ "users:read": "users:read";
2768
+ "email:send": "email:send";
2769
+ "hooks.email-transport:register": "hooks.email-transport:register";
2770
+ "hooks.email-events:register": "hooks.email-events:register";
2771
+ "hooks.page-fragments:register": "hooks.page-fragments:register";
2612
2772
  }>>;
2613
2773
  allowedHosts: z$1.ZodArray<z$1.ZodString>;
2614
2774
  storage: z$1.ZodRecord<z$1.ZodString, z$1.ZodObject<{
@@ -2704,6 +2864,18 @@ declare const pluginManifestSchema: z$1.ZodObject<{
2704
2864
  type: z$1.ZodLiteral<"secret">;
2705
2865
  label: z$1.ZodString;
2706
2866
  description: z$1.ZodOptional<z$1.ZodString>;
2867
+ }, z$1.core.$strip>, z$1.ZodObject<{
2868
+ type: z$1.ZodLiteral<"url">;
2869
+ default: z$1.ZodOptional<z$1.ZodString>;
2870
+ placeholder: z$1.ZodOptional<z$1.ZodString>;
2871
+ label: z$1.ZodString;
2872
+ description: z$1.ZodOptional<z$1.ZodString>;
2873
+ }, z$1.core.$strip>, z$1.ZodObject<{
2874
+ type: z$1.ZodLiteral<"email">;
2875
+ default: z$1.ZodOptional<z$1.ZodString>;
2876
+ placeholder: z$1.ZodOptional<z$1.ZodString>;
2877
+ label: z$1.ZodString;
2878
+ description: z$1.ZodOptional<z$1.ZodString>;
2707
2879
  }, z$1.core.$strip>], "type">>>;
2708
2880
  pages: z$1.ZodOptional<z$1.ZodArray<z$1.ZodObject<{
2709
2881
  path: z$1.ZodString;
@@ -2726,14 +2898,14 @@ declare const pluginManifestSchema: z$1.ZodObject<{
2726
2898
  string: "string";
2727
2899
  number: "number";
2728
2900
  boolean: "boolean";
2901
+ file: "file";
2902
+ select: "select";
2729
2903
  text: "text";
2730
2904
  integer: "integer";
2731
2905
  datetime: "datetime";
2732
- select: "select";
2733
2906
  multiSelect: "multiSelect";
2734
2907
  portableText: "portableText";
2735
2908
  image: "image";
2736
- file: "file";
2737
2909
  reference: "reference";
2738
2910
  json: "json";
2739
2911
  slug: "slug";
@@ -3010,6 +3182,15 @@ declare class HookPipeline {
3010
3182
  getExclusiveHookProviders(hookName: string): Array<{
3011
3183
  pluginId: string;
3012
3184
  }>;
3185
+ /**
3186
+ * Get all plugins that registered a non-exclusive handler for a given
3187
+ * hook (e.g. `email:beforeSend`, `email:afterSend`), preserving priority
3188
+ * order. Partitions with `getExclusiveHookProviders()`, which returns
3189
+ * plugins whose registration is marked `exclusive: true`.
3190
+ */
3191
+ getHookProviders(hookName: string): Array<{
3192
+ pluginId: string;
3193
+ }>;
3013
3194
  /**
3014
3195
  * Invoke an exclusive hook — dispatch only to the selected provider.
3015
3196
  * Returns null if no provider is selected or if the selected hook
@@ -3973,8 +4154,18 @@ interface GetPreviewUrlOptions {
3973
4154
  expiresIn?: string | number;
3974
4155
  /** Base URL of the site. If not provided, returns a relative URL. */
3975
4156
  baseUrl?: string;
3976
- /** Custom path pattern. Use {collection} and {id} as placeholders. Default: "/{collection}/{id}" */
4157
+ /**
4158
+ * Custom path pattern. Supports `{collection}`, `{id}` and `{locale}`
4159
+ * placeholders. Default: `"/{collection}/{id}"`.
4160
+ */
3977
4161
  pathPattern?: string;
4162
+ /**
4163
+ * Locale segment substituted for the `{locale}` placeholder in `pathPattern`.
4164
+ * Pass an empty string to omit the locale prefix (e.g. for the default locale
4165
+ * when `prefixDefaultLocale` is `false`); adjacent slashes left by an empty
4166
+ * value are collapsed and any trailing slash is trimmed.
4167
+ */
4168
+ locale?: string;
3978
4169
  }
3979
4170
  /**
3980
4171
  * Generate a preview URL for content
@@ -4375,6 +4566,11 @@ declare function invalidateTermCache(): void;
4375
4566
  declare function getTaxonomyDefs(): Promise<TaxonomyDef[]>;
4376
4567
  /**
4377
4568
  * Get a single taxonomy definition by name
4569
+ *
4570
+ * If `getTaxonomyDefs()` has already loaded the full list in this request
4571
+ * (which happens during entry-term hydration on every page that renders a
4572
+ * collection), find the matching def in memory rather than running a
4573
+ * second `WHERE name=?` query against `_emdash_taxonomy_defs`.
4378
4574
  */
4379
4575
  declare function getTaxonomyDef(name: string): Promise<TaxonomyDef | null>;
4380
4576
  /**
@@ -4547,7 +4743,14 @@ interface SearchResult {
4547
4743
  locale: string;
4548
4744
  /** Entry title (if available) */
4549
4745
  title?: string;
4550
- /** Highlighted snippet showing match context */
4746
+ /**
4747
+ * Highlighted snippet showing match context.
4748
+ *
4749
+ * Sanitized server-side to be safe for `set:html` / `innerHTML`:
4750
+ * all HTML metacharacters in the source text are escaped, and
4751
+ * matched terms are wrapped in literal `<mark>...</mark>` tags
4752
+ * (the only HTML the snippet is allowed to contain).
4753
+ */
4551
4754
  snippet?: string;
4552
4755
  /** Relevance score (higher = more relevant) */
4553
4756
  score: number;
@@ -4808,5 +5011,5 @@ declare function extractPlainText(blocks: PortableTextBlock$1[] | string | null
4808
5011
  */
4809
5012
  declare function extractSearchableFields(entry: Record<string, unknown>, fields: string[]): Record<string, string>;
4810
5013
  //#endregion
4811
- export { UpdateMenuInput as $, TranslationSummary as $n, RevisionResponse as $r, SuggestedAction as $t, getEntriesByTerm as A, reference as Ai, WxrTag as An, SandboxOptions as Ar, probeUrl as At, TaxonomyTerm as B, ContentRepository as Bi, getI18nConfig as Bn, SectionSource as Br, ImportContext as Bt, ReorderWidgetsInput as C, ApiContext as Ci, definePlugin as Cn, PortableTextTextBlock as Cr, parseWxrDate as Ct, WidgetComponentDef as D, ListResponse as Di, WxrData as Dn, ProseMirrorNode as Dr, getFileSources as Dt, WidgetArea as E, FieldDescriptor as Ei, WxrCategory as En, ProseMirrorMark as Er, getAllSources as Et, getTerm as F, ImageValue as Fi, EntryFilter as Fn, getSection as Fr, FetchOptions as Ft, getMenu as G, CollectionFilter$1 as Gn, MediaListResponse as Gr, OAuthInput as Gt, UpdateTermInput as H, EmDashDatabaseError as Hi, WaitUntilFn as Hn, getCollectionInfo as Hr, ImportResult as Ht, getTermsForEntries as I, PortableTextBlock$2 as Ii, emdashLoader as In, getSections as Ir, FieldCompatibility as It, CreateMenuItemInput as J, EditFieldMeta as Jn, handleMediaDelete as Jr, ProbeResult as Jt, getMenus as K, CollectionResult as Kn, MediaResponse as Kr, PostTypeAnalysis as Kt, invalidateTermCache as L, CreateMediaInput as Li, getDb as Ln, CreateSectionInput as Lr, FileInput as Lt, getTaxonomyDef as M, FieldDefinition as Mi, parseWxrString as Mn, SandboxRunnerFactory as Mr, importReusableBlocksAsSections as Mt, getTaxonomyDefs as N, FieldUIHints as Ni, CollectionFilter as Nn, SandboxedPlugin as Nr, AttachmentInfo as Nt, WidgetType as O, ManifestResponse as Oi, WxrPost as On, SandboxEmailMessage as Or, getSource as Ot, getTaxonomyTerms as P, FileValue as Pi, EntryData as Pn, SerializedRequest as Pr, CollectionSchemaStatus as Pt, ReorderMenuItemsInput as Q, ResolvePathResult as Qn, RevisionListResponse as Qr, SourceProbeResult as Qt, CreateTermInput as R, MediaItem as Ri, I18nConfig as Rn, GetSectionsOptions as Rr, ImportAnalysis as Rt, PropDef as S, handleContentUpdate as Si, ExternalAuthConfig as Sn, PortableTextSpan as Sr, wordpressRestSource as St, Widget as T, ContentResponse as Ti, WxrAuthor as Tn, ProseMirrorDocument as Tr, clearSources as Tt, getByline as U, after as Un, SchemaError as Ur, ImportSource as Ut, TaxonomyTermRow as V, DatabaseConfig as Vi, isI18nEnabled as Vn, UpdateSectionInput as Vr, ImportFieldDef as Vt, getBylineBySlug as W, CacheHint as Wn, SchemaRegistry as Wr, NormalizedItem as Wt, MenuItem as X, EntryResult as Xn, handleMediaList as Xr, SourceCapabilities as Xt, Menu as Y, EmDashCollections as Yn, handleMediaGet as Yr, SourceAuth as Yt, MenuItemType as Z, InferCollectionData as Zn, handleMediaUpdate as Zr, SourceInput as Zt, getWidgetArea as _, handleContentRestore as _i, S3StorageConfig as _n, prosemirrorToPortableText as _r, VerifyPreviewTokenOptions as _t, search as a, handleContentCountScheduled as ai, createPluginManager as an, resolveEmDashPath as ar, getPluginSetting as at, CreateWidgetAreaInput as b, handleContentUnpublish as bi, AuthProviderModule as bn, PortableTextLinkMark as br, parseContentId as bt, FTSManager as c, handleContentDelete as ci, HookPipeline as cn, FieldAnnotation as cr, getSiteSettings as ct, SearchOptions as d, handleContentGet as di, ValidatedPluginManifest as dn, decodeSlug as dr, isPreviewRequest as dt, handleRevisionGet as ei, UrlInput as en, TranslationsResult as er, UpdateMenuItemInput as et, SearchResponse as f, handleContentGetIncludingTrashed as fi, pluginManifestSchema as fn, isSafeHref as fr, GetPreviewUrlOptions as ft, Suggestion as g, handleContentPublish as gi, LocalStorageConfig as gn, portableTextToProsemirror as gr, PreviewTokenPayload as gt, SuggestOptions as h, handleContentPermanentDelete as hi, getStoredConfig as hn, hashString as hr, GeneratePreviewTokenOptions as ht, getSuggestions as i, handleContentCompare as ii, PluginManager as in, getTranslations as ir, getComments as it, getEntryTerms as j, image as ji, parseWxr as jn, SandboxRunner as jr, registerSource as jt, getAllTermsForEntries as k, portableText as ki, WxrSite as kn, SandboxEmailSendCallback as kr, getUrlSources as kt, CollectionSearchOptions as l, handleContentDiscardDraft as li, HookResult as ln, createEditable as lr, setSiteSettings as lt, SearchStats as m, handleContentListTrashed as mi, PluginDescriptor as mn, computeContentHash as mr, getPreviewUrl as mt, extractSearchableFields as n, handleRevisionRestore as ni, SandboxNotAvailableError as nn, getEmDashCollection as nr, GetCommentsResult as nt, searchCollection as o, handleContentCountTrashed as oi, PluginRouteError as on, CMSAnnotation as or, getPluginSettings as ot, SearchResult as p, handleContentList as pi, EmDashConfig as pn, sanitizeHref as pr, buildPreviewUrl as pt, CreateMenuInput as q, ContentEntry as qn, handleMediaCreate as qr, PostTypeMapping as qt, getSearchStats as r, generateManifest as ri, createNoopSandboxRunner as rn, getEmDashEntry as rr, getCommentCount as rt, searchWithDb as s, handleContentCreate as si, EmailPipeline as sn, EditProxy as sr, getSiteSetting as st, extractPlainText as t, handleRevisionList as ti, NoopSandboxRunner as tn, getEditMeta as tr, GetCommentsOptions as tt, SearchConfig as u, handleContentDuplicate as ui, createHookPipeline as un, createNoop as ur, getPreviewToken as ut, getWidgetAreas as v, handleContentSchedule as vi, StorageDescriptor as vn, PortableTextCodeBlock as vr, VerifyPreviewTokenResult as vt, UpdateWidgetInput as w, ContentListResponse as wi, WxrAttachment as wn, PortableTextUnknownBlock as wr, wxrSource as wt, CreateWidgetInput as x, handleContentUnschedule as xi, AuthResult as xn, PortableTextMarkDef as xr, verifyPreviewToken as xt, getWidgetComponents as y, handleContentTranslations as yi, AuthDescriptor as yn, PortableTextImageBlock as yr, generatePreviewToken as yt, TaxonomyDef as z, MediaRepository as zi, getFallbackChain as zn, Section as zr, ImportConfig as zt };
4812
- //# sourceMappingURL=index-De6_Xv3v.d.mts.map
5014
+ export { UpdateMenuInput as $, EntryResult as $n, handleMediaList as $r, SuggestedAction as $t, getEntriesByTerm as A, ListResponse as Ai, WxrData as An, ProseMirrorNode as Ar, probeUrl as At, TaxonomyTerm as B, CreateMediaInput as Bi, getDb as Bn, CreateSectionInput as Br, ImportContext as Bt, ReorderWidgetsInput as C, handleContentUnpublish as Ci, AuthResult as Cn, PortableTextLinkMark as Cr, parseWxrDate as Ct, WidgetComponentDef as D, ContentListResponse as Di, WxrAttachment as Dn, PortableTextUnknownBlock as Dr, getFileSources as Dt, WidgetArea as E, ApiContext as Ei, definePlugin as En, PortableTextTextBlock as Er, getAllSources as Et, getTerm as F, FieldDefinition as Fi, parseWxrString as Fn, SandboxRunnerFactory as Fr, FetchOptions as Ft, getMenu as G, EmDashDatabaseError as Gi, WaitUntilFn as Gn, getCollectionInfo as Gr, OAuthInput as Gt, UpdateTermInput as H, MediaRepository as Hi, getFallbackChain as Hn, Section as Hr, ImportResult as Ht, getTermsForEntries as I, FieldUIHints as Ii, CollectionFilter as In, SandboxedPlugin as Ir, FieldCompatibility as It, CreateMenuItemInput as J, CollectionFilter$1 as Jn, MediaListResponse as Jr, ProbeResult as Jt, getMenus as K, after as Kn, SchemaError as Kr, PostTypeAnalysis as Kt, invalidateTermCache as L, FileValue as Li, EntryData as Ln, SerializedRequest as Lr, FileInput as Lt, getTaxonomyDef as M, portableText as Mi, WxrSite as Mn, SandboxEmailSendCallback as Mr, importReusableBlocksAsSections as Mt, getTaxonomyDefs as N, reference as Ni, WxrTag as Nn, SandboxOptions as Nr, AttachmentInfo as Nt, WidgetType as O, ContentResponse as Oi, WxrAuthor as On, ProseMirrorDocument as Or, getSource as Ot, getTaxonomyTerms as P, image as Pi, parseWxr as Pn, SandboxRunner as Pr, CollectionSchemaStatus as Pt, ReorderMenuItemsInput as Q, EmDashCollections as Qn, handleMediaGet as Qr, SourceProbeResult as Qt, CreateTermInput as R, ImageValue as Ri, EntryFilter as Rn, getSection as Rr, ImportAnalysis as Rt, PropDef as S, handleContentTranslations as Si, AuthProviderModule as Sn, PortableTextImageBlock as Sr, wordpressRestSource as St, Widget as T, handleContentUpdate as Ti, ExternalAuthConfig as Tn, PortableTextSpan as Tr, clearSources as Tt, getByline as U, ContentRepository as Ui, getI18nConfig as Un, SectionSource as Ur, ImportSource as Ut, TaxonomyTermRow as V, MediaItem as Vi, I18nConfig as Vn, GetSectionsOptions as Vr, ImportFieldDef as Vt, getBylineBySlug as W, DatabaseConfig as Wi, isI18nEnabled as Wn, UpdateSectionInput as Wr, NormalizedItem as Wt, MenuItem as X, ContentEntry as Xn, handleMediaCreate as Xr, SourceCapabilities as Xt, Menu as Y, CollectionResult as Yn, MediaResponse as Yr, SourceAuth as Yt, MenuItemType as Z, EditFieldMeta as Zn, handleMediaDelete as Zr, SourceInput as Zt, getWidgetArea as _, handleContentListTrashed as _i, S3StorageConfig as _n, computeContentHash as _r, VerifyPreviewTokenOptions as _t, search as a, handleRevisionRestore as ai, createPluginManager as an, getEmDashCollection as ar, getPluginSetting as at, CreateWidgetAreaInput as b, handleContentRestore as bi, AuthProviderAdminExports as bn, prosemirrorToPortableText as br, parseContentId as bt, FTSManager as c, handleContentCountScheduled as ci, HookPipeline as cn, resolveEmDashPath as cr, getSiteSettings as ct, SearchOptions as d, handleContentDelete as di, ValidatedPluginManifest as dn, FieldAnnotation as dr, isPreviewRequest as dt, handleMediaUpdate as ei, UrlInput as en, InferCollectionData as er, UpdateMenuItemInput as et, SearchResponse as f, handleContentDiscardDraft as fi, pluginManifestSchema as fn, createEditable as fr, GetPreviewUrlOptions as ft, Suggestion as g, handleContentList as gi, LocalStorageConfig as gn, sanitizeHref as gr, PreviewTokenPayload as gt, SuggestOptions as h, handleContentGetIncludingTrashed as hi, getStoredConfig as hn, isSafeHref as hr, GeneratePreviewTokenOptions as ht, getSuggestions as i, handleRevisionList as ii, PluginManager as in, getEditMeta as ir, getComments as it, getEntryTerms as j, ManifestResponse as ji, WxrPost as jn, SandboxEmailMessage as jr, registerSource as jt, getAllTermsForEntries as k, FieldDescriptor as ki, WxrCategory as kn, ProseMirrorMark as kr, getUrlSources as kt, CollectionSearchOptions as l, handleContentCountTrashed as li, HookResult as ln, CMSAnnotation as lr, setSiteSettings as lt, SearchStats as m, handleContentGet as mi, PluginDescriptor as mn, decodeSlug as mr, getPreviewUrl as mt, extractSearchableFields as n, RevisionResponse as ni, SandboxNotAvailableError as nn, TranslationSummary as nr, GetCommentsResult as nt, searchCollection as o, generateManifest as oi, PluginRouteError as on, getEmDashEntry as or, getPluginSettings as ot, SearchResult as p, handleContentDuplicate as pi, EmDashConfig as pn, createNoop as pr, buildPreviewUrl as pt, CreateMenuInput as q, CacheHint as qn, SchemaRegistry as qr, PostTypeMapping as qt, getSearchStats as r, handleRevisionGet as ri, createNoopSandboxRunner as rn, TranslationsResult as rr, getCommentCount as rt, searchWithDb as s, handleContentCompare as si, EmailPipeline as sn, getTranslations as sr, getSiteSetting as st, extractPlainText as t, RevisionListResponse as ti, NoopSandboxRunner as tn, ResolvePathResult as tr, GetCommentsOptions as tt, SearchConfig as u, handleContentCreate as ui, createHookPipeline as un, EditProxy as ur, getPreviewToken as ut, getWidgetAreas as v, handleContentPermanentDelete as vi, StorageDescriptor as vn, hashString as vr, VerifyPreviewTokenResult as vt, UpdateWidgetInput as w, handleContentUnschedule as wi, AuthRouteDescriptor as wn, PortableTextMarkDef as wr, wxrSource as wt, CreateWidgetInput as x, handleContentSchedule as xi, AuthProviderDescriptor as xn, PortableTextCodeBlock as xr, verifyPreviewToken as xt, getWidgetComponents as y, handleContentPublish as yi, AuthDescriptor as yn, portableTextToProsemirror as yr, generatePreviewToken as yt, TaxonomyDef as z, PortableTextBlock$2 as zi, emdashLoader as zn, getSections as zr, ImportConfig as zt };
5015
+ //# sourceMappingURL=index-BFRaVcD6.d.mts.map