1
0

refactor: 项目更名为 DiAL(统一拨测平台)

将 gateway-checker/Gateway Checker 统一替换为 dial-server/DiAL
- 包名、可执行文件名、API service 标识改为 dial-server
- UI 标题改为 DiAL,副标题改为统一拨测平台
- 同步更新测试断言、构建脚本、示例配置和文档
This commit is contained in:
2026-05-11 22:23:17 +08:00
parent 767f26617e
commit 3fa1b3957e
13 changed files with 25 additions and 25 deletions

View File

@@ -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
```
## 测试

View File

@@ -27,7 +27,7 @@
系统 SHALL 通过单一命令行参数接受 YAML 配置文件路径。
#### Scenario: 指定配置文件启动
- **WHEN** 用户执行 `./gateway-checker ./probes.yaml`
- **WHEN** 用户执行 `./dial-server ./probes.yaml`
- **THEN** 系统 SHALL 读取并解析指定路径的 YAML 文件作为配置
#### Scenario: 未提供配置文件路径

View File

@@ -1,5 +1,5 @@
{
"name": "gateway-checker",
"name": "dial-server",
"type": "module",
"private": true,
"scripts": {

View File

@@ -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

View File

@@ -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));

View File

@@ -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) {

View File

@@ -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(),
};
}

View File

@@ -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]! };

View File

@@ -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;
}

View File

@@ -2,7 +2,7 @@ export type RuntimeMode = "development" | "production" | "test";
export interface HealthResponse {
ok: true;
service: "gateway-checker";
service: "dial-server";
timestamp: string;
}

View File

@@ -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>}

View File

@@ -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>

View File

@@ -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 () => {