- Console:React 19 + antd 6.6.5 前端(登录 admin/admin)+ Hono 管理 API (Nodes/Domains/Mailboxes/Emails/Webhooks/Keys/OAuth/Admin) - Node:Bun 转发节点(HMAC 签名、有限重试、心跳、结构化日志、优雅退出) - Email Worker:Cloudflare email handler + 本地联调入口 - shared:HMAC 协议(docs/04)、wmh_ Key(32 位)、AES-GCM 加密、SSRF 防护 - 邮件管线:postal-mime 解析、附件、catch-all、限额、malformed 降级、TTL 1 天 - Webhook:签名投递、指数退避重试、SSRF 校验、投递日志 - API v1 + MCP(JSON-RPC,六工具,凭据 kind 隔离) - Cloudflare OAuth:真实 + 本地 sim 模式,自动安装管线(幂等,无需手工命令) - 测试:bun test 41 例(协议安全/管线/TTL/Webhook/SSRF/MCP/OAuth/鉴权)+ Playwright UI 冒烟 - LOGO/favicon 由 codex CLI 生成
56 lines
1.9 KiB
TypeScript
56 lines
1.9 KiB
TypeScript
/** 前端入口:antd v6 + react-router,路由守卫由 App 内 authGate 状态控制 */
|
|
import React from "react";
|
|
import { createRoot } from "react-dom/client";
|
|
import { ConfigProvider, App as AntdApp } from "antd";
|
|
import zhCN from "antd/locale/zh_CN";
|
|
import { createBrowserRouter, RouterProvider } from "react-router-dom";
|
|
import { antdTheme } from "./theme.ts";
|
|
import "./styles.css";
|
|
import { App } from "./App.tsx";
|
|
import { LoginPage } from "./pages/Login.tsx";
|
|
import { OAuthSimPage } from "./pages/OAuthSim.tsx";
|
|
import { DashboardPage } from "./pages/Dashboard.tsx";
|
|
import { NodesPage } from "./pages/Nodes.tsx";
|
|
import { DomainsPage } from "./pages/Domains.tsx";
|
|
import { MailboxesPage } from "./pages/Mailboxes.tsx";
|
|
import { EmailsPage } from "./pages/Emails.tsx";
|
|
import { WebhooksPage } from "./pages/Webhooks.tsx";
|
|
import { KeysPage } from "./pages/Keys.tsx";
|
|
import { setUnauthorizedHandler } from "./api.ts";
|
|
|
|
/** # 成员变量: 路由表 **/
|
|
const router = createBrowserRouter([
|
|
{ path: "/login", element: <LoginPage /> },
|
|
{ path: "/oauth/sim/authorize", element: <OAuthSimPage /> },
|
|
{
|
|
path: "/",
|
|
element: <App />,
|
|
children: [
|
|
{ index: true, element: <DashboardPage /> },
|
|
{ path: "nodes", element: <NodesPage /> },
|
|
{ path: "domains", element: <DomainsPage /> },
|
|
{ path: "mailboxes", element: <MailboxesPage /> },
|
|
{ path: "emails", element: <EmailsPage /> },
|
|
{ path: "webhooks", element: <WebhooksPage /> },
|
|
{ path: "keys", element: <KeysPage /> },
|
|
],
|
|
},
|
|
]);
|
|
|
|
/** 未登录统一跳登录页 */
|
|
setUnauthorizedHandler(() => {
|
|
if (!location.pathname.startsWith("/login")) {
|
|
location.href = "/login";
|
|
}
|
|
});
|
|
|
|
createRoot(document.getElementById("root")!).render(
|
|
<React.StrictMode>
|
|
<ConfigProvider locale={zhCN} theme={antdTheme}>
|
|
<AntdApp>
|
|
<RouterProvider router={router} />
|
|
</AntdApp>
|
|
</ConfigProvider>
|
|
</React.StrictMode>,
|
|
);
|