@notionx/core 0.1.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 (208) hide show
  1. package/dist/admin/index.d.ts +137 -0
  2. package/dist/admin/index.js +206 -0
  3. package/dist/admin/index.js.map +1 -0
  4. package/dist/admin/pages/index.d.ts +324 -0
  5. package/dist/admin/pages/index.js +827 -0
  6. package/dist/admin/pages/index.js.map +1 -0
  7. package/dist/auth/auth-pages/forgot-password.d.ts +20 -0
  8. package/dist/auth/auth-pages/forgot-password.js +70 -0
  9. package/dist/auth/auth-pages/forgot-password.js.map +1 -0
  10. package/dist/auth/auth-pages/index.d.ts +6 -0
  11. package/dist/auth/auth-pages/index.js +342 -0
  12. package/dist/auth/auth-pages/index.js.map +1 -0
  13. package/dist/auth/auth-pages/login.d.ts +30 -0
  14. package/dist/auth/auth-pages/login.js +125 -0
  15. package/dist/auth/auth-pages/login.js.map +1 -0
  16. package/dist/auth/auth-pages/register.d.ts +17 -0
  17. package/dist/auth/auth-pages/register.js +81 -0
  18. package/dist/auth/auth-pages/register.js.map +1 -0
  19. package/dist/auth/auth-pages/reset-password.d.ts +18 -0
  20. package/dist/auth/auth-pages/reset-password.js +72 -0
  21. package/dist/auth/auth-pages/reset-password.js.map +1 -0
  22. package/dist/auth/index.d.ts +72 -0
  23. package/dist/auth/index.js +1011 -0
  24. package/dist/auth/index.js.map +1 -0
  25. package/dist/auth/passwords.d.ts +6 -0
  26. package/dist/auth/passwords.js +79 -0
  27. package/dist/auth/passwords.js.map +1 -0
  28. package/dist/auth/rate-limit.d.ts +28 -0
  29. package/dist/auth/rate-limit.js +245 -0
  30. package/dist/auth/rate-limit.js.map +1 -0
  31. package/dist/auth/routes/google-callback.d.ts +6 -0
  32. package/dist/auth/routes/google-callback.js +404 -0
  33. package/dist/auth/routes/google-callback.js.map +1 -0
  34. package/dist/auth/routes/google.d.ts +6 -0
  35. package/dist/auth/routes/google.js +250 -0
  36. package/dist/auth/routes/google.js.map +1 -0
  37. package/dist/auth/routes/index.d.ts +22 -0
  38. package/dist/auth/routes/index.js +619 -0
  39. package/dist/auth/routes/index.js.map +1 -0
  40. package/dist/auth/routes/verify-email.d.ts +6 -0
  41. package/dist/auth/routes/verify-email.js +317 -0
  42. package/dist/auth/routes/verify-email.js.map +1 -0
  43. package/dist/auth/routes/viewer.d.ts +6 -0
  44. package/dist/auth/routes/viewer.js +372 -0
  45. package/dist/auth/routes/viewer.js.map +1 -0
  46. package/dist/auth/session.d.ts +9 -0
  47. package/dist/auth/session.js +1 -0
  48. package/dist/auth/session.js.map +1 -0
  49. package/dist/auth/turnstile.d.ts +20 -0
  50. package/dist/auth/turnstile.js +301 -0
  51. package/dist/auth/turnstile.js.map +1 -0
  52. package/dist/auth/user-session.d.ts +42 -0
  53. package/dist/auth/user-session.js +419 -0
  54. package/dist/auth/user-session.js.map +1 -0
  55. package/dist/auth/users.d.ts +112 -0
  56. package/dist/auth/users.js +558 -0
  57. package/dist/auth/users.js.map +1 -0
  58. package/dist/bootstrap-CN2g76M6.d.ts +67 -0
  59. package/dist/cache/index.d.ts +6 -0
  60. package/dist/cache/index.js +47 -0
  61. package/dist/cache/index.js.map +1 -0
  62. package/dist/content/admin-summary.d.ts +24 -0
  63. package/dist/content/admin-summary.js +36 -0
  64. package/dist/content/admin-summary.js.map +1 -0
  65. package/dist/content/index.d.ts +9 -0
  66. package/dist/content/index.js +473 -0
  67. package/dist/content/index.js.map +1 -0
  68. package/dist/content/models.d.ts +69 -0
  69. package/dist/content/models.js +24 -0
  70. package/dist/content/models.js.map +1 -0
  71. package/dist/content/prewarm.d.ts +28 -0
  72. package/dist/content/prewarm.js +56 -0
  73. package/dist/content/prewarm.js.map +1 -0
  74. package/dist/content/revalidate.d.ts +37 -0
  75. package/dist/content/revalidate.js +170 -0
  76. package/dist/content/revalidate.js.map +1 -0
  77. package/dist/content/search-index.d.ts +54 -0
  78. package/dist/content/search-index.js +172 -0
  79. package/dist/content/search-index.js.map +1 -0
  80. package/dist/content/search.d.ts +8 -0
  81. package/dist/content/search.js +57 -0
  82. package/dist/content/search.js.map +1 -0
  83. package/dist/doctor/cli.d.ts +1 -0
  84. package/dist/doctor/cli.js +360 -0
  85. package/dist/doctor/cli.js.map +1 -0
  86. package/dist/doctor/index.d.ts +139 -0
  87. package/dist/doctor/index.js +289 -0
  88. package/dist/doctor/index.js.map +1 -0
  89. package/dist/email/index.d.ts +38 -0
  90. package/dist/email/index.js +126 -0
  91. package/dist/email/index.js.map +1 -0
  92. package/dist/env-C5qu-0R-.d.ts +35 -0
  93. package/dist/hooks/index.d.ts +2 -0
  94. package/dist/hooks/index.js +1 -0
  95. package/dist/hooks/index.js.map +1 -0
  96. package/dist/i18n/index.d.ts +26 -0
  97. package/dist/i18n/index.js +73 -0
  98. package/dist/i18n/index.js.map +1 -0
  99. package/dist/index.d.ts +8 -0
  100. package/dist/index.js +1281 -0
  101. package/dist/index.js.map +1 -0
  102. package/dist/internal/admin/index.d.ts +75 -0
  103. package/dist/internal/admin/index.js +365 -0
  104. package/dist/internal/admin/index.js.map +1 -0
  105. package/dist/media/index.d.ts +24 -0
  106. package/dist/media/index.js +86 -0
  107. package/dist/media/index.js.map +1 -0
  108. package/dist/media/routes/index.d.ts +1 -0
  109. package/dist/media/routes/index.js +585 -0
  110. package/dist/media/routes/index.js.map +1 -0
  111. package/dist/media/routes/notion-media.d.ts +19 -0
  112. package/dist/media/routes/notion-media.js +588 -0
  113. package/dist/media/routes/notion-media.js.map +1 -0
  114. package/dist/middleware.d.ts +95 -0
  115. package/dist/middleware.js +79 -0
  116. package/dist/middleware.js.map +1 -0
  117. package/dist/notion/block-text.d.ts +5 -0
  118. package/dist/notion/block-text.js +37 -0
  119. package/dist/notion/block-text.js.map +1 -0
  120. package/dist/notion/blocks.d.ts +24 -0
  121. package/dist/notion/blocks.js +46 -0
  122. package/dist/notion/blocks.js.map +1 -0
  123. package/dist/notion/client.d.ts +7 -0
  124. package/dist/notion/client.js +13 -0
  125. package/dist/notion/client.js.map +1 -0
  126. package/dist/notion/config.d.ts +25 -0
  127. package/dist/notion/config.js +147 -0
  128. package/dist/notion/config.js.map +1 -0
  129. package/dist/notion/content-cache.d.ts +45 -0
  130. package/dist/notion/content-cache.js +166 -0
  131. package/dist/notion/content-cache.js.map +1 -0
  132. package/dist/notion/generic-source.d.ts +61 -0
  133. package/dist/notion/generic-source.js +408 -0
  134. package/dist/notion/generic-source.js.map +1 -0
  135. package/dist/notion/index.d.ts +13 -0
  136. package/dist/notion/index.js +1278 -0
  137. package/dist/notion/index.js.map +1 -0
  138. package/dist/notion/mappers.d.ts +1 -0
  139. package/dist/notion/mappers.js +152 -0
  140. package/dist/notion/mappers.js.map +1 -0
  141. package/dist/notion/media.d.ts +22 -0
  142. package/dist/notion/media.js +209 -0
  143. package/dist/notion/media.js.map +1 -0
  144. package/dist/notion/property-mappers.d.ts +24 -0
  145. package/dist/notion/property-mappers.js +152 -0
  146. package/dist/notion/property-mappers.js.map +1 -0
  147. package/dist/notion/routes/index.d.ts +8 -0
  148. package/dist/notion/routes/index.js +428 -0
  149. package/dist/notion/routes/index.js.map +1 -0
  150. package/dist/notion/routes/webhook.d.ts +98 -0
  151. package/dist/notion/routes/webhook.js +428 -0
  152. package/dist/notion/routes/webhook.js.map +1 -0
  153. package/dist/notion/types.d.ts +152 -0
  154. package/dist/notion/types.js +1 -0
  155. package/dist/notion/types.js.map +1 -0
  156. package/dist/notion/webhook.d.ts +83 -0
  157. package/dist/notion/webhook.js +490 -0
  158. package/dist/notion/webhook.js.map +1 -0
  159. package/dist/platform/capabilities.d.ts +34 -0
  160. package/dist/platform/capabilities.js +42 -0
  161. package/dist/platform/capabilities.js.map +1 -0
  162. package/dist/platform/current.d.ts +13 -0
  163. package/dist/platform/current.js +181 -0
  164. package/dist/platform/current.js.map +1 -0
  165. package/dist/platform/index.d.ts +5 -0
  166. package/dist/platform/index.js +269 -0
  167. package/dist/platform/index.js.map +1 -0
  168. package/dist/platform/runtime.d.ts +118 -0
  169. package/dist/platform/runtime.js +160 -0
  170. package/dist/platform/runtime.js.map +1 -0
  171. package/dist/platform/selection.d.ts +10 -0
  172. package/dist/platform/selection.js +22 -0
  173. package/dist/platform/selection.js.map +1 -0
  174. package/dist/storage/index.d.ts +17 -0
  175. package/dist/storage/index.js +218 -0
  176. package/dist/storage/index.js.map +1 -0
  177. package/dist/storage/routes/cdn.d.ts +19 -0
  178. package/dist/storage/routes/cdn.js +289 -0
  179. package/dist/storage/routes/cdn.js.map +1 -0
  180. package/dist/storage/routes/files.d.ts +27 -0
  181. package/dist/storage/routes/files.js +216 -0
  182. package/dist/storage/routes/files.js.map +1 -0
  183. package/dist/storage/routes/index.d.ts +2 -0
  184. package/dist/storage/routes/index.js +352 -0
  185. package/dist/storage/routes/index.js.map +1 -0
  186. package/dist/types-BsAcZSNX.d.ts +94 -0
  187. package/dist/types.d.ts +78 -0
  188. package/dist/types.js +1 -0
  189. package/dist/types.js.map +1 -0
  190. package/dist/util/index.d.ts +18 -0
  191. package/dist/util/index.js +48 -0
  192. package/dist/util/index.js.map +1 -0
  193. package/dist/worker/index.d.ts +6 -0
  194. package/dist/worker/index.js +1026 -0
  195. package/dist/worker/index.js.map +1 -0
  196. package/dist/worker/routes/content-prewarm.d.ts +34 -0
  197. package/dist/worker/routes/content-prewarm.js +38 -0
  198. package/dist/worker/routes/content-prewarm.js.map +1 -0
  199. package/dist/worker/routes/content-revalidate.d.ts +81 -0
  200. package/dist/worker/routes/content-revalidate.js +64 -0
  201. package/dist/worker/routes/content-revalidate.js.map +1 -0
  202. package/dist/worker/routes/health.d.ts +14 -0
  203. package/dist/worker/routes/health.js +278 -0
  204. package/dist/worker/routes/health.js.map +1 -0
  205. package/dist/worker/routes/index.d.ts +6 -0
  206. package/dist/worker/routes/index.js +373 -0
  207. package/dist/worker/routes/index.js.map +1 -0
  208. package/package.json +124 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/admin/pages/delete-button.tsx","../../../src/admin/pages/dashboard.tsx","../../../src/admin/pages/users.tsx","../../../src/admin/pages/settings.tsx","../../../src/admin/pages/account.tsx","../../../src/admin/pages/content-models.tsx","../../../src/admin/pages/index.ts","../../../src/admin/pages/delete-button-lazy.tsx","../../../src/admin/pages/loading.tsx"],"sourcesContent":["// admin/pages/delete-button.tsx\n//\n// Generic admin \"Delete\" button. Wraps a destructive form action in\n// an alert dialog. Used in the admin review queue and other places\n// where an admin needs to confirm a destructive action. The\n// `deletePostAction` is supplied via `context.actions.deletePost`;\n// UI primitives come from `context.ui`.\n\n\"use client\";\n\nimport { useRef, useState } from \"react\";\nimport { Trash2 } from \"lucide-react\";\nimport type { AdminPageContext } from \"./types\";\n\nexport interface AdminDeleteButtonProps {\n context: AdminPageContext;\n slug: string;\n title: string;\n}\n\nexport default function AdminDeleteButton({\n context,\n slug,\n title,\n}: AdminDeleteButtonProps) {\n const { ui, actions } = context;\n const { Button, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } = ui;\n\n const formRef = useRef<HTMLFormElement>(null);\n const [open, setOpen] = useState(false);\n const deleteAction = actions?.deletePost;\n\n if (!deleteAction) return null;\n\n return (\n <AlertDialog open={open} onOpenChange={setOpen}>\n <AlertDialogTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-destructive hover:text-destructive\"\n >\n <Trash2 className=\"mr-1 h-3 w-3\" />\n 删除\n </Button>\n </AlertDialogTrigger>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>确定要删除这篇文章吗?</AlertDialogTitle>\n <AlertDialogDescription>\n <span className=\"font-medium text-foreground\">{title}</span>\n <br />\n <code className=\"rounded bg-muted px-1.5 py-0.5 text-xs\">{slug}</code>\n <br />\n <br />\n 此操作不可撤销。文章将从 D1 数据库和博客列表中永久移除。\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>取消</AlertDialogCancel>\n <AlertDialogAction\n onClick={() => formRef.current?.requestSubmit()}\n className=\"bg-destructive text-destructive-foreground hover:bg-destructive/90\"\n >\n 确认删除\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n <form ref={formRef} action={deleteAction} style={{ display: \"none\" }}>\n <input type=\"hidden\" name=\"slug\" value={slug} />\n </form>\n </AlertDialog>\n );\n}\n","// admin/pages/dashboard.tsx\n//\n// Generic admin dashboard. Renders a list of the most recent\n// Notion-managed posts with quick links to view, edit, and open in\n// Notion. The dashboard's data comes from `context.data.getNotionPostsMeta`\n// and `context.data.getNotionEditBaseUrl`. UI primitives come from\n// `context.ui`.\n\nimport Link from \"next/link\";\nimport { ExternalLink, Plus } from \"lucide-react\";\nimport type { AdminPageContext } from \"./types\";\n\nexport interface AdminDashboardPageProps {\n context: AdminPageContext;\n searchParams: {\n error?: string;\n };\n}\n\nexport default async function AdminDashboardPage({\n context,\n searchParams,\n}: AdminDashboardPageProps) {\n const { ui, data } = context;\n const { Button, Badge, Table, TableHeader, TableBody, TableRow, TableHead, TableCell, Alert, AlertTitle, AlertDescription } = ui;\n\n const { error } = searchParams;\n const posts = (await data?.getNotionPostsMeta?.()) ?? [];\n const notionHref = data?.getNotionEditBaseUrl?.() ?? \"#\";\n\n return (\n <div className=\"space-y-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-3xl font-bold tracking-tight\">文章管理</h1>\n <p className=\"text-sm text-muted-foreground\">\n 内容现由 Notion 管理,这里展示公开索引。\n </p>\n </div>\n <Button asChild>\n <a href={notionHref} target=\"_blank\" rel=\"noreferrer\">\n <Plus className=\"mr-1 h-4 w-4\" />\n 在 Notion 中新建\n </a>\n </Button>\n </div>\n\n {error && (\n <Alert variant=\"destructive\">\n <AlertTitle>无法访问</AlertTitle>\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n )}\n\n {posts.length === 0 ? (\n <div className=\"rounded-lg border border-dashed py-16 text-center text-sm text-muted-foreground\">\n 还没有可显示的 Notion 文章。\n </div>\n ) : (\n <div className=\"rounded-md border\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"w-[40%]\">标题</TableHead>\n <TableHead>作者</TableHead>\n <TableHead>日期</TableHead>\n <TableHead>标签</TableHead>\n <TableHead className=\"text-right\">操作</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {posts.map((post) => (\n <TableRow key={post.slug}>\n <TableCell className=\"font-medium\">{post.title}</TableCell>\n <TableCell>\n <span className=\"text-xs text-muted-foreground\">\n {post.author}\n </span>\n </TableCell>\n <TableCell>\n <time dateTime={post.date}>{post.date}</time>\n </TableCell>\n <TableCell>\n <div className=\"flex flex-wrap gap-1\">\n {post.tags.slice(0, 2).map((tag) => (\n <Badge key={tag} variant=\"secondary\" className=\"text-xs\">\n {tag}\n </Badge>\n ))}\n {post.tags.length > 2 && (\n <span className=\"text-xs text-muted-foreground\">\n +{post.tags.length - 2}\n </span>\n )}\n </div>\n </TableCell>\n <TableCell className=\"text-right\">\n <div className=\"flex items-center justify-end gap-2\">\n <Button asChild variant=\"ghost\" size=\"sm\">\n <Link href={`/blog/${post.slug}`} prefetch={true}>\n 查看\n </Link>\n </Button>\n <Button asChild variant=\"ghost\" size=\"sm\">\n <Link href={`/admin/${post.slug}/edit`} prefetch={true}>\n 编辑\n </Link>\n </Button>\n {post.editUrl && (\n <Button asChild variant=\"ghost\" size=\"sm\">\n <a\n href={post.editUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n <ExternalLink className=\"mr-1 h-3 w-3\" />\n Notion\n </a>\n </Button>\n )}\n </div>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n </div>\n );\n}\n","// admin/pages/users.tsx\n//\n// Generic admin user-management page. Lists all users with their\n// roles, login methods, and post counts, and provides inline actions\n// to revoke sessions, change roles, or delete the user. All\n// server-side work is done by helpers passed in via\n// `context.data` and `context.actions`.\n\nimport { redirect } from \"next/navigation\";\nimport { Crown, LogOut, Trash2, UserCheck, Users } from \"lucide-react\";\nimport type { AdminPageContext } from \"./types\";\n\nexport interface AdminUsersPageProps {\n context: AdminPageContext;\n searchParams: {\n revoked?: string;\n deleted?: string;\n roleUpdated?: string;\n error?: string;\n };\n}\n\nexport default async function AdminUsersPage({\n context,\n searchParams,\n}: AdminUsersPageProps) {\n const { ui, data, actions } = context;\n const { Badge, Button, Card, CardHeader, CardTitle, CardDescription, CardContent, Alert, AlertTitle, AlertDescription, Table, TableHeader, TableBody, TableRow, TableHead, TableCell } = ui;\n\n const viewer = (await data?.getAdminViewer?.()) ?? null;\n if (!viewer?.viewer) redirect(\"/login\");\n if (!viewer.admin) {\n redirect(\"/admin?error=需要管理员权限\");\n }\n\n const { revoked, deleted, roleUpdated, error } = searchParams;\n const users = (await data?.listUsersWithPostCounts?.()) ?? [];\n\n return (\n <div className=\"space-y-6\">\n <div>\n <h1 className=\"flex items-center gap-2 text-3xl font-bold tracking-tight\">\n <Users className=\"h-7 w-7\" />\n 用户管理\n </h1>\n <p className=\"text-sm text-muted-foreground\">\n 强制下线会使该用户所有设备上的会话立即失效;删除用户会将其文章归属转移给管理员。\n </p>\n </div>\n\n {revoked && (\n <Alert>\n <AlertTitle>已强制下线</AlertTitle>\n <AlertDescription>{revoked} 的所有会话已失效。</AlertDescription>\n </Alert>\n )}\n {deleted && (\n <Alert>\n <AlertTitle>用户已删除</AlertTitle>\n <AlertDescription>\n 已删除 {deleted},其文章已归属管理员。\n </AlertDescription>\n </Alert>\n )}\n {roleUpdated && (\n <Alert>\n <AlertTitle>角色已更新</AlertTitle>\n <AlertDescription>{roleUpdated} 的权限已更新。</AlertDescription>\n </Alert>\n )}\n {error && (\n <Alert variant=\"destructive\">\n <AlertTitle>操作失败</AlertTitle>\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n )}\n\n <Card>\n <CardHeader>\n <CardTitle>注册用户</CardTitle>\n <CardDescription>共 {users.length} 个账户</CardDescription>\n </CardHeader>\n <CardContent>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>邮箱</TableHead>\n <TableHead>角色</TableHead>\n <TableHead>登录方式</TableHead>\n <TableHead>文章数</TableHead>\n <TableHead>最近活跃</TableHead>\n <TableHead className=\"text-right\">操作</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {users.map((u) => {\n const isSelf = u.email === viewer.viewerEmail;\n const loginMethod =\n u.google_sub && u.password_hash\n ? \"Google + 密码\"\n : u.google_sub\n ? \"Google\"\n : \"邮箱密码\";\n const role: \"user\" | \"vip\" | \"admin\" =\n u.role === \"admin\" || u.role === \"vip\"\n ? u.role\n : \"user\";\n\n return (\n <TableRow key={u.id}>\n <TableCell className=\"font-medium\">\n {u.email}\n {isSelf && (\n <Badge variant=\"secondary\" className=\"ml-2\">\n 当前\n </Badge>\n )}\n </TableCell>\n <TableCell>\n {role === \"admin\" ? (\n <Badge>管理员</Badge>\n ) : role === \"vip\" ? (\n <Badge variant=\"secondary\" className=\"gap-1\">\n <Crown className=\"h-3 w-3\" />\n VIP\n </Badge>\n ) : (\n <Badge variant=\"outline\">用户</Badge>\n )}\n </TableCell>\n <TableCell className=\"text-muted-foreground\">\n {loginMethod}\n </TableCell>\n <TableCell>{u.post_count}</TableCell>\n <TableCell className=\"text-muted-foreground text-xs\">\n {u.last_seen_at}\n </TableCell>\n <TableCell className=\"text-right\">\n <div className=\"flex justify-end gap-2\">\n {!isSelf && role !== \"admin\" && actions?.adminSetUserRole && (\n <form action={actions.adminSetUserRole}>\n <input type=\"hidden\" name=\"userId\" value={u.id} />\n <input\n type=\"hidden\"\n name=\"role\"\n value={role === \"vip\" ? \"user\" : \"vip\"}\n />\n <Button type=\"submit\" variant=\"outline\" size=\"sm\">\n {role === \"vip\" ? (\n <>\n <UserCheck className=\"mr-1 h-3 w-3\" />\n 设为用户\n </>\n ) : (\n <>\n <Crown className=\"mr-1 h-3 w-3\" />\n 设为 VIP\n </>\n )}\n </Button>\n </form>\n )}\n {actions?.adminRevokeSessions && (\n <form action={actions.adminRevokeSessions}>\n <input type=\"hidden\" name=\"userId\" value={u.id} />\n <Button type=\"submit\" variant=\"outline\" size=\"sm\">\n <LogOut className=\"mr-1 h-3 w-3\" />\n 强制下线\n </Button>\n </form>\n )}\n {!isSelf && role !== \"admin\" && actions?.adminDeleteUser && (\n <form action={actions.adminDeleteUser}>\n <input type=\"hidden\" name=\"userId\" value={u.id} />\n <Button\n type=\"submit\"\n variant=\"destructive\"\n size=\"sm\"\n >\n <Trash2 className=\"mr-1 h-3 w-3\" />\n 删除\n </Button>\n </form>\n )}\n </div>\n </TableCell>\n </TableRow>\n );\n })}\n </TableBody>\n </Table>\n </CardContent>\n </Card>\n </div>\n );\n}\n","// admin/pages/settings.tsx\n//\n// Generic admin settings page. Lets an admin update the site title,\n// Google OAuth config, and Turnstile config. Reads/writes the\n// `app_settings` table and reads the worker env for the Turnstile\n// secret. All data fetching and mutation is delegated to helpers\n// passed in via `context.data` and `context.actions`.\n\nimport { redirect } from \"next/navigation\";\nimport { Bot, Save, Power, Settings2, ShieldCheck, Webhook } from \"lucide-react\";\nimport type { AdminPageContext } from \"./types\";\n\nexport interface AdminSettingsPageProps {\n context: AdminPageContext;\n searchParams: {\n saved?: string;\n error?: string;\n };\n}\n\nexport default async function AdminSettingsPage({\n context,\n searchParams,\n}: AdminSettingsPageProps) {\n const { ui, data, actions } = context;\n const { Card, CardHeader, CardTitle, CardDescription, CardContent, Button, Input, Label, Alert, AlertTitle, AlertDescription, Separator, Badge } = ui;\n\n const user = (await data?.getCurrentUser?.()) ?? null;\n if (!user) redirect(\"/login\");\n await data?.ensureAdminBootstrap?.();\n if (!(await data?.isAdminEmail?.(user.email))) {\n redirect(\"/admin?error=需要管理员权限\");\n }\n\n const { saved, error } = searchParams;\n const s = (await data?.getAppSettings?.()) ?? {\n admin_email: user.email,\n site_title: \"\",\n google_enabled: 0 as const,\n google_client_id: null,\n google_client_secret: null,\n turnstile_enabled: 0 as const,\n turnstile_site_key: null,\n };\n const turnstile = (await data?.getTurnstilePublicConfig?.()) ?? {\n enabled: false,\n secretConfigured: false,\n };\n const siteHost = (() => {\n try {\n return new URL(data?.getSiteUrl?.() ?? \"\").hostname;\n } catch {\n return \"your-domain.com\";\n }\n })();\n const callbackUrl = `<your-domain>/api/auth/google/callback`;\n\n return (\n <div className=\"space-y-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"flex items-center gap-2 text-3xl font-bold tracking-tight\">\n <Settings2 className=\"h-7 w-7\" />\n 系统设置\n </h1>\n <p className=\"text-sm text-muted-foreground\">\n 只有管理员 <code className=\"rounded bg-muted px-1.5 py-0.5 text-xs\">{s.admin_email}</code> 可以访问\n </p>\n </div>\n <Badge variant=\"secondary\" className=\"gap-1\">\n <ShieldCheck className=\"h-3.5 w-3.5\" />\n 管理员\n </Badge>\n </div>\n\n {error && (\n <Alert variant=\"destructive\">\n <AlertTitle>保存失败</AlertTitle>\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n )}\n {saved === \"google\" && (\n <Alert>\n <AlertTitle>已保存</AlertTitle>\n <AlertDescription>Google 登录配置已更新。</AlertDescription>\n </Alert>\n )}\n {saved === \"disabled\" && (\n <Alert>\n <AlertTitle>已关闭</AlertTitle>\n <AlertDescription>Google 登录已停用。</AlertDescription>\n </Alert>\n )}\n {saved === \"title\" && (\n <Alert>\n <AlertTitle>已保存</AlertTitle>\n <AlertDescription>站点名称已更新。</AlertDescription>\n </Alert>\n )}\n {saved === \"turnstile\" && (\n <Alert>\n <AlertTitle>已保存</AlertTitle>\n <AlertDescription>Turnstile 人机验证已更新。</AlertDescription>\n </Alert>\n )}\n {saved === \"turnstile_disabled\" && (\n <Alert>\n <AlertTitle>已关闭</AlertTitle>\n <AlertDescription>Turnstile 人机验证已停用。</AlertDescription>\n </Alert>\n )}\n\n <Card>\n <CardHeader>\n <CardTitle>站点信息</CardTitle>\n <CardDescription>对所有用户可见的基础信息</CardDescription>\n </CardHeader>\n <CardContent>\n <form action={actions?.saveSiteTitle} className=\"flex items-end gap-3\">\n <div className=\"flex-1 space-y-2\">\n <Label htmlFor=\"site_title\">站点名称</Label>\n <Input\n id=\"site_title\"\n name=\"site_title\"\n defaultValue={s.site_title}\n maxLength={80}\n required\n />\n </div>\n <Button type=\"submit\">\n <Save className=\"mr-1 h-4 w-4\" />\n 保存\n </Button>\n </form>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center justify-between\">\n <span>Google 登录</span>\n {s.google_enabled === 1 ? (\n <Badge>已启用</Badge>\n ) : (\n <Badge variant=\"secondary\">未启用</Badge>\n )}\n </CardTitle>\n <CardDescription>\n 在 Google Cloud Console 创建 OAuth Web 应用,将回调地址填为\n <code className=\"mx-1 rounded bg-muted px-1.5 py-0.5 text-xs\">\n {callbackUrl}\n </code>\n 然后把 Client ID / Secret 填到下面。\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <form action={actions?.saveGoogleSettings} className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"google_client_id\">Client ID</Label>\n <Input\n id=\"google_client_id\"\n name=\"google_client_id\"\n defaultValue={s.google_client_id ?? \"\"}\n placeholder=\"xxxxx.apps.googleusercontent.com\"\n autoComplete=\"off\"\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"google_client_secret\">Client Secret</Label>\n <Input\n id=\"google_client_secret\"\n name=\"google_client_secret\"\n type=\"password\"\n placeholder={\n s.google_client_secret ? \"已配置,留空表示不修改\" : \"GOCSPX-...\"\n }\n autoComplete=\"new-password\"\n />\n {s.google_client_secret && (\n <p className=\"text-xs text-muted-foreground\">\n 当前已保存一条 Secret;为安全起见,输入框不回显明文,留空不会改动。\n </p>\n )}\n </div>\n\n <Separator />\n\n <label className=\"flex cursor-pointer items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n name=\"google_enabled\"\n value=\"1\"\n defaultChecked={s.google_enabled === 1}\n className=\"h-4 w-4 rounded border-input\"\n />\n <span>启用 Google 登录(登录页会显示“使用 Google 登录”按钮)</span>\n </label>\n\n <div className=\"flex items-center gap-2\">\n <Button type=\"submit\">\n <Save className=\"mr-1 h-4 w-4\" />\n 保存 Google 配置\n </Button>\n </div>\n </form>\n\n {s.google_enabled === 1 && actions?.disableGoogleSettings && (\n <form action={actions.disableGoogleSettings}>\n <Button type=\"submit\" variant=\"outline\">\n <Power className=\"mr-1 h-4 w-4\" />\n 关闭 Google 登录\n </Button>\n </form>\n )}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center justify-between\">\n <span className=\"flex items-center gap-2\">\n <Bot className=\"h-4 w-4\" />\n Turnstile 人机验证\n </span>\n {turnstile.enabled ? (\n <Badge>已启用</Badge>\n ) : (\n <Badge variant=\"secondary\">未启用</Badge>\n )}\n </CardTitle>\n <CardDescription>\n 与 Workers 同属 Cloudflare 账户,但需在{\" \"}\n <a\n href=\"https://dash.cloudflare.com/?to=/:account/turnstile\"\n className=\"underline\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n Turnstile 控制台\n </a>{\" \"}\n 单独创建 Widget。域名请包含 <code className=\"rounded bg-muted px-1 text-xs\">localhost</code>、\n <code className=\"rounded bg-muted px-1 text-xs\">127.0.0.1</code> 与{\" \"}\n <code className=\"rounded bg-muted px-1 text-xs\">{siteHost}</code>。\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <form action={actions?.saveTurnstileSettings} className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"turnstile_site_key\">Site Key(公开)</Label>\n <Input\n id=\"turnstile_site_key\"\n name=\"turnstile_site_key\"\n defaultValue={s.turnstile_site_key ?? \"\"}\n placeholder=\"0x4AAAAAAA...\"\n autoComplete=\"off\"\n />\n </div>\n <p className=\"text-xs text-muted-foreground\">\n Secret Key 不要写入数据库。生产环境执行:\n <code className=\"mx-1 rounded bg-muted px-1.5 py-0.5\">\n wrangler secret put TURNSTILE_SECRET_KEY\n </code>\n ;本地在 <code className=\"rounded bg-muted px-1\">.dev.vars</code> 添加同名变量。\n {turnstile.secretConfigured ? (\n <span className=\"ml-1 text-emerald-600 dark:text-emerald-400\">\n (当前已检测到 Secret)\n </span>\n ) : (\n <span className=\"ml-1 text-amber-600 dark:text-amber-400\">\n (当前未检测到 Secret,启用前需配置)\n </span>\n )}\n </p>\n <label className=\"flex cursor-pointer items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n name=\"turnstile_enabled\"\n value=\"1\"\n defaultChecked={s.turnstile_enabled === 1}\n className=\"h-4 w-4 rounded border-input\"\n />\n <span>启用 Turnstile(登录 / 注册 / 忘记密码 / 重发验证)</span>\n </label>\n <Button type=\"submit\">\n <Save className=\"mr-1 h-4 w-4\" />\n 保存 Turnstile 配置\n </Button>\n </form>\n {s.turnstile_enabled === 1 && actions?.disableTurnstileSettings && (\n <form action={actions.disableTurnstileSettings}>\n <Button type=\"submit\" variant=\"outline\">\n <Power className=\"mr-1 h-4 w-4\" />\n 关闭 Turnstile\n </Button>\n </form>\n )}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <Webhook className=\"h-4 w-4\" />\n Google OAuth 回调地址\n </CardTitle>\n <CardDescription>\n 请在 Google Cloud Console 把下方地址作为 “Authorized redirect URI”\n </CardDescription>\n </CardHeader>\n <CardContent>\n <code className=\"block break-all rounded bg-muted px-3 py-2 text-xs\">\n {callbackUrl}\n </code>\n </CardContent>\n </Card>\n </div>\n );\n}\n","// admin/pages/account.tsx\n//\n// Generic \"account\" page. Shows the current user their profile info,\n// lets them change their password, and (for non-admins) delete their\n// own account. All data fetching and mutation is delegated to\n// helpers passed in via `context.data` and `context.actions`.\n\nimport { redirect } from \"next/navigation\";\nimport { KeyRound, Trash2, UserCircle } from \"lucide-react\";\nimport type { AdminPageContext } from \"./types\";\n\nexport interface AdminAccountPageProps {\n context: AdminPageContext;\n searchParams: {\n saved?: string;\n error?: string;\n };\n}\n\nexport default async function AdminAccountPage({\n context,\n searchParams,\n}: AdminAccountPageProps) {\n const { ui, data, actions } = context;\n const { Button, Input, Label, Card, CardHeader, CardTitle, CardContent, CardDescription, Alert, AlertTitle, AlertDescription, Separator } = ui;\n\n const session = (await data?.getCurrentUser?.()) ?? null;\n if (!session) redirect(\"/login\");\n\n const user = (await data?.getUserById?.(session.uid)) ?? null;\n if (!user) redirect(\"/login\");\n\n const { saved, error } = searchParams;\n const hasPassword = Boolean(user.password_hash);\n const isAdmin = (await data?.isAdminEmail?.(user.email)) ?? false;\n\n return (\n <div className=\"mx-auto max-w-lg space-y-6\">\n <div>\n <h1 className=\"flex items-center gap-2 text-3xl font-bold tracking-tight\">\n <UserCircle className=\"h-7 w-7\" />\n 账户设置\n </h1>\n <p className=\"text-sm text-muted-foreground\">\n 管理登录邮箱与密码\n </p>\n </div>\n\n {saved && (\n <Alert>\n <AlertTitle>密码已更新</AlertTitle>\n <AlertDescription>\n 新密码已生效,其他设备上的旧会话已失效。\n </AlertDescription>\n </Alert>\n )}\n {error && (\n <Alert variant=\"destructive\">\n <AlertTitle>操作失败</AlertTitle>\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n )}\n\n <Card>\n <CardHeader>\n <CardTitle>基本信息</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between gap-4\">\n <span className=\"text-muted-foreground\">邮箱</span>\n <span className=\"font-medium\">{user.email}</span>\n </div>\n <div className=\"flex justify-between gap-4\">\n <span className=\"text-muted-foreground\">登录方式</span>\n <span className=\"font-medium\">\n {user.google_sub && user.password_hash\n ? \"Google + 邮箱密码\"\n : user.google_sub\n ? \"Google\"\n : \"邮箱密码\"}\n </span>\n </div>\n </CardContent>\n </Card>\n\n {hasPassword ? (\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2\">\n <KeyRound className=\"h-4 w-4\" />\n 修改密码\n </CardTitle>\n <CardDescription>\n 修改后当前及其他设备的登录会话将立即失效。\n </CardDescription>\n </CardHeader>\n <CardContent>\n <form action={actions?.changePassword} className=\"space-y-3\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"currentPassword\">当前密码</Label>\n <Input\n id=\"currentPassword\"\n name=\"currentPassword\"\n type=\"password\"\n required\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"newPassword\">新密码</Label>\n <Input\n id=\"newPassword\"\n name=\"newPassword\"\n type=\"password\"\n placeholder=\"至少 8 位,包含字母和数字\"\n required\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"confirmPassword\">确认新密码</Label>\n <Input\n id=\"confirmPassword\"\n name=\"confirmPassword\"\n type=\"password\"\n required\n />\n </div>\n <Button type=\"submit\">保存新密码</Button>\n </form>\n </CardContent>\n </Card>\n ) : (\n <Card>\n <CardHeader>\n <CardTitle>密码</CardTitle>\n <CardDescription>\n 你使用 Google 登录,账户未设置密码。如需密码登录,请联系管理员或使用邮箱注册流程。\n </CardDescription>\n </CardHeader>\n </Card>\n )}\n\n {!isAdmin && (\n <Card className=\"border-destructive/40\">\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-destructive\">\n <Trash2 className=\"h-4 w-4\" />\n 注销账户\n </CardTitle>\n <CardDescription>\n 此操作不可恢复。你的文章将转移给管理员,账户数据将被永久删除。\n </CardDescription>\n </CardHeader>\n <CardContent>\n <form action={actions?.deleteAccount} className=\"space-y-3\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"confirmEmail\">\n 输入邮箱 <span className=\"font-medium\">{user.email}</span> 以确认\n </Label>\n <Input\n id=\"confirmEmail\"\n name=\"confirmEmail\"\n type=\"email\"\n placeholder={user.email}\n required\n />\n </div>\n {hasPassword && (\n <div className=\"space-y-2\">\n <Label htmlFor=\"deletePassword\">当前密码</Label>\n <Input\n id=\"deletePassword\"\n name=\"currentPassword\"\n type=\"password\"\n required\n />\n </div>\n )}\n <Separator />\n <Button type=\"submit\" variant=\"destructive\">\n 永久注销账户\n </Button>\n </form>\n </CardContent>\n </Card>\n )}\n </div>\n );\n}\n","// admin/pages/content-models.tsx\n//\n// Generic \"content models\" admin page. Renders a registry-style\n// overview of every content model registered by the project (id,\n// kind, visibility, public routes, capabilities, fields). Data\n// comes from `context.data.getContentModelAdminSummaries`; UI\n// primitives come from `context.ui`.\n\nimport type { Metadata } from \"next\";\nimport { Database, Route } from \"lucide-react\";\nimport type { AdminPageContext, ContentModelAdminSummary } from \"./types\";\n\nexport const metadata: Metadata = {\n title: \"Content Sources\",\n};\n\nexport interface AdminContentModelsPageProps {\n context: AdminPageContext;\n}\n\nfunction statusVariant(value: string) {\n if (value === \"public+admin\" || value === \"public\") return \"default\";\n if (value === \"admin\") return \"secondary\";\n return \"outline\";\n}\n\nfunction capabilityBadges(model: ContentModelAdminSummary) {\n return [\n model.capabilities.richBlocks ? \"rich blocks\" : \"\",\n model.capabilities.coverImages ? \"cover images\" : \"\",\n model.capabilities.gatedAssets ? \"gated assets\" : \"\",\n ].filter(Boolean);\n}\n\nexport default function AdminContentModelsPage({\n context,\n}: AdminContentModelsPageProps) {\n const { ui, data } = context;\n const { Badge, Card, CardHeader, CardTitle, CardDescription, CardContent, Table, TableHeader, TableBody, TableRow, TableHead, TableCell } = ui;\n\n const models = data?.getContentModelAdminSummaries?.() ?? [];\n\n return (\n <div className=\"space-y-6\">\n <div>\n <h1 className=\"flex items-center gap-2 text-3xl font-bold tracking-tight\">\n <Database className=\"h-7 w-7\" />\n 内容来源\n </h1>\n <p className=\"text-sm text-muted-foreground\">\n 查看当前项目直接实现的 Notion 数据源、公开路由和基础能力。\n </p>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>模型注册表</CardTitle>\n <CardDescription>\n 这些模型来自 <code className=\"rounded bg-muted px-1.5 py-0.5 text-xs\">lib/content/models.ts</code>。\n 新领域由 AI 直接新增模型、路由和 UI 代码。\n </CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"rounded-md border\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>模型</TableHead>\n <TableHead>类型</TableHead>\n <TableHead>可见性</TableHead>\n <TableHead>Notion</TableHead>\n <TableHead>路由</TableHead>\n <TableHead>能力</TableHead>\n <TableHead className=\"text-right\">字段</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {models.map((model) => (\n <TableRow key={model.id}>\n <TableCell>\n <div className=\"font-medium\">{model.name}</div>\n <div className=\"text-xs text-muted-foreground\">\n {model.id}\n </div>\n </TableCell>\n <TableCell>{model.kind}</TableCell>\n <TableCell>\n <Badge variant={statusVariant(model.visibility) as \"default\" | \"secondary\" | \"outline\"}>\n {model.visibility}\n </Badge>\n </TableCell>\n <TableCell>\n <div className=\"font-mono text-xs\">\n {model.dataSourceEnv}\n </div>\n {model.hasDefaultDataSource && (\n <Badge variant=\"secondary\" className=\"mt-1\">\n default id\n </Badge>\n )}\n </TableCell>\n <TableCell>\n <div className=\"text-xs\">{model.listPath}</div>\n <div className=\"text-xs text-muted-foreground\">\n {model.detailPath}\n </div>\n {model.publicApiPath && (\n <div className=\"text-xs text-muted-foreground\">\n {model.publicApiPath}\n </div>\n )}\n </TableCell>\n <TableCell>\n <div className=\"flex flex-wrap gap-1.5\">\n {capabilityBadges(model).map((capability) => (\n <Badge key={capability} variant=\"secondary\">\n {capability}\n </Badge>\n ))}\n </div>\n </TableCell>\n <TableCell className=\"text-right\">\n {model.fieldCount}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n </CardContent>\n </Card>\n\n <div className=\"grid gap-4 lg:grid-cols-2\">\n {models.map((model) => (\n <Card key={model.id}>\n <CardHeader>\n <CardTitle className=\"flex items-center justify-between gap-3\">\n <span>{model.name}</span>\n <Badge variant={statusVariant(model.visibility) as \"default\" | \"secondary\" | \"outline\"}>\n {model.visibility}\n </Badge>\n </CardTitle>\n <CardDescription className=\"flex flex-wrap items-center gap-3\">\n <span className=\"inline-flex items-center gap-1\">\n <Route className=\"h-3.5 w-3.5\" />\n {model.listPath}\n </span>\n <span>{model.detailPath}</span>\n {model.publicApiPath && <span>{model.publicApiPath}</span>}\n </CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"grid gap-3 text-sm\">\n <div>\n <div className=\"text-xs font-medium text-muted-foreground\">\n Notion data source env\n </div>\n <code className=\"mt-1 block rounded-md bg-muted px-2 py-1.5 text-xs\">\n {model.dataSourceEnv}\n </code>\n </div>\n <div>\n <div className=\"text-xs font-medium text-muted-foreground\">\n Public API\n </div>\n <div>{model.publicApiPath ?? \"None\"}</div>\n </div>\n <div>\n <div className=\"text-xs font-medium text-muted-foreground\">\n Capabilities\n </div>\n <div className=\"mt-1 flex flex-wrap gap-1.5\">\n {capabilityBadges(model).map((capability) => (\n <Badge key={capability} variant=\"secondary\">\n {capability}\n </Badge>\n ))}\n </div>\n </div>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n </div>\n );\n}\n","// Public surface for the @notionx/core/admin/pages subpath.\n//\n// The package ships the generic admin page implementations\n// (dashboard, users, settings, account, content-models) and the\n// shared `DeleteButton` and `Loading` placeholders. The starter\n// re-exports the default export from its own `app/admin/<page>/page.tsx`\n// files, passing in a `context` with UI primitives, server actions,\n// and data-fetching helpers.\n\nexport { default as DashboardPage } from \"./dashboard\";\nexport type { AdminDashboardPageProps } from \"./dashboard\";\n\nexport { default as UsersPage } from \"./users\";\nexport type { AdminUsersPageProps } from \"./users\";\n\nexport { default as SettingsPage } from \"./settings\";\nexport type { AdminSettingsPageProps } from \"./settings\";\n\nexport { default as AccountPage } from \"./account\";\nexport type { AdminAccountPageProps } from \"./account\";\n\nexport { default as ContentModelsPage } from \"./content-models\";\nexport type { AdminContentModelsPageProps } from \"./content-models\";\n\nexport { default as DeleteButton } from \"./delete-button\";\nexport type { AdminDeleteButtonProps } from \"./delete-button\";\n\nexport { default as DeleteButtonLazy } from \"./delete-button-lazy\";\nexport type { AdminDeleteButtonLazyProps } from \"./delete-button-lazy\";\n\nexport { default as LoadingPage } from \"./loading\";\nexport type { AdminLoadingPageProps } from \"./loading\";\n\nexport type {\n AdminFormAction,\n AdminPageUI,\n AdminPageActions,\n AdminPageData,\n AdminPageContext,\n ContentModelAdminSummary,\n} from \"./types\";\n","// admin/pages/delete-button-lazy.tsx\n//\n// Client-only dynamic loader for `AdminDeleteButton`. Used by server\n// components that need to embed the delete button without paying the\n// alert-dialog cost on the first paint.\n\n\"use client\";\n\nimport dynamic from \"next/dynamic\";\nimport type { AdminPageContext } from \"./types\";\n\nexport interface AdminDeleteButtonLazyProps {\n context: AdminPageContext;\n slug: string;\n title: string;\n}\n\nconst AdminDeleteButton = dynamic(() => import(\"./delete-button\"));\n\nexport default function AdminDeleteButtonLazy(\n props: AdminDeleteButtonLazyProps\n) {\n return <AdminDeleteButton {...props} />;\n}\n","// admin/pages/loading.tsx\n//\n// Generic \"loading\" placeholder used by Next.js when admin pages\n// are streaming. Renders a few skeleton rows to keep the layout\n// from shifting. UI primitives come from `context.ui`.\n\nimport type { AdminPageContext } from \"./types\";\n\nexport interface AdminLoadingPageProps {\n context: AdminPageContext;\n}\n\nexport default function AdminLoadingPage({ context }: AdminLoadingPageProps) {\n const { ui } = context;\n const { Skeleton } = ui;\n\n return (\n <div className=\"space-y-6\">\n <div className=\"space-y-2\">\n <Skeleton className=\"h-9 w-40\" />\n <Skeleton className=\"h-4 w-28\" />\n </div>\n\n <div className=\"rounded-md border p-4\">\n <div className=\"space-y-3\">\n <Skeleton className=\"h-10 w-full\" />\n <Skeleton className=\"h-10 w-full\" />\n <Skeleton className=\"h-10 w-full\" />\n <Skeleton className=\"h-10 w-11/12\" />\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["Trash2","jsx","jsxs","jsx","jsxs","redirect","jsx","jsxs","redirect","Trash2","jsx","jsxs","jsx","jsxs","jsxs","jsx","jsx","AdminDeleteButton","jsx","jsxs"]}
@@ -0,0 +1,20 @@
1
+ import * as react from 'react';
2
+ import { A as AuthPageContext } from '../../types-BsAcZSNX.js';
3
+
4
+ interface ForgotPasswordPageProps {
5
+ ui: AuthPageContext["ui"];
6
+ searchParams: {
7
+ sent?: string;
8
+ email?: string;
9
+ error?: string;
10
+ retry?: string;
11
+ };
12
+ forgotPasswordAction: AuthPageContext["actions"] extends infer A ? A extends {
13
+ forgotPassword: infer F;
14
+ } ? F : never : never;
15
+ isAuthenticated?: AuthPageContext["isAuthenticated"];
16
+ redirectWhenAuthenticated?: string;
17
+ }
18
+ declare function ForgotPasswordPage({ ui, searchParams, forgotPasswordAction, isAuthenticated, redirectWhenAuthenticated, }: ForgotPasswordPageProps): Promise<react.JSX.Element>;
19
+
20
+ export { type ForgotPasswordPageProps, ForgotPasswordPage as default };
@@ -0,0 +1,70 @@
1
+ // src/auth/auth-pages/forgot-password.tsx
2
+ import { redirect } from "next/navigation";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ async function ForgotPasswordPage({
5
+ ui,
6
+ searchParams,
7
+ forgotPasswordAction,
8
+ isAuthenticated,
9
+ redirectWhenAuthenticated = "/admin"
10
+ }) {
11
+ if (isAuthenticated && await isAuthenticated()) {
12
+ redirect(redirectWhenAuthenticated);
13
+ }
14
+ const { sent, email, error, retry } = searchParams;
15
+ const { Button, Input, Label, Card, CardHeader, CardTitle, CardDescription, CardContent, Turnstile } = ui;
16
+ return /* @__PURE__ */ jsx(
17
+ "main",
18
+ {
19
+ style: {
20
+ minHeight: "100vh",
21
+ display: "flex",
22
+ alignItems: "center",
23
+ justifyContent: "center",
24
+ padding: "1rem",
25
+ background: "linear-gradient(to bottom right, var(--background), var(--muted))"
26
+ },
27
+ children: /* @__PURE__ */ jsxs(Card, { className: "w-full max-w-sm", children: [
28
+ /* @__PURE__ */ jsxs(CardHeader, { children: [
29
+ /* @__PURE__ */ jsx(CardTitle, { children: "\u5FD8\u8BB0\u5BC6\u7801" }),
30
+ /* @__PURE__ */ jsx(CardDescription, { children: "\u8F93\u5165\u6CE8\u518C\u90AE\u7BB1\uFF0C\u6211\u4EEC\u4F1A\u53D1\u9001\u91CD\u7F6E\u94FE\u63A5\uFF081 \u5C0F\u65F6\u5185\u6709\u6548\uFF09\u3002" })
31
+ ] }),
32
+ /* @__PURE__ */ jsxs(CardContent, { children: [
33
+ sent && /* @__PURE__ */ jsxs("div", { className: "rounded-md bg-emerald-500/10 px-3 py-2 text-sm text-emerald-700 dark:text-emerald-400", children: [
34
+ "\u5982\u679C ",
35
+ email ?? "\u8BE5\u90AE\u7BB1",
36
+ " \u5DF2\u6CE8\u518C\u4E14\u5DF2\u9A8C\u8BC1\uFF0C\u4F60\u4F1A\u6536\u5230\u91CD\u7F6E\u5BC6\u7801\u90AE\u4EF6\u3002"
37
+ ] }),
38
+ error === "invalid" && /* @__PURE__ */ jsx("div", { className: "rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive", children: "\u90AE\u7BB1\u683C\u5F0F\u4E0D\u6B63\u786E" }),
39
+ error === "captcha" && /* @__PURE__ */ jsx("div", { className: "rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive", children: "\u8BF7\u5B8C\u6210\u4EBA\u673A\u9A8C\u8BC1\u540E\u518D\u8BD5" }),
40
+ error === "rate" && /* @__PURE__ */ jsxs("div", { className: "rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive", children: [
41
+ "\u8BF7\u6C42\u8FC7\u4E8E\u9891\u7E41\uFF0C\u8BF7 ",
42
+ retry ?? "900",
43
+ " \u79D2\u540E\u518D\u8BD5"
44
+ ] }),
45
+ /* @__PURE__ */ jsxs("form", { action: forgotPasswordAction, children: [
46
+ /* @__PURE__ */ jsx(Label, { htmlFor: "email", children: "\u90AE\u7BB1" }),
47
+ /* @__PURE__ */ jsx(
48
+ Input,
49
+ {
50
+ id: "email",
51
+ name: "email",
52
+ type: "email",
53
+ placeholder: "you@example.com",
54
+ defaultValue: email ?? "",
55
+ required: true
56
+ }
57
+ ),
58
+ Turnstile && /* @__PURE__ */ jsx(Turnstile, { action: "forgot_password" }),
59
+ /* @__PURE__ */ jsx(Button, { type: "submit", className: "w-full", children: "\u53D1\u9001\u91CD\u7F6E\u94FE\u63A5" })
60
+ ] }),
61
+ /* @__PURE__ */ jsx(Button, { asChild: true, variant: "ghost", className: "w-full", children: /* @__PURE__ */ jsx("a", { href: "/login", children: "\u8FD4\u56DE\u767B\u5F55" }) })
62
+ ] })
63
+ ] })
64
+ }
65
+ );
66
+ }
67
+ export {
68
+ ForgotPasswordPage as default
69
+ };
70
+ //# sourceMappingURL=forgot-password.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/auth/auth-pages/forgot-password.tsx"],"sourcesContent":["// auth/auth-pages/forgot-password.tsx\n\nimport { redirect } from \"next/navigation\";\nimport type { AuthPageContext } from \"./types\";\n\nexport interface ForgotPasswordPageProps {\n ui: AuthPageContext[\"ui\"];\n searchParams: {\n sent?: string;\n email?: string;\n error?: string;\n retry?: string;\n };\n forgotPasswordAction: AuthPageContext[\"actions\"] extends infer A\n ? A extends { forgotPassword: infer F }\n ? F\n : never\n : never;\n isAuthenticated?: AuthPageContext[\"isAuthenticated\"];\n redirectWhenAuthenticated?: string;\n}\n\nexport default async function ForgotPasswordPage({\n ui,\n searchParams,\n forgotPasswordAction,\n isAuthenticated,\n redirectWhenAuthenticated = \"/admin\",\n}: ForgotPasswordPageProps) {\n if (isAuthenticated && (await isAuthenticated())) {\n redirect(redirectWhenAuthenticated);\n }\n const { sent, email, error, retry } = searchParams;\n const { Button, Input, Label, Card, CardHeader, CardTitle, CardDescription, CardContent, Turnstile } = ui;\n\n return (\n <main\n style={{\n minHeight: \"100vh\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: \"1rem\",\n background: \"linear-gradient(to bottom right, var(--background), var(--muted))\",\n }}\n >\n <Card className=\"w-full max-w-sm\">\n <CardHeader>\n <CardTitle>忘记密码</CardTitle>\n <CardDescription>\n 输入注册邮箱,我们会发送重置链接(1 小时内有效)。\n </CardDescription>\n </CardHeader>\n <CardContent>\n {sent && (\n <div className=\"rounded-md bg-emerald-500/10 px-3 py-2 text-sm text-emerald-700 dark:text-emerald-400\">\n 如果 {email ?? \"该邮箱\"} 已注册且已验证,你会收到重置密码邮件。\n </div>\n )}\n {error === \"invalid\" && (\n <div className=\"rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n 邮箱格式不正确\n </div>\n )}\n {error === \"captcha\" && (\n <div className=\"rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n 请完成人机验证后再试\n </div>\n )}\n {error === \"rate\" && (\n <div className=\"rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n 请求过于频繁,请 {retry ?? \"900\"} 秒后再试\n </div>\n )}\n\n <form action={forgotPasswordAction as unknown as (formData: FormData) => void}>\n <Label htmlFor=\"email\">邮箱</Label>\n <Input\n id=\"email\"\n name=\"email\"\n type=\"email\"\n placeholder=\"you@example.com\"\n defaultValue={email ?? \"\"}\n required\n />\n {Turnstile && <Turnstile action=\"forgot_password\" />}\n <Button type=\"submit\" className=\"w-full\">发送重置链接</Button>\n </form>\n\n <Button asChild variant=\"ghost\" className=\"w-full\">\n <a href=\"/login\">返回登录</a>\n </Button>\n </CardContent>\n </Card>\n </main>\n );\n}\n"],"mappings":";AAEA,SAAS,gBAAgB;AA6CjB,SACE,KADF;AAzBR,eAAO,mBAA0C;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,4BAA4B;AAC9B,GAA4B;AAC1B,MAAI,mBAAoB,MAAM,gBAAgB,GAAI;AAChD,aAAS,yBAAyB;AAAA,EACpC;AACA,QAAM,EAAE,MAAM,OAAO,OAAO,MAAM,IAAI;AACtC,QAAM,EAAE,QAAQ,OAAO,OAAO,MAAM,YAAY,WAAW,iBAAiB,aAAa,UAAU,IAAI;AAEvG,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,WAAW;AAAA,QACX,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,SAAS;AAAA,QACT,YAAY;AAAA,MACd;AAAA,MAEA,+BAAC,QAAK,WAAU,mBACd;AAAA,6BAAC,cACC;AAAA,8BAAC,aAAU,sCAAI;AAAA,UACf,oBAAC,mBAAgB,gKAEjB;AAAA,WACF;AAAA,QACA,qBAAC,eACE;AAAA,kBACC,qBAAC,SAAI,WAAU,yFAAwF;AAAA;AAAA,YACjG,SAAS;AAAA,YAAM;AAAA,aACrB;AAAA,UAED,UAAU,aACT,oBAAC,SAAI,WAAU,mEAAkE,wDAEjF;AAAA,UAED,UAAU,aACT,oBAAC,SAAI,WAAU,mEAAkE,0EAEjF;AAAA,UAED,UAAU,UACT,qBAAC,SAAI,WAAU,mEAAkE;AAAA;AAAA,YACrE,SAAS;AAAA,YAAM;AAAA,aAC3B;AAAA,UAGF,qBAAC,UAAK,QAAQ,sBACZ;AAAA,gCAAC,SAAM,SAAQ,SAAQ,0BAAE;AAAA,YACzB;AAAA,cAAC;AAAA;AAAA,gBACC,IAAG;AAAA,gBACH,MAAK;AAAA,gBACL,MAAK;AAAA,gBACL,aAAY;AAAA,gBACZ,cAAc,SAAS;AAAA,gBACvB,UAAQ;AAAA;AAAA,YACV;AAAA,YACC,aAAa,oBAAC,aAAU,QAAO,mBAAkB;AAAA,YAClD,oBAAC,UAAO,MAAK,UAAS,WAAU,UAAS,kDAAM;AAAA,aACjD;AAAA,UAEA,oBAAC,UAAO,SAAO,MAAC,SAAQ,SAAQ,WAAU,UACxC,8BAAC,OAAE,MAAK,UAAS,sCAAI,GACvB;AAAA,WACF;AAAA,SACF;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -0,0 +1,6 @@
1
+ export { default as LoginPage, LoginPageProps } from './login.js';
2
+ export { default as RegisterPage, RegisterPageProps } from './register.js';
3
+ export { default as ForgotPasswordPage, ForgotPasswordPageProps } from './forgot-password.js';
4
+ export { default as ResetPasswordPage, ResetPasswordPageProps } from './reset-password.js';
5
+ export { A as AuthPageContext, a as AuthPageUI, F as FormAction, T as TurnstileSlot } from '../../types-BsAcZSNX.js';
6
+ import 'react';
@@ -0,0 +1,342 @@
1
+ // src/auth/auth-pages/login.tsx
2
+ import { redirect } from "next/navigation";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ async function LoginPage({
5
+ ui,
6
+ searchParams,
7
+ emailLoginAction,
8
+ resendVerificationAction,
9
+ isAuthenticated,
10
+ getCurrentUser,
11
+ getGoogleOAuthConfig,
12
+ redirectWhenAuthenticated = "/admin"
13
+ }) {
14
+ if (isAuthenticated && await isAuthenticated()) {
15
+ redirect(redirectWhenAuthenticated);
16
+ }
17
+ const {
18
+ loginError,
19
+ registered,
20
+ email,
21
+ verifyError,
22
+ resendSent,
23
+ resendError,
24
+ retry,
25
+ accountDeleted
26
+ } = searchParams;
27
+ const user = getCurrentUser ? await getCurrentUser() : null;
28
+ const googleCfg = getGoogleOAuthConfig ? await getGoogleOAuthConfig() : null;
29
+ const googleEnabled = Boolean(googleCfg);
30
+ const { Button, Input, Label, Card, CardHeader, CardTitle, CardDescription, CardContent, Separator, Turnstile } = ui;
31
+ return /* @__PURE__ */ jsx(
32
+ "main",
33
+ {
34
+ style: {
35
+ minHeight: "100vh",
36
+ display: "flex",
37
+ alignItems: "center",
38
+ justifyContent: "center",
39
+ padding: "1rem",
40
+ background: "linear-gradient(to bottom right, var(--background), var(--muted))"
41
+ },
42
+ children: /* @__PURE__ */ jsxs(Card, { className: "w-full max-w-sm", children: [
43
+ /* @__PURE__ */ jsxs(CardHeader, { children: [
44
+ /* @__PURE__ */ jsx(CardTitle, { children: "\u540E\u53F0\u767B\u5F55" }),
45
+ /* @__PURE__ */ jsx(CardDescription, { children: "\u591A\u79CD\u65B9\u5F0F\u767B\u5F55\u7BA1\u7406\u9762\u677F" })
46
+ ] }),
47
+ /* @__PURE__ */ jsxs(CardContent, { children: [
48
+ accountDeleted && /* @__PURE__ */ jsx("div", { className: "rounded-md bg-muted px-3 py-2 text-sm text-muted-foreground", children: "\u8D26\u6237\u5DF2\u6CE8\u9500\u3002\u5982\u9700\u518D\u6B21\u4F7F\u7528\uFF0C\u8BF7\u91CD\u65B0\u6CE8\u518C\u3002" }),
49
+ registered && /* @__PURE__ */ jsxs("div", { className: "rounded-md bg-emerald-500/10 px-3 py-2 text-sm text-emerald-700 dark:text-emerald-400", children: [
50
+ "\u9A8C\u8BC1\u90AE\u4EF6\u5DF2\u53D1\u9001\u5230 ",
51
+ email ?? "\u4F60\u7684\u90AE\u7BB1",
52
+ "\uFF0C\u8BF7\u5148\u9A8C\u8BC1\u540E\u518D\u767B\u5F55\u3002"
53
+ ] }),
54
+ verifyError && /* @__PURE__ */ jsx("div", { className: "rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive", children: "\u9A8C\u8BC1\u94FE\u63A5\u65E0\u6548\u6216\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u9A8C\u8BC1\u90AE\u4EF6\u3002" }),
55
+ resendSent && /* @__PURE__ */ jsxs("div", { className: "rounded-md bg-emerald-500/10 px-3 py-2 text-sm text-emerald-700 dark:text-emerald-400", children: [
56
+ "\u5982\u679C ",
57
+ email ?? "\u8BE5\u90AE\u7BB1",
58
+ " \u6709\u5F85\u9A8C\u8BC1\u8D26\u6237\uFF0C\u9A8C\u8BC1\u90AE\u4EF6\u5DF2\u91CD\u65B0\u53D1\u9001\u3002"
59
+ ] }),
60
+ resendError === "verified" && /* @__PURE__ */ jsx("div", { className: "rounded-md bg-amber-500/10 px-3 py-2 text-sm text-amber-700 dark:text-amber-400", children: "\u8BE5\u90AE\u7BB1\u5DF2\u9A8C\u8BC1\uFF0C\u8BF7\u76F4\u63A5\u767B\u5F55\u3002" }),
61
+ resendError === "captcha" && /* @__PURE__ */ jsx("div", { className: "rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive", children: "\u8BF7\u5B8C\u6210\u4EBA\u673A\u9A8C\u8BC1\u540E\u518D\u91CD\u53D1\u90AE\u4EF6" }),
62
+ resendError === "rate" && /* @__PURE__ */ jsxs("div", { className: "rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive", children: [
63
+ "\u91CD\u53D1\u8FC7\u4E8E\u9891\u7E41\uFF0C\u8BF7 ",
64
+ retry ?? "900",
65
+ " \u79D2\u540E\u518D\u8BD5"
66
+ ] }),
67
+ googleEnabled ? /* @__PURE__ */ jsx(Button, { asChild: true, variant: "outline", className: "w-full", size: "lg", children: /* @__PURE__ */ jsx("a", { href: "/api/auth/google", children: "\u4F7F\u7528 Google \u767B\u5F55" }) }) : /* @__PURE__ */ jsxs("div", { className: "rounded-md border border-dashed p-3 text-xs text-muted-foreground", children: [
68
+ "Google \u767B\u5F55\u672A\u542F\u7528\uFF08\u7BA1\u7406\u5458\u53EF\u5728 ",
69
+ /* @__PURE__ */ jsx("a", { href: "/admin/settings", className: "underline", children: "/admin/settings" }),
70
+ " \u914D\u7F6E\uFF09"
71
+ ] }),
72
+ /* @__PURE__ */ jsx(Separator, {}),
73
+ /* @__PURE__ */ jsxs("form", { action: emailLoginAction, children: [
74
+ /* @__PURE__ */ jsx(Label, { htmlFor: "email", children: "\u90AE\u7BB1" }),
75
+ /* @__PURE__ */ jsx(
76
+ Input,
77
+ {
78
+ id: "email",
79
+ name: "email",
80
+ type: "email",
81
+ placeholder: "you@example.com",
82
+ required: true
83
+ }
84
+ ),
85
+ /* @__PURE__ */ jsx(Label, { htmlFor: "email-password", children: "\u5BC6\u7801" }),
86
+ /* @__PURE__ */ jsx(
87
+ Input,
88
+ {
89
+ id: "email-password",
90
+ name: "password",
91
+ type: "password",
92
+ placeholder: "\u8F93\u5165\u5BC6\u7801",
93
+ required: true
94
+ }
95
+ ),
96
+ loginError === "rate" && /* @__PURE__ */ jsxs("div", { className: "rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive", children: [
97
+ "\u767B\u5F55\u5C1D\u8BD5\u8FC7\u591A\uFF0C\u8BF7 ",
98
+ retry ?? "900",
99
+ " \u79D2\u540E\u518D\u8BD5"
100
+ ] }),
101
+ loginError === "captcha" && /* @__PURE__ */ jsx("div", { className: "rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive", children: "\u8BF7\u5B8C\u6210\u4EBA\u673A\u9A8C\u8BC1\u540E\u518D\u8BD5" }),
102
+ loginError === "invalid" && /* @__PURE__ */ jsx("div", { className: "rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive", children: "\u90AE\u7BB1\u6216\u5BC6\u7801\u9519\u8BEF" }),
103
+ loginError === "unverified" && /* @__PURE__ */ jsx("div", { className: "rounded-md bg-amber-500/10 px-3 py-2 text-sm text-amber-700 dark:text-amber-400", children: "\u90AE\u7BB1\u8FD8\u6CA1\u6709\u9A8C\u8BC1\uFF0C\u8BF7\u5148\u6253\u5F00\u9A8C\u8BC1\u90AE\u4EF6\u4E2D\u7684\u94FE\u63A5\u3002" }),
104
+ Turnstile && /* @__PURE__ */ jsx(Turnstile, { action: "login" }),
105
+ /* @__PURE__ */ jsx(Button, { type: "submit", className: "w-full", children: "\u4F7F\u7528\u90AE\u7BB1\u767B\u5F55" })
106
+ ] }),
107
+ loginError === "unverified" && email && resendVerificationAction && /* @__PURE__ */ jsxs("form", { action: resendVerificationAction, children: [
108
+ /* @__PURE__ */ jsx("input", { type: "hidden", name: "email", value: email }),
109
+ Turnstile && /* @__PURE__ */ jsx(Turnstile, { action: "resend_verify" }),
110
+ /* @__PURE__ */ jsx(Button, { type: "submit", variant: "outline", size: "sm", className: "w-full", children: "\u91CD\u65B0\u53D1\u9001\u9A8C\u8BC1\u90AE\u4EF6" })
111
+ ] }),
112
+ /* @__PURE__ */ jsx(Button, { asChild: true, variant: "secondary", className: "w-full", children: /* @__PURE__ */ jsx("a", { href: "/register", children: "\u65B0\u7528\u6237\u6CE8\u518C" }) }),
113
+ user && /* @__PURE__ */ jsxs("p", { className: "text-center text-xs text-muted-foreground", children: [
114
+ "\u5F53\u524D\u5DF2\u767B\u5F55\uFF1A",
115
+ user.email
116
+ ] })
117
+ ] })
118
+ ] })
119
+ }
120
+ );
121
+ }
122
+
123
+ // src/auth/auth-pages/register.tsx
124
+ import { redirect as redirect2 } from "next/navigation";
125
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
126
+ async function RegisterPage({
127
+ ui,
128
+ searchParams,
129
+ registerAction,
130
+ isAuthenticated,
131
+ redirectWhenAuthenticated = "/admin"
132
+ }) {
133
+ if (isAuthenticated && await isAuthenticated()) {
134
+ redirect2(redirectWhenAuthenticated);
135
+ }
136
+ const { error } = searchParams;
137
+ const { Button, Input, Label, Card, CardHeader, CardTitle, CardDescription, CardContent, Turnstile } = ui;
138
+ return /* @__PURE__ */ jsx2(
139
+ "main",
140
+ {
141
+ style: {
142
+ minHeight: "100vh",
143
+ display: "flex",
144
+ alignItems: "center",
145
+ justifyContent: "center",
146
+ padding: "1rem",
147
+ background: "linear-gradient(to bottom right, var(--background), var(--muted))"
148
+ },
149
+ children: /* @__PURE__ */ jsxs2(Card, { className: "w-full max-w-sm", children: [
150
+ /* @__PURE__ */ jsxs2(CardHeader, { children: [
151
+ /* @__PURE__ */ jsx2(CardTitle, { children: "\u90AE\u7BB1\u6CE8\u518C" }),
152
+ /* @__PURE__ */ jsx2(CardDescription, { children: "\u6CE8\u518C\u540E\u4F1A\u53D1\u9001\u9A8C\u8BC1\u90AE\u4EF6\uFF0C\u9A8C\u8BC1\u5B8C\u6210\u5373\u53EF\u8FDB\u5165\u540E\u53F0\u3002" })
153
+ ] }),
154
+ /* @__PURE__ */ jsxs2(CardContent, { children: [
155
+ /* @__PURE__ */ jsxs2("form", { action: registerAction, children: [
156
+ /* @__PURE__ */ jsx2(Label, { htmlFor: "email", children: "\u90AE\u7BB1" }),
157
+ /* @__PURE__ */ jsx2(
158
+ Input,
159
+ {
160
+ id: "email",
161
+ name: "email",
162
+ type: "email",
163
+ placeholder: "you@example.com",
164
+ autoFocus: true,
165
+ required: true
166
+ }
167
+ ),
168
+ /* @__PURE__ */ jsx2(Label, { htmlFor: "password", children: "\u5BC6\u7801" }),
169
+ /* @__PURE__ */ jsx2(
170
+ Input,
171
+ {
172
+ id: "password",
173
+ name: "password",
174
+ type: "password",
175
+ placeholder: "\u81F3\u5C11 8 \u4F4D\uFF0C\u5305\u542B\u5B57\u6BCD\u548C\u6570\u5B57",
176
+ required: true
177
+ }
178
+ ),
179
+ /* @__PURE__ */ jsx2(Label, { htmlFor: "confirmPassword", children: "\u786E\u8BA4\u5BC6\u7801" }),
180
+ /* @__PURE__ */ jsx2(
181
+ Input,
182
+ {
183
+ id: "confirmPassword",
184
+ name: "confirmPassword",
185
+ type: "password",
186
+ placeholder: "\u518D\u6B21\u8F93\u5165\u5BC6\u7801",
187
+ required: true
188
+ }
189
+ ),
190
+ error && /* @__PURE__ */ jsx2("div", { className: "rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive", children: error }),
191
+ Turnstile && /* @__PURE__ */ jsx2(Turnstile, { action: "register" }),
192
+ /* @__PURE__ */ jsx2(Button, { type: "submit", className: "w-full", children: "\u6CE8\u518C\u5E76\u53D1\u9001\u9A8C\u8BC1\u90AE\u4EF6" })
193
+ ] }),
194
+ /* @__PURE__ */ jsx2(Button, { asChild: true, variant: "ghost", className: "w-full", children: /* @__PURE__ */ jsx2("a", { href: "/login", children: "\u8FD4\u56DE\u767B\u5F55" }) })
195
+ ] })
196
+ ] })
197
+ }
198
+ );
199
+ }
200
+
201
+ // src/auth/auth-pages/forgot-password.tsx
202
+ import { redirect as redirect3 } from "next/navigation";
203
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
204
+ async function ForgotPasswordPage({
205
+ ui,
206
+ searchParams,
207
+ forgotPasswordAction,
208
+ isAuthenticated,
209
+ redirectWhenAuthenticated = "/admin"
210
+ }) {
211
+ if (isAuthenticated && await isAuthenticated()) {
212
+ redirect3(redirectWhenAuthenticated);
213
+ }
214
+ const { sent, email, error, retry } = searchParams;
215
+ const { Button, Input, Label, Card, CardHeader, CardTitle, CardDescription, CardContent, Turnstile } = ui;
216
+ return /* @__PURE__ */ jsx3(
217
+ "main",
218
+ {
219
+ style: {
220
+ minHeight: "100vh",
221
+ display: "flex",
222
+ alignItems: "center",
223
+ justifyContent: "center",
224
+ padding: "1rem",
225
+ background: "linear-gradient(to bottom right, var(--background), var(--muted))"
226
+ },
227
+ children: /* @__PURE__ */ jsxs3(Card, { className: "w-full max-w-sm", children: [
228
+ /* @__PURE__ */ jsxs3(CardHeader, { children: [
229
+ /* @__PURE__ */ jsx3(CardTitle, { children: "\u5FD8\u8BB0\u5BC6\u7801" }),
230
+ /* @__PURE__ */ jsx3(CardDescription, { children: "\u8F93\u5165\u6CE8\u518C\u90AE\u7BB1\uFF0C\u6211\u4EEC\u4F1A\u53D1\u9001\u91CD\u7F6E\u94FE\u63A5\uFF081 \u5C0F\u65F6\u5185\u6709\u6548\uFF09\u3002" })
231
+ ] }),
232
+ /* @__PURE__ */ jsxs3(CardContent, { children: [
233
+ sent && /* @__PURE__ */ jsxs3("div", { className: "rounded-md bg-emerald-500/10 px-3 py-2 text-sm text-emerald-700 dark:text-emerald-400", children: [
234
+ "\u5982\u679C ",
235
+ email ?? "\u8BE5\u90AE\u7BB1",
236
+ " \u5DF2\u6CE8\u518C\u4E14\u5DF2\u9A8C\u8BC1\uFF0C\u4F60\u4F1A\u6536\u5230\u91CD\u7F6E\u5BC6\u7801\u90AE\u4EF6\u3002"
237
+ ] }),
238
+ error === "invalid" && /* @__PURE__ */ jsx3("div", { className: "rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive", children: "\u90AE\u7BB1\u683C\u5F0F\u4E0D\u6B63\u786E" }),
239
+ error === "captcha" && /* @__PURE__ */ jsx3("div", { className: "rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive", children: "\u8BF7\u5B8C\u6210\u4EBA\u673A\u9A8C\u8BC1\u540E\u518D\u8BD5" }),
240
+ error === "rate" && /* @__PURE__ */ jsxs3("div", { className: "rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive", children: [
241
+ "\u8BF7\u6C42\u8FC7\u4E8E\u9891\u7E41\uFF0C\u8BF7 ",
242
+ retry ?? "900",
243
+ " \u79D2\u540E\u518D\u8BD5"
244
+ ] }),
245
+ /* @__PURE__ */ jsxs3("form", { action: forgotPasswordAction, children: [
246
+ /* @__PURE__ */ jsx3(Label, { htmlFor: "email", children: "\u90AE\u7BB1" }),
247
+ /* @__PURE__ */ jsx3(
248
+ Input,
249
+ {
250
+ id: "email",
251
+ name: "email",
252
+ type: "email",
253
+ placeholder: "you@example.com",
254
+ defaultValue: email ?? "",
255
+ required: true
256
+ }
257
+ ),
258
+ Turnstile && /* @__PURE__ */ jsx3(Turnstile, { action: "forgot_password" }),
259
+ /* @__PURE__ */ jsx3(Button, { type: "submit", className: "w-full", children: "\u53D1\u9001\u91CD\u7F6E\u94FE\u63A5" })
260
+ ] }),
261
+ /* @__PURE__ */ jsx3(Button, { asChild: true, variant: "ghost", className: "w-full", children: /* @__PURE__ */ jsx3("a", { href: "/login", children: "\u8FD4\u56DE\u767B\u5F55" }) })
262
+ ] })
263
+ ] })
264
+ }
265
+ );
266
+ }
267
+
268
+ // src/auth/auth-pages/reset-password.tsx
269
+ import { redirect as redirect4 } from "next/navigation";
270
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
271
+ async function ResetPasswordPage({
272
+ ui,
273
+ searchParams,
274
+ resetPasswordAction,
275
+ isAuthenticated,
276
+ redirectWhenAuthenticated = "/admin"
277
+ }) {
278
+ if (isAuthenticated && await isAuthenticated()) {
279
+ redirect4(redirectWhenAuthenticated);
280
+ }
281
+ const { token, error } = searchParams;
282
+ if (!token) {
283
+ redirect4("/forgot-password?error=missing");
284
+ }
285
+ const { Button, Input, Label, Card, CardHeader, CardTitle, CardDescription, CardContent } = ui;
286
+ return /* @__PURE__ */ jsx4(
287
+ "main",
288
+ {
289
+ style: {
290
+ minHeight: "100vh",
291
+ display: "flex",
292
+ alignItems: "center",
293
+ justifyContent: "center",
294
+ padding: "1rem",
295
+ background: "linear-gradient(to bottom right, var(--background), var(--muted))"
296
+ },
297
+ children: /* @__PURE__ */ jsxs4(Card, { className: "w-full max-w-sm", children: [
298
+ /* @__PURE__ */ jsxs4(CardHeader, { children: [
299
+ /* @__PURE__ */ jsx4(CardTitle, { children: "\u8BBE\u7F6E\u65B0\u5BC6\u7801" }),
300
+ /* @__PURE__ */ jsx4(CardDescription, { children: "\u8BF7\u8F93\u5165\u65B0\u5BC6\u7801\uFF0C\u63D0\u4EA4\u540E\u5C06\u81EA\u52A8\u767B\u5F55\u3002" })
301
+ ] }),
302
+ /* @__PURE__ */ jsxs4(CardContent, { children: [
303
+ error && /* @__PURE__ */ jsx4("div", { className: "rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive", children: error }),
304
+ /* @__PURE__ */ jsxs4("form", { action: resetPasswordAction, children: [
305
+ /* @__PURE__ */ jsx4("input", { type: "hidden", name: "token", value: token }),
306
+ /* @__PURE__ */ jsx4(Label, { htmlFor: "password", children: "\u65B0\u5BC6\u7801" }),
307
+ /* @__PURE__ */ jsx4(
308
+ Input,
309
+ {
310
+ id: "password",
311
+ name: "password",
312
+ type: "password",
313
+ placeholder: "\u81F3\u5C11 8 \u4F4D\uFF0C\u5305\u542B\u5B57\u6BCD\u548C\u6570\u5B57",
314
+ required: true
315
+ }
316
+ ),
317
+ /* @__PURE__ */ jsx4(Label, { htmlFor: "confirmPassword", children: "\u786E\u8BA4\u65B0\u5BC6\u7801" }),
318
+ /* @__PURE__ */ jsx4(
319
+ Input,
320
+ {
321
+ id: "confirmPassword",
322
+ name: "confirmPassword",
323
+ type: "password",
324
+ placeholder: "\u518D\u6B21\u8F93\u5165\u65B0\u5BC6\u7801",
325
+ required: true
326
+ }
327
+ ),
328
+ /* @__PURE__ */ jsx4(Button, { type: "submit", className: "w-full", children: "\u66F4\u65B0\u5BC6\u7801\u5E76\u767B\u5F55" })
329
+ ] }),
330
+ /* @__PURE__ */ jsx4(Button, { asChild: true, variant: "ghost", className: "w-full", children: /* @__PURE__ */ jsx4("a", { href: "/login", children: "\u8FD4\u56DE\u767B\u5F55" }) })
331
+ ] })
332
+ ] })
333
+ }
334
+ );
335
+ }
336
+ export {
337
+ ForgotPasswordPage,
338
+ LoginPage,
339
+ RegisterPage,
340
+ ResetPasswordPage
341
+ };
342
+ //# sourceMappingURL=index.js.map