emdash 0.0.0-a → 0.0.1

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 (661) hide show
  1. package/README.md +87 -1
  2. package/dist/adapters-BLMa4JGD.d.mts +106 -0
  3. package/dist/adapters-BLMa4JGD.d.mts.map +1 -0
  4. package/dist/apply-Bjfq_b4-.mjs +1293 -0
  5. package/dist/apply-Bjfq_b4-.mjs.map +1 -0
  6. package/dist/astro/index.d.mts +51 -0
  7. package/dist/astro/index.d.mts.map +1 -0
  8. package/dist/astro/index.mjs +1333 -0
  9. package/dist/astro/index.mjs.map +1 -0
  10. package/dist/astro/middleware/auth.d.mts +31 -0
  11. package/dist/astro/middleware/auth.d.mts.map +1 -0
  12. package/dist/astro/middleware/auth.mjs +654 -0
  13. package/dist/astro/middleware/auth.mjs.map +1 -0
  14. package/dist/astro/middleware/redirect.d.mts +22 -0
  15. package/dist/astro/middleware/redirect.d.mts.map +1 -0
  16. package/dist/astro/middleware/redirect.mjs +63 -0
  17. package/dist/astro/middleware/redirect.mjs.map +1 -0
  18. package/dist/astro/middleware/request-context.d.mts +18 -0
  19. package/dist/astro/middleware/request-context.d.mts.map +1 -0
  20. package/dist/astro/middleware/request-context.mjs +1310 -0
  21. package/dist/astro/middleware/request-context.mjs.map +1 -0
  22. package/dist/astro/middleware/setup.d.mts +20 -0
  23. package/dist/astro/middleware/setup.d.mts.map +1 -0
  24. package/dist/astro/middleware/setup.mjs +47 -0
  25. package/dist/astro/middleware/setup.mjs.map +1 -0
  26. package/dist/astro/middleware.d.mts +13 -0
  27. package/dist/astro/middleware.d.mts.map +1 -0
  28. package/dist/astro/middleware.mjs +1613 -0
  29. package/dist/astro/middleware.mjs.map +1 -0
  30. package/dist/astro/types.d.mts +250 -0
  31. package/dist/astro/types.d.mts.map +1 -0
  32. package/dist/astro/types.mjs +1 -0
  33. package/dist/base64-MBPo9ozB.mjs +59 -0
  34. package/dist/base64-MBPo9ozB.mjs.map +1 -0
  35. package/dist/byline-CL847F26.mjs +213 -0
  36. package/dist/byline-CL847F26.mjs.map +1 -0
  37. package/dist/bylines-C2a-2TGt.mjs +136 -0
  38. package/dist/bylines-C2a-2TGt.mjs.map +1 -0
  39. package/dist/chunk-ClPoSABd.mjs +21 -0
  40. package/dist/cli/index.d.mts +1 -0
  41. package/dist/cli/index.mjs +3909 -0
  42. package/dist/cli/index.mjs.map +1 -0
  43. package/dist/client/cf-access.d.mts +60 -0
  44. package/dist/client/cf-access.d.mts.map +1 -0
  45. package/dist/client/cf-access.mjs +179 -0
  46. package/dist/client/cf-access.mjs.map +1 -0
  47. package/dist/client/index.d.mts +398 -0
  48. package/dist/client/index.d.mts.map +1 -0
  49. package/dist/client/index.mjs +346 -0
  50. package/dist/client/index.mjs.map +1 -0
  51. package/dist/config-CKE8p9xM.mjs +55 -0
  52. package/dist/config-CKE8p9xM.mjs.map +1 -0
  53. package/dist/connection-B4zVnQIa.mjs +40 -0
  54. package/dist/connection-B4zVnQIa.mjs.map +1 -0
  55. package/dist/content-D6C2WsZC.mjs +824 -0
  56. package/dist/content-D6C2WsZC.mjs.map +1 -0
  57. package/dist/db/index.d.mts +4 -0
  58. package/dist/db/index.mjs +62 -0
  59. package/dist/db/index.mjs.map +1 -0
  60. package/dist/db/libsql.d.mts +11 -0
  61. package/dist/db/libsql.d.mts.map +1 -0
  62. package/dist/db/libsql.mjs +17 -0
  63. package/dist/db/libsql.mjs.map +1 -0
  64. package/dist/db/postgres.d.mts +11 -0
  65. package/dist/db/postgres.d.mts.map +1 -0
  66. package/dist/db/postgres.mjs +30 -0
  67. package/dist/db/postgres.mjs.map +1 -0
  68. package/dist/db/sqlite.d.mts +11 -0
  69. package/dist/db/sqlite.d.mts.map +1 -0
  70. package/dist/db/sqlite.mjs +16 -0
  71. package/dist/db/sqlite.mjs.map +1 -0
  72. package/dist/default-Cyi4aAxu.mjs +81 -0
  73. package/dist/default-Cyi4aAxu.mjs.map +1 -0
  74. package/dist/dialect-helpers-B9uSp2GJ.mjs +90 -0
  75. package/dist/dialect-helpers-B9uSp2GJ.mjs.map +1 -0
  76. package/dist/error-Cxz0tQeO.mjs +27 -0
  77. package/dist/error-Cxz0tQeO.mjs.map +1 -0
  78. package/dist/index-C1xF3OGh.d.mts +4527 -0
  79. package/dist/index-C1xF3OGh.d.mts.map +1 -0
  80. package/dist/index.d.mts +16 -0
  81. package/dist/index.mjs +30 -0
  82. package/dist/load-yOOlckBj.mjs +28 -0
  83. package/dist/load-yOOlckBj.mjs.map +1 -0
  84. package/dist/loader-fz8Q_3EO.mjs +447 -0
  85. package/dist/loader-fz8Q_3EO.mjs.map +1 -0
  86. package/dist/manifest-schema-Dcl0R6nM.mjs +184 -0
  87. package/dist/manifest-schema-Dcl0R6nM.mjs.map +1 -0
  88. package/dist/media/index.d.mts +26 -0
  89. package/dist/media/index.d.mts.map +1 -0
  90. package/dist/media/index.mjs +55 -0
  91. package/dist/media/index.mjs.map +1 -0
  92. package/dist/media/local-runtime.d.mts +39 -0
  93. package/dist/media/local-runtime.d.mts.map +1 -0
  94. package/dist/media/local-runtime.mjs +133 -0
  95. package/dist/media/local-runtime.mjs.map +1 -0
  96. package/dist/media-DqHVh136.mjs +200 -0
  97. package/dist/media-DqHVh136.mjs.map +1 -0
  98. package/dist/mode-C2EzN1uE.mjs +23 -0
  99. package/dist/mode-C2EzN1uE.mjs.map +1 -0
  100. package/dist/page/index.d.mts +140 -0
  101. package/dist/page/index.d.mts.map +1 -0
  102. package/dist/page/index.mjs +416 -0
  103. package/dist/page/index.mjs.map +1 -0
  104. package/dist/placeholder-CmGAmqeO.d.mts +276 -0
  105. package/dist/placeholder-CmGAmqeO.d.mts.map +1 -0
  106. package/dist/placeholder-SmpOx-_v.mjs +243 -0
  107. package/dist/placeholder-SmpOx-_v.mjs.map +1 -0
  108. package/dist/plugin-utils.d.mts +58 -0
  109. package/dist/plugin-utils.d.mts.map +1 -0
  110. package/dist/plugin-utils.mjs +78 -0
  111. package/dist/plugin-utils.mjs.map +1 -0
  112. package/dist/plugins/adapt-sandbox-entry.d.mts +22 -0
  113. package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -0
  114. package/dist/plugins/adapt-sandbox-entry.mjs +113 -0
  115. package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -0
  116. package/dist/query-CS_iSj34.mjs +460 -0
  117. package/dist/query-CS_iSj34.mjs.map +1 -0
  118. package/dist/redirect-DIfIni3r.mjs +329 -0
  119. package/dist/redirect-DIfIni3r.mjs.map +1 -0
  120. package/dist/registry-D_w5HW4G.mjs +863 -0
  121. package/dist/registry-D_w5HW4G.mjs.map +1 -0
  122. package/dist/request-context.d.mts +49 -0
  123. package/dist/request-context.d.mts.map +1 -0
  124. package/dist/request-context.mjs +43 -0
  125. package/dist/request-context.mjs.map +1 -0
  126. package/dist/runner-B-u2F2b6.mjs +1412 -0
  127. package/dist/runner-B-u2F2b6.mjs.map +1 -0
  128. package/dist/runner-EAtf0ZIe.d.mts +27 -0
  129. package/dist/runner-EAtf0ZIe.d.mts.map +1 -0
  130. package/dist/runtime.d.mts +26 -0
  131. package/dist/runtime.d.mts.map +1 -0
  132. package/dist/runtime.mjs +42 -0
  133. package/dist/runtime.mjs.map +1 -0
  134. package/dist/search-DG603UrT.mjs +9211 -0
  135. package/dist/search-DG603UrT.mjs.map +1 -0
  136. package/dist/seed/index.d.mts +3 -0
  137. package/dist/seed/index.mjs +15 -0
  138. package/dist/seo/index.d.mts +70 -0
  139. package/dist/seo/index.d.mts.map +1 -0
  140. package/dist/seo/index.mjs +70 -0
  141. package/dist/seo/index.mjs.map +1 -0
  142. package/dist/storage/local.d.mts +39 -0
  143. package/dist/storage/local.d.mts.map +1 -0
  144. package/dist/storage/local.mjs +166 -0
  145. package/dist/storage/local.mjs.map +1 -0
  146. package/dist/storage/s3.d.mts +32 -0
  147. package/dist/storage/s3.d.mts.map +1 -0
  148. package/dist/storage/s3.mjs +175 -0
  149. package/dist/storage/s3.mjs.map +1 -0
  150. package/dist/tokens-DpgrkrXK.mjs +171 -0
  151. package/dist/tokens-DpgrkrXK.mjs.map +1 -0
  152. package/dist/transport-BFGblqwG.d.mts +42 -0
  153. package/dist/transport-BFGblqwG.d.mts.map +1 -0
  154. package/dist/transport-yxiQsi8I.mjs +418 -0
  155. package/dist/transport-yxiQsi8I.mjs.map +1 -0
  156. package/dist/types-BRuPJGdV.d.mts +102 -0
  157. package/dist/types-BRuPJGdV.d.mts.map +1 -0
  158. package/dist/types-C4-fAxN3.d.mts +182 -0
  159. package/dist/types-C4-fAxN3.d.mts.map +1 -0
  160. package/dist/types-CMMN0pNg.mjs +31 -0
  161. package/dist/types-CMMN0pNg.mjs.map +1 -0
  162. package/dist/types-CUBbjgmP.mjs +16 -0
  163. package/dist/types-CUBbjgmP.mjs.map +1 -0
  164. package/dist/types-DRjfYOEv.d.mts +426 -0
  165. package/dist/types-DRjfYOEv.d.mts.map +1 -0
  166. package/dist/types-DY5zk5HN.mjs +73 -0
  167. package/dist/types-DY5zk5HN.mjs.map +1 -0
  168. package/dist/types-DaNLHo_T.d.mts +184 -0
  169. package/dist/types-DaNLHo_T.d.mts.map +1 -0
  170. package/dist/types-DvhsUmSJ.d.mts +1111 -0
  171. package/dist/types-DvhsUmSJ.d.mts.map +1 -0
  172. package/dist/validate-CpBtVMsD.d.mts +378 -0
  173. package/dist/validate-CpBtVMsD.d.mts.map +1 -0
  174. package/dist/validate-CqRJb_xU.mjs +97 -0
  175. package/dist/validate-CqRJb_xU.mjs.map +1 -0
  176. package/dist/validate-O7PWmlnq.mjs +328 -0
  177. package/dist/validate-O7PWmlnq.mjs.map +1 -0
  178. package/locals.d.ts +46 -0
  179. package/package.json +233 -19
  180. package/src/api/authorize.ts +63 -0
  181. package/src/api/csrf.ts +48 -0
  182. package/src/api/error.ts +99 -0
  183. package/src/api/errors.ts +445 -0
  184. package/src/api/escape.ts +9 -0
  185. package/src/api/handlers/api-tokens.ts +240 -0
  186. package/src/api/handlers/comments.ts +314 -0
  187. package/src/api/handlers/content.ts +1315 -0
  188. package/src/api/handlers/dashboard.ts +205 -0
  189. package/src/api/handlers/device-flow.ts +687 -0
  190. package/src/api/handlers/index.ts +163 -0
  191. package/src/api/handlers/manifest.ts +158 -0
  192. package/src/api/handlers/marketplace.ts +930 -0
  193. package/src/api/handlers/media.ts +207 -0
  194. package/src/api/handlers/menus.ts +493 -0
  195. package/src/api/handlers/oauth-authorization.ts +429 -0
  196. package/src/api/handlers/oauth-clients.ts +353 -0
  197. package/src/api/handlers/oauth-user-lookup.ts +39 -0
  198. package/src/api/handlers/plugins.ts +254 -0
  199. package/src/api/handlers/redirects.ts +360 -0
  200. package/src/api/handlers/revision.ts +145 -0
  201. package/src/api/handlers/schema.ts +534 -0
  202. package/src/api/handlers/sections.ts +289 -0
  203. package/src/api/handlers/seo.ts +115 -0
  204. package/src/api/handlers/settings.ts +49 -0
  205. package/src/api/handlers/snapshot.ts +350 -0
  206. package/src/api/handlers/taxonomies.ts +523 -0
  207. package/src/api/index.ts +6 -0
  208. package/src/api/openapi/document.ts +2368 -0
  209. package/src/api/openapi/index.ts +1 -0
  210. package/src/api/parse.ts +139 -0
  211. package/src/api/redirect.ts +14 -0
  212. package/src/api/rev.ts +67 -0
  213. package/src/api/schemas/auth.ts +112 -0
  214. package/src/api/schemas/bylines.ts +85 -0
  215. package/src/api/schemas/comments.ts +117 -0
  216. package/src/api/schemas/common.ts +89 -0
  217. package/src/api/schemas/content.ts +191 -0
  218. package/src/api/schemas/import.ts +52 -0
  219. package/src/api/schemas/index.ts +17 -0
  220. package/src/api/schemas/media.ts +116 -0
  221. package/src/api/schemas/menus.ts +111 -0
  222. package/src/api/schemas/redirects.ts +155 -0
  223. package/src/api/schemas/schema.ts +203 -0
  224. package/src/api/schemas/search.ts +63 -0
  225. package/src/api/schemas/sections.ts +67 -0
  226. package/src/api/schemas/settings.ts +63 -0
  227. package/src/api/schemas/setup.ts +37 -0
  228. package/src/api/schemas/taxonomies.ts +113 -0
  229. package/src/api/schemas/users.ts +96 -0
  230. package/src/api/schemas/widgets.ts +80 -0
  231. package/src/api/site-url.ts +25 -0
  232. package/src/api/types.ts +82 -0
  233. package/src/astro/index.ts +27 -0
  234. package/src/astro/integration/index.ts +303 -0
  235. package/src/astro/integration/routes.ts +834 -0
  236. package/src/astro/integration/runtime.ts +338 -0
  237. package/src/astro/integration/virtual-modules.ts +469 -0
  238. package/src/astro/integration/vite-config.ts +328 -0
  239. package/src/astro/middleware/auth.ts +743 -0
  240. package/src/astro/middleware/redirect.ts +89 -0
  241. package/src/astro/middleware/request-context.ts +129 -0
  242. package/src/astro/middleware/setup.ts +89 -0
  243. package/src/astro/middleware.ts +398 -0
  244. package/src/astro/routes/PluginRegistry.tsx +15 -0
  245. package/src/astro/routes/admin.astro +81 -0
  246. package/src/astro/routes/api/admin/allowed-domains/[domain].ts +112 -0
  247. package/src/astro/routes/api/admin/allowed-domains/index.ts +108 -0
  248. package/src/astro/routes/api/admin/api-tokens/[id].ts +40 -0
  249. package/src/astro/routes/api/admin/api-tokens/index.ts +68 -0
  250. package/src/astro/routes/api/admin/bylines/[id]/index.ts +87 -0
  251. package/src/astro/routes/api/admin/bylines/index.ts +72 -0
  252. package/src/astro/routes/api/admin/comments/[id]/status.ts +120 -0
  253. package/src/astro/routes/api/admin/comments/[id].ts +64 -0
  254. package/src/astro/routes/api/admin/comments/bulk.ts +42 -0
  255. package/src/astro/routes/api/admin/comments/counts.ts +30 -0
  256. package/src/astro/routes/api/admin/comments/index.ts +46 -0
  257. package/src/astro/routes/api/admin/hooks/exclusive/[hookName].ts +91 -0
  258. package/src/astro/routes/api/admin/hooks/exclusive/index.ts +51 -0
  259. package/src/astro/routes/api/admin/oauth-clients/[id].ts +110 -0
  260. package/src/astro/routes/api/admin/oauth-clients/index.ts +71 -0
  261. package/src/astro/routes/api/admin/plugins/[id]/disable.ts +39 -0
  262. package/src/astro/routes/api/admin/plugins/[id]/enable.ts +39 -0
  263. package/src/astro/routes/api/admin/plugins/[id]/index.ts +38 -0
  264. package/src/astro/routes/api/admin/plugins/[id]/uninstall.ts +48 -0
  265. package/src/astro/routes/api/admin/plugins/[id]/update.ts +59 -0
  266. package/src/astro/routes/api/admin/plugins/index.ts +32 -0
  267. package/src/astro/routes/api/admin/plugins/marketplace/[id]/icon.ts +61 -0
  268. package/src/astro/routes/api/admin/plugins/marketplace/[id]/index.ts +33 -0
  269. package/src/astro/routes/api/admin/plugins/marketplace/[id]/install.ts +62 -0
  270. package/src/astro/routes/api/admin/plugins/marketplace/index.ts +38 -0
  271. package/src/astro/routes/api/admin/plugins/updates.ts +28 -0
  272. package/src/astro/routes/api/admin/themes/marketplace/[id]/index.ts +33 -0
  273. package/src/astro/routes/api/admin/themes/marketplace/[id]/thumbnail.ts +61 -0
  274. package/src/astro/routes/api/admin/themes/marketplace/index.ts +45 -0
  275. package/src/astro/routes/api/admin/users/[id]/disable.ts +69 -0
  276. package/src/astro/routes/api/admin/users/[id]/enable.ts +48 -0
  277. package/src/astro/routes/api/admin/users/[id]/index.ts +146 -0
  278. package/src/astro/routes/api/admin/users/[id]/send-recovery.ts +72 -0
  279. package/src/astro/routes/api/admin/users/index.ts +66 -0
  280. package/src/astro/routes/api/auth/dev-bypass.ts +139 -0
  281. package/src/astro/routes/api/auth/invite/accept.ts +52 -0
  282. package/src/astro/routes/api/auth/invite/complete.ts +84 -0
  283. package/src/astro/routes/api/auth/invite/index.ts +99 -0
  284. package/src/astro/routes/api/auth/logout.ts +40 -0
  285. package/src/astro/routes/api/auth/magic-link/send.ts +89 -0
  286. package/src/astro/routes/api/auth/magic-link/verify.ts +71 -0
  287. package/src/astro/routes/api/auth/me.ts +60 -0
  288. package/src/astro/routes/api/auth/oauth/[provider]/callback.ts +219 -0
  289. package/src/astro/routes/api/auth/oauth/[provider].ts +119 -0
  290. package/src/astro/routes/api/auth/passkey/[id].ts +124 -0
  291. package/src/astro/routes/api/auth/passkey/index.ts +54 -0
  292. package/src/astro/routes/api/auth/passkey/options.ts +82 -0
  293. package/src/astro/routes/api/auth/passkey/register/options.ts +86 -0
  294. package/src/astro/routes/api/auth/passkey/register/verify.ts +117 -0
  295. package/src/astro/routes/api/auth/passkey/verify.ts +66 -0
  296. package/src/astro/routes/api/auth/signup/complete.ts +85 -0
  297. package/src/astro/routes/api/auth/signup/request.ts +77 -0
  298. package/src/astro/routes/api/auth/signup/verify.ts +53 -0
  299. package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +312 -0
  300. package/src/astro/routes/api/content/[collection]/[id]/compare.ts +28 -0
  301. package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +54 -0
  302. package/src/astro/routes/api/content/[collection]/[id]/duplicate.ts +61 -0
  303. package/src/astro/routes/api/content/[collection]/[id]/permanent.ts +33 -0
  304. package/src/astro/routes/api/content/[collection]/[id]/preview-url.ts +107 -0
  305. package/src/astro/routes/api/content/[collection]/[id]/publish.ts +56 -0
  306. package/src/astro/routes/api/content/[collection]/[id]/restore.ts +54 -0
  307. package/src/astro/routes/api/content/[collection]/[id]/revisions.ts +31 -0
  308. package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +105 -0
  309. package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +140 -0
  310. package/src/astro/routes/api/content/[collection]/[id]/translations.ts +30 -0
  311. package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +56 -0
  312. package/src/astro/routes/api/content/[collection]/[id].ts +137 -0
  313. package/src/astro/routes/api/content/[collection]/index.ts +59 -0
  314. package/src/astro/routes/api/content/[collection]/trash.ts +33 -0
  315. package/src/astro/routes/api/dashboard.ts +32 -0
  316. package/src/astro/routes/api/dev/emails.ts +36 -0
  317. package/src/astro/routes/api/import/probe.ts +47 -0
  318. package/src/astro/routes/api/import/wordpress/analyze.ts +510 -0
  319. package/src/astro/routes/api/import/wordpress/execute.ts +283 -0
  320. package/src/astro/routes/api/import/wordpress/media.ts +338 -0
  321. package/src/astro/routes/api/import/wordpress/prepare.ts +181 -0
  322. package/src/astro/routes/api/import/wordpress/rewrite-urls.ts +393 -0
  323. package/src/astro/routes/api/import/wordpress-plugin/analyze.ts +111 -0
  324. package/src/astro/routes/api/import/wordpress-plugin/callback.ts +58 -0
  325. package/src/astro/routes/api/import/wordpress-plugin/execute.ts +347 -0
  326. package/src/astro/routes/api/manifest.ts +62 -0
  327. package/src/astro/routes/api/mcp.ts +124 -0
  328. package/src/astro/routes/api/media/[id]/confirm.ts +93 -0
  329. package/src/astro/routes/api/media/[id].ts +145 -0
  330. package/src/astro/routes/api/media/file/[key].ts +79 -0
  331. package/src/astro/routes/api/media/providers/[providerId]/[itemId].ts +86 -0
  332. package/src/astro/routes/api/media/providers/[providerId]/index.ts +111 -0
  333. package/src/astro/routes/api/media/providers/index.ts +30 -0
  334. package/src/astro/routes/api/media/upload-url.ts +137 -0
  335. package/src/astro/routes/api/media.ts +190 -0
  336. package/src/astro/routes/api/menus/[name]/items.ts +87 -0
  337. package/src/astro/routes/api/menus/[name]/reorder.ts +33 -0
  338. package/src/astro/routes/api/menus/[name].ts +65 -0
  339. package/src/astro/routes/api/menus/index.ts +47 -0
  340. package/src/astro/routes/api/oauth/authorize.ts +412 -0
  341. package/src/astro/routes/api/oauth/device/authorize.ts +45 -0
  342. package/src/astro/routes/api/oauth/device/code.ts +51 -0
  343. package/src/astro/routes/api/oauth/device/token.ts +69 -0
  344. package/src/astro/routes/api/oauth/token/refresh.ts +38 -0
  345. package/src/astro/routes/api/oauth/token/revoke.ts +38 -0
  346. package/src/astro/routes/api/oauth/token.ts +184 -0
  347. package/src/astro/routes/api/openapi.json.ts +32 -0
  348. package/src/astro/routes/api/plugins/[pluginId]/[...path].ts +92 -0
  349. package/src/astro/routes/api/redirects/404s/index.ts +72 -0
  350. package/src/astro/routes/api/redirects/404s/summary.ts +33 -0
  351. package/src/astro/routes/api/redirects/[id].ts +84 -0
  352. package/src/astro/routes/api/redirects/index.ts +52 -0
  353. package/src/astro/routes/api/revisions/[revisionId]/index.ts +29 -0
  354. package/src/astro/routes/api/revisions/[revisionId]/restore.ts +62 -0
  355. package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +76 -0
  356. package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +52 -0
  357. package/src/astro/routes/api/schema/collections/[slug]/fields/reorder.ts +32 -0
  358. package/src/astro/routes/api/schema/collections/[slug]/index.ts +80 -0
  359. package/src/astro/routes/api/schema/collections/index.ts +47 -0
  360. package/src/astro/routes/api/schema/index.ts +109 -0
  361. package/src/astro/routes/api/schema/orphans/[slug].ts +36 -0
  362. package/src/astro/routes/api/schema/orphans/index.ts +26 -0
  363. package/src/astro/routes/api/search/enable.ts +64 -0
  364. package/src/astro/routes/api/search/index.ts +55 -0
  365. package/src/astro/routes/api/search/rebuild.ts +72 -0
  366. package/src/astro/routes/api/search/stats.ts +35 -0
  367. package/src/astro/routes/api/search/suggest.ts +53 -0
  368. package/src/astro/routes/api/sections/[slug].ts +84 -0
  369. package/src/astro/routes/api/sections/index.ts +52 -0
  370. package/src/astro/routes/api/settings/email.ts +150 -0
  371. package/src/astro/routes/api/settings.ts +67 -0
  372. package/src/astro/routes/api/setup/admin-verify.ts +100 -0
  373. package/src/astro/routes/api/setup/admin.ts +94 -0
  374. package/src/astro/routes/api/setup/dev-bypass.ts +199 -0
  375. package/src/astro/routes/api/setup/dev-reset.ts +40 -0
  376. package/src/astro/routes/api/setup/index.ts +126 -0
  377. package/src/astro/routes/api/setup/status.ts +122 -0
  378. package/src/astro/routes/api/snapshot.ts +75 -0
  379. package/src/astro/routes/api/taxonomies/[name]/terms/[slug].ts +95 -0
  380. package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +69 -0
  381. package/src/astro/routes/api/taxonomies/index.ts +59 -0
  382. package/src/astro/routes/api/themes/preview.ts +77 -0
  383. package/src/astro/routes/api/typegen.ts +114 -0
  384. package/src/astro/routes/api/well-known/auth.ts +68 -0
  385. package/src/astro/routes/api/well-known/oauth-authorization-server.ts +44 -0
  386. package/src/astro/routes/api/well-known/oauth-protected-resource.ts +37 -0
  387. package/src/astro/routes/api/widget-areas/[name]/reorder.ts +72 -0
  388. package/src/astro/routes/api/widget-areas/[name]/widgets/[id].ts +127 -0
  389. package/src/astro/routes/api/widget-areas/[name]/widgets.ts +80 -0
  390. package/src/astro/routes/api/widget-areas/[name].ts +87 -0
  391. package/src/astro/routes/api/widget-areas/index.ts +99 -0
  392. package/src/astro/routes/api/widget-components.ts +22 -0
  393. package/src/astro/routes/robots.txt.ts +77 -0
  394. package/src/astro/routes/sitemap.xml.ts +97 -0
  395. package/src/astro/storage/adapters.ts +74 -0
  396. package/src/astro/storage/index.ts +19 -0
  397. package/src/astro/storage/types.ts +60 -0
  398. package/src/astro/types.ts +346 -0
  399. package/src/auth/api-tokens.ts +25 -0
  400. package/src/auth/challenge-store.ts +80 -0
  401. package/src/auth/mode.ts +96 -0
  402. package/src/auth/oauth-state-store.ts +96 -0
  403. package/src/auth/passkey-config.ts +27 -0
  404. package/src/auth/rate-limit.ts +158 -0
  405. package/src/auth/scopes.ts +33 -0
  406. package/src/auth/types.ts +104 -0
  407. package/src/aws-sdk.d.ts +100 -0
  408. package/src/bylines/index.ts +237 -0
  409. package/src/cleanup.ts +153 -0
  410. package/src/cli/client-factory.ts +100 -0
  411. package/src/cli/commands/auth.ts +46 -0
  412. package/src/cli/commands/bundle-utils.ts +247 -0
  413. package/src/cli/commands/bundle.ts +609 -0
  414. package/src/cli/commands/content.ts +442 -0
  415. package/src/cli/commands/dev.ts +191 -0
  416. package/src/cli/commands/doctor.ts +211 -0
  417. package/src/cli/commands/export-seed.ts +630 -0
  418. package/src/cli/commands/import/wordpress.ts +1056 -0
  419. package/src/cli/commands/init.ts +192 -0
  420. package/src/cli/commands/login.ts +547 -0
  421. package/src/cli/commands/media.ts +165 -0
  422. package/src/cli/commands/menu.ts +67 -0
  423. package/src/cli/commands/plugin-init.ts +291 -0
  424. package/src/cli/commands/plugin-validate.ts +31 -0
  425. package/src/cli/commands/plugin.ts +33 -0
  426. package/src/cli/commands/publish.ts +699 -0
  427. package/src/cli/commands/schema.ts +233 -0
  428. package/src/cli/commands/search-cmd.ts +54 -0
  429. package/src/cli/commands/seed.ts +288 -0
  430. package/src/cli/commands/taxonomy.ts +128 -0
  431. package/src/cli/commands/types.ts +68 -0
  432. package/src/cli/credentials.ts +236 -0
  433. package/src/cli/index.ts +70 -0
  434. package/src/cli/output.ts +75 -0
  435. package/src/cli/wxr/parser.ts +969 -0
  436. package/src/client/cf-access.ts +193 -0
  437. package/src/client/index.ts +854 -0
  438. package/src/client/portable-text.ts +413 -0
  439. package/src/client/transport.ts +200 -0
  440. package/src/comments/moderator.ts +46 -0
  441. package/src/comments/notifications.ts +144 -0
  442. package/src/comments/query.ts +105 -0
  443. package/src/comments/service.ts +213 -0
  444. package/src/components/Break.astro +45 -0
  445. package/src/components/Button.astro +71 -0
  446. package/src/components/Buttons.astro +49 -0
  447. package/src/components/Code.astro +59 -0
  448. package/src/components/Columns.astro +59 -0
  449. package/src/components/CommentForm.astro +315 -0
  450. package/src/components/Comments.astro +232 -0
  451. package/src/components/Cover.astro +128 -0
  452. package/src/components/EmDashBodyEnd.astro +32 -0
  453. package/src/components/EmDashBodyStart.astro +32 -0
  454. package/src/components/EmDashHead.astro +53 -0
  455. package/src/components/EmDashImage.astro +178 -0
  456. package/src/components/EmDashMedia.astro +167 -0
  457. package/src/components/Embed.astro +128 -0
  458. package/src/components/File.astro +122 -0
  459. package/src/components/Gallery.astro +93 -0
  460. package/src/components/HtmlBlock.astro +33 -0
  461. package/src/components/Image.astro +178 -0
  462. package/src/components/InlineEditor.astro +27 -0
  463. package/src/components/InlinePortableTextEditor.tsx +1905 -0
  464. package/src/components/LiveSearch.astro +614 -0
  465. package/src/components/PortableText.astro +51 -0
  466. package/src/components/Pullquote.astro +51 -0
  467. package/src/components/Table.astro +108 -0
  468. package/src/components/WidgetArea.astro +22 -0
  469. package/src/components/WidgetRenderer.astro +72 -0
  470. package/src/components/index.ts +116 -0
  471. package/src/components/marks/Link.astro +31 -0
  472. package/src/components/marks/StrikeThrough.astro +7 -0
  473. package/src/components/marks/Subscript.astro +7 -0
  474. package/src/components/marks/Superscript.astro +7 -0
  475. package/src/components/marks/Underline.astro +7 -0
  476. package/src/components/widgets/Archives.astro +65 -0
  477. package/src/components/widgets/Categories.astro +35 -0
  478. package/src/components/widgets/RecentPosts.astro +51 -0
  479. package/src/components/widgets/Search.astro +18 -0
  480. package/src/components/widgets/Tags.astro +38 -0
  481. package/src/content/converters/index.ts +9 -0
  482. package/src/content/converters/portable-text-to-prosemirror.ts +385 -0
  483. package/src/content/converters/prosemirror-to-portable-text.ts +413 -0
  484. package/src/content/converters/types.ts +120 -0
  485. package/src/content/index.ts +5 -0
  486. package/src/database/connection.ts +67 -0
  487. package/src/database/dialect-helpers.ts +138 -0
  488. package/src/database/index.ts +5 -0
  489. package/src/database/migrations/001_initial.ts +136 -0
  490. package/src/database/migrations/002_media_status.ts +26 -0
  491. package/src/database/migrations/003_schema_registry.ts +79 -0
  492. package/src/database/migrations/004_plugins.ts +62 -0
  493. package/src/database/migrations/005_menus.ts +67 -0
  494. package/src/database/migrations/006_taxonomy_defs.ts +51 -0
  495. package/src/database/migrations/007_widgets.ts +42 -0
  496. package/src/database/migrations/008_auth.ts +194 -0
  497. package/src/database/migrations/009_user_disabled.ts +27 -0
  498. package/src/database/migrations/011_sections.ts +65 -0
  499. package/src/database/migrations/012_search.ts +25 -0
  500. package/src/database/migrations/013_scheduled_publishing.ts +51 -0
  501. package/src/database/migrations/014_draft_revisions.ts +72 -0
  502. package/src/database/migrations/015_indexes.ts +82 -0
  503. package/src/database/migrations/016_api_tokens.ts +89 -0
  504. package/src/database/migrations/017_authorization_codes.ts +45 -0
  505. package/src/database/migrations/018_seo.ts +56 -0
  506. package/src/database/migrations/019_i18n.ts +618 -0
  507. package/src/database/migrations/020_collection_url_pattern.ts +23 -0
  508. package/src/database/migrations/021_remove_section_categories.ts +43 -0
  509. package/src/database/migrations/022_marketplace_plugin_state.ts +46 -0
  510. package/src/database/migrations/023_plugin_metadata.ts +33 -0
  511. package/src/database/migrations/024_media_placeholders.ts +32 -0
  512. package/src/database/migrations/025_oauth_clients.ts +28 -0
  513. package/src/database/migrations/026_cron_tasks.ts +49 -0
  514. package/src/database/migrations/027_comments.ts +87 -0
  515. package/src/database/migrations/028_drop_author_url.ts +9 -0
  516. package/src/database/migrations/029_redirects.ts +67 -0
  517. package/src/database/migrations/030_widen_scheduled_index.ts +48 -0
  518. package/src/database/migrations/031_bylines.ts +90 -0
  519. package/src/database/migrations/032_rate_limits.ts +42 -0
  520. package/src/database/migrations/runner.ts +170 -0
  521. package/src/database/repositories/audit.ts +294 -0
  522. package/src/database/repositories/byline.ts +387 -0
  523. package/src/database/repositories/comment.ts +458 -0
  524. package/src/database/repositories/content.ts +1144 -0
  525. package/src/database/repositories/index.ts +30 -0
  526. package/src/database/repositories/media.ts +347 -0
  527. package/src/database/repositories/options.ts +150 -0
  528. package/src/database/repositories/plugin-storage.ts +373 -0
  529. package/src/database/repositories/redirect.ts +480 -0
  530. package/src/database/repositories/revision.ts +200 -0
  531. package/src/database/repositories/seo.ts +176 -0
  532. package/src/database/repositories/taxonomy.ts +294 -0
  533. package/src/database/repositories/types.ts +132 -0
  534. package/src/database/repositories/user.ts +258 -0
  535. package/src/database/transaction.ts +54 -0
  536. package/src/database/types.ts +501 -0
  537. package/src/database/validate.ts +138 -0
  538. package/src/db/adapters.ts +125 -0
  539. package/src/db/index.ts +37 -0
  540. package/src/db/libsql.ts +23 -0
  541. package/src/db/postgres.ts +30 -0
  542. package/src/db/sqlite.ts +27 -0
  543. package/src/emdash-runtime.ts +2096 -0
  544. package/src/fields/boolean.ts +34 -0
  545. package/src/fields/datetime.ts +44 -0
  546. package/src/fields/file.ts +41 -0
  547. package/src/fields/image.ts +34 -0
  548. package/src/fields/index.ts +42 -0
  549. package/src/fields/integer.ts +50 -0
  550. package/src/fields/json.ts +37 -0
  551. package/src/fields/multiselect.ts +48 -0
  552. package/src/fields/number.ts +52 -0
  553. package/src/fields/portable-text.ts +33 -0
  554. package/src/fields/reference.ts +29 -0
  555. package/src/fields/richtext.ts +31 -0
  556. package/src/fields/select.ts +46 -0
  557. package/src/fields/slug.ts +38 -0
  558. package/src/fields/text.ts +55 -0
  559. package/src/fields/textarea.ts +52 -0
  560. package/src/fields/types.ts +64 -0
  561. package/src/i18n/config.ts +68 -0
  562. package/src/import/index.ts +90 -0
  563. package/src/import/menus.ts +436 -0
  564. package/src/import/registry.ts +111 -0
  565. package/src/import/sections.ts +103 -0
  566. package/src/import/settings.ts +281 -0
  567. package/src/import/sources/wordpress-plugin.ts +641 -0
  568. package/src/import/sources/wordpress-rest.ts +191 -0
  569. package/src/import/sources/wxr.ts +330 -0
  570. package/src/import/ssrf.ts +260 -0
  571. package/src/import/types.ts +418 -0
  572. package/src/import/utils.ts +412 -0
  573. package/src/index.ts +481 -0
  574. package/src/loader.ts +770 -0
  575. package/src/mcp/server.ts +1463 -0
  576. package/src/media/index.ts +32 -0
  577. package/src/media/local-runtime.ts +213 -0
  578. package/src/media/local.ts +46 -0
  579. package/src/media/normalize.ts +190 -0
  580. package/src/media/placeholder.ts +150 -0
  581. package/src/media/provider-loader.ts +78 -0
  582. package/src/media/types.ts +279 -0
  583. package/src/menus/index.ts +324 -0
  584. package/src/menus/types.ts +112 -0
  585. package/src/page/context.ts +93 -0
  586. package/src/page/fragments.ts +89 -0
  587. package/src/page/index.ts +58 -0
  588. package/src/page/jsonld.ts +94 -0
  589. package/src/page/metadata.ts +185 -0
  590. package/src/page/seo-contributions.ts +136 -0
  591. package/src/plugin-utils.ts +80 -0
  592. package/src/plugins/adapt-sandbox-entry.ts +207 -0
  593. package/src/plugins/context.ts +833 -0
  594. package/src/plugins/cron.ts +361 -0
  595. package/src/plugins/define-plugin.ts +259 -0
  596. package/src/plugins/email-console.ts +73 -0
  597. package/src/plugins/email.ts +209 -0
  598. package/src/plugins/hooks.ts +1273 -0
  599. package/src/plugins/index.ts +193 -0
  600. package/src/plugins/manager.ts +595 -0
  601. package/src/plugins/manifest-schema.ts +230 -0
  602. package/src/plugins/marketplace.ts +460 -0
  603. package/src/plugins/request-meta.ts +139 -0
  604. package/src/plugins/routes.ts +302 -0
  605. package/src/plugins/sandbox/index.ts +18 -0
  606. package/src/plugins/sandbox/noop.ts +76 -0
  607. package/src/plugins/sandbox/types.ts +173 -0
  608. package/src/plugins/scheduler/node.ts +122 -0
  609. package/src/plugins/scheduler/piggyback.ts +71 -0
  610. package/src/plugins/scheduler/types.ts +27 -0
  611. package/src/plugins/state.ts +208 -0
  612. package/src/plugins/storage-indexes.ts +326 -0
  613. package/src/plugins/storage-query.ts +240 -0
  614. package/src/plugins/types.ts +1284 -0
  615. package/src/preview/helpers.ts +27 -0
  616. package/src/preview/index.ts +40 -0
  617. package/src/preview/tokens.ts +279 -0
  618. package/src/preview/urls.ts +118 -0
  619. package/src/query.ts +674 -0
  620. package/src/redirects/patterns.ts +224 -0
  621. package/src/request-context.ts +67 -0
  622. package/src/runtime.ts +21 -0
  623. package/src/schema/index.ts +29 -0
  624. package/src/schema/query.ts +44 -0
  625. package/src/schema/registry.ts +965 -0
  626. package/src/schema/types.ts +276 -0
  627. package/src/schema/zod-generator.ts +413 -0
  628. package/src/search/fts-manager.ts +452 -0
  629. package/src/search/index.ts +26 -0
  630. package/src/search/query.ts +396 -0
  631. package/src/search/text-extraction.ts +162 -0
  632. package/src/search/types.ts +114 -0
  633. package/src/sections/index.ts +226 -0
  634. package/src/sections/types.ts +86 -0
  635. package/src/seed/apply.ts +1141 -0
  636. package/src/seed/default.ts +86 -0
  637. package/src/seed/index.ts +28 -0
  638. package/src/seed/load.ts +35 -0
  639. package/src/seed/types.ts +341 -0
  640. package/src/seed/validate.ts +642 -0
  641. package/src/seo/index.ts +179 -0
  642. package/src/settings/index.ts +203 -0
  643. package/src/settings/types.ts +58 -0
  644. package/src/storage/index.ts +28 -0
  645. package/src/storage/local.ts +253 -0
  646. package/src/storage/s3.ts +271 -0
  647. package/src/storage/types.ts +204 -0
  648. package/src/taxonomies/index.ts +309 -0
  649. package/src/taxonomies/types.ts +61 -0
  650. package/src/ui.ts +75 -0
  651. package/src/utils/base64.ts +73 -0
  652. package/src/utils/hash.ts +36 -0
  653. package/src/utils/sanitize.ts +20 -0
  654. package/src/utils/slugify.ts +29 -0
  655. package/src/utils/url.ts +48 -0
  656. package/src/virtual-modules.d.ts +111 -0
  657. package/src/visual-editing/editable.ts +108 -0
  658. package/src/visual-editing/toolbar.ts +1229 -0
  659. package/src/widgets/components.ts +105 -0
  660. package/src/widgets/index.ts +131 -0
  661. package/src/widgets/types.ts +81 -0
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Restore content from trash endpoint - injected by EmDash integration
3
+ *
4
+ * POST /_emdash/api/content/{collection}/{id}/restore - Restore from trash
5
+ */
6
+
7
+ import type { APIRoute } from "astro";
8
+
9
+ import { requireOwnerPerm } from "#api/authorize.js";
10
+ import { apiError, mapErrorStatus, unwrapResult } from "#api/error.js";
11
+
12
+ export const prerender = false;
13
+
14
+ export const POST: APIRoute = async ({ params, locals, cache }) => {
15
+ const { emdash, user } = locals;
16
+ const collection = params.collection!;
17
+ const id = params.id!;
18
+
19
+ if (!emdash?.handleContentRestore || !emdash?.handleContentGetIncludingTrashed) {
20
+ return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
21
+ }
22
+
23
+ // Fetch item including trashed items to check ownership
24
+ const existing = await emdash.handleContentGetIncludingTrashed(collection, id);
25
+ if (!existing.success) {
26
+ return apiError(
27
+ existing.error?.code ?? "UNKNOWN_ERROR",
28
+ existing.error?.message ?? "Unknown error",
29
+ mapErrorStatus(existing.error?.code),
30
+ );
31
+ }
32
+ const existingData =
33
+ existing.data && typeof existing.data === "object"
34
+ ? // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- handler returns unknown data; narrowed by typeof check above
35
+ (existing.data as Record<string, unknown>)
36
+ : undefined;
37
+ // Handler returns { item, _rev } — extract the item for ownership check
38
+ const existingItem =
39
+ existingData?.item && typeof existingData.item === "object"
40
+ ? // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- narrowed by typeof check above
41
+ (existingData.item as Record<string, unknown>)
42
+ : existingData;
43
+ const authorId = typeof existingItem?.authorId === "string" ? existingItem.authorId : "";
44
+ const denied = requireOwnerPerm(user, authorId, "content:edit_own", "content:edit_any");
45
+ if (denied) return denied;
46
+
47
+ const result = await emdash.handleContentRestore(collection, id);
48
+
49
+ if (!result.success) return unwrapResult(result);
50
+
51
+ if (cache.enabled) await cache.invalidate({ tags: [collection, id] });
52
+
53
+ return unwrapResult(result);
54
+ };
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Revisions API endpoint - injected by EmDash integration
3
+ *
4
+ * GET /_emdash/api/content/{collection}/{id}/revisions - List revisions
5
+ */
6
+
7
+ import type { APIRoute } from "astro";
8
+
9
+ import { requirePerm } from "#api/authorize.js";
10
+ import { apiError, unwrapResult } from "#api/error.js";
11
+
12
+ export const prerender = false;
13
+
14
+ export const GET: APIRoute = async ({ params, url, locals }) => {
15
+ const { emdash, user } = locals;
16
+ const denied = requirePerm(user, "content:read");
17
+ if (denied) return denied;
18
+ const collection = params.collection!;
19
+ const id = params.id!;
20
+
21
+ if (!emdash?.handleRevisionList) {
22
+ return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
23
+ }
24
+
25
+ const limit = url.searchParams.get("limit");
26
+ const result = await emdash.handleRevisionList(collection, id, {
27
+ limit: limit ? parseInt(limit, 10) : undefined,
28
+ });
29
+
30
+ return unwrapResult(result);
31
+ };
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Schedule content for future publishing - injected by EmDash integration
3
+ *
4
+ * POST /_emdash/api/content/{collection}/{id}/schedule - Schedule for publishing
5
+ * DELETE /_emdash/api/content/{collection}/{id}/schedule - Unschedule (clear scheduled time)
6
+ */
7
+
8
+ import type { APIRoute } from "astro";
9
+
10
+ import { requireOwnerPerm } from "#api/authorize.js";
11
+ import { apiError, mapErrorStatus, unwrapResult } from "#api/error.js";
12
+ import { parseBody, isParseError } from "#api/parse.js";
13
+ import { contentScheduleBody } from "#api/schemas.js";
14
+
15
+ export const prerender = false;
16
+
17
+ /**
18
+ * Extract author ID from a content item response (shared by POST and DELETE).
19
+ */
20
+ function extractOwnership(data: unknown): { authorId: string; resolvedId: string | undefined } {
21
+ const obj =
22
+ data && typeof data === "object"
23
+ ? // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- handler returns unknown; narrowed by typeof
24
+ (data as Record<string, unknown>)
25
+ : undefined;
26
+ const item =
27
+ obj?.item && typeof obj.item === "object"
28
+ ? // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- narrowed by typeof
29
+ (obj.item as Record<string, unknown>)
30
+ : obj;
31
+ return {
32
+ authorId: typeof item?.authorId === "string" ? item.authorId : "",
33
+ resolvedId: typeof item?.id === "string" ? item.id : undefined,
34
+ };
35
+ }
36
+
37
+ export const POST: APIRoute = async ({ params, request, locals, cache }) => {
38
+ const { emdash, user } = locals;
39
+ const collection = params.collection!;
40
+ const id = params.id!;
41
+ const body = await parseBody(request, contentScheduleBody);
42
+ if (isParseError(body)) return body;
43
+
44
+ if (!emdash?.handleContentSchedule || !emdash?.handleContentGet) {
45
+ return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
46
+ }
47
+
48
+ // Fetch item to check ownership
49
+ const existing = await emdash.handleContentGet(collection, id);
50
+ if (!existing.success) {
51
+ return apiError(
52
+ existing.error?.code ?? "UNKNOWN_ERROR",
53
+ existing.error?.message ?? "Unknown error",
54
+ mapErrorStatus(existing.error?.code),
55
+ );
56
+ }
57
+
58
+ const { authorId, resolvedId } = extractOwnership(existing.data);
59
+ const denied = requireOwnerPerm(user, authorId, "content:publish_own", "content:publish_any");
60
+ if (denied) return denied;
61
+
62
+ const result = await emdash.handleContentSchedule(
63
+ collection,
64
+ resolvedId ?? id,
65
+ body.scheduledAt,
66
+ );
67
+
68
+ if (!result.success) return unwrapResult(result);
69
+
70
+ if (cache.enabled) await cache.invalidate({ tags: [collection, resolvedId ?? id] });
71
+
72
+ return unwrapResult(result);
73
+ };
74
+
75
+ export const DELETE: APIRoute = async ({ params, locals, cache }) => {
76
+ const { emdash, user } = locals;
77
+ const collection = params.collection!;
78
+ const id = params.id!;
79
+
80
+ if (!emdash?.handleContentUnschedule || !emdash?.handleContentGet) {
81
+ return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
82
+ }
83
+
84
+ // Fetch item to check ownership
85
+ const existing = await emdash.handleContentGet(collection, id);
86
+ if (!existing.success) {
87
+ return apiError(
88
+ existing.error?.code ?? "UNKNOWN_ERROR",
89
+ existing.error?.message ?? "Unknown error",
90
+ mapErrorStatus(existing.error?.code),
91
+ );
92
+ }
93
+
94
+ const { authorId, resolvedId } = extractOwnership(existing.data);
95
+ const denied = requireOwnerPerm(user, authorId, "content:publish_own", "content:publish_any");
96
+ if (denied) return denied;
97
+
98
+ const result = await emdash.handleContentUnschedule(collection, resolvedId ?? id);
99
+
100
+ if (!result.success) return unwrapResult(result);
101
+
102
+ if (cache.enabled) await cache.invalidate({ tags: [collection, resolvedId ?? id] });
103
+
104
+ return unwrapResult(result);
105
+ };
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Content-taxonomy association endpoint
3
+ *
4
+ * GET /_emdash/api/content/:collection/:id/terms/:taxonomy - Get terms for an entry
5
+ * POST /_emdash/api/content/:collection/:id/terms/:taxonomy - Set terms for an entry
6
+ */
7
+
8
+ import type { APIRoute } from "astro";
9
+
10
+ import { requirePerm, requireOwnerPerm } from "#api/authorize.js";
11
+ import { apiError, apiSuccess, handleError, requireDb } from "#api/error.js";
12
+ import { parseBody, isParseError } from "#api/parse.js";
13
+ import { contentTermsBody } from "#api/schemas.js";
14
+ import { TaxonomyRepository } from "#db/repositories/taxonomy.js";
15
+
16
+ export const prerender = false;
17
+
18
+ /**
19
+ * Get terms assigned to an entry
20
+ */
21
+ export const GET: APIRoute = async ({ params, locals }) => {
22
+ const { emdash, user } = locals;
23
+ const { collection, id, taxonomy } = params;
24
+
25
+ const denied = requirePerm(user, "content:read");
26
+ if (denied) return denied;
27
+
28
+ if (!collection || !id || !taxonomy) {
29
+ return apiError("VALIDATION_ERROR", "Collection, id, and taxonomy required", 400);
30
+ }
31
+
32
+ const dbErr = requireDb(emdash?.db);
33
+ if (dbErr) return dbErr;
34
+
35
+ try {
36
+ const repo = new TaxonomyRepository(emdash!.db);
37
+ const terms = await repo.getTermsForEntry(collection, id, taxonomy);
38
+
39
+ return apiSuccess({
40
+ terms: terms.map((t) => ({
41
+ id: t.id,
42
+ name: t.name,
43
+ slug: t.slug,
44
+ label: t.label,
45
+ parentId: t.parentId,
46
+ })),
47
+ });
48
+ } catch (error) {
49
+ return handleError(error, "Failed to get entry terms", "TERMS_GET_ERROR");
50
+ }
51
+ };
52
+
53
+ /**
54
+ * Set terms for an entry (replaces existing)
55
+ */
56
+ export const POST: APIRoute = async ({ params, request, locals }) => {
57
+ const { emdash, user } = locals;
58
+ const { collection, id, taxonomy } = params;
59
+
60
+ if (!collection || !id || !taxonomy) {
61
+ return apiError("VALIDATION_ERROR", "Collection, id, and taxonomy required", 400);
62
+ }
63
+
64
+ const denied = requirePerm(user, "content:edit_own");
65
+ if (denied) return denied;
66
+
67
+ const dbErr = requireDb(emdash?.db);
68
+ if (dbErr) return dbErr;
69
+
70
+ if (!emdash!.handleContentGet) {
71
+ return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
72
+ }
73
+
74
+ // Verify the content exists before modifying its terms
75
+ const existing = await emdash!.handleContentGet(collection, id);
76
+ if (!existing.success) {
77
+ return apiError(
78
+ existing.error?.code ?? "NOT_FOUND",
79
+ existing.error?.message ?? "Content not found",
80
+ existing.error?.code === "NOT_FOUND" ? 404 : 500,
81
+ );
82
+ }
83
+
84
+ // Check ownership for edit permission
85
+ const existingData =
86
+ existing.data && typeof existing.data === "object"
87
+ ? // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- handler returns unknown data; narrowed by typeof check above
88
+ (existing.data as Record<string, unknown>)
89
+ : undefined;
90
+ // Handler returns { item, _rev } — extract the item for ownership check
91
+ const existingItem =
92
+ existingData?.item && typeof existingData.item === "object"
93
+ ? // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- narrowed by typeof check above
94
+ (existingData.item as Record<string, unknown>)
95
+ : existingData;
96
+ const authorId = typeof existingItem?.authorId === "string" ? existingItem.authorId : "";
97
+ const editDenied = requireOwnerPerm(user, authorId, "content:edit_own", "content:edit_any");
98
+ if (editDenied) return editDenied;
99
+
100
+ try {
101
+ const body = await parseBody(request, contentTermsBody);
102
+ if (isParseError(body)) return body;
103
+ const { termIds } = body;
104
+
105
+ const repo = new TaxonomyRepository(emdash!.db);
106
+
107
+ // Verify all term IDs exist and belong to the correct taxonomy
108
+ for (const termId of termIds) {
109
+ const term = await repo.findById(termId);
110
+ if (!term) {
111
+ return apiError("NOT_FOUND", `Term ID '${termId}' not found`, 404);
112
+ }
113
+ if (term.name !== taxonomy) {
114
+ return apiError(
115
+ "VALIDATION_ERROR",
116
+ `Term ID '${termId}' does not belong to taxonomy '${taxonomy}'`,
117
+ 400,
118
+ );
119
+ }
120
+ }
121
+
122
+ // Set the terms (replaces existing)
123
+ await repo.setTermsForEntry(collection, id, taxonomy, termIds);
124
+
125
+ // Get the updated terms
126
+ const terms = await repo.getTermsForEntry(collection, id, taxonomy);
127
+
128
+ return apiSuccess({
129
+ terms: terms.map((t) => ({
130
+ id: t.id,
131
+ name: t.name,
132
+ slug: t.slug,
133
+ label: t.label,
134
+ parentId: t.parentId,
135
+ })),
136
+ });
137
+ } catch (error) {
138
+ return handleError(error, "Failed to set entry terms", "TERMS_SET_ERROR");
139
+ }
140
+ };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Content translations endpoint
3
+ *
4
+ * GET /_emdash/api/content/{collection}/{id}/translations
5
+ *
6
+ * Returns all locale variants linked to the same translation group.
7
+ */
8
+
9
+ import type { APIRoute } from "astro";
10
+
11
+ import { requirePerm } from "#api/authorize.js";
12
+ import { apiError, unwrapResult } from "#api/error.js";
13
+
14
+ export const prerender = false;
15
+
16
+ export const GET: APIRoute = async ({ params, locals }) => {
17
+ const { emdash, user } = locals;
18
+ const denied = requirePerm(user, "content:read");
19
+ if (denied) return denied;
20
+ const collection = params.collection!;
21
+ const id = params.id!;
22
+
23
+ if (!emdash?.handleContentTranslations) {
24
+ return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
25
+ }
26
+
27
+ const result = await emdash.handleContentTranslations(collection, id);
28
+
29
+ return unwrapResult(result);
30
+ };
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Unpublish content - removes from public view, preserves draft
3
+ *
4
+ * POST /_emdash/api/content/{collection}/{id}/unpublish
5
+ */
6
+
7
+ import type { APIRoute } from "astro";
8
+
9
+ import { requireOwnerPerm } from "#api/authorize.js";
10
+ import { apiError, mapErrorStatus, unwrapResult } from "#api/error.js";
11
+
12
+ export const prerender = false;
13
+
14
+ export const POST: APIRoute = async ({ params, locals, cache }) => {
15
+ const { emdash, user } = locals;
16
+ const collection = params.collection!;
17
+ const id = params.id!;
18
+
19
+ if (!emdash?.handleContentUnpublish || !emdash?.handleContentGet) {
20
+ return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
21
+ }
22
+
23
+ // Fetch item to check ownership
24
+ const existing = await emdash.handleContentGet(collection, id);
25
+ if (!existing.success) {
26
+ return apiError(
27
+ existing.error?.code ?? "UNKNOWN_ERROR",
28
+ existing.error?.message ?? "Unknown error",
29
+ mapErrorStatus(existing.error?.code),
30
+ );
31
+ }
32
+
33
+ const existingData =
34
+ existing.data && typeof existing.data === "object"
35
+ ? // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- handler returns unknown data; narrowed by typeof check above
36
+ (existing.data as Record<string, unknown>)
37
+ : undefined;
38
+ const existingItem =
39
+ existingData?.item && typeof existingData.item === "object"
40
+ ? // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- narrowed by typeof check above
41
+ (existingData.item as Record<string, unknown>)
42
+ : existingData;
43
+ const authorId = typeof existingItem?.authorId === "string" ? existingItem.authorId : "";
44
+ const denied = requireOwnerPerm(user, authorId, "content:publish_own", "content:publish_any");
45
+ if (denied) return denied;
46
+
47
+ const resolvedId = typeof existingItem?.id === "string" ? existingItem.id : id;
48
+
49
+ const result = await emdash.handleContentUnpublish(collection, resolvedId);
50
+
51
+ if (!result.success) return unwrapResult(result);
52
+
53
+ if (cache.enabled) await cache.invalidate({ tags: [collection, resolvedId] });
54
+
55
+ return unwrapResult(result);
56
+ };
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Single content item endpoints - injected by EmDash integration
3
+ *
4
+ * GET /_emdash/api/content/{collection}/{id} - Get content
5
+ * PUT /_emdash/api/content/{collection}/{id} - Update content
6
+ * DELETE /_emdash/api/content/{collection}/{id} - Delete content
7
+ */
8
+
9
+ import { hasPermission, type Permission } from "@emdash-cms/auth";
10
+ import type { APIRoute } from "astro";
11
+
12
+ import { requirePerm, requireOwnerPerm } from "#api/authorize.js";
13
+ import { apiError, mapErrorStatus, unwrapResult } from "#api/error.js";
14
+ import { parseBody, isParseError } from "#api/parse.js";
15
+ import { contentUpdateBody } from "#api/schemas.js";
16
+
17
+ export const prerender = false;
18
+
19
+ export const GET: APIRoute = async ({ params, url, locals }) => {
20
+ const { emdash, user } = locals;
21
+ const denied = requirePerm(user, "content:read");
22
+ if (denied) return denied;
23
+ const collection = params.collection!;
24
+ const id = params.id!;
25
+ const locale = url.searchParams.get("locale") || undefined;
26
+
27
+ if (!emdash?.handleContentGet) {
28
+ return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
29
+ }
30
+
31
+ const result = await emdash.handleContentGet(collection, id, locale);
32
+
33
+ return unwrapResult(result);
34
+ };
35
+
36
+ export const PUT: APIRoute = async ({ params, request, locals, cache }) => {
37
+ const { emdash, user } = locals;
38
+ const collection = params.collection!;
39
+ const id = params.id!;
40
+ const body = await parseBody(request, contentUpdateBody);
41
+ if (isParseError(body)) return body;
42
+
43
+ if (!emdash?.handleContentUpdate || !emdash?.handleContentGet) {
44
+ return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
45
+ }
46
+
47
+ // Fetch item to check ownership
48
+ const existing = await emdash.handleContentGet(collection, id);
49
+ if (!existing.success) {
50
+ return apiError(
51
+ existing.error?.code ?? "UNKNOWN_ERROR",
52
+ existing.error?.message ?? "Unknown error",
53
+ mapErrorStatus(existing.error?.code),
54
+ );
55
+ }
56
+
57
+ const existingData =
58
+ existing.data && typeof existing.data === "object"
59
+ ? // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- handler returns unknown data; narrowed by typeof check above
60
+ (existing.data as Record<string, unknown>)
61
+ : undefined;
62
+ // Handler returns { item, _rev } — extract the item for ownership and ID resolution
63
+ const existingItem =
64
+ existingData?.item && typeof existingData.item === "object"
65
+ ? // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- narrowed by typeof check above
66
+ (existingData.item as Record<string, unknown>)
67
+ : existingData;
68
+ const authorId = typeof existingItem?.authorId === "string" ? existingItem.authorId : "";
69
+ const editDenied = requireOwnerPerm(user, authorId, "content:edit_own", "content:edit_any");
70
+ if (editDenied) return editDenied;
71
+
72
+ // Use the resolved ID (handles slug → ID resolution)
73
+ const resolvedId = typeof existingItem?.id === "string" ? existingItem.id : id;
74
+
75
+ // Only allow authorId changes if user has content:edit_any permission (editor+)
76
+ const canChangeAuthor =
77
+ body.authorId !== undefined && user && hasPermission(user, "content:edit_any" as Permission);
78
+ const updateBody = canChangeAuthor ? body : { ...body, authorId: undefined };
79
+
80
+ // Pass _rev through for optimistic concurrency validation
81
+ const result = await emdash.handleContentUpdate(collection, resolvedId, {
82
+ ...updateBody,
83
+ _rev: body._rev,
84
+ });
85
+
86
+ if (!result.success) return unwrapResult(result);
87
+
88
+ if (cache.enabled) await cache.invalidate({ tags: [collection, resolvedId] });
89
+
90
+ return unwrapResult(result);
91
+ };
92
+
93
+ export const DELETE: APIRoute = async ({ params, locals, cache }) => {
94
+ const { emdash, user } = locals;
95
+ const collection = params.collection!;
96
+ const id = params.id!;
97
+
98
+ if (!emdash?.handleContentDelete || !emdash?.handleContentGet) {
99
+ return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
100
+ }
101
+
102
+ // Fetch item to check ownership
103
+ const existing = await emdash.handleContentGet(collection, id);
104
+ if (!existing.success) {
105
+ return apiError(
106
+ existing.error?.code ?? "UNKNOWN_ERROR",
107
+ existing.error?.message ?? "Unknown error",
108
+ mapErrorStatus(existing.error?.code),
109
+ );
110
+ }
111
+
112
+ const deleteData =
113
+ existing.data && typeof existing.data === "object"
114
+ ? // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- handler returns unknown data; narrowed by typeof check above
115
+ (existing.data as Record<string, unknown>)
116
+ : undefined;
117
+ // Handler returns { item, _rev } — extract the item for ownership and ID resolution
118
+ const deleteItem =
119
+ deleteData?.item && typeof deleteData.item === "object"
120
+ ? // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- narrowed by typeof check above
121
+ (deleteData.item as Record<string, unknown>)
122
+ : deleteData;
123
+ const authorId = typeof deleteItem?.authorId === "string" ? deleteItem.authorId : "";
124
+ const deleteDenied = requireOwnerPerm(user, authorId, "content:delete_own", "content:delete_any");
125
+ if (deleteDenied) return deleteDenied;
126
+
127
+ // Use the resolved ID (handles slug → ID resolution)
128
+ const resolvedId = typeof deleteItem?.id === "string" ? deleteItem.id : id;
129
+
130
+ const result = await emdash.handleContentDelete(collection, resolvedId);
131
+
132
+ if (!result.success) return unwrapResult(result);
133
+
134
+ if (cache.enabled) await cache.invalidate({ tags: [collection, resolvedId] });
135
+
136
+ return unwrapResult(result);
137
+ };
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Content list and create endpoints - injected by EmDash integration
3
+ *
4
+ * GET /_emdash/api/content/{collection} - List content
5
+ * POST /_emdash/api/content/{collection} - Create content
6
+ */
7
+
8
+ import type { APIRoute } from "astro";
9
+
10
+ import { requirePerm } from "#api/authorize.js";
11
+ import { apiError, unwrapResult } from "#api/error.js";
12
+ import { parseBody, parseQuery, isParseError } from "#api/parse.js";
13
+ import { contentListQuery, contentCreateBody } from "#api/schemas.js";
14
+
15
+ export const prerender = false;
16
+
17
+ export const GET: APIRoute = async ({ params, url, locals }) => {
18
+ const { emdash, user } = locals;
19
+ const denied = requirePerm(user, "content:read");
20
+ if (denied) return denied;
21
+ const collection = params.collection!;
22
+ const query = parseQuery(url, contentListQuery);
23
+ if (isParseError(query)) return query;
24
+
25
+ if (!emdash?.handleContentList) {
26
+ return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
27
+ }
28
+
29
+ const result = await emdash.handleContentList(collection, query);
30
+
31
+ return unwrapResult(result);
32
+ };
33
+
34
+ export const POST: APIRoute = async ({ params, request, locals, cache }) => {
35
+ const { emdash, user } = locals;
36
+ const denied = requirePerm(user, "content:create");
37
+ if (denied) return denied;
38
+ const collection = params.collection!;
39
+ const body = await parseBody(request, contentCreateBody);
40
+ if (isParseError(body)) return body;
41
+
42
+ if (!emdash?.handleContentCreate) {
43
+ return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
44
+ }
45
+
46
+ // Auto-set authorId to current user when creating content
47
+ const result = await emdash.handleContentCreate(collection, {
48
+ ...body,
49
+ authorId: user?.id,
50
+ locale: body.locale,
51
+ translationOf: body.translationOf,
52
+ });
53
+
54
+ if (!result.success) return unwrapResult(result);
55
+
56
+ if (cache.enabled) await cache.invalidate({ tags: [collection] });
57
+
58
+ return unwrapResult(result, 201);
59
+ };
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Trash endpoints for content collection - injected by EmDash integration
3
+ *
4
+ * GET /_emdash/api/content/{collection}/trash - List trashed items
5
+ */
6
+
7
+ import type { APIRoute } from "astro";
8
+
9
+ import { requirePerm } from "#api/authorize.js";
10
+ import { apiError, unwrapResult } from "#api/error.js";
11
+ import { parseQuery, isParseError } from "#api/parse.js";
12
+ import { contentTrashQuery } from "#api/schemas.js";
13
+
14
+ export const prerender = false;
15
+
16
+ export const GET: APIRoute = async ({ params, url, locals }) => {
17
+ const { emdash, user } = locals;
18
+ const collection = params.collection!;
19
+
20
+ const denied = requirePerm(user, "content:read");
21
+ if (denied) return denied;
22
+
23
+ if (!emdash?.handleContentListTrashed) {
24
+ return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
25
+ }
26
+
27
+ const query = parseQuery(url, contentTrashQuery);
28
+ if (isParseError(query)) return query;
29
+
30
+ const result = await emdash.handleContentListTrashed(collection, query);
31
+
32
+ return unwrapResult(result);
33
+ };
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Dashboard stats endpoint
3
+ *
4
+ * GET /_emdash/api/dashboard - Collection counts, media/user counts, recent items
5
+ */
6
+
7
+ import type { APIRoute } from "astro";
8
+
9
+ import { requirePerm } from "#api/authorize.js";
10
+ import { apiError, handleError, unwrapResult } from "#api/error.js";
11
+ import { handleDashboardStats } from "#api/handlers/dashboard.js";
12
+
13
+ export const prerender = false;
14
+
15
+ export const GET: APIRoute = async ({ locals }) => {
16
+ const { emdash, user } = locals;
17
+
18
+ const denied = requirePerm(user, "content:read");
19
+ if (denied) return denied;
20
+
21
+ if (!emdash?.db) {
22
+ return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
23
+ }
24
+
25
+ try {
26
+ const result = await handleDashboardStats(emdash.db);
27
+
28
+ return unwrapResult(result);
29
+ } catch (error) {
30
+ return handleError(error, "Failed to load dashboard", "DASHBOARD_ERROR");
31
+ }
32
+ };