emdash 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (354) hide show
  1. package/dist/{adapters-Di31kZ28.d.mts → adapters-DoNJiveC.d.mts} +1 -1
  2. package/dist/{adapters-Di31kZ28.d.mts.map → adapters-DoNJiveC.d.mts.map} +1 -1
  3. package/dist/{apply-5uslYdUu.mjs → apply-BzltprvY.mjs} +90 -139
  4. package/dist/apply-BzltprvY.mjs.map +1 -0
  5. package/dist/astro/index.d.mts +6 -6
  6. package/dist/astro/index.d.mts.map +1 -1
  7. package/dist/astro/index.mjs +194 -17
  8. package/dist/astro/index.mjs.map +1 -1
  9. package/dist/astro/middleware/auth.d.mts +6 -7
  10. package/dist/astro/middleware/auth.d.mts.map +1 -1
  11. package/dist/astro/middleware/auth.mjs +34 -57
  12. package/dist/astro/middleware/auth.mjs.map +1 -1
  13. package/dist/astro/middleware/redirect.d.mts.map +1 -1
  14. package/dist/astro/middleware/redirect.mjs +17 -12
  15. package/dist/astro/middleware/redirect.mjs.map +1 -1
  16. package/dist/astro/middleware/request-context.d.mts.map +1 -1
  17. package/dist/astro/middleware/request-context.mjs +9 -6
  18. package/dist/astro/middleware/request-context.mjs.map +1 -1
  19. package/dist/astro/middleware/setup.mjs +1 -1
  20. package/dist/astro/middleware.d.mts.map +1 -1
  21. package/dist/astro/middleware.mjs +301 -165
  22. package/dist/astro/middleware.mjs.map +1 -1
  23. package/dist/astro/types.d.mts +34 -10
  24. package/dist/astro/types.d.mts.map +1 -1
  25. package/dist/{base64-MBPo9ozB.mjs → base64-BRICGH2l.mjs} +1 -1
  26. package/dist/{base64-MBPo9ozB.mjs.map → base64-BRICGH2l.mjs.map} +1 -1
  27. package/dist/{byline-C4OVd8b3.mjs → byline-BSaNL1w7.mjs} +5 -5
  28. package/dist/byline-BSaNL1w7.mjs.map +1 -0
  29. package/dist/bylines-CvJ3PYz2.mjs +113 -0
  30. package/dist/bylines-CvJ3PYz2.mjs.map +1 -0
  31. package/dist/cache-C6N_hhN7.mjs +65 -0
  32. package/dist/cache-C6N_hhN7.mjs.map +1 -0
  33. package/dist/{chunks-HGz06Soa.mjs → chunks-NBQVDOci.mjs} +8 -2
  34. package/dist/{chunks-HGz06Soa.mjs.map → chunks-NBQVDOci.mjs.map} +1 -1
  35. package/dist/cli/index.mjs +229 -31
  36. package/dist/cli/index.mjs.map +1 -1
  37. package/dist/client/cf-access.d.mts +1 -1
  38. package/dist/client/index.d.mts +1 -1
  39. package/dist/client/index.mjs +3 -3
  40. package/dist/client/index.mjs.map +1 -1
  41. package/dist/{config-BXwuX8Bx.mjs → config-BI0V3ICQ.mjs} +1 -1
  42. package/dist/{config-BXwuX8Bx.mjs.map → config-BI0V3ICQ.mjs.map} +1 -1
  43. package/dist/{content-D7J5y73J.mjs → content-8lOYF0pr.mjs} +43 -28
  44. package/dist/content-8lOYF0pr.mjs.map +1 -0
  45. package/dist/db/index.d.mts +3 -3
  46. package/dist/db/index.mjs +2 -2
  47. package/dist/db/libsql.d.mts +1 -1
  48. package/dist/db/libsql.d.mts.map +1 -1
  49. package/dist/db/libsql.mjs +7 -2
  50. package/dist/db/libsql.mjs.map +1 -1
  51. package/dist/db/postgres.d.mts +1 -1
  52. package/dist/db/sqlite.d.mts +1 -1
  53. package/dist/db/sqlite.d.mts.map +1 -1
  54. package/dist/db/sqlite.mjs +8 -3
  55. package/dist/db/sqlite.mjs.map +1 -1
  56. package/dist/{db-errors-D0UT85nC.mjs → db-errors-WRezodiz.mjs} +1 -1
  57. package/dist/{db-errors-D0UT85nC.mjs.map → db-errors-WRezodiz.mjs.map} +1 -1
  58. package/dist/{default-CME5YdZ3.mjs → default-D8ksjWhO.mjs} +1 -1
  59. package/dist/{default-CME5YdZ3.mjs.map → default-D8ksjWhO.mjs.map} +1 -1
  60. package/dist/{dialect-helpers-DhTzaUxP.mjs → dialect-helpers-BKCvISIQ.mjs} +19 -2
  61. package/dist/dialect-helpers-BKCvISIQ.mjs.map +1 -0
  62. package/dist/{error-CiYn9yDu.mjs → error-D_-tqP-I.mjs} +1 -1
  63. package/dist/error-D_-tqP-I.mjs.map +1 -0
  64. package/dist/{index-De6_Xv3v.d.mts → index-BFRaVcD6.d.mts} +243 -40
  65. package/dist/index-BFRaVcD6.d.mts.map +1 -0
  66. package/dist/index.d.mts +11 -11
  67. package/dist/index.mjs +29 -25
  68. package/dist/{load-CBcmDIot.mjs → load-DDqMMvZL.mjs} +2 -2
  69. package/dist/{load-CBcmDIot.mjs.map → load-DDqMMvZL.mjs.map} +1 -1
  70. package/dist/{loader-DeiBJEMe.mjs → loader-CKLbBnhK.mjs} +32 -10
  71. package/dist/loader-CKLbBnhK.mjs.map +1 -0
  72. package/dist/{manifest-schema-V30qsMft.mjs → manifest-schema-DqWNC3lM.mjs} +45 -3
  73. package/dist/manifest-schema-DqWNC3lM.mjs.map +1 -0
  74. package/dist/media/index.d.mts +1 -1
  75. package/dist/media/index.mjs +1 -1
  76. package/dist/media/local-runtime.d.mts +7 -7
  77. package/dist/media/local-runtime.mjs +3 -3
  78. package/dist/{media-DqHVh136.mjs → media-BW32b4gi.mjs} +4 -7
  79. package/dist/media-BW32b4gi.mjs.map +1 -0
  80. package/dist/{mode-CpNnGkPz.mjs → mode-ier8jbBk.mjs} +1 -1
  81. package/dist/mode-ier8jbBk.mjs.map +1 -0
  82. package/dist/options-BVp3UsTS.mjs +117 -0
  83. package/dist/options-BVp3UsTS.mjs.map +1 -0
  84. package/dist/page/index.d.mts +2 -2
  85. package/dist/{placeholder-tzpqGWII.d.mts → placeholder-BE4o_2dc.d.mts} +1 -1
  86. package/dist/{placeholder-tzpqGWII.d.mts.map → placeholder-BE4o_2dc.d.mts.map} +1 -1
  87. package/dist/{placeholder-C-fk5hYI.mjs → placeholder-CIJejMlK.mjs} +1 -1
  88. package/dist/placeholder-CIJejMlK.mjs.map +1 -0
  89. package/dist/plugins/adapt-sandbox-entry.d.mts +5 -5
  90. package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
  91. package/dist/plugins/adapt-sandbox-entry.mjs +6 -5
  92. package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
  93. package/dist/public-url-DByxYjUw.mjs +51 -0
  94. package/dist/public-url-DByxYjUw.mjs.map +1 -0
  95. package/dist/{query-g4Ug-9j9.mjs → query-Cg9ZKRQ0.mjs} +114 -16
  96. package/dist/query-Cg9ZKRQ0.mjs.map +1 -0
  97. package/dist/{redirect-CN0Rt9Ob.mjs → redirect-BhUBKRc1.mjs} +13 -8
  98. package/dist/redirect-BhUBKRc1.mjs.map +1 -0
  99. package/dist/{registry-Ci3WxVAr.mjs → registry-Dw70ChxB.mjs} +69 -11
  100. package/dist/registry-Dw70ChxB.mjs.map +1 -0
  101. package/dist/{request-cache-DiR961CV.mjs → request-cache-B-bmkipQ.mjs} +1 -1
  102. package/dist/request-cache-B-bmkipQ.mjs.map +1 -0
  103. package/dist/runner-Bnoj7vjK.d.mts +44 -0
  104. package/dist/runner-Bnoj7vjK.d.mts.map +1 -0
  105. package/dist/{runner-tQ7BJ4T7.mjs → runner-C7ADox5q.mjs} +185 -55
  106. package/dist/{runner-tQ7BJ4T7.mjs.map → runner-C7ADox5q.mjs.map} +1 -1
  107. package/dist/runtime.d.mts +6 -6
  108. package/dist/runtime.mjs +4 -4
  109. package/dist/{search-B0effn3j.mjs → search-dOGEccMa.mjs} +341 -152
  110. package/dist/search-dOGEccMa.mjs.map +1 -0
  111. package/dist/secrets-CW3reAnU.mjs +314 -0
  112. package/dist/secrets-CW3reAnU.mjs.map +1 -0
  113. package/dist/seed/index.d.mts +2 -2
  114. package/dist/seed/index.mjs +15 -14
  115. package/dist/seo/index.d.mts +1 -1
  116. package/dist/storage/local.d.mts +1 -1
  117. package/dist/storage/local.mjs +1 -1
  118. package/dist/storage/s3.d.mts +1 -1
  119. package/dist/storage/s3.d.mts.map +1 -1
  120. package/dist/storage/s3.mjs +4 -4
  121. package/dist/storage/s3.mjs.map +1 -1
  122. package/dist/{taxonomies-K2z0Uhnj.mjs → taxonomies-ZlRtD6AG.mjs} +14 -7
  123. package/dist/taxonomies-ZlRtD6AG.mjs.map +1 -0
  124. package/dist/{tokens-BFPFx3CA.mjs → tokens-D7zMmWi2.mjs} +2 -2
  125. package/dist/{tokens-BFPFx3CA.mjs.map → tokens-D7zMmWi2.mjs.map} +1 -1
  126. package/dist/{transport-BykRfpyy.mjs → transport-BeMCmin1.mjs} +6 -5
  127. package/dist/{transport-BykRfpyy.mjs.map → transport-BeMCmin1.mjs.map} +1 -1
  128. package/dist/{transport-H4Iwx7tC.d.mts → transport-DNEfeMaU.d.mts} +1 -1
  129. package/dist/{transport-H4Iwx7tC.d.mts.map → transport-DNEfeMaU.d.mts.map} +1 -1
  130. package/dist/types-4fVtCIm0.mjs +68 -0
  131. package/dist/types-4fVtCIm0.mjs.map +1 -0
  132. package/dist/{types-CnZYHyLW.d.mts → types-BSyXeCFW.d.mts} +24 -2
  133. package/dist/{types-CnZYHyLW.d.mts.map → types-BSyXeCFW.d.mts.map} +1 -1
  134. package/dist/{types-DgrIP0tF.d.mts → types-BuBIptGk.d.mts} +80 -106
  135. package/dist/types-BuBIptGk.d.mts.map +1 -0
  136. package/dist/{types-BH2L167P.mjs → types-CDbKp7ND.mjs} +1 -1
  137. package/dist/{types-BH2L167P.mjs.map → types-CDbKp7ND.mjs.map} +1 -1
  138. package/dist/{types-DDS4MxsT.mjs → types-CIOg5AR8.mjs} +1 -1
  139. package/dist/{types-DDS4MxsT.mjs.map → types-CIOg5AR8.mjs.map} +1 -1
  140. package/dist/{types-6CUZRrZP.d.mts → types-CJsYGpco.d.mts} +24 -2
  141. package/dist/{types-6CUZRrZP.d.mts.map → types-CJsYGpco.d.mts.map} +1 -1
  142. package/dist/types-CRxNbK-Z.mjs +68 -0
  143. package/dist/types-CRxNbK-Z.mjs.map +1 -0
  144. package/dist/{types-C2v0c34j.d.mts → types-CrtWgIvl.d.mts} +1 -1
  145. package/dist/{types-C2v0c34j.d.mts.map → types-CrtWgIvl.d.mts.map} +1 -1
  146. package/dist/{types-CFWjXmus.d.mts → types-M78DQ1lx.d.mts} +1 -1
  147. package/dist/{types-CFWjXmus.d.mts.map → types-M78DQ1lx.d.mts.map} +1 -1
  148. package/dist/{validate-CqsNItbt.mjs → validate-Baqf0slj.mjs} +3 -3
  149. package/dist/{validate-CqsNItbt.mjs.map → validate-Baqf0slj.mjs.map} +1 -1
  150. package/dist/{validate-kM8Pjuf7.d.mts → validate-BfQh_C_y.d.mts} +4 -4
  151. package/dist/{validate-kM8Pjuf7.d.mts.map → validate-BfQh_C_y.d.mts.map} +1 -1
  152. package/dist/validation-BfEI7tNe.mjs +144 -0
  153. package/dist/validation-BfEI7tNe.mjs.map +1 -0
  154. package/dist/version-DoxrVdYf.mjs +7 -0
  155. package/dist/{version-BnTKdfam.mjs.map → version-DoxrVdYf.mjs.map} +1 -1
  156. package/dist/zod-generator-CC0xNe_K.mjs +132 -0
  157. package/dist/zod-generator-CC0xNe_K.mjs.map +1 -0
  158. package/locals.d.ts +1 -6
  159. package/package.json +21 -7
  160. package/src/api/auth-storage.ts +37 -0
  161. package/src/api/error.ts +6 -0
  162. package/src/api/errors.ts +8 -0
  163. package/src/api/handlers/comments.ts +19 -4
  164. package/src/api/handlers/content.ts +151 -4
  165. package/src/api/handlers/device-flow.ts +5 -0
  166. package/src/api/handlers/index.ts +2 -0
  167. package/src/api/handlers/marketplace.ts +11 -4
  168. package/src/api/handlers/media.ts +8 -1
  169. package/src/api/handlers/menus.ts +160 -21
  170. package/src/api/handlers/oauth-authorization.ts +72 -33
  171. package/src/api/handlers/redirects.ts +16 -3
  172. package/src/api/handlers/revision.ts +23 -14
  173. package/src/api/handlers/sections.ts +8 -1
  174. package/src/api/handlers/taxonomies.ts +131 -22
  175. package/src/api/handlers/validation.ts +212 -0
  176. package/src/api/openapi/document.ts +4 -1
  177. package/src/api/public-url.ts +54 -5
  178. package/src/api/route-utils.ts +14 -0
  179. package/src/api/schemas/comments.ts +2 -2
  180. package/src/api/schemas/common.ts +1 -1
  181. package/src/api/schemas/content.ts +17 -0
  182. package/src/api/schemas/sections.ts +3 -3
  183. package/src/api/schemas/setup.ts +8 -0
  184. package/src/api/schemas/users.ts +1 -1
  185. package/src/api/schemas/widgets.ts +12 -10
  186. package/src/api/setup-complete.ts +40 -0
  187. package/src/api/types.ts +5 -1
  188. package/src/astro/integration/index.ts +30 -2
  189. package/src/astro/integration/routes.ts +28 -0
  190. package/src/astro/integration/runtime.ts +49 -1
  191. package/src/astro/integration/virtual-modules.ts +73 -2
  192. package/src/astro/integration/vite-config.ts +49 -13
  193. package/src/astro/middleware/auth.ts +34 -6
  194. package/src/astro/middleware/redirect.ts +29 -16
  195. package/src/astro/middleware/request-context.ts +15 -5
  196. package/src/astro/middleware.ts +41 -10
  197. package/src/astro/routes/PluginRegistry.tsx +10 -1
  198. package/src/astro/routes/api/auth/invite/complete.ts +6 -1
  199. package/src/astro/routes/api/auth/mode.ts +57 -0
  200. package/src/astro/routes/api/auth/oauth/[provider]/callback.ts +23 -3
  201. package/src/astro/routes/api/auth/oauth/[provider].ts +10 -4
  202. package/src/astro/routes/api/auth/passkey/register/verify.ts +6 -1
  203. package/src/astro/routes/api/auth/passkey/verify.ts +6 -1
  204. package/src/astro/routes/api/auth/signup/complete.ts +6 -1
  205. package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +2 -2
  206. package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +4 -2
  207. package/src/astro/routes/api/content/[collection]/[id]/preview-url.ts +34 -12
  208. package/src/astro/routes/api/content/[collection]/[id]/publish.ts +32 -2
  209. package/src/astro/routes/api/content/[collection]/[id]/restore.ts +4 -2
  210. package/src/astro/routes/api/content/[collection]/[id]/revisions.ts +3 -2
  211. package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +8 -4
  212. package/src/astro/routes/api/content/[collection]/[id]/translations.ts +1 -1
  213. package/src/astro/routes/api/content/[collection]/[id].ts +12 -0
  214. package/src/astro/routes/api/content/[collection]/index.ts +1 -9
  215. package/src/astro/routes/api/import/wordpress/execute.ts +3 -1
  216. package/src/astro/routes/api/import/wordpress/media.ts +2 -7
  217. package/src/astro/routes/api/import/wordpress/prepare.ts +9 -0
  218. package/src/astro/routes/api/import/wordpress-plugin/execute.ts +3 -1
  219. package/src/astro/routes/api/manifest.ts +62 -45
  220. package/src/astro/routes/api/media/[id]/confirm.ts +10 -1
  221. package/src/astro/routes/api/media/providers/[providerId]/index.ts +12 -3
  222. package/src/astro/routes/api/openapi.json.ts +27 -10
  223. package/src/astro/routes/api/redirects/404s/index.ts +10 -4
  224. package/src/astro/routes/api/redirects/404s/summary.ts +4 -2
  225. package/src/astro/routes/api/redirects/[id].ts +10 -4
  226. package/src/astro/routes/api/redirects/index.ts +7 -3
  227. package/src/astro/routes/api/revisions/[revisionId]/index.ts +1 -1
  228. package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +0 -2
  229. package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +0 -1
  230. package/src/astro/routes/api/schema/collections/[slug]/fields/reorder.ts +0 -1
  231. package/src/astro/routes/api/schema/collections/[slug]/index.ts +2 -2
  232. package/src/astro/routes/api/schema/collections/index.ts +1 -1
  233. package/src/astro/routes/api/search/index.ts +10 -2
  234. package/src/astro/routes/api/sections/[slug].ts +10 -4
  235. package/src/astro/routes/api/sections/index.ts +7 -3
  236. package/src/astro/routes/api/settings/email.ts +4 -9
  237. package/src/astro/routes/api/setup/admin-verify.ts +6 -1
  238. package/src/astro/routes/api/setup/admin.ts +8 -2
  239. package/src/astro/routes/api/setup/index.ts +2 -2
  240. package/src/astro/routes/api/setup/status.ts +3 -1
  241. package/src/astro/routes/api/snapshot.ts +44 -18
  242. package/src/astro/routes/api/taxonomies/index.ts +0 -1
  243. package/src/astro/routes/api/themes/preview.ts +11 -5
  244. package/src/astro/routes/api/widget-areas/[name]/widgets/[id].ts +4 -1
  245. package/src/astro/routes/api/widget-areas/[name]/widgets.ts +4 -1
  246. package/src/astro/routes/api/widget-areas/[name].ts +4 -1
  247. package/src/astro/routes/api/widget-areas/index.ts +4 -1
  248. package/src/astro/types.ts +32 -3
  249. package/src/auth/allowed-origins.ts +168 -0
  250. package/src/auth/mode.ts +15 -3
  251. package/src/auth/passkey-config.ts +35 -13
  252. package/src/auth/providers/github-admin.tsx +29 -0
  253. package/src/auth/providers/github.ts +31 -0
  254. package/src/auth/providers/google-admin.tsx +44 -0
  255. package/src/auth/providers/google.ts +31 -0
  256. package/src/auth/types.ts +114 -4
  257. package/src/bylines/index.ts +37 -88
  258. package/src/cli/commands/auth.ts +28 -6
  259. package/src/cli/commands/bundle-utils.ts +11 -2
  260. package/src/cli/commands/bundle.ts +31 -9
  261. package/src/cli/commands/content.ts +13 -0
  262. package/src/cli/commands/login.ts +8 -1
  263. package/src/cli/commands/publish.ts +24 -0
  264. package/src/cli/commands/secrets.ts +183 -0
  265. package/src/cli/credentials.ts +1 -1
  266. package/src/cli/index.ts +5 -1
  267. package/src/client/index.ts +4 -4
  268. package/src/client/transport.ts +17 -7
  269. package/src/components/Break.astro +2 -2
  270. package/src/components/EmDashHead.astro +18 -13
  271. package/src/components/EmDashImage.astro +7 -6
  272. package/src/components/Embed.astro +1 -1
  273. package/src/components/Gallery.astro +6 -4
  274. package/src/components/Image.astro +9 -4
  275. package/src/components/InlinePortableTextEditor.tsx +106 -19
  276. package/src/components/LiveSearch.astro +5 -14
  277. package/src/config/secrets.ts +528 -0
  278. package/src/database/dialect-helpers.ts +50 -0
  279. package/src/database/migrations/034_published_at_index.ts +1 -1
  280. package/src/database/migrations/035_bounded_404_log.ts +56 -39
  281. package/src/database/migrations/runner.ts +156 -23
  282. package/src/database/repositories/audit.ts +6 -8
  283. package/src/database/repositories/byline.ts +6 -8
  284. package/src/database/repositories/comment.ts +12 -16
  285. package/src/database/repositories/content.ts +76 -52
  286. package/src/database/repositories/index.ts +1 -1
  287. package/src/database/repositories/media.ts +10 -13
  288. package/src/database/repositories/plugin-storage.ts +4 -6
  289. package/src/database/repositories/redirect.ts +26 -19
  290. package/src/database/repositories/taxonomy.ts +40 -3
  291. package/src/database/repositories/types.ts +57 -8
  292. package/src/database/repositories/user.ts +6 -8
  293. package/src/db/libsql.ts +1 -3
  294. package/src/db/sqlite.ts +2 -5
  295. package/src/emdash-runtime.ts +388 -247
  296. package/src/index.ts +14 -1
  297. package/src/loader.ts +30 -6
  298. package/src/mcp/server.ts +781 -141
  299. package/src/media/normalize.ts +1 -1
  300. package/src/media/url.ts +78 -0
  301. package/src/page/site-identity.ts +58 -0
  302. package/src/plugins/adapt-sandbox-entry.ts +22 -10
  303. package/src/plugins/context.ts +13 -10
  304. package/src/plugins/define-plugin.ts +40 -12
  305. package/src/plugins/email-console.ts +10 -3
  306. package/src/plugins/hooks.ts +34 -19
  307. package/src/plugins/index.ts +9 -0
  308. package/src/plugins/manifest-schema.ts +49 -2
  309. package/src/plugins/types.ts +174 -13
  310. package/src/preview/urls.ts +23 -3
  311. package/src/query.ts +149 -6
  312. package/src/redirects/cache.ts +38 -18
  313. package/src/request-cache.ts +3 -0
  314. package/src/schema/registry.ts +97 -5
  315. package/src/schema/zod-generator.ts +27 -5
  316. package/src/search/fts-manager.ts +0 -2
  317. package/src/search/query.ts +111 -26
  318. package/src/search/types.ts +8 -1
  319. package/src/sections/index.ts +7 -9
  320. package/src/seed/apply.ts +2 -0
  321. package/src/settings/index.ts +80 -6
  322. package/src/settings/types.ts +23 -1
  323. package/src/storage/s3.ts +12 -6
  324. package/src/taxonomies/index.ts +11 -1
  325. package/src/virtual-modules.d.ts +21 -1
  326. package/src/widgets/index.ts +1 -1
  327. package/dist/apply-5uslYdUu.mjs.map +0 -1
  328. package/dist/byline-C4OVd8b3.mjs.map +0 -1
  329. package/dist/bylines-hPTW79hw.mjs +0 -157
  330. package/dist/bylines-hPTW79hw.mjs.map +0 -1
  331. package/dist/cache-BkKBuIvS.mjs +0 -56
  332. package/dist/cache-BkKBuIvS.mjs.map +0 -1
  333. package/dist/chunk-ClPoSABd.mjs +0 -21
  334. package/dist/content-D7J5y73J.mjs.map +0 -1
  335. package/dist/dialect-helpers-DhTzaUxP.mjs.map +0 -1
  336. package/dist/error-CiYn9yDu.mjs.map +0 -1
  337. package/dist/index-De6_Xv3v.d.mts.map +0 -1
  338. package/dist/loader-DeiBJEMe.mjs.map +0 -1
  339. package/dist/manifest-schema-V30qsMft.mjs.map +0 -1
  340. package/dist/media-DqHVh136.mjs.map +0 -1
  341. package/dist/mode-CpNnGkPz.mjs.map +0 -1
  342. package/dist/placeholder-C-fk5hYI.mjs.map +0 -1
  343. package/dist/query-g4Ug-9j9.mjs.map +0 -1
  344. package/dist/redirect-CN0Rt9Ob.mjs.map +0 -1
  345. package/dist/registry-Ci3WxVAr.mjs.map +0 -1
  346. package/dist/request-cache-DiR961CV.mjs.map +0 -1
  347. package/dist/runner-BR2xKwhn.d.mts +0 -34
  348. package/dist/runner-BR2xKwhn.d.mts.map +0 -1
  349. package/dist/search-B0effn3j.mjs.map +0 -1
  350. package/dist/taxonomies-K2z0Uhnj.mjs.map +0 -1
  351. package/dist/types-CMMN0pNg.mjs +0 -31
  352. package/dist/types-CMMN0pNg.mjs.map +0 -1
  353. package/dist/types-DgrIP0tF.d.mts.map +0 -1
  354. package/dist/version-BnTKdfam.mjs +0 -7
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Resolution and validation of multi-origin passkey verification.
3
+ *
4
+ * `allowedOrigins` lets one EmDash deployment accept passkey assertions from
5
+ * several hostnames sharing the same `rpId` (e.g. apex + preview/staging
6
+ * subdomains under one registrable parent). Origins come from two sources:
7
+ *
8
+ * - `EmDashConfig.allowedOrigins` (declared in `astro.config.mjs`)
9
+ * - `EMDASH_ALLOWED_ORIGINS` (comma-separated runtime env var)
10
+ *
11
+ * Sources are merged (union of permissions, deduplicated). Each entry is
12
+ * validated against `siteUrl` to fail loud on dead config the browser would
13
+ * never honor.
14
+ */
15
+
16
+ import { getEnvAllowedOrigins } from "../api/public-url.js";
17
+ import type { EmDashConfig } from "../astro/integration/runtime.js";
18
+
19
+ export type AllowedOriginSource = "config.allowedOrigins" | "EMDASH_ALLOWED_ORIGINS";
20
+
21
+ export interface TaggedOrigin {
22
+ /** Raw entry as declared by the operator. */
23
+ origin: string;
24
+ /** Where the entry came from (used for source-attributed errors). */
25
+ source: AllowedOriginSource;
26
+ }
27
+
28
+ /**
29
+ * Collect raw allowedOrigins from config and env, source-tagged.
30
+ *
31
+ * Returns raw values — the caller is expected to pass the result through
32
+ * `validateAllowedOrigins()` before use in passkey verification.
33
+ */
34
+ export function getConfiguredAllowedOrigins(config?: EmDashConfig): TaggedOrigin[] {
35
+ const tagged: TaggedOrigin[] = [];
36
+ if (config?.allowedOrigins) {
37
+ for (const origin of config.allowedOrigins) {
38
+ if (origin) tagged.push({ origin, source: "config.allowedOrigins" });
39
+ }
40
+ }
41
+ for (const origin of getEnvAllowedOrigins()) {
42
+ tagged.push({ origin, source: "EMDASH_ALLOWED_ORIGINS" });
43
+ }
44
+ return tagged;
45
+ }
46
+
47
+ /**
48
+ * Validate per-entry shape rules (no `siteUrl` needed):
49
+ * - parses as `URL`
50
+ * - protocol is `http:` or `https:`
51
+ * - hostname has no trailing dot (`example.com.` rejected)
52
+ * - hostname has no empty labels (`foo..example.com` rejected)
53
+ *
54
+ * Returns the deduplicated, normalized origin form (`URL.origin`) of every
55
+ * input, in input order. Throws on the first violation with a source-tagged
56
+ * error message.
57
+ */
58
+ export function validateOriginShape(tagged: TaggedOrigin[]): string[] {
59
+ const normalized: string[] = [];
60
+ const seen = new Set<string>();
61
+ for (const { origin, source } of tagged) {
62
+ let parsed: URL;
63
+ try {
64
+ parsed = new URL(origin);
65
+ } catch (e) {
66
+ throw configError(source, `invalid URL: "${origin}"`, e);
67
+ }
68
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
69
+ throw configError(
70
+ source,
71
+ `origin must be http or https: "${origin}" (got ${parsed.protocol})`,
72
+ );
73
+ }
74
+ if (parsed.hostname.endsWith(".")) {
75
+ throw configError(
76
+ source,
77
+ `hostname has a trailing dot: "${origin}". Remove the trailing dot — assertion origins from the browser do not include it.`,
78
+ );
79
+ }
80
+ if (parsed.hostname.split(".").includes("")) {
81
+ throw configError(source, `hostname has empty labels: "${origin}"`);
82
+ }
83
+ if (!seen.has(parsed.origin)) {
84
+ seen.add(parsed.origin);
85
+ normalized.push(parsed.origin);
86
+ }
87
+ }
88
+ return normalized;
89
+ }
90
+
91
+ /**
92
+ * Validate the effective merged allowedOrigins set against `siteUrl`.
93
+ *
94
+ * Performs `validateOriginShape()` plus the siteUrl-dependent rules:
95
+ * - Rule A: non-empty origins ⇒ `siteUrl` is set
96
+ * - `siteUrl` hostname is not an IP literal (multi-origin requires a domain)
97
+ * - `siteUrl` hostname has no trailing dot (cannot match assertion origins)
98
+ * - Rule B: each origin's hostname is `siteHost` exactly or a subdomain
99
+ *
100
+ * Throws on first violation. Returns the deduplicated normalized origins.
101
+ *
102
+ * Use this at the runtime chokepoint (where config + env are merged into the
103
+ * effective set). At Astro integration init, prefer `validateOriginShape()`
104
+ * for shape-only checks on `config.allowedOrigins`, since `siteUrl` may be
105
+ * supplied at runtime via `EMDASH_SITE_URL`.
106
+ */
107
+ export function validateAllowedOrigins(
108
+ siteUrl: string | undefined,
109
+ tagged: TaggedOrigin[],
110
+ ): string[] {
111
+ const normalized = validateOriginShape(tagged);
112
+ if (normalized.length === 0) return normalized;
113
+
114
+ if (!siteUrl) {
115
+ throw new Error(
116
+ `EmDash config error: allowedOrigins is set (${normalized.length} ${
117
+ normalized.length === 1 ? "entry" : "entries"
118
+ }) but siteUrl is not. Without a canonical siteUrl, rpId is derived from the request hostname, defeating multi-origin passkeys. Set siteUrl in astro.config.mjs or via EMDASH_SITE_URL.`,
119
+ );
120
+ }
121
+
122
+ let siteHost: string;
123
+ try {
124
+ siteHost = new URL(siteUrl).hostname;
125
+ } catch (e) {
126
+ throw new Error(`EmDash config error: siteUrl is not a valid URL: "${siteUrl}"`, {
127
+ cause: e,
128
+ });
129
+ }
130
+
131
+ if (siteHost.endsWith(".")) {
132
+ throw new Error(
133
+ `EmDash config error: siteUrl "${siteUrl}" has a trailing-dot hostname, which cannot match assertion origins. Remove the trailing dot when using allowedOrigins.`,
134
+ );
135
+ }
136
+ if (isIPLiteralHostname(siteHost)) {
137
+ throw new Error(
138
+ `EmDash config error: siteUrl "${siteUrl}" uses an IP-literal hostname. Multi-origin passkeys require a domain-based siteUrl — IP addresses cannot have valid subdomains for WebAuthn rpId.`,
139
+ );
140
+ }
141
+
142
+ for (const { origin, source } of tagged) {
143
+ const h = new URL(origin).hostname;
144
+ if (h !== siteHost && !h.endsWith("." + siteHost)) {
145
+ throw configError(
146
+ source,
147
+ `"${origin}" is not a subdomain of siteUrl "${siteUrl}". Allowed origins must be the same hostname as siteUrl or a subdomain of it.`,
148
+ );
149
+ }
150
+ }
151
+
152
+ return normalized;
153
+ }
154
+
155
+ function configError(source: AllowedOriginSource, detail: string, cause?: unknown): Error {
156
+ const err = new Error(`EmDash config error in ${source}: ${detail}`);
157
+ if (cause !== undefined) (err as Error & { cause?: unknown }).cause = cause;
158
+ return err;
159
+ }
160
+
161
+ const IPV4_DOTTED_DECIMAL_RE = /^\d+(\.\d+){3}$/;
162
+
163
+ function isIPLiteralHostname(h: string): boolean {
164
+ // IPv6 hostnames are bracketed by URL.hostname, e.g. "[::1]"
165
+ if (h.startsWith("[")) return true;
166
+ // IPv4 dotted-decimal
167
+ return IPV4_DOTTED_DECIMAL_RE.test(h);
168
+ }
package/src/auth/mode.ts CHANGED
@@ -6,9 +6,21 @@
6
6
  */
7
7
 
8
8
  import type { EmDashConfig } from "../astro/integration/runtime.js";
9
- import type { AuthDescriptor, AuthResult, ExternalAuthConfig } from "./types.js";
9
+ import type {
10
+ AuthDescriptor,
11
+ AuthProviderDescriptor,
12
+ AuthRouteDescriptor,
13
+ AuthResult,
14
+ ExternalAuthConfig,
15
+ } from "./types.js";
10
16
 
11
- export type { AuthDescriptor, AuthResult, ExternalAuthConfig };
17
+ export type {
18
+ AuthDescriptor,
19
+ AuthProviderDescriptor,
20
+ AuthRouteDescriptor,
21
+ AuthResult,
22
+ ExternalAuthConfig,
23
+ };
12
24
 
13
25
  /**
14
26
  * Passkey auth mode (default)
@@ -59,7 +71,7 @@ export function getAuthMode(
59
71
  ): AuthMode {
60
72
  const auth = config?.auth;
61
73
 
62
- // Check for AuthDescriptor (new style)
74
+ // Check for AuthDescriptor (transparent external auth like Cloudflare Access)
63
75
  if (auth && "entrypoint" in auth && auth.entrypoint) {
64
76
  return {
65
77
  type: "external",
@@ -9,7 +9,12 @@
9
9
  export interface PasskeyConfig {
10
10
  rpName: string;
11
11
  rpId: string;
12
- origin: string;
12
+ /**
13
+ * Accepted client-data origins. First entry is the canonical/preferred origin;
14
+ * additional entries support multi-origin deployments (e.g. apex + preview
15
+ * subdomain sharing the same `rpId`). See `allowedOrigins` parameter.
16
+ */
17
+ origins: string[];
13
18
  }
14
19
 
15
20
  /**
@@ -18,10 +23,22 @@ export interface PasskeyConfig {
18
23
  * @param url The request URL (typically `new URL(Astro.request.url)` or `new URL(request.url)`)
19
24
  * @param siteName Optional site name for rpName (defaults to hostname from `url` or public origin)
20
25
  * @param siteUrl Optional browser-facing origin (see `EmDashConfig.siteUrl`).
21
- * When set, **origin** and **rpId** are taken from this URL so they match WebAuthn `clientData.origin`.
26
+ * When set, the canonical **origin** and **rpId** are taken from this URL.
27
+ * @param allowedOrigins Optional list of additional accepted origins for verification.
28
+ * Each must share `rpId` with the canonical origin (WebAuthn requirement).
29
+ * Typical use: apex + preview subdomain on the same registrable domain.
22
30
  * @throws If `siteUrl` is non-empty but not parseable by `new URL()`.
23
31
  */
24
- export function getPasskeyConfig(url: URL, siteName?: string, siteUrl?: string): PasskeyConfig {
32
+ export function getPasskeyConfig(
33
+ url: URL,
34
+ siteName?: string,
35
+ siteUrl?: string,
36
+ allowedOrigins?: string[],
37
+ ): PasskeyConfig {
38
+ let rpName: string;
39
+ let rpId: string;
40
+ let canonicalOrigin: string;
41
+
25
42
  if (siteUrl) {
26
43
  let publicUrl: URL;
27
44
  try {
@@ -29,16 +46,21 @@ export function getPasskeyConfig(url: URL, siteName?: string, siteUrl?: string):
29
46
  } catch (e) {
30
47
  throw new Error(`Invalid siteUrl: "${siteUrl}"`, { cause: e });
31
48
  }
32
- return {
33
- rpName: siteName || publicUrl.hostname,
34
- rpId: publicUrl.hostname,
35
- origin: publicUrl.origin,
36
- };
49
+ rpName = siteName || publicUrl.hostname;
50
+ rpId = publicUrl.hostname;
51
+ canonicalOrigin = publicUrl.origin;
52
+ } else {
53
+ rpName = siteName || url.hostname;
54
+ rpId = url.hostname;
55
+ canonicalOrigin = url.origin;
56
+ }
57
+
58
+ const origins = [canonicalOrigin];
59
+ if (allowedOrigins) {
60
+ for (const extra of allowedOrigins) {
61
+ if (extra && !origins.includes(extra)) origins.push(extra);
62
+ }
37
63
  }
38
64
 
39
- return {
40
- rpName: siteName || url.hostname,
41
- rpId: url.hostname,
42
- origin: url.origin,
43
- };
65
+ return { rpName, rpId, origins };
44
66
  }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * GitHub OAuth Admin Components
3
+ *
4
+ * LoginButton for the login page, rendered via the auth provider virtual module.
5
+ */
6
+
7
+ import { LinkButton } from "@cloudflare/kumo";
8
+ import * as React from "react";
9
+
10
+ function GitHubIcon({ className }: { className?: string }) {
11
+ return (
12
+ <svg className={className} viewBox="0 0 24 24" fill="currentColor">
13
+ <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
14
+ </svg>
15
+ );
16
+ }
17
+
18
+ export function LoginButton() {
19
+ return (
20
+ <LinkButton
21
+ href="/_emdash/api/auth/oauth/github"
22
+ variant="outline"
23
+ className="w-full justify-center"
24
+ >
25
+ <GitHubIcon className="h-5 w-5" />
26
+ <span>GitHub</span>
27
+ </LinkButton>
28
+ );
29
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * GitHub OAuth Auth Provider
3
+ *
4
+ * Returns an AuthProviderDescriptor for GitHub OAuth login.
5
+ * Credentials are read from environment variables at runtime.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { github } from "emdash/auth/providers/github";
10
+ *
11
+ * emdash({
12
+ * authProviders: [github()],
13
+ * })
14
+ * ```
15
+ */
16
+
17
+ import type { AuthProviderDescriptor } from "../types.js";
18
+
19
+ /**
20
+ * Configure GitHub OAuth as an auth provider.
21
+ *
22
+ * Requires `EMDASH_OAUTH_GITHUB_CLIENT_ID` and `EMDASH_OAUTH_GITHUB_CLIENT_SECRET`
23
+ * (or `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET`) environment variables.
24
+ */
25
+ export function github(): AuthProviderDescriptor {
26
+ return {
27
+ id: "github",
28
+ label: "GitHub",
29
+ adminEntry: "emdash/auth/providers/github-admin",
30
+ };
31
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Google OAuth Admin Components
3
+ *
4
+ * LoginButton for the login page, rendered via the auth provider virtual module.
5
+ */
6
+
7
+ import { LinkButton } from "@cloudflare/kumo";
8
+ import * as React from "react";
9
+
10
+ function GoogleIcon({ className }: { className?: string }) {
11
+ return (
12
+ <svg className={className} viewBox="0 0 24 24">
13
+ <path
14
+ fill="#4285F4"
15
+ d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
16
+ />
17
+ <path
18
+ fill="#34A853"
19
+ d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
20
+ />
21
+ <path
22
+ fill="#FBBC05"
23
+ d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
24
+ />
25
+ <path
26
+ fill="#EA4335"
27
+ d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
28
+ />
29
+ </svg>
30
+ );
31
+ }
32
+
33
+ export function LoginButton() {
34
+ return (
35
+ <LinkButton
36
+ href="/_emdash/api/auth/oauth/google"
37
+ variant="outline"
38
+ className="w-full justify-center"
39
+ >
40
+ <GoogleIcon className="h-5 w-5" />
41
+ <span>Google</span>
42
+ </LinkButton>
43
+ );
44
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Google OAuth Auth Provider
3
+ *
4
+ * Returns an AuthProviderDescriptor for Google OAuth login.
5
+ * Credentials are read from environment variables at runtime.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { google } from "emdash/auth/providers/google";
10
+ *
11
+ * emdash({
12
+ * authProviders: [google()],
13
+ * })
14
+ * ```
15
+ */
16
+
17
+ import type { AuthProviderDescriptor } from "../types.js";
18
+
19
+ /**
20
+ * Configure Google OAuth as an auth provider.
21
+ *
22
+ * Requires `EMDASH_OAUTH_GOOGLE_CLIENT_ID` and `EMDASH_OAUTH_GOOGLE_CLIENT_SECRET`
23
+ * (or `GOOGLE_CLIENT_ID` / `GOOGLE_CLIENT_SECRET`) environment variables.
24
+ */
25
+ export function google(): AuthProviderDescriptor {
26
+ return {
27
+ id: "google",
28
+ label: "Google",
29
+ adminEntry: "emdash/auth/providers/google-admin",
30
+ };
31
+ }
package/src/auth/types.ts CHANGED
@@ -2,7 +2,13 @@
2
2
  * Auth Provider Types
3
3
  *
4
4
  * Defines the interfaces for pluggable authentication providers.
5
- * Providers like Cloudflare Access implement these interfaces.
5
+ *
6
+ * Two systems coexist:
7
+ * - `AuthDescriptor` — transparent auth (Cloudflare Access) that authenticates
8
+ * every request via headers/cookies. No login UI needed.
9
+ * - `AuthProviderDescriptor` — pluggable login methods (GitHub, Google,
10
+ * AT Protocol, etc.) that appear as options on the login page and setup
11
+ * wizard. Passkey is built-in; providers are additive.
6
12
  */
7
13
 
8
14
  /**
@@ -22,10 +28,10 @@ export interface AuthResult {
22
28
  }
23
29
 
24
30
  /**
25
- * Auth descriptor - returned by auth adapter functions (e.g., access())
31
+ * Auth descriptor transparent auth providers (e.g., Cloudflare Access).
26
32
  *
27
- * Similar to DatabaseDescriptor and StorageDescriptor, this allows
28
- * auth providers to be configured at build time and loaded at runtime.
33
+ * These authenticate every request via headers/cookies. No login UI needed.
34
+ * The module's `authenticate()` function is called by middleware on each request.
29
35
  */
30
36
  export interface AuthDescriptor {
31
37
  /**
@@ -64,6 +70,110 @@ export interface AuthProviderModule {
64
70
  authenticate(request: Request, config: unknown): Promise<AuthResult>;
65
71
  }
66
72
 
73
+ // ---------------------------------------------------------------------------
74
+ // Pluggable Auth Providers (additive login methods)
75
+ // ---------------------------------------------------------------------------
76
+
77
+ /**
78
+ * Descriptor for a pluggable auth provider.
79
+ *
80
+ * Auth providers appear as login options on the login page and setup wizard.
81
+ * They coexist with passkey (which is built-in) and with each other.
82
+ * Any provider can be used to create the initial admin account.
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * // astro.config.ts
87
+ * import { atproto } from "@emdash-cms/auth-atproto";
88
+ *
89
+ * emdash({
90
+ * authProviders: [atproto(), github(), google()],
91
+ * })
92
+ * ```
93
+ */
94
+ export interface AuthProviderDescriptor {
95
+ /** Unique provider ID (e.g., "github", "atproto") */
96
+ id: string;
97
+
98
+ /** Human-readable label for UI (e.g., "GitHub", "AT Protocol") */
99
+ label: string;
100
+
101
+ /** Provider-specific config (JSON-serializable) */
102
+ config?: unknown;
103
+
104
+ /**
105
+ * Module exporting React components for the admin UI.
106
+ * Statically imported at build time via virtual module.
107
+ *
108
+ * The module should export components matching `AuthProviderAdminExports`.
109
+ */
110
+ adminEntry?: string;
111
+
112
+ /**
113
+ * Astro route handlers this provider needs injected at build time.
114
+ * Used for login initiation, OAuth callbacks, well-known endpoints, etc.
115
+ */
116
+ routes?: AuthRouteDescriptor[];
117
+
118
+ /**
119
+ * URL prefixes/paths that should bypass auth middleware.
120
+ * Added to the public routes set so login/callback endpoints work
121
+ * for unauthenticated users.
122
+ */
123
+ publicRoutes?: string[];
124
+
125
+ /**
126
+ * Storage collections for persistent auth state (e.g., OAuth sessions).
127
+ * Same format as plugin storage — collections are stored in the shared
128
+ * `_plugin_storage` table namespaced under `auth:<providerId>`.
129
+ *
130
+ * Access via `getAuthProviderStorage()` from `emdash/api/route-utils`.
131
+ */
132
+ storage?: Record<
133
+ string,
134
+ { indexes?: Array<string | string[]>; uniqueIndexes?: Array<string | string[]> }
135
+ >;
136
+ }
137
+
138
+ /**
139
+ * A route that an auth provider needs injected into the Astro app.
140
+ */
141
+ export interface AuthRouteDescriptor {
142
+ /** URL pattern (e.g., "/_emdash/api/auth/atproto/login") */
143
+ pattern: string;
144
+ /** Module specifier for the Astro route handler */
145
+ entrypoint: string;
146
+ }
147
+
148
+ /**
149
+ * Expected exports from an auth provider's `adminEntry` module.
150
+ *
151
+ * All exports are optional. Providers export whichever components
152
+ * make sense for their auth flow.
153
+ */
154
+ export interface AuthProviderAdminExports {
155
+ /**
156
+ * Compact button for the login page (icon + label).
157
+ * Used for providers with a simple redirect flow (GitHub, Google).
158
+ * Rendered in the "Or continue with" section.
159
+ */
160
+ LoginButton?: import("react").ComponentType;
161
+
162
+ /**
163
+ * Full login form for providers that need custom input.
164
+ * Used for providers like AT Protocol that need a handle field.
165
+ * Rendered as an expandable section on the login page.
166
+ */
167
+ LoginForm?: import("react").ComponentType;
168
+
169
+ /**
170
+ * Setup wizard step for creating the admin account via this provider.
171
+ * When present, this provider appears as an option in the setup wizard's
172
+ * "Create admin account" step.
173
+ */
174
+ SetupStep?: import("react").ComponentType<{ onComplete: () => void }>;
175
+ }
176
+
67
177
  /**
68
178
  * Configuration options common to external auth providers
69
179
  */