emdash 0.0.0-b → 0.0.2

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 -43
  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 +1336 -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-C0hCbYnD.mjs +1412 -0
  127. package/dist/runner-C0hCbYnD.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 +684 -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 +349 -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 +335 -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 +116 -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 +115 -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 +101 -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 +58 -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 +68 -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 +697 -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 +286 -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 +170 -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 +39 -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 +249 -0
  646. package/src/storage/s3.ts +263 -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,199 @@
1
+ /**
2
+ * POST /_emdash/api/setup/dev-bypass
3
+ * GET /_emdash/api/setup/dev-bypass
4
+ *
5
+ * Development-only endpoint to bypass the setup wizard.
6
+ * Runs migrations, creates a dev admin user, and marks setup complete.
7
+ *
8
+ * ONLY available when import.meta.env.DEV is true.
9
+ *
10
+ * Usage:
11
+ * - GET with redirect: /_emdash/api/setup/dev-bypass?redirect=/_emdash/admin
12
+ * - POST for API: Returns JSON with setup info
13
+ *
14
+ * For agent/browser testing, navigate to:
15
+ * /_emdash/api/setup/dev-bypass?redirect=/_emdash/admin
16
+ */
17
+
18
+ import type { APIRoute } from "astro";
19
+
20
+ export const prerender = false;
21
+
22
+ import { ulid } from "ulidx";
23
+
24
+ import { apiError, apiSuccess, handleError } from "#api/error.js";
25
+ import { escapeHtml } from "#api/escape.js";
26
+ import { handleApiTokenCreate } from "#api/handlers/api-tokens.js";
27
+ import { isSafeRedirect } from "#api/redirect.js";
28
+ import { runMigrations } from "#db/migrations/runner.js";
29
+ import { OptionsRepository } from "#db/repositories/options.js";
30
+ import { applySeed } from "#seed/apply.js";
31
+ import { loadSeed } from "#seed/load.js";
32
+ import { validateSeed } from "#seed/validate.js";
33
+
34
+ // RBAC role levels (matching @emdash-cms/auth)
35
+ const ROLE_ADMIN = 50;
36
+
37
+ const DEV_USER_EMAIL = "dev@emdash.local";
38
+ const DEV_USER_NAME = "Dev Admin";
39
+ const DEV_SITE_TITLE = "EmDash Dev Site";
40
+
41
+ async function handleDevBypass(context: Parameters<APIRoute>[0]): Promise<Response> {
42
+ // CRITICAL: Only allow in development mode
43
+ if (!import.meta.env.DEV) {
44
+ return apiError("FORBIDDEN", "Dev bypass is only available in development mode", 403);
45
+ }
46
+
47
+ const { locals, url, session } = context;
48
+ const { emdash } = locals;
49
+
50
+ if (!emdash?.db) {
51
+ return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
52
+ }
53
+
54
+ try {
55
+ // Run migrations
56
+ const migrations = await runMigrations(emdash.db);
57
+ console.log("[setup-dev-bypass] Migrations applied:", migrations.applied);
58
+
59
+ // Apply seed (user seed or built-in default)
60
+ const seed = await loadSeed();
61
+ const validation = validateSeed(seed);
62
+ if (validation.valid) {
63
+ const seedResult = await applySeed(emdash.db, seed, {
64
+ includeContent: true,
65
+ onConflict: "skip",
66
+ storage: emdash.storage ?? undefined,
67
+ });
68
+ console.log(
69
+ `[setup-dev-bypass] Seed applied: ${seedResult.collections.created} collections, ${seedResult.fields.created} fields`,
70
+ );
71
+ }
72
+
73
+ const options = new OptionsRepository(emdash.db);
74
+
75
+ // Find or create dev user (direct DB access to avoid @emdash-cms/auth import issues in dev)
76
+ const existingUser = await emdash.db
77
+ .selectFrom("users")
78
+ .selectAll()
79
+ .where("email", "=", DEV_USER_EMAIL)
80
+ .executeTakeFirst();
81
+
82
+ let user: { id: string; email: string; name: string; role: number };
83
+ let userCreated = false;
84
+
85
+ if (!existingUser) {
86
+ const now = new Date().toISOString();
87
+ const newUser = {
88
+ id: ulid(),
89
+ email: DEV_USER_EMAIL,
90
+ name: DEV_USER_NAME,
91
+ role: ROLE_ADMIN,
92
+ email_verified: 1,
93
+ created_at: now,
94
+ updated_at: now,
95
+ };
96
+
97
+ await emdash.db.insertInto("users").values(newUser).execute();
98
+
99
+ user = {
100
+ id: newUser.id,
101
+ email: newUser.email,
102
+ name: newUser.name,
103
+ role: newUser.role,
104
+ };
105
+ userCreated = true;
106
+ console.log("[setup-dev-bypass] Created dev admin user:", user.email);
107
+ } else {
108
+ user = {
109
+ id: existingUser.id,
110
+ email: existingUser.email,
111
+ name: existingUser.name || DEV_USER_NAME,
112
+ role: existingUser.role,
113
+ };
114
+ }
115
+
116
+ // Set site title if not already set
117
+ const existingTitle = await options.get("emdash:site_title");
118
+ if (!existingTitle) {
119
+ await options.set("emdash:site_title", DEV_SITE_TITLE);
120
+ }
121
+
122
+ // Store canonical site URL (used by magic-link/recovery emails)
123
+ await options.set("emdash:site_url", url.origin);
124
+
125
+ // Mark setup complete
126
+ await options.set("emdash:setup_complete", true);
127
+
128
+ // Create session
129
+ if (session) {
130
+ session.set("user", { id: user.id });
131
+ }
132
+
133
+ // Optionally create a PAT token (?token=1) for headless/CLI testing.
134
+ let token: string | undefined;
135
+ if (url.searchParams.has("token")) {
136
+ const result = await handleApiTokenCreate(emdash.db, user.id, {
137
+ name: "dev-bypass-token",
138
+ scopes: [
139
+ "content:read",
140
+ "content:write",
141
+ "media:read",
142
+ "media:write",
143
+ "schema:read",
144
+ "schema:write",
145
+ "admin",
146
+ ],
147
+ });
148
+ if (result.success) {
149
+ token = result.data.token;
150
+ }
151
+ }
152
+
153
+ // Check for redirect parameter
154
+ const redirect = url.searchParams.get("redirect");
155
+
156
+ if (redirect) {
157
+ // Validate redirect is a safe local path (prevent open redirect via //evil.com or /\evil.com)
158
+ if (!isSafeRedirect(redirect)) {
159
+ return apiError("INVALID_REDIRECT", "Redirect must be a local path", 400);
160
+ }
161
+
162
+ // Return an HTML page with meta-refresh redirect
163
+ // This ensures the session is fully saved before redirect
164
+ const safeRedirect = escapeHtml(redirect);
165
+ const html = `<!DOCTYPE html>
166
+ <html>
167
+ <head>
168
+ <meta http-equiv="refresh" content="0;url=${safeRedirect}">
169
+ </head>
170
+ <body>Redirecting...</body>
171
+ </html>`;
172
+ return new Response(html, {
173
+ status: 200,
174
+ headers: { "Content-Type": "text/html" },
175
+ });
176
+ }
177
+
178
+ // Return JSON response
179
+ return apiSuccess({
180
+ success: true,
181
+ message: "Dev setup complete",
182
+ migrations: migrations.applied,
183
+ userCreated,
184
+ user: {
185
+ id: user.id,
186
+ email: user.email,
187
+ name: user.name,
188
+ role: user.role,
189
+ },
190
+ ...(token ? { token } : {}),
191
+ });
192
+ } catch (error) {
193
+ return handleError(error, "Dev bypass failed", "DEV_BYPASS_ERROR");
194
+ }
195
+ }
196
+
197
+ // Support both GET and POST
198
+ export const GET: APIRoute = handleDevBypass;
199
+ export const POST: APIRoute = handleDevBypass;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * POST /_emdash/api/setup/dev-reset
3
+ *
4
+ * Development-only endpoint to reset setup state for testing.
5
+ * Clears the setup_complete flag and deletes all users,
6
+ * returning the site to the pre-setup state.
7
+ *
8
+ * ONLY available when import.meta.env.DEV is true.
9
+ */
10
+
11
+ import type { APIRoute } from "astro";
12
+
13
+ export const prerender = false;
14
+
15
+ import { apiError, apiSuccess, handleError } from "#api/error.js";
16
+ import { OptionsRepository } from "#db/repositories/options.js";
17
+
18
+ export const POST: APIRoute = async ({ locals }) => {
19
+ if (!import.meta.env.DEV) {
20
+ return apiError("FORBIDDEN", "Dev reset is only available in development mode", 403);
21
+ }
22
+
23
+ const { emdash } = locals;
24
+
25
+ if (!emdash?.db) {
26
+ return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
27
+ }
28
+
29
+ try {
30
+ const options = new OptionsRepository(emdash.db);
31
+
32
+ await options.delete("emdash:setup_complete");
33
+ await options.delete("emdash:setup_state");
34
+ await emdash.db.deleteFrom("users").execute();
35
+
36
+ return apiSuccess({ success: true });
37
+ } catch (error) {
38
+ return handleError(error, "Dev reset failed", "DEV_RESET_ERROR");
39
+ }
40
+ };
@@ -0,0 +1,126 @@
1
+ /**
2
+ * POST /_emdash/api/setup
3
+ *
4
+ * Executes the setup wizard - applies seed file and marks setup complete
5
+ */
6
+
7
+ import type { APIRoute } from "astro";
8
+
9
+ export const prerender = false;
10
+
11
+ import { apiError, apiSuccess, handleError } from "#api/error.js";
12
+ import { isParseError, parseBody } from "#api/parse.js";
13
+ import { setupBody } from "#api/schemas.js";
14
+ import { getAuthMode } from "#auth/mode.js";
15
+ import { runMigrations } from "#db/migrations/runner.js";
16
+ import { OptionsRepository } from "#db/repositories/options.js";
17
+ import { applySeed } from "#seed/apply.js";
18
+ import { loadSeed } from "#seed/load.js";
19
+ import { validateSeed } from "#seed/validate.js";
20
+
21
+ export const POST: APIRoute = async ({ request, locals }) => {
22
+ const { emdash } = locals;
23
+
24
+ if (!emdash?.db) {
25
+ return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
26
+ }
27
+
28
+ try {
29
+ // Guard: reject if setup has already been completed.
30
+ // The options table may not exist on first-ever setup (pre-migration),
31
+ // so a query failure means setup hasn't run yet — allow it to proceed.
32
+ try {
33
+ const options = new OptionsRepository(emdash.db);
34
+ const setupComplete = await options.get("emdash:setup_complete");
35
+
36
+ if (setupComplete === true || setupComplete === "true") {
37
+ return apiError("ALREADY_CONFIGURED", "Setup has already been completed", 409);
38
+ }
39
+ } catch {
40
+ // Options table doesn't exist yet — first-ever setup, allow it
41
+ }
42
+
43
+ // Parse request body
44
+ const body = await parseBody(request, setupBody);
45
+ if (isParseError(body)) return body;
46
+
47
+ // 1. Run core migrations
48
+ try {
49
+ await runMigrations(emdash.db);
50
+ } catch (error) {
51
+ return handleError(error, "Failed to run database migrations", "MIGRATION_ERROR");
52
+ }
53
+
54
+ // 2. Load seed file (user seed or built-in default)
55
+ const seed = await loadSeed();
56
+
57
+ // 3. Override seed settings with form values
58
+ seed.settings = {
59
+ ...seed.settings,
60
+ title: body.title,
61
+ tagline: body.tagline,
62
+ };
63
+
64
+ // 4. Apply seed
65
+ const validation = validateSeed(seed);
66
+ if (!validation.valid) {
67
+ return apiError("INVALID_SEED", `Invalid seed file: ${validation.errors.join(", ")}`, 400);
68
+ }
69
+
70
+ let result;
71
+ try {
72
+ result = await applySeed(emdash.db, seed, {
73
+ includeContent: body.includeContent,
74
+ onConflict: "skip",
75
+ storage: emdash.storage ?? undefined,
76
+ });
77
+ } catch (error) {
78
+ return handleError(error, "Failed to apply seed", "SEED_ERROR");
79
+ }
80
+
81
+ // 5. Store setup state
82
+ // In external auth mode, mark setup complete immediately (first user to login becomes admin)
83
+ // In passkey mode, setup_complete is set after admin user is created
84
+ const authMode = getAuthMode(emdash.config);
85
+ const useExternalAuth = authMode.type === "external";
86
+
87
+ try {
88
+ const options = new OptionsRepository(emdash.db);
89
+
90
+ // Store the canonical site URL from the setup request.
91
+ // This is trusted because setup runs on the real domain.
92
+ const siteUrl = new URL(request.url).origin;
93
+ await options.set("emdash:site_url", siteUrl);
94
+
95
+ if (useExternalAuth) {
96
+ // External auth mode: mark setup complete now
97
+ // First user to log in via external provider will become admin
98
+ await options.set("emdash:setup_complete", true);
99
+ await options.set("emdash:site_title", body.title);
100
+ if (body.tagline) {
101
+ await options.set("emdash:site_tagline", body.tagline);
102
+ }
103
+ } else {
104
+ // Passkey mode: store state for next step (admin creation)
105
+ await options.set("emdash:setup_state", {
106
+ step: "site_complete",
107
+ title: body.title,
108
+ tagline: body.tagline,
109
+ });
110
+ }
111
+ } catch (error) {
112
+ console.error("Failed to save setup state:", error);
113
+ // Non-fatal - continue anyway
114
+ }
115
+
116
+ // 6. Return success with result
117
+ return apiSuccess({
118
+ success: true,
119
+ // In external auth mode, setup is complete - redirect to admin
120
+ setupComplete: useExternalAuth,
121
+ result,
122
+ });
123
+ } catch (error) {
124
+ return handleError(error, "Setup failed", "SETUP_ERROR");
125
+ }
126
+ };
@@ -0,0 +1,122 @@
1
+ /**
2
+ * GET /_emdash/api/setup/status
3
+ *
4
+ * Returns setup status and seed file information
5
+ */
6
+
7
+ import type { APIRoute } from "astro";
8
+
9
+ export const prerender = false;
10
+
11
+ import { apiError, apiSuccess, handleError } from "#api/error.js";
12
+ import { getAuthMode } from "#auth/mode.js";
13
+ import { loadUserSeed } from "#seed/load.js";
14
+
15
+ export const GET: APIRoute = async ({ locals }) => {
16
+ const { emdash } = locals;
17
+
18
+ if (!emdash?.db) {
19
+ return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
20
+ }
21
+
22
+ try {
23
+ // Check if setup is complete
24
+ const setupComplete = await emdash.db
25
+ .selectFrom("options")
26
+ .select("value")
27
+ .where("name", "=", "emdash:setup_complete")
28
+ .executeTakeFirst();
29
+
30
+ // Value is JSON-encoded, parse it. Accepts both boolean true and string "true"
31
+ const isComplete =
32
+ setupComplete &&
33
+ (() => {
34
+ try {
35
+ const parsed = JSON.parse(setupComplete.value);
36
+ return parsed === true || parsed === "true";
37
+ } catch {
38
+ return false;
39
+ }
40
+ })();
41
+
42
+ // Also check if users exist
43
+ let hasUsers = false;
44
+ try {
45
+ const userCount = await emdash.db
46
+ .selectFrom("users")
47
+ .select((eb) => eb.fn.countAll<number>().as("count"))
48
+ .executeTakeFirstOrThrow();
49
+ hasUsers = userCount.count > 0;
50
+ } catch {
51
+ // Users table might not exist yet
52
+ }
53
+
54
+ // Setup is complete only if flag is set AND users exist
55
+ if (isComplete && hasUsers) {
56
+ return apiSuccess({
57
+ needsSetup: false,
58
+ });
59
+ }
60
+
61
+ // Determine current step
62
+ // step: "start" | "site" | "admin" | "complete"
63
+ let step: "start" | "site" | "admin" = "start";
64
+
65
+ // Get setup state if it exists
66
+ const setupState = await emdash.db
67
+ .selectFrom("options")
68
+ .select("value")
69
+ .where("name", "=", "emdash:setup_state")
70
+ .executeTakeFirst();
71
+
72
+ if (setupState) {
73
+ try {
74
+ const state = JSON.parse(setupState.value);
75
+ if (state.step === "admin") {
76
+ step = "admin";
77
+ } else if (state.step === "site") {
78
+ step = "site";
79
+ }
80
+ } catch {
81
+ // Invalid state, stay at start
82
+ }
83
+ }
84
+
85
+ // If setup_complete but no users, jump to admin step
86
+ if (isComplete && !hasUsers) {
87
+ step = "admin";
88
+ }
89
+
90
+ // Check auth mode
91
+ const authMode = getAuthMode(emdash.config);
92
+ const useExternalAuth = authMode.type === "external";
93
+
94
+ // In external auth mode, setup is complete if flag is set (no users required initially)
95
+ if (useExternalAuth && isComplete) {
96
+ return apiSuccess({
97
+ needsSetup: false,
98
+ });
99
+ }
100
+
101
+ // Setup needed - try to load seed file info
102
+ const seed = await loadUserSeed();
103
+ const seedInfo = seed
104
+ ? {
105
+ name: seed.meta?.name || "Unknown Template",
106
+ description: seed.meta?.description || "",
107
+ collections: seed.collections?.length || 0,
108
+ hasContent: !!(seed.content && Object.keys(seed.content).length > 0),
109
+ }
110
+ : null;
111
+
112
+ return apiSuccess({
113
+ needsSetup: true,
114
+ step,
115
+ seedInfo,
116
+ // Tell the wizard which auth mode is active
117
+ authMode: useExternalAuth ? authMode.providerType : "passkey",
118
+ });
119
+ } catch (error) {
120
+ return handleError(error, "Failed to check setup status", "SETUP_STATUS_ERROR");
121
+ }
122
+ };
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Snapshot endpoint — exports a portable database snapshot for preview mode.
3
+ *
4
+ * Security:
5
+ * - Authenticated users: requires content:read + schema:read permissions
6
+ * - Preview services: requires valid X-Preview-Signature header (HMAC-SHA256)
7
+ * - Excludes auth/user/session/token tables
8
+ */
9
+
10
+ import type { APIRoute } from "astro";
11
+
12
+ import { requirePerm } from "#api/authorize.js";
13
+ import { apiError, apiSuccess, handleError } from "#api/error.js";
14
+ import {
15
+ generateSnapshot,
16
+ parsePreviewSignatureHeader,
17
+ verifyPreviewSignature,
18
+ } from "#api/handlers/snapshot.js";
19
+
20
+ export const prerender = false;
21
+
22
+ export const GET: APIRoute = async ({ request, locals, url }) => {
23
+ const { emdash, user } = locals;
24
+
25
+ if (!emdash?.db) {
26
+ return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
27
+ }
28
+
29
+ // Check for preview signature auth (used by DO preview services)
30
+ const previewSig = request.headers.get("X-Preview-Signature");
31
+ let authorized = false;
32
+
33
+ if (previewSig) {
34
+ const secret = import.meta.env.EMDASH_PREVIEW_SECRET || import.meta.env.PREVIEW_SECRET || "";
35
+ if (!secret) {
36
+ console.warn(
37
+ "[snapshot] X-Preview-Signature header present but no PREVIEW_SECRET configured",
38
+ );
39
+ } else {
40
+ const parsed = parsePreviewSignatureHeader(previewSig);
41
+ if (!parsed) {
42
+ console.warn("[snapshot] Failed to parse X-Preview-Signature header");
43
+ } else {
44
+ authorized = await verifyPreviewSignature(parsed.source, parsed.exp, parsed.sig, secret);
45
+ if (!authorized) {
46
+ console.warn("[snapshot] Preview signature verification failed", {
47
+ source: parsed.source,
48
+ exp: parsed.exp,
49
+ expired: parsed.exp < Date.now() / 1000,
50
+ });
51
+ }
52
+ }
53
+ }
54
+ }
55
+
56
+ if (!authorized) {
57
+ // Fall back to standard user auth
58
+ const contentDenied = requirePerm(user, "content:read");
59
+ if (contentDenied) return contentDenied;
60
+ const schemaDenied = requirePerm(user, "schema:read");
61
+ if (schemaDenied) return schemaDenied;
62
+ }
63
+
64
+ try {
65
+ const includeDrafts = url.searchParams.get("drafts") === "true";
66
+ const snapshot = await generateSnapshot(emdash.db, {
67
+ includeDrafts,
68
+ origin: url.origin,
69
+ });
70
+
71
+ return apiSuccess(snapshot);
72
+ } catch (error) {
73
+ return handleError(error, "Failed to generate snapshot", "SNAPSHOT_ERROR");
74
+ }
75
+ };
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Single term endpoint
3
+ *
4
+ * GET /_emdash/api/taxonomies/:name/terms/:slug - Get a single term
5
+ * PUT /_emdash/api/taxonomies/:name/terms/:slug - Update a term
6
+ * DELETE /_emdash/api/taxonomies/:name/terms/:slug - Delete a term
7
+ */
8
+
9
+ import type { APIRoute } from "astro";
10
+
11
+ import { requirePerm } from "#api/authorize.js";
12
+ import { apiError, handleError, requireDb, unwrapResult } from "#api/error.js";
13
+ import { handleTermDelete, handleTermGet, handleTermUpdate } from "#api/handlers/taxonomies.js";
14
+ import { isParseError, parseBody } from "#api/parse.js";
15
+ import { updateTermBody } from "#api/schemas.js";
16
+
17
+ export const prerender = false;
18
+
19
+ /**
20
+ * Get a single term
21
+ */
22
+ export const GET: APIRoute = async ({ params, locals }) => {
23
+ const { emdash, user } = locals;
24
+ const { name, slug } = params;
25
+
26
+ if (!name || !slug) {
27
+ return apiError("VALIDATION_ERROR", "Taxonomy name and slug required", 400);
28
+ }
29
+
30
+ const dbErr = requireDb(emdash?.db);
31
+ if (dbErr) return dbErr;
32
+
33
+ const denied = requirePerm(user, "taxonomies:read");
34
+ if (denied) return denied;
35
+
36
+ try {
37
+ const result = await handleTermGet(emdash.db, name, slug);
38
+ return unwrapResult(result);
39
+ } catch (error) {
40
+ return handleError(error, "Failed to get term", "TERM_GET_ERROR");
41
+ }
42
+ };
43
+
44
+ /**
45
+ * Update a term
46
+ */
47
+ export const PUT: APIRoute = async ({ params, request, locals }) => {
48
+ const { emdash, user } = locals;
49
+ const { name, slug } = params;
50
+
51
+ if (!name || !slug) {
52
+ return apiError("VALIDATION_ERROR", "Taxonomy name and slug required", 400);
53
+ }
54
+
55
+ const dbErr = requireDb(emdash?.db);
56
+ if (dbErr) return dbErr;
57
+
58
+ const denied = requirePerm(user, "taxonomies:manage");
59
+ if (denied) return denied;
60
+
61
+ try {
62
+ const body = await parseBody(request, updateTermBody);
63
+ if (isParseError(body)) return body;
64
+
65
+ const result = await handleTermUpdate(emdash.db, name, slug, body);
66
+ return unwrapResult(result);
67
+ } catch (error) {
68
+ return handleError(error, "Failed to update term", "TERM_UPDATE_ERROR");
69
+ }
70
+ };
71
+
72
+ /**
73
+ * Delete a term
74
+ */
75
+ export const DELETE: APIRoute = async ({ params, locals }) => {
76
+ const { emdash, user } = locals;
77
+ const { name, slug } = params;
78
+
79
+ if (!name || !slug) {
80
+ return apiError("VALIDATION_ERROR", "Taxonomy name and slug required", 400);
81
+ }
82
+
83
+ const dbErr = requireDb(emdash?.db);
84
+ if (dbErr) return dbErr;
85
+
86
+ const denied = requirePerm(user, "taxonomies:manage");
87
+ if (denied) return denied;
88
+
89
+ try {
90
+ const result = await handleTermDelete(emdash.db, name, slug);
91
+ return unwrapResult(result);
92
+ } catch (error) {
93
+ return handleError(error, "Failed to delete term", "TERM_DELETE_ERROR");
94
+ }
95
+ };