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
@@ -98,6 +98,10 @@ export const POST: APIRoute = async ({ params, request, locals }) => {
98
98
  const editDenied = requireOwnerPerm(user, authorId, "content:edit_own", "content:edit_any");
99
99
  if (editDenied) return editDenied;
100
100
 
101
+ // Resolve the canonical content ID from the handler result.
102
+ // The URL `id` param may be a slug; we must use the real ID for term storage.
103
+ const canonicalId = typeof existingItem?.id === "string" ? existingItem.id : id;
104
+
101
105
  try {
102
106
  const body = await parseBody(request, contentTermsBody);
103
107
  if (isParseError(body)) return body;
@@ -120,15 +124,15 @@ export const POST: APIRoute = async ({ params, request, locals }) => {
120
124
  }
121
125
  }
122
126
 
123
- // Set the terms (replaces existing)
124
- await repo.setTermsForEntry(collection, id, taxonomy, termIds);
127
+ // Set the terms (replaces existing) using the canonical ID
128
+ await repo.setTermsForEntry(collection, canonicalId, taxonomy, termIds);
125
129
 
126
130
  // Term assignments changed — invalidate the hasAnyTermAssignments cache
127
131
  // so hydration on subsequent reads issues a fresh query.
128
132
  invalidateTermCache();
129
133
 
130
- // Get the updated terms
131
- const terms = await repo.getTermsForEntry(collection, id, taxonomy);
134
+ // Get the updated terms using the canonical ID
135
+ const terms = await repo.getTermsForEntry(collection, canonicalId, taxonomy);
132
136
 
133
137
  return apiSuccess({
134
138
  terms: terms.map((t) => ({
@@ -6,7 +6,7 @@
6
6
  * Returns all locale variants linked to the same translation group.
7
7
  */
8
8
 
9
- import { hasPermission, type Permission } from "@emdash-cms/auth";
9
+ import { hasPermission } from "@emdash-cms/auth";
10
10
  import type { APIRoute } from "astro";
11
11
 
12
12
  import { requirePerm } from "#api/authorize.js";
@@ -47,6 +47,18 @@ export const GET: APIRoute = async ({ params, url, locals }) => {
47
47
  if (status !== "published") {
48
48
  return apiError("NOT_FOUND", `Content item not found: ${id}`, 404);
49
49
  }
50
+
51
+ // Strip draft hydration data from response for users without read_drafts.
52
+ // handleContentGet overlays draft revision data onto item.data and exposes
53
+ // the published values in item.liveData. Without this, subscribers see
54
+ // unpublished edits in the data field.
55
+ if (item) {
56
+ if (item.liveData && typeof item.liveData === "object") {
57
+ item.data = item.liveData;
58
+ }
59
+ delete item.liveData;
60
+ delete item.draftRevisionId;
61
+ }
50
62
  }
51
63
 
52
64
  return unwrapResult(result);
@@ -61,15 +61,7 @@ export const POST: APIRoute = async ({ params, request, locals, cache }) => {
61
61
  mapErrorStatus(source.error?.code),
62
62
  );
63
63
  }
64
- const sourceData =
65
- source.data && typeof source.data === "object"
66
- ? (source.data as Record<string, unknown>)
67
- : undefined;
68
- const sourceItem =
69
- sourceData?.item && typeof sourceData.item === "object"
70
- ? (sourceData.item as Record<string, unknown>)
71
- : sourceData;
72
- const sourceAuthor = typeof sourceItem?.authorId === "string" ? sourceItem.authorId : "";
64
+ const sourceAuthor = source.data.item.authorId ?? "";
73
65
  const translationDenied = requireOwnerPerm(
74
66
  user,
75
67
  sourceAuthor,
@@ -60,7 +60,7 @@ export interface ImportResult {
60
60
  }
61
61
 
62
62
  export const POST: APIRoute = async ({ request, locals }) => {
63
- const { emdash, emdashManifest, user } = locals;
63
+ const { emdash, user } = locals;
64
64
 
65
65
  const denied = requirePerm(user, "import:execute");
66
66
  if (denied) return denied;
@@ -70,6 +70,8 @@ export const POST: APIRoute = async ({ request, locals }) => {
70
70
  }
71
71
 
72
72
  try {
73
+ const emdashManifest = await emdash.getManifest();
74
+
73
75
  const formData = await request.formData();
74
76
  const fileEntry = formData.get("file");
75
77
  const file = fileEntry instanceof File ? fileEntry : null;
@@ -92,7 +92,6 @@ export const POST: APIRoute = async ({ request, locals }) => {
92
92
  attachments,
93
93
  emdash.db,
94
94
  emdash.storage,
95
- request.url,
96
95
  sendProgress,
97
96
  );
98
97
 
@@ -117,7 +116,6 @@ export const POST: APIRoute = async ({ request, locals }) => {
117
116
  attachments,
118
117
  emdash.db,
119
118
  emdash.storage,
120
- request.url,
121
119
  () => {}, // No-op progress callback
122
120
  );
123
121
 
@@ -131,12 +129,9 @@ async function importMediaWithProgress(
131
129
  attachments: AttachmentInfo[],
132
130
  db: NonNullable<EmDashHandlers["db"]>,
133
131
  storage: NonNullable<EmDashHandlers["storage"]>,
134
- requestUrl: string,
135
132
  onProgress: (progress: MediaImportProgress) => void,
136
133
  ): Promise<MediaImportResult> {
137
134
  const repo = new MediaRepository(db);
138
- const url = new URL(requestUrl);
139
- const baseUrl = `${url.protocol}//${url.host}`;
140
135
  const total = attachments.length;
141
136
 
142
137
  const result: MediaImportResult = {
@@ -237,7 +232,7 @@ async function importMediaWithProgress(
237
232
  const existing = await repo.findByContentHash(contentHash);
238
233
  if (existing) {
239
234
  // Same content already exists - reuse it
240
- const existingUrl = `${baseUrl}/_emdash/api/media/file/${existing.storageKey}`;
235
+ const existingUrl = `/_emdash/api/media/file/${existing.storageKey}`;
241
236
  result.urlMap[attachment.url] = existingUrl;
242
237
  result.imported.push({
243
238
  wpId: attachment.id,
@@ -290,7 +285,7 @@ async function importMediaWithProgress(
290
285
  });
291
286
 
292
287
  // Build the new URL
293
- const newUrl = `${baseUrl}/_emdash/api/media/file/${storageKey}`;
288
+ const newUrl = `/_emdash/api/media/file/${storageKey}`;
294
289
 
295
290
  result.imported.push({
296
291
  wpId: attachment.id,
@@ -58,6 +58,15 @@ export const POST: APIRoute = async ({ request, locals }) => {
58
58
  // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- Zod schema output narrowed to PrepareRequest
59
59
  const result = await prepareImport(emdash.db, body as PrepareRequest);
60
60
 
61
+ // Invalidate the URL pattern cache when prepare adds new collections so
62
+ // public routing picks up their patterns immediately. The manifest
63
+ // itself is built fresh per admin request, so cross-request
64
+ // staleness (the original failure mode in #747) is no longer
65
+ // possible — the execute step always reads live schema.
66
+ if (result.collectionsCreated.length > 0) {
67
+ emdash.invalidateUrlPatternCache();
68
+ }
69
+
61
70
  return apiSuccess(result, result.success ? 200 : 400);
62
71
  } catch (error) {
63
72
  return handleError(error, "Failed to prepare import", "WXR_PREPARE_ERROR");
@@ -36,7 +36,7 @@ export interface WpPluginImportResponse {
36
36
  }
37
37
 
38
38
  export const POST: APIRoute = async ({ request, locals }) => {
39
- const { emdash, emdashManifest, user } = locals;
39
+ const { emdash, user } = locals;
40
40
 
41
41
  const denied = requirePerm(user, "import:execute");
42
42
  if (denied) return denied;
@@ -46,6 +46,8 @@ export const POST: APIRoute = async ({ request, locals }) => {
46
46
  }
47
47
 
48
48
  try {
49
+ const emdashManifest = await emdash.getManifest();
50
+
49
51
  const body = await parseBody(request, wpPluginExecuteBody);
50
52
  if (isParseError(body)) return body;
51
53
 
@@ -9,64 +9,81 @@
9
9
 
10
10
  import type { APIRoute } from "astro";
11
11
 
12
+ import { handleError } from "#api/error.js";
12
13
  import { getAuthMode } from "#auth/mode.js";
13
14
 
14
15
  import { COMMIT, VERSION } from "../../../version.js";
15
- import { getStoredConfig } from "../../integration/runtime.js";
16
16
  import type { EmDashManifest } from "../../types.js";
17
17
 
18
18
  export const prerender = false;
19
19
 
20
20
  export const GET: APIRoute = async ({ locals }) => {
21
- const { emdashManifest, emdash } = locals;
21
+ const { emdash } = locals;
22
22
 
23
- // Determine auth mode from config
24
- const authMode = getAuthMode(emdash?.config);
23
+ try {
24
+ // Manifest is built fresh from the live database per admin request.
25
+ // `requestCached` inside `getManifest` dedupes if multiple consumers
26
+ // share the request. Wrapped in try/catch so any future DB-touching
27
+ // additions to `getManifest()` (plugin manifest loading, marketplace
28
+ // lookup, etc.) return the standard error envelope rather than an
29
+ // unstructured 500 — matches the pattern used by the WP execute
30
+ // routes.
31
+ const emdashManifest = emdash ? await emdash.getManifest() : null;
25
32
 
26
- // Read admin branding from build-time config
27
- const storedConfig = getStoredConfig();
28
- const adminBranding = storedConfig?.admin;
33
+ // Determine auth mode from config
34
+ const authMode = getAuthMode(emdash?.config);
29
35
 
30
- // Check if self-signup is enabled (any allowed domain with enabled = 1)
31
- // Only relevant for passkey auth external auth providers handle their own signup
32
- let signupEnabled = false;
33
- if (emdash?.db && authMode.type === "passkey") {
34
- try {
35
- const { sql } = await import("kysely");
36
- const result = await sql<{ cnt: unknown }>`
37
- SELECT COUNT(*) as cnt FROM allowed_domains WHERE enabled = 1
38
- `.execute(emdash.db);
39
- signupEnabled = Number(result.rows[0]?.cnt ?? 0) > 0;
40
- } catch {
41
- // Table may not exist yet, that's fine
42
- }
43
- }
36
+ // Read admin branding from the per-request config plumbed through middleware
37
+ // (same source admin.astro reads from). Reading from a build-time global
38
+ // here was unreliable -- the virtual config module exports the config but
39
+ // doesn't assign it to globalThis, so getStoredConfig() always returned
40
+ // null and the React SPA never received custom logo/siteName/favicon.
41
+ // See issue #835.
42
+ const adminBranding = emdash?.config?.admin;
44
43
 
45
- const manifest: EmDashManifest = emdashManifest
46
- ? {
47
- ...emdashManifest,
48
- authMode: authMode.type === "external" ? authMode.providerType : "passkey",
49
- signupEnabled,
50
- admin: adminBranding,
44
+ // Check if self-signup is enabled (any allowed domain with enabled = 1)
45
+ // Only relevant for passkey auth — external auth providers handle their own signup
46
+ let signupEnabled = false;
47
+ if (emdash?.db && authMode.type === "passkey") {
48
+ try {
49
+ const { sql } = await import("kysely");
50
+ const result = await sql<{ cnt: unknown }>`
51
+ SELECT COUNT(*) as cnt FROM allowed_domains WHERE enabled = 1
52
+ `.execute(emdash.db);
53
+ signupEnabled = Number(result.rows[0]?.cnt ?? 0) > 0;
54
+ } catch {
55
+ // Table may not exist yet, that's fine
51
56
  }
52
- : {
53
- version: VERSION,
54
- commit: COMMIT,
55
- hash: "default",
56
- collections: {},
57
- plugins: {},
58
- taxonomies: [],
59
- authMode: "passkey",
60
- signupEnabled,
61
- admin: adminBranding,
62
- };
57
+ }
63
58
 
64
- return Response.json(
65
- { data: manifest },
66
- {
67
- headers: {
68
- "Cache-Control": "private, no-store",
59
+ const manifest: EmDashManifest = emdashManifest
60
+ ? {
61
+ ...emdashManifest,
62
+ authMode: authMode.type === "external" ? authMode.providerType : "passkey",
63
+ signupEnabled,
64
+ admin: adminBranding,
65
+ }
66
+ : {
67
+ version: VERSION,
68
+ commit: COMMIT,
69
+ hash: "default",
70
+ collections: {},
71
+ plugins: {},
72
+ taxonomies: [],
73
+ authMode: "passkey",
74
+ signupEnabled,
75
+ admin: adminBranding,
76
+ };
77
+
78
+ return Response.json(
79
+ { data: manifest },
80
+ {
81
+ headers: {
82
+ "Cache-Control": "private, no-store",
83
+ },
69
84
  },
70
- },
71
- );
85
+ );
86
+ } catch (error) {
87
+ return handleError(error, "Failed to build manifest", "MANIFEST_BUILD_ERROR");
88
+ }
72
89
  };
@@ -10,7 +10,7 @@
10
10
  import type { APIRoute } from "astro";
11
11
  import { MediaRepository } from "emdash";
12
12
 
13
- import { requirePerm } from "#api/authorize.js";
13
+ import { requireOwnerPerm, requirePerm } from "#api/authorize.js";
14
14
  import { apiError, apiSuccess, handleError } from "#api/error.js";
15
15
  import { isParseError, parseOptionalBody } from "#api/parse.js";
16
16
  import { mediaConfirmBody } from "#api/schemas.js";
@@ -62,6 +62,15 @@ export const POST: APIRoute = async ({ params, request, locals }) => {
62
62
  return apiError("INVALID_STATE", `Media item is not pending: ${existing.status}`, 400);
63
63
  }
64
64
 
65
+ // Only the uploader or a user with media:edit_any can confirm/fail a pending upload
66
+ const ownerDenied = requireOwnerPerm(
67
+ user,
68
+ existing.authorId ?? "",
69
+ "media:edit_own",
70
+ "media:edit_any",
71
+ );
72
+ if (ownerDenied) return ownerDenied;
73
+
65
74
  // Optionally verify the file exists in storage
66
75
  if (emdash.storage) {
67
76
  const exists = await emdash.storage.exists(existing.storageKey);
@@ -37,9 +37,8 @@ export const GET: APIRoute = async ({ params, request, locals }) => {
37
37
 
38
38
  const url = new URL(request.url);
39
39
  const cursor = url.searchParams.get("cursor") || undefined;
40
- const limit = url.searchParams.get("limit")
41
- ? parseInt(url.searchParams.get("limit")!, 10)
42
- : undefined;
40
+ const rawLimit = url.searchParams.get("limit");
41
+ const limit = rawLimit ? Math.max(1, Math.min(parseInt(rawLimit, 10) || 50, 100)) : undefined;
43
42
  const query = url.searchParams.get("query") || undefined;
44
43
  const mimeType = url.searchParams.get("mimeType") || undefined;
45
44
 
@@ -98,6 +97,16 @@ export const POST: APIRoute = async ({ params, request, locals }) => {
98
97
  return apiError("NO_FILE", "No file provided", 400);
99
98
  }
100
99
 
100
+ // Basic size validation (default 50MB, configurable via maxUploadSize)
101
+ const maxSize = emdash.config?.maxUploadSize ?? 50 * 1024 * 1024;
102
+ if (file.size > maxSize) {
103
+ return apiError(
104
+ "FILE_TOO_LARGE",
105
+ `File exceeds maximum size of ${Math.round(maxSize / 1024 / 1024)}MB`,
106
+ 413,
107
+ );
108
+ }
109
+
101
110
  const item = await provider.upload({
102
111
  file,
103
112
  filename: file.name,
@@ -9,33 +9,50 @@
9
9
 
10
10
  import type { APIRoute } from "astro";
11
11
 
12
+ import { handleError } from "../../../api/error.js";
12
13
  import { generateOpenApiDocument } from "../../../api/openapi/index.js";
13
14
 
14
15
  export const prerender = false;
15
16
 
16
- let cachedSpec: string | null = null;
17
+ // Use globalThis with Symbol.for to survive Vite's SSR module duplication
18
+ const OPENAPI_CACHE_KEY = Symbol.for("emdash.openapi.cachedSpec");
19
+
20
+ function getCachedSpec(): string | null {
21
+ const val = (globalThis as Record<symbol, unknown>)[OPENAPI_CACHE_KEY];
22
+ return typeof val === "string" ? val : null;
23
+ }
24
+
25
+ function setCachedSpec(spec: string): void {
26
+ (globalThis as Record<symbol, unknown>)[OPENAPI_CACHE_KEY] = spec;
27
+ }
17
28
 
18
29
  export const GET: APIRoute = async ({ locals }) => {
19
30
  const { emdash } = locals;
20
- if (!cachedSpec && emdash) {
31
+
32
+ let spec = getCachedSpec();
33
+ if (!spec && emdash) {
21
34
  try {
22
35
  const doc = generateOpenApiDocument({ maxUploadSize: emdash.config.maxUploadSize });
23
- cachedSpec = JSON.stringify(doc);
24
- } catch {
25
- return new Response(
26
- JSON.stringify({ error: "Failed to generate OpenAPI document: invalid configuration" }),
27
- { status: 500, headers: { "Content-Type": "application/json" } },
28
- );
36
+ spec = JSON.stringify(doc);
37
+ setCachedSpec(spec);
38
+ } catch (error) {
39
+ return handleError(error, "Failed to generate OpenAPI document", "OPENAPI_ERROR");
29
40
  }
30
41
  }
31
42
 
32
- const spec = cachedSpec ?? JSON.stringify(generateOpenApiDocument());
43
+ if (!spec) {
44
+ try {
45
+ spec = JSON.stringify(generateOpenApiDocument());
46
+ } catch (error) {
47
+ return handleError(error, "Failed to generate OpenAPI document", "OPENAPI_ERROR");
48
+ }
49
+ }
33
50
 
34
51
  return new Response(spec, {
35
52
  status: 200,
36
53
  headers: {
37
54
  "Content-Type": "application/json",
38
- "Cache-Control": "public, max-age=3600",
55
+ "Cache-Control": "private, no-store",
39
56
  "Access-Control-Allow-Origin": "*",
40
57
  },
41
58
  });
@@ -9,7 +9,7 @@
9
9
  import type { APIRoute } from "astro";
10
10
 
11
11
  import { requirePerm } from "#api/authorize.js";
12
- import { handleError, unwrapResult } from "#api/error.js";
12
+ import { handleError, requireDb, unwrapResult } from "#api/error.js";
13
13
  import {
14
14
  handleNotFoundClear,
15
15
  handleNotFoundList,
@@ -22,7 +22,9 @@ export const prerender = false;
22
22
 
23
23
  export const GET: APIRoute = async ({ url, locals }) => {
24
24
  const { emdash, user } = locals;
25
- const db = emdash.db;
25
+ const dbErr = requireDb(emdash?.db);
26
+ if (dbErr) return dbErr;
27
+ const db = emdash!.db;
26
28
 
27
29
  const denied = requirePerm(user, "redirects:read");
28
30
  if (denied) return denied;
@@ -40,7 +42,9 @@ export const GET: APIRoute = async ({ url, locals }) => {
40
42
 
41
43
  export const DELETE: APIRoute = async ({ locals }) => {
42
44
  const { emdash, user } = locals;
43
- const db = emdash.db;
45
+ const dbErr = requireDb(emdash?.db);
46
+ if (dbErr) return dbErr;
47
+ const db = emdash!.db;
44
48
 
45
49
  const denied = requirePerm(user, "redirects:manage");
46
50
  if (denied) return denied;
@@ -55,7 +59,9 @@ export const DELETE: APIRoute = async ({ locals }) => {
55
59
 
56
60
  export const POST: APIRoute = async ({ request, locals }) => {
57
61
  const { emdash, user } = locals;
58
- const db = emdash.db;
62
+ const dbErr = requireDb(emdash?.db);
63
+ if (dbErr) return dbErr;
64
+ const db = emdash!.db;
59
65
 
60
66
  const denied = requirePerm(user, "redirects:manage");
61
67
  if (denied) return denied;
@@ -7,7 +7,7 @@
7
7
  import type { APIRoute } from "astro";
8
8
 
9
9
  import { requirePerm } from "#api/authorize.js";
10
- import { handleError, unwrapResult } from "#api/error.js";
10
+ import { handleError, requireDb, unwrapResult } from "#api/error.js";
11
11
  import { handleNotFoundSummary } from "#api/handlers/redirects.js";
12
12
  import { isParseError, parseQuery } from "#api/parse.js";
13
13
  import { notFoundSummaryQuery } from "#api/schemas.js";
@@ -16,7 +16,9 @@ export const prerender = false;
16
16
 
17
17
  export const GET: APIRoute = async ({ url, locals }) => {
18
18
  const { emdash, user } = locals;
19
- const db = emdash.db;
19
+ const dbErr = requireDb(emdash?.db);
20
+ if (dbErr) return dbErr;
21
+ const db = emdash!.db;
20
22
 
21
23
  const denied = requirePerm(user, "redirects:read");
22
24
  if (denied) return denied;
@@ -9,7 +9,7 @@
9
9
  import type { APIRoute } from "astro";
10
10
 
11
11
  import { requirePerm } from "#api/authorize.js";
12
- import { apiError, handleError, unwrapResult } from "#api/error.js";
12
+ import { apiError, handleError, requireDb, unwrapResult } from "#api/error.js";
13
13
  import {
14
14
  handleRedirectDelete,
15
15
  handleRedirectGet,
@@ -23,7 +23,9 @@ export const prerender = false;
23
23
 
24
24
  export const GET: APIRoute = async ({ params, locals }) => {
25
25
  const { emdash, user } = locals;
26
- const db = emdash.db;
26
+ const dbErr = requireDb(emdash?.db);
27
+ if (dbErr) return dbErr;
28
+ const db = emdash!.db;
27
29
  const { id } = params;
28
30
 
29
31
  const denied = requirePerm(user, "redirects:read");
@@ -43,7 +45,9 @@ export const GET: APIRoute = async ({ params, locals }) => {
43
45
 
44
46
  export const PUT: APIRoute = async ({ params, request, locals }) => {
45
47
  const { emdash, user } = locals;
46
- const db = emdash.db;
48
+ const dbErr = requireDb(emdash?.db);
49
+ if (dbErr) return dbErr;
50
+ const db = emdash!.db;
47
51
  const { id } = params;
48
52
 
49
53
  const denied = requirePerm(user, "redirects:manage");
@@ -67,7 +71,9 @@ export const PUT: APIRoute = async ({ params, request, locals }) => {
67
71
 
68
72
  export const DELETE: APIRoute = async ({ params, locals }) => {
69
73
  const { emdash, user } = locals;
70
- const db = emdash.db;
74
+ const dbErr = requireDb(emdash?.db);
75
+ if (dbErr) return dbErr;
76
+ const db = emdash!.db;
71
77
  const { id } = params;
72
78
 
73
79
  const denied = requirePerm(user, "redirects:manage");
@@ -8,7 +8,7 @@
8
8
  import type { APIRoute } from "astro";
9
9
 
10
10
  import { requirePerm } from "#api/authorize.js";
11
- import { handleError, unwrapResult } from "#api/error.js";
11
+ import { handleError, requireDb, unwrapResult } from "#api/error.js";
12
12
  import { handleRedirectCreate, handleRedirectList } from "#api/handlers/redirects.js";
13
13
  import { isParseError, parseBody, parseQuery } from "#api/parse.js";
14
14
  import { createRedirectBody, redirectsListQuery } from "#api/schemas.js";
@@ -18,7 +18,9 @@ export const prerender = false;
18
18
 
19
19
  export const GET: APIRoute = async ({ url, locals }) => {
20
20
  const { emdash, user } = locals;
21
- const db = emdash.db;
21
+ const dbErr = requireDb(emdash?.db);
22
+ if (dbErr) return dbErr;
23
+ const db = emdash!.db;
22
24
 
23
25
  const denied = requirePerm(user, "redirects:read");
24
26
  if (denied) return denied;
@@ -36,7 +38,9 @@ export const GET: APIRoute = async ({ url, locals }) => {
36
38
 
37
39
  export const POST: APIRoute = async ({ request, locals }) => {
38
40
  const { emdash, user } = locals;
39
- const db = emdash.db;
41
+ const dbErr = requireDb(emdash?.db);
42
+ if (dbErr) return dbErr;
43
+ const db = emdash!.db;
40
44
 
41
45
  const denied = requirePerm(user, "redirects:manage");
42
46
  if (denied) return denied;
@@ -16,7 +16,7 @@ export const GET: APIRoute = async ({ params, locals }) => {
16
16
  const { emdash, user } = locals;
17
17
  const revisionId = params.revisionId!;
18
18
 
19
- const denied = requirePerm(user, "content:read");
19
+ const denied = requirePerm(user, "content:read_drafts");
20
20
  if (denied) return denied;
21
21
 
22
22
  if (!emdash?.handleRevisionGet) {
@@ -57,7 +57,6 @@ export const PUT: APIRoute = async ({ params, request, locals }) => {
57
57
  fieldSlug,
58
58
  body as UpdateFieldInput,
59
59
  );
60
- if (result.success) emdash!.invalidateManifest();
61
60
  return unwrapResult(result);
62
61
  };
63
62
 
@@ -73,6 +72,5 @@ export const DELETE: APIRoute = async ({ params, locals }) => {
73
72
  if (denied) return denied;
74
73
 
75
74
  const result = await handleSchemaFieldDelete(emdash!.db, collectionSlug, fieldSlug);
76
- if (result.success) emdash!.invalidateManifest();
77
75
  return unwrapResult(result);
78
76
  };
@@ -48,6 +48,5 @@ export const POST: APIRoute = async ({ params, request, locals }) => {
48
48
  collectionSlug,
49
49
  body as CreateFieldInput,
50
50
  );
51
- if (result.success) emdash!.invalidateManifest();
52
51
  return unwrapResult(result, 201);
53
52
  };
@@ -28,6 +28,5 @@ export const POST: APIRoute = async ({ params, request, locals }) => {
28
28
  if (isParseError(body)) return body;
29
29
 
30
30
  const result = await handleSchemaFieldReorder(emdash!.db, collectionSlug, body.fieldSlugs);
31
- if (result.success) emdash!.invalidateManifest();
32
31
  return unwrapResult(result);
33
32
  };
@@ -59,7 +59,7 @@ export const PUT: APIRoute = async ({ params, request, locals }) => {
59
59
  // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- parseBody validates via Zod
60
60
  body as UpdateCollectionInput,
61
61
  );
62
- emdash!.invalidateManifest();
62
+ emdash!.invalidateUrlPatternCache();
63
63
  return unwrapResult(result);
64
64
  };
65
65
 
@@ -77,6 +77,6 @@ export const DELETE: APIRoute = async ({ params, url, locals }) => {
77
77
  const result = await handleSchemaCollectionDelete(emdash!.db, slug, {
78
78
  force,
79
79
  });
80
- emdash!.invalidateManifest();
80
+ emdash!.invalidateUrlPatternCache();
81
81
  return unwrapResult(result);
82
82
  };
@@ -43,6 +43,6 @@ export const POST: APIRoute = async ({ request, locals }) => {
43
43
 
44
44
  // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- Zod schema output narrowed to CreateCollectionInput
45
45
  const result = await handleSchemaCollectionCreate(emdash!.db, body as CreateCollectionInput);
46
- emdash!.invalidateManifest();
46
+ emdash!.invalidateUrlPatternCache();
47
47
  return unwrapResult(result, 201);
48
48
  };