refactor: 项目更名为 DiAL(统一拨测平台)
将 gateway-checker/Gateway Checker 统一替换为 dial-server/DiAL - 包名、可执行文件名、API service 标识改为 dial-server - UI 标题改为 DiAL,副标题改为统一拨测平台 - 同步更新测试断言、构建脚本、示例配置和文档
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# Gateway Checker
|
||||
# DiAL
|
||||
|
||||
基于 Bun + TypeScript 的多类型拨测监控工具。通过 YAML 配置文件定义 HTTP 和命令行拨测目标,后端按配置定时并发拨测,结果持久化到本地 SQLite,前端 Dashboard 展示各目标实时状态、可用率、耗时趋势等。
|
||||
|
||||
@@ -233,12 +233,12 @@ bun run build
|
||||
1. 运行 `vite build`,输出前端资源到 `dist/web`
|
||||
2. 生成临时 `.build/static-assets.ts`,嵌入 Vite 产物
|
||||
3. 生成临时 `.build/server-entry.ts`,作为生产入口
|
||||
4. 运行 `Bun.build({ compile })`,输出 `dist/gateway-checker`
|
||||
4. 运行 `Bun.build({ compile })`,输出 `dist/dial-server`
|
||||
|
||||
运行 executable:
|
||||
|
||||
```bash
|
||||
./dist/gateway-checker probes.yaml
|
||||
./dist/dial-server probes.yaml
|
||||
```
|
||||
|
||||
## 运行参数
|
||||
@@ -246,7 +246,7 @@ bun run build
|
||||
CLI 只接受一个参数:YAML 配置文件路径。
|
||||
|
||||
```bash
|
||||
./dist/gateway-checker ./probes.yaml
|
||||
./dist/dial-server ./probes.yaml
|
||||
```
|
||||
|
||||
## 测试
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
系统 SHALL 通过单一命令行参数接受 YAML 配置文件路径。
|
||||
|
||||
#### Scenario: 指定配置文件启动
|
||||
- **WHEN** 用户执行 `./gateway-checker ./probes.yaml`
|
||||
- **WHEN** 用户执行 `./dial-server ./probes.yaml`
|
||||
- **THEN** 系统 SHALL 读取并解析指定路径的 YAML 文件作为配置
|
||||
|
||||
#### Scenario: 未提供配置文件路径
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "gateway-checker",
|
||||
"name": "dial-server",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -99,13 +99,13 @@ targets:
|
||||
http:
|
||||
url: "https://httpbin.org/headers"
|
||||
headers:
|
||||
X-Custom-Header: "gateway-checker"
|
||||
X-Custom-Header: "dial-server"
|
||||
expect:
|
||||
status: [200]
|
||||
body:
|
||||
- json:
|
||||
path: "$.headers.X-Custom-Header"
|
||||
equals: "gateway-checker"
|
||||
equals: "dial-server"
|
||||
|
||||
- name: "响应头自定义校验"
|
||||
type: http
|
||||
|
||||
@@ -5,7 +5,7 @@ import { $ } from "bun";
|
||||
|
||||
const buildDir = fileURLToPath(new URL("../.build/", import.meta.url));
|
||||
const webDistDir = fileURLToPath(new URL("../dist/web/", import.meta.url));
|
||||
const executablePath = fileURLToPath(new URL("../dist/gateway-checker", import.meta.url));
|
||||
const executablePath = fileURLToPath(new URL("../dist/dial-server", import.meta.url));
|
||||
const generatedAssetsPath = fileURLToPath(new URL("../.build/static-assets.ts", import.meta.url));
|
||||
const generatedEntryPath = fileURLToPath(new URL("../.build/server-entry.ts", import.meta.url));
|
||||
|
||||
|
||||
@@ -5,11 +5,11 @@ import { join } from "node:path";
|
||||
import { tmpdir } from "node:os";
|
||||
import type { HealthResponse, SummaryResponse } from "../src/shared/api";
|
||||
|
||||
const executablePath = process.argv[2] ?? fileURLToPath(new URL("../dist/gateway-checker", import.meta.url));
|
||||
const executablePath = process.argv[2] ?? fileURLToPath(new URL("../dist/dial-server", import.meta.url));
|
||||
|
||||
await assertExecutableExists(executablePath);
|
||||
|
||||
const tempDir = mkdtempSync(join(tmpdir(), "gc-smoke-"));
|
||||
const tempDir = mkdtempSync(join(tmpdir(), "dial-smoke-"));
|
||||
const configPath = join(tempDir, "probes.yaml");
|
||||
|
||||
const port = await getFreePort();
|
||||
@@ -61,11 +61,11 @@ try {
|
||||
assert(missingTarget.status === 404, "不存在的目标应返回 404");
|
||||
|
||||
const { body: rootHtml, response: rootResponse } = await expectText(`${baseUrl}/`, 200);
|
||||
assert(rootHtml.includes("Gateway Checker"), "前端根页面缺少标题");
|
||||
assert(rootHtml.includes("DiAL"), "前端根页面缺少标题");
|
||||
assert(rootResponse.headers.get("cache-control") === "no-cache", "前端根页面应使用 no-cache");
|
||||
|
||||
const { body: fallbackHtml } = await expectText(`${baseUrl}/dashboard`, 200);
|
||||
assert(fallbackHtml.includes("Gateway Checker"), "SPA fallback 未返回前端入口页面");
|
||||
assert(fallbackHtml.includes("DiAL"), "SPA fallback 未返回前端入口页面");
|
||||
|
||||
const assetPath = rootHtml.match(/(?:src|href)="(\/assets\/[^"]+)"/)?.[1];
|
||||
assert(assetPath !== undefined, "前端入口页面未引用 /assets/* 资源");
|
||||
@@ -74,7 +74,7 @@ try {
|
||||
assert(asset.status === 200, `静态资源 ${assetPath} 未返回 200`);
|
||||
|
||||
const missingAsset = await expectText(`${baseUrl}/assets/not-found.js`, 404);
|
||||
assert(!missingAsset.body.includes("Gateway Checker"), "未知静态资源不应返回前端入口页面");
|
||||
assert(!missingAsset.body.includes("DiAL"), "未知静态资源不应返回前端入口页面");
|
||||
|
||||
console.log(`Smoke test passed: ${baseUrl}`);
|
||||
} catch (error) {
|
||||
|
||||
@@ -244,7 +244,7 @@ function formatDuration(ms: number): string {
|
||||
function createHealthResponse(): HealthResponse {
|
||||
return {
|
||||
ok: true,
|
||||
service: "gateway-checker",
|
||||
service: "dial-server",
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export function readRuntimeConfig(argv: string[] = process.argv.slice(2)): { configPath: string } {
|
||||
if (argv.length === 0) {
|
||||
throw new Error("需要指定 YAML 配置文件路径\n用法: gateway-checker <config.yaml>");
|
||||
throw new Error("需要指定 YAML 配置文件路径\n用法: dial-server <config.yaml>");
|
||||
}
|
||||
|
||||
return { configPath: argv[0]! };
|
||||
|
||||
@@ -23,7 +23,7 @@ export function startServer(options: StartServerOptions) {
|
||||
}),
|
||||
});
|
||||
|
||||
console.log(`Gateway Checker listening on ${server.url}`);
|
||||
console.log(`DiAL listening on ${server.url}`);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ export type RuntimeMode = "development" | "production" | "test";
|
||||
|
||||
export interface HealthResponse {
|
||||
ok: true;
|
||||
service: "gateway-checker";
|
||||
service: "dial-server";
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,8 @@ export function App() {
|
||||
return (
|
||||
<main className="dashboard">
|
||||
<header className="dashboard-header">
|
||||
<h1>Gateway Checker</h1>
|
||||
<p className="dashboard-subtitle">HTTP 拨测监控面板</p>
|
||||
<h1>DiAL</h1>
|
||||
<p className="dashboard-subtitle">统一拨测平台</p>
|
||||
</header>
|
||||
|
||||
{error && <div className="error-banner">请求失败: {error},将在下一次轮询周期自动重试</div>}
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="Gateway Checker - HTTP 拨测监控面板" />
|
||||
<title>Gateway Checker</title>
|
||||
<meta name="description" content="DiAL - 统一拨测平台" />
|
||||
<title>DiAL</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -7,7 +7,7 @@ import { join } from "node:path";
|
||||
import { tmpdir } from "node:os";
|
||||
|
||||
const staticAssets: StaticAssets = {
|
||||
indexHtml: new Blob(['<!doctype html><title>Gateway Checker</title><div id="root"></div>'], {
|
||||
indexHtml: new Blob(['<!doctype html><title>DiAL</title><div id="root"></div>'], {
|
||||
type: "text/html",
|
||||
}),
|
||||
files: {
|
||||
@@ -21,7 +21,7 @@ describe("API 路由", () => {
|
||||
let fetchHandler: ReturnType<typeof createFetchHandler>;
|
||||
|
||||
beforeAll(async () => {
|
||||
tempDir = join(tmpdir(), `gc-api-test-${Date.now()}`);
|
||||
tempDir = join(tmpdir(), `dial-api-test-${Date.now()}`);
|
||||
await mkdir(tempDir, { recursive: true });
|
||||
store = new ProbeStore(join(tempDir, "test.db"));
|
||||
store.syncTargets([
|
||||
@@ -93,7 +93,7 @@ describe("API 路由", () => {
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(body.ok).toBe(true);
|
||||
expect(body.service).toBe("gateway-checker");
|
||||
expect(body.service).toBe("dial-server");
|
||||
});
|
||||
|
||||
test("/api/summary 返回总览统计", async () => {
|
||||
|
||||
Reference in New Issue
Block a user