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,194 @@
1
+ import type { Kysely } from "kysely";
2
+ import { sql } from "kysely";
3
+
4
+ import { binaryType, currentTimestamp, currentTimestampValue } from "../dialect-helpers.js";
5
+
6
+ /**
7
+ * Auth migration - passkey-first authentication
8
+ *
9
+ * Changes:
10
+ * - Removes password_hash from users (no passwords)
11
+ * - Adds role as integer (RBAC levels)
12
+ * - Adds email_verified, avatar_url, updated_at to users
13
+ * - Creates credentials table (passkeys)
14
+ * - Creates auth_tokens table (magic links, invites)
15
+ * - Creates oauth_accounts table (external provider links)
16
+ * - Creates allowed_domains table (self-signup)
17
+ */
18
+ export async function up(db: Kysely<unknown>): Promise<void> {
19
+ // SQLite doesn't support DROP COLUMN directly, so we need to recreate the table
20
+ // Create new users table with updated schema
21
+ await db.schema
22
+ .createTable("users_new")
23
+ .addColumn("id", "text", (col) => col.primaryKey())
24
+ .addColumn("email", "text", (col) => col.notNull().unique())
25
+ .addColumn("name", "text")
26
+ .addColumn("avatar_url", "text")
27
+ .addColumn("role", "integer", (col) => col.notNull().defaultTo(10)) // SUBSCRIBER
28
+ .addColumn("email_verified", "integer", (col) => col.notNull().defaultTo(0))
29
+ .addColumn("data", "text")
30
+ .addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db)))
31
+ .addColumn("updated_at", "text", (col) => col.defaultTo(currentTimestamp(db)))
32
+ .execute();
33
+
34
+ // Migrate existing data (map old role strings to new integer levels)
35
+ await sql`
36
+ INSERT INTO users_new (id, email, name, role, data, created_at, updated_at)
37
+ SELECT
38
+ id,
39
+ email,
40
+ name,
41
+ CASE role
42
+ WHEN 'admin' THEN 50
43
+ WHEN 'editor' THEN 40
44
+ WHEN 'author' THEN 30
45
+ WHEN 'contributor' THEN 20
46
+ ELSE 10
47
+ END,
48
+ data,
49
+ created_at,
50
+ ${currentTimestampValue(db)}
51
+ FROM users
52
+ `.execute(db);
53
+
54
+ // Drop old table and rename new one
55
+ await db.schema.dropTable("users").execute();
56
+ await sql`ALTER TABLE users_new RENAME TO users`.execute(db);
57
+
58
+ // Recreate index
59
+ await db.schema.createIndex("idx_users_email").on("users").column("email").execute();
60
+
61
+ // Passkey credentials
62
+ await db.schema
63
+ .createTable("credentials")
64
+ .addColumn("id", "text", (col) => col.primaryKey()) // Base64url credential ID
65
+ .addColumn("user_id", "text", (col) => col.notNull())
66
+ .addColumn("public_key", binaryType(db), (col) => col.notNull()) // COSE public key
67
+ .addColumn("counter", "integer", (col) => col.notNull().defaultTo(0))
68
+ .addColumn("device_type", "text", (col) => col.notNull()) // 'singleDevice' | 'multiDevice'
69
+ .addColumn("backed_up", "integer", (col) => col.notNull().defaultTo(0))
70
+ .addColumn("transports", "text") // JSON array
71
+ .addColumn("name", "text") // User-friendly name
72
+ .addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db)))
73
+ .addColumn("last_used_at", "text", (col) => col.defaultTo(currentTimestamp(db)))
74
+ .addForeignKeyConstraint("credentials_user_fk", ["user_id"], "users", ["id"], (cb) =>
75
+ cb.onDelete("cascade"),
76
+ )
77
+ .execute();
78
+
79
+ await db.schema.createIndex("idx_credentials_user").on("credentials").column("user_id").execute();
80
+
81
+ // Auth tokens (magic links, email verification, invites, recovery)
82
+ await db.schema
83
+ .createTable("auth_tokens")
84
+ .addColumn("hash", "text", (col) => col.primaryKey()) // SHA-256 hash of token
85
+ .addColumn("user_id", "text")
86
+ .addColumn("email", "text") // For pre-user tokens
87
+ .addColumn("type", "text", (col) => col.notNull()) // 'magic_link' | 'email_verify' | 'invite' | 'recovery'
88
+ .addColumn("role", "integer") // For invites
89
+ .addColumn("invited_by", "text")
90
+ .addColumn("expires_at", "text", (col) => col.notNull())
91
+ .addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db)))
92
+ .addForeignKeyConstraint("auth_tokens_user_fk", ["user_id"], "users", ["id"], (cb) =>
93
+ cb.onDelete("cascade"),
94
+ )
95
+ .addForeignKeyConstraint("auth_tokens_invited_by_fk", ["invited_by"], "users", ["id"], (cb) =>
96
+ cb.onDelete("set null"),
97
+ )
98
+ .execute();
99
+
100
+ await db.schema.createIndex("idx_auth_tokens_email").on("auth_tokens").column("email").execute();
101
+
102
+ // OAuth accounts (external provider links)
103
+ await db.schema
104
+ .createTable("oauth_accounts")
105
+ .addColumn("provider", "text", (col) => col.notNull())
106
+ .addColumn("provider_account_id", "text", (col) => col.notNull())
107
+ .addColumn("user_id", "text", (col) => col.notNull())
108
+ .addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db)))
109
+ .addPrimaryKeyConstraint("oauth_accounts_pk", ["provider", "provider_account_id"])
110
+ .addForeignKeyConstraint("oauth_accounts_user_fk", ["user_id"], "users", ["id"], (cb) =>
111
+ cb.onDelete("cascade"),
112
+ )
113
+ .execute();
114
+
115
+ await db.schema
116
+ .createIndex("idx_oauth_accounts_user")
117
+ .on("oauth_accounts")
118
+ .column("user_id")
119
+ .execute();
120
+
121
+ // Allowed domains for self-signup
122
+ await db.schema
123
+ .createTable("allowed_domains")
124
+ .addColumn("domain", "text", (col) => col.primaryKey())
125
+ .addColumn("default_role", "integer", (col) => col.notNull().defaultTo(20)) // CONTRIBUTOR
126
+ .addColumn("enabled", "integer", (col) => col.notNull().defaultTo(1))
127
+ .addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db)))
128
+ .execute();
129
+
130
+ // WebAuthn challenges (ephemeral, with TTL)
131
+ await db.schema
132
+ .createTable("auth_challenges")
133
+ .addColumn("challenge", "text", (col) => col.primaryKey()) // Base64url challenge
134
+ .addColumn("type", "text", (col) => col.notNull()) // 'registration' | 'authentication'
135
+ .addColumn("user_id", "text") // For registration, the user being registered
136
+ .addColumn("data", "text") // JSON for additional context
137
+ .addColumn("expires_at", "text", (col) => col.notNull())
138
+ .addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db)))
139
+ .execute();
140
+
141
+ // Index for efficient cleanup of expired challenges
142
+ await db.schema
143
+ .createIndex("idx_auth_challenges_expires")
144
+ .on("auth_challenges")
145
+ .column("expires_at")
146
+ .execute();
147
+ }
148
+
149
+ export async function down(db: Kysely<unknown>): Promise<void> {
150
+ // Drop new tables
151
+ await db.schema.dropTable("auth_challenges").execute();
152
+ await db.schema.dropTable("allowed_domains").execute();
153
+ await db.schema.dropTable("oauth_accounts").execute();
154
+ await db.schema.dropTable("auth_tokens").execute();
155
+ await db.schema.dropTable("credentials").execute();
156
+
157
+ // Recreate old users table with password_hash
158
+ await db.schema
159
+ .createTable("users_old")
160
+ .addColumn("id", "text", (col) => col.primaryKey())
161
+ .addColumn("email", "text", (col) => col.notNull().unique())
162
+ .addColumn("password_hash", "text", (col) => col.notNull())
163
+ .addColumn("name", "text")
164
+ .addColumn("role", "text", (col) => col.defaultTo("subscriber"))
165
+ .addColumn("avatar_id", "text")
166
+ .addColumn("data", "text")
167
+ .addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db)))
168
+ .execute();
169
+
170
+ // Migrate data back (users will have empty password_hash)
171
+ await sql`
172
+ INSERT INTO users_old (id, email, password_hash, name, role, data, created_at)
173
+ SELECT
174
+ id,
175
+ email,
176
+ '', -- No way to restore password
177
+ name,
178
+ CASE role
179
+ WHEN 50 THEN 'admin'
180
+ WHEN 40 THEN 'editor'
181
+ WHEN 30 THEN 'author'
182
+ WHEN 20 THEN 'contributor'
183
+ ELSE 'subscriber'
184
+ END,
185
+ data,
186
+ created_at
187
+ FROM users
188
+ `.execute(db);
189
+
190
+ await db.schema.dropTable("users").execute();
191
+ await sql`ALTER TABLE users_old RENAME TO users`.execute(db);
192
+
193
+ await db.schema.createIndex("idx_users_email").on("users").column("email").execute();
194
+ }
@@ -0,0 +1,27 @@
1
+ import type { Kysely } from "kysely";
2
+ import { sql } from "kysely";
3
+
4
+ /**
5
+ * User disabled column - for soft-disabling users
6
+ *
7
+ * Changes:
8
+ * - Adds disabled column to users table (INTEGER, default 0)
9
+ * - Disabled users cannot log in
10
+ */
11
+ export async function up(db: Kysely<unknown>): Promise<void> {
12
+ // SQLite supports ADD COLUMN
13
+ await sql`ALTER TABLE users ADD COLUMN disabled INTEGER NOT NULL DEFAULT 0`.execute(db);
14
+
15
+ // Create index for querying active users
16
+ await db.schema.createIndex("idx_users_disabled").on("users").column("disabled").execute();
17
+ }
18
+
19
+ export async function down(db: Kysely<unknown>): Promise<void> {
20
+ // SQLite doesn't support DROP COLUMN directly, but we can drop the index
21
+ // For full rollback, table would need to be recreated
22
+ await db.schema.dropIndex("idx_users_disabled").execute();
23
+
24
+ // SQLite 3.35.0+ supports DROP COLUMN, but for compatibility:
25
+ // We'll leave the column but document that it's deprecated
26
+ // In production, you'd recreate the table without the column
27
+ }
@@ -0,0 +1,65 @@
1
+ import { type Kysely, sql } from "kysely";
2
+
3
+ /**
4
+ * Migration: Add sections tables and performance indexes
5
+ *
6
+ * Sections are reusable content blocks that can be inserted into any Portable Text field.
7
+ * They provide a library of pre-built page sections (heroes, CTAs, testimonials, etc.)
8
+ * that content authors can browse and insert with a single click.
9
+ */
10
+ export async function up(db: Kysely<unknown>): Promise<void> {
11
+ // Section categories table
12
+ await db.schema
13
+ .createTable("_emdash_section_categories")
14
+ .addColumn("id", "text", (col) => col.primaryKey())
15
+ .addColumn("slug", "text", (col) => col.notNull().unique())
16
+ .addColumn("label", "text", (col) => col.notNull())
17
+ .addColumn("sort_order", "integer", (col) => col.defaultTo(0))
18
+ .addColumn("created_at", "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`))
19
+ .execute();
20
+
21
+ // Sections table
22
+ await db.schema
23
+ .createTable("_emdash_sections")
24
+ .addColumn("id", "text", (col) => col.primaryKey())
25
+ .addColumn("slug", "text", (col) => col.notNull().unique())
26
+ .addColumn("title", "text", (col) => col.notNull())
27
+ .addColumn("description", "text")
28
+ // Categorization
29
+ .addColumn("category_id", "text", (col) =>
30
+ col.references("_emdash_section_categories.id").onDelete("set null"),
31
+ )
32
+ .addColumn("keywords", "text") // JSON array for search
33
+ // Content (Portable Text array)
34
+ .addColumn("content", "text", (col) => col.notNull()) // JSON
35
+ // Preview image (optional)
36
+ .addColumn("preview_media_id", "text")
37
+ // Source tracking
38
+ .addColumn("source", "text", (col) => col.notNull().defaultTo("user")) // 'theme', 'user', 'import'
39
+ .addColumn("theme_id", "text") // Which theme provided it (if source='theme')
40
+ // Metadata
41
+ .addColumn("created_at", "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`))
42
+ .addColumn("updated_at", "text", (col) => col.defaultTo(sql`CURRENT_TIMESTAMP`))
43
+ .execute();
44
+
45
+ // Index for efficient category lookups
46
+ await db.schema
47
+ .createIndex("idx_sections_category")
48
+ .on("_emdash_sections")
49
+ .columns(["category_id"])
50
+ .execute();
51
+
52
+ // Index for filtering by source
53
+ await db.schema
54
+ .createIndex("idx_sections_source")
55
+ .on("_emdash_sections")
56
+ .columns(["source"])
57
+ .execute();
58
+ }
59
+
60
+ export async function down(db: Kysely<unknown>): Promise<void> {
61
+ await db.schema.dropIndex("idx_content_taxonomies_term").execute();
62
+ await db.schema.dropIndex("idx_media_mime_type").execute();
63
+ await db.schema.dropTable("_emdash_sections").execute();
64
+ await db.schema.dropTable("_emdash_section_categories").execute();
65
+ }
@@ -0,0 +1,25 @@
1
+ import type { Kysely } from "kysely";
2
+
3
+ /**
4
+ * Migration: Search Support
5
+ *
6
+ * Adds search configuration to collections and searchable flag to fields.
7
+ * FTS5 tables are created dynamically when search is enabled for a collection.
8
+ */
9
+ export async function up(db: Kysely<unknown>): Promise<void> {
10
+ // Add search_config to collections (JSON: { enabled, weights })
11
+ await db.schema.alterTable("_emdash_collections").addColumn("search_config", "text").execute();
12
+
13
+ // Add searchable flag to fields
14
+ await db.schema
15
+ .alterTable("_emdash_fields")
16
+ .addColumn("searchable", "integer", (col) => col.defaultTo(0))
17
+ .execute();
18
+ }
19
+
20
+ export async function down(db: Kysely<unknown>): Promise<void> {
21
+ // SQLite doesn't support DROP COLUMN in older versions, but modern SQLite does
22
+ // These columns are safe to drop
23
+ await db.schema.alterTable("_emdash_fields").dropColumn("searchable").execute();
24
+ await db.schema.alterTable("_emdash_collections").dropColumn("search_config").execute();
25
+ }
@@ -0,0 +1,51 @@
1
+ import type { Kysely } from "kysely";
2
+ import { sql } from "kysely";
3
+
4
+ import { listTablesLike } from "../dialect-helpers.js";
5
+
6
+ /**
7
+ * Migration: Add scheduled publishing support
8
+ *
9
+ * Adds scheduled_at column to all ec_* content tables.
10
+ * When scheduled_at is set and status is 'scheduled', the content
11
+ * will be auto-published when the scheduled time is reached.
12
+ */
13
+ export async function up(db: Kysely<unknown>): Promise<void> {
14
+ // Get all ec_* content tables
15
+ const tableNames = await listTablesLike(db, "ec_%");
16
+
17
+ // Add scheduled_at column to each content table
18
+ for (const tableName of tableNames) {
19
+ const table = { name: tableName };
20
+ await sql`
21
+ ALTER TABLE ${sql.ref(table.name)}
22
+ ADD COLUMN scheduled_at TEXT
23
+ `.execute(db);
24
+
25
+ // Create index for efficient scheduled content queries
26
+ await sql`
27
+ CREATE INDEX ${sql.ref(`idx_${table.name}_scheduled`)}
28
+ ON ${sql.ref(table.name)} (scheduled_at)
29
+ WHERE scheduled_at IS NOT NULL AND status = 'scheduled'
30
+ `.execute(db);
31
+ }
32
+ }
33
+
34
+ export async function down(db: Kysely<unknown>): Promise<void> {
35
+ // Get all ec_* content tables
36
+ const tableNames = await listTablesLike(db, "ec_%");
37
+
38
+ // Drop scheduled_at column from each content table
39
+ for (const tableName of tableNames) {
40
+ const table = { name: tableName };
41
+ // Drop index first
42
+ await sql`
43
+ DROP INDEX IF EXISTS ${sql.ref(`idx_${table.name}_scheduled`)}
44
+ `.execute(db);
45
+
46
+ await sql`
47
+ ALTER TABLE ${sql.ref(table.name)}
48
+ DROP COLUMN scheduled_at
49
+ `.execute(db);
50
+ }
51
+ }
@@ -0,0 +1,72 @@
1
+ import type { Kysely } from "kysely";
2
+ import { sql } from "kysely";
3
+
4
+ export async function up(db: Kysely<unknown>): Promise<void> {
5
+ // Get all content tables
6
+ const tables = await db
7
+ // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- Kysely migration runs against unknown schema
8
+ .selectFrom("_emdash_collections" as never)
9
+ // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- Kysely migration runs against unknown schema
10
+ .select("slug" as never)
11
+ .execute();
12
+
13
+ // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- Kysely execute returns unknown[]; narrowing to known shape
14
+ for (const row of tables as Array<{ slug: string }>) {
15
+ const tableName = `ec_${row.slug}`;
16
+
17
+ // Add live_revision_id column
18
+ await sql`
19
+ ALTER TABLE ${sql.ref(tableName)}
20
+ ADD COLUMN live_revision_id TEXT REFERENCES revisions(id)
21
+ `.execute(db);
22
+
23
+ // Add draft_revision_id column
24
+ await sql`
25
+ ALTER TABLE ${sql.ref(tableName)}
26
+ ADD COLUMN draft_revision_id TEXT REFERENCES revisions(id)
27
+ `.execute(db);
28
+
29
+ // Create indexes for the new columns
30
+ await sql`
31
+ CREATE INDEX ${sql.ref(`idx_${row.slug}_live_revision`)}
32
+ ON ${sql.ref(tableName)} (live_revision_id)
33
+ `.execute(db);
34
+
35
+ await sql`
36
+ CREATE INDEX ${sql.ref(`idx_${row.slug}_draft_revision`)}
37
+ ON ${sql.ref(tableName)} (draft_revision_id)
38
+ `.execute(db);
39
+ }
40
+ }
41
+
42
+ export async function down(db: Kysely<unknown>): Promise<void> {
43
+ const tables = await db
44
+ // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- Kysely migration runs against unknown schema
45
+ .selectFrom("_emdash_collections" as never)
46
+ // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- Kysely migration runs against unknown schema
47
+ .select("slug" as never)
48
+ .execute();
49
+
50
+ // eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- Kysely execute returns unknown[]; narrowing to known shape
51
+ for (const row of tables as Array<{ slug: string }>) {
52
+ const tableName = `ec_${row.slug}`;
53
+
54
+ await sql`
55
+ DROP INDEX IF EXISTS ${sql.ref(`idx_${row.slug}_draft_revision`)}
56
+ `.execute(db);
57
+
58
+ await sql`
59
+ DROP INDEX IF EXISTS ${sql.ref(`idx_${row.slug}_live_revision`)}
60
+ `.execute(db);
61
+
62
+ await sql`
63
+ ALTER TABLE ${sql.ref(tableName)}
64
+ DROP COLUMN draft_revision_id
65
+ `.execute(db);
66
+
67
+ await sql`
68
+ ALTER TABLE ${sql.ref(tableName)}
69
+ DROP COLUMN live_revision_id
70
+ `.execute(db);
71
+ }
72
+ }
@@ -0,0 +1,82 @@
1
+ import type { Kysely } from "kysely";
2
+ import { sql } from "kysely";
3
+
4
+ import { listTablesLike } from "../dialect-helpers.js";
5
+
6
+ /**
7
+ * Add performance indexes for common query patterns.
8
+ *
9
+ * Covers:
10
+ * 1. Media table: mime_type, filename, created_at
11
+ * 2. content_taxonomies: reverse lookup by taxonomy_id
12
+ * 3. taxonomies: parent_id FK
13
+ * 4. audit_logs: compound (resource_type, resource_id)
14
+ * 5. Retroactive author_id + updated_at on existing ec_* content tables
15
+ * (new tables get these from createContentTable() in registry.ts)
16
+ */
17
+ export async function up(db: Kysely<unknown>): Promise<void> {
18
+ // ── Media indexes ────────────────────────────────────────────────
19
+ await db.schema.createIndex("idx_media_mime_type").on("media").column("mime_type").execute();
20
+ await db.schema.createIndex("idx_media_filename").on("media").column("filename").execute();
21
+ await db.schema.createIndex("idx_media_created_at").on("media").column("created_at").execute();
22
+
23
+ // ── Taxonomy indexes ─────────────────────────────────────────────
24
+ // Reverse lookup: find entries with a specific term
25
+ await db.schema
26
+ .createIndex("idx_content_taxonomies_term")
27
+ .on("content_taxonomies")
28
+ .column("taxonomy_id")
29
+ .execute();
30
+
31
+ // Hierarchical queries filter on parent_id FK
32
+ await db.schema
33
+ .createIndex("idx_taxonomies_parent")
34
+ .on("taxonomies")
35
+ .column("parent_id")
36
+ .execute();
37
+
38
+ // ── Audit log indexes ────────────────────────────────────────────
39
+ // findByResource() compound query
40
+ await db.schema
41
+ .createIndex("idx_audit_resource")
42
+ .on("audit_logs")
43
+ .columns(["resource_type", "resource_id"])
44
+ .execute();
45
+
46
+ // ── Retroactive content table indexes ────────────────────────────
47
+ // Add author_id and updated_at indexes to all existing ec_* tables.
48
+ // New tables created after this migration get these from createContentTable().
49
+ const tableNames = await listTablesLike(db, "ec_%");
50
+
51
+ for (const tableName of tableNames) {
52
+ const table = { name: tableName };
53
+ await sql`
54
+ CREATE INDEX ${sql.ref(`idx_${table.name}_author`)}
55
+ ON ${sql.ref(table.name)} (author_id)
56
+ `.execute(db);
57
+
58
+ await sql`
59
+ CREATE INDEX ${sql.ref(`idx_${table.name}_updated`)}
60
+ ON ${sql.ref(table.name)} (updated_at)
61
+ `.execute(db);
62
+ }
63
+ }
64
+
65
+ export async function down(db: Kysely<unknown>): Promise<void> {
66
+ // Drop retroactive content table indexes
67
+ const tableNames = await listTablesLike(db, "ec_%");
68
+
69
+ for (const tableName of tableNames) {
70
+ const table = { name: tableName };
71
+ await sql`DROP INDEX IF EXISTS ${sql.ref(`idx_${table.name}_updated`)}`.execute(db);
72
+ await sql`DROP INDEX IF EXISTS ${sql.ref(`idx_${table.name}_author`)}`.execute(db);
73
+ }
74
+
75
+ // Drop system table indexes
76
+ await db.schema.dropIndex("idx_audit_resource").execute();
77
+ await db.schema.dropIndex("idx_taxonomies_parent").execute();
78
+ await db.schema.dropIndex("idx_content_taxonomies_term").execute();
79
+ await db.schema.dropIndex("idx_media_created_at").execute();
80
+ await db.schema.dropIndex("idx_media_filename").execute();
81
+ await db.schema.dropIndex("idx_media_mime_type").execute();
82
+ }
@@ -0,0 +1,89 @@
1
+ import type { Kysely } from "kysely";
2
+
3
+ import { currentTimestamp } from "../dialect-helpers.js";
4
+
5
+ /**
6
+ * API token tables for programmatic access.
7
+ *
8
+ * Three tables:
9
+ * 1. _emdash_api_tokens — Personal Access Tokens (ec_pat_...)
10
+ * 2. _emdash_oauth_tokens — OAuth access/refresh tokens (ec_oat_/ec_ort_...)
11
+ * 3. _emdash_device_codes — OAuth Device Flow state (RFC 8628)
12
+ */
13
+ export async function up(db: Kysely<unknown>): Promise<void> {
14
+ // ── Personal Access Tokens ───────────────────────────────────────
15
+ await db.schema
16
+ .createTable("_emdash_api_tokens")
17
+ .addColumn("id", "text", (col) => col.primaryKey())
18
+ .addColumn("name", "text", (col) => col.notNull())
19
+ .addColumn("token_hash", "text", (col) => col.notNull().unique())
20
+ .addColumn("prefix", "text", (col) => col.notNull())
21
+ .addColumn("user_id", "text", (col) => col.notNull())
22
+ .addColumn("scopes", "text", (col) => col.notNull()) // JSON array
23
+ .addColumn("expires_at", "text") // null = no expiry
24
+ .addColumn("last_used_at", "text")
25
+ .addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db)))
26
+ .addForeignKeyConstraint("api_tokens_user_fk", ["user_id"], "users", ["id"], (cb) =>
27
+ cb.onDelete("cascade"),
28
+ )
29
+ .execute();
30
+
31
+ await db.schema
32
+ .createIndex("idx_api_tokens_token_hash")
33
+ .on("_emdash_api_tokens")
34
+ .column("token_hash")
35
+ .execute();
36
+
37
+ await db.schema
38
+ .createIndex("idx_api_tokens_user_id")
39
+ .on("_emdash_api_tokens")
40
+ .column("user_id")
41
+ .execute();
42
+
43
+ // ── OAuth Tokens ─────────────────────────────────────────────────
44
+ await db.schema
45
+ .createTable("_emdash_oauth_tokens")
46
+ .addColumn("token_hash", "text", (col) => col.primaryKey())
47
+ .addColumn("token_type", "text", (col) => col.notNull()) // 'access' | 'refresh'
48
+ .addColumn("user_id", "text", (col) => col.notNull())
49
+ .addColumn("scopes", "text", (col) => col.notNull()) // JSON array
50
+ .addColumn("client_type", "text", (col) => col.notNull().defaultTo("cli"))
51
+ .addColumn("expires_at", "text", (col) => col.notNull())
52
+ .addColumn("refresh_token_hash", "text") // links access → refresh
53
+ .addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db)))
54
+ .addForeignKeyConstraint("oauth_tokens_user_fk", ["user_id"], "users", ["id"], (cb) =>
55
+ cb.onDelete("cascade"),
56
+ )
57
+ .execute();
58
+
59
+ await db.schema
60
+ .createIndex("idx_oauth_tokens_user_id")
61
+ .on("_emdash_oauth_tokens")
62
+ .column("user_id")
63
+ .execute();
64
+
65
+ await db.schema
66
+ .createIndex("idx_oauth_tokens_expires")
67
+ .on("_emdash_oauth_tokens")
68
+ .column("expires_at")
69
+ .execute();
70
+
71
+ // ── Device Codes (OAuth Device Flow, RFC 8628) ───────────────────
72
+ await db.schema
73
+ .createTable("_emdash_device_codes")
74
+ .addColumn("device_code", "text", (col) => col.primaryKey())
75
+ .addColumn("user_code", "text", (col) => col.notNull().unique())
76
+ .addColumn("scopes", "text", (col) => col.notNull()) // JSON array
77
+ .addColumn("user_id", "text") // set when user authorizes
78
+ .addColumn("status", "text", (col) => col.notNull().defaultTo("pending"))
79
+ .addColumn("expires_at", "text", (col) => col.notNull())
80
+ .addColumn("interval", "integer", (col) => col.notNull().defaultTo(5))
81
+ .addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db)))
82
+ .execute();
83
+ }
84
+
85
+ export async function down(db: Kysely<unknown>): Promise<void> {
86
+ await db.schema.dropTable("_emdash_device_codes").execute();
87
+ await db.schema.dropTable("_emdash_oauth_tokens").execute();
88
+ await db.schema.dropTable("_emdash_api_tokens").execute();
89
+ }
@@ -0,0 +1,45 @@
1
+ import type { Kysely } from "kysely";
2
+ import { sql } from "kysely";
3
+
4
+ import { currentTimestamp } from "../dialect-helpers.js";
5
+
6
+ /**
7
+ * Authorization codes for OAuth 2.1 Authorization Code + PKCE flow.
8
+ *
9
+ * Used by MCP clients (Claude Desktop, VS Code, etc.) to authenticate
10
+ * via the standard OAuth authorization code grant.
11
+ *
12
+ * Also adds client_id tracking to oauth_tokens for per-client revocation.
13
+ */
14
+ export async function up(db: Kysely<unknown>): Promise<void> {
15
+ await db.schema
16
+ .createTable("_emdash_authorization_codes")
17
+ .addColumn("code_hash", "text", (col) => col.primaryKey()) // SHA-256 hash of authorization code
18
+ .addColumn("client_id", "text", (col) => col.notNull()) // CIMD URL or opaque string
19
+ .addColumn("redirect_uri", "text", (col) => col.notNull()) // Must match exactly on exchange
20
+ .addColumn("user_id", "text", (col) => col.notNull())
21
+ .addColumn("scopes", "text", (col) => col.notNull()) // JSON array
22
+ .addColumn("code_challenge", "text", (col) => col.notNull()) // S256 challenge
23
+ .addColumn("code_challenge_method", "text", (col) => col.notNull().defaultTo("S256"))
24
+ .addColumn("resource", "text") // RFC 8707 resource indicator
25
+ .addColumn("expires_at", "text", (col) => col.notNull())
26
+ .addColumn("created_at", "text", (col) => col.defaultTo(currentTimestamp(db)))
27
+ .addForeignKeyConstraint("auth_codes_user_fk", ["user_id"], "users", ["id"], (cb) =>
28
+ cb.onDelete("cascade"),
29
+ )
30
+ .execute();
31
+
32
+ await db.schema
33
+ .createIndex("idx_auth_codes_expires")
34
+ .on("_emdash_authorization_codes")
35
+ .column("expires_at")
36
+ .execute();
37
+
38
+ // Track which client obtained a token (for per-client revocation)
39
+ await sql`ALTER TABLE _emdash_oauth_tokens ADD COLUMN client_id TEXT`.execute(db);
40
+ }
41
+
42
+ export async function down(db: Kysely<unknown>): Promise<void> {
43
+ await db.schema.dropTable("_emdash_authorization_codes").execute();
44
+ // SQLite doesn't support DROP COLUMN, but this is only for dev rollback
45
+ }