Merge branch 'v2-dev' of https://github.com/certd/certd into v2-dev

This commit is contained in:
xiaojunnuo
2025-10-05 14:47:45 +08:00
12 changed files with 290 additions and 481 deletions

4
.npmrc
View File

@@ -1,2 +1,6 @@
link-workspace-packages=deep
prefer-workspace-packages=true
better_sqlite3_binary_host=https://registry.npmmirror.com/-/binary/better-sqlite3
better_sqlite3_binary_host_mirror=https://registry.npmmirror.com/-/binary/better-sqlite3
better-sqlite3_binary_host=https://registry.npmmirror.com/-/binary/better-sqlite3
better-sqlite3_binary_host_mirror=https://registry.npmmirror.com/-/binary/better-sqlite3

8
.vscode/launch.json vendored
View File

@@ -10,8 +10,8 @@
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}/packages/ui/certd-client",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev"],
"runtimeExecutable": "pnpm",
"runtimeArgs": ["dev"],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
},
@@ -20,8 +20,8 @@
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}/packages/ui/certd-server",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev"],
"runtimeExecutable": "pnpm",
"runtimeArgs": ["dev"],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
},

View File

@@ -11,9 +11,12 @@
git clone https://github.com/certd/certd --depth=1
# git checkout v1.x.x # 当v2主干分支代码无法正常启动时可以尝试此命令1.x.x换成最新版本号
cd certd
# 启动服务
./start.sh
```
>如果是windows请先安装`git for windows` ,然后右键,选择`open git bash here`打开终端,再执行`./start.sh`命令

View File

@@ -1,7 +1,9 @@
//转换为import
//@ts-ignore
import childProcess from "child_process";
import { safePromise } from "./util.promise.js";
import { ILogger, logger } from "./util.log.js";
//@ts-ignore
import iconv from "iconv-lite";
export type ExecOption = {
cmd: string | string[];
@@ -28,12 +30,13 @@ async function exec(opts: ExecOption): Promise<string> {
cmd,
{
env: {
//@ts-ignore
...process.env,
...opts.env,
},
...opts.options,
},
(error, stdout, stderr) => {
(error: any, stdout: { toString: (arg0: string) => any }, stderr: any) => {
if (error) {
log.error(`exec error: ${error}`);
reject(error);
@@ -57,6 +60,7 @@ export type SpawnOption = {
};
function isWindows() {
// @ts-ignore
return process.platform === "win32";
}
function convert(buffer: any) {
@@ -94,39 +98,39 @@ async function spawn(opts: SpawnOption): Promise<string> {
const ls = childProcess.spawn(cmd, {
shell: true,
env: {
//@ts-ignore
...process.env,
...opts.env,
},
...opts.options,
});
ls.stdout.on("data", data => {
ls.stdout.on("data", (data: string) => {
data = convert(data);
log.info(`stdout: ${data}`);
stdout += data;
});
ls.stderr.on("data", data => {
ls.stderr.on("data", (data: string) => {
data = convert(data);
log.warn(`stderr: ${data}`);
stderr += data;
});
ls.on("error", error => {
ls.on("error", (error: any) => {
log.error(`child process error: ${error}`);
const e = error;
// @ts-ignore
e.stderr = stderr;
// @ts-ignore
e.stdout = stdout;
//@ts-ignore
error.stderr = stderr;
//@ts-ignore
error.stdout = stdout;
reject(error);
});
ls.on("close", (code: number) => {
if (code !== 0) {
log.error(`child process exited with code ${code}`);
const e = new Error(stderr || `return ${code}`);
// @ts-ignore
const e = new Error(stderr || "return " + code);
//@ts-ignore
e.stderr = stderr;
// @ts-ignore
//@ts-ignore
e.stdout = stdout;
reject(e);
} else {

View File

@@ -31,7 +31,6 @@
"devDependencies": {
"@types/chai": "^4.3.3",
"@types/mocha": "^10.0.0",
"@types/psl": "^1.1.3",
"@typescript-eslint/eslint-plugin": "^8.26.1",
"@typescript-eslint/parser": "^8.26.1",
"chai": "^4.3.6",

View File

@@ -41,7 +41,6 @@
"devDependencies": {
"@types/chai": "^4.3.3",
"@types/mocha": "^10.0.0",
"@types/psl": "^1.1.3",
"@typescript-eslint/eslint-plugin": "^8.26.1",
"@typescript-eslint/parser": "^8.26.1",
"chai": "^4.3.6",

View File

@@ -78,7 +78,7 @@ const createPingTestMethod = async () => {
const createTelnetTestMethod = async () => {
const domain = getCurrentDomain();
const port = getCurrentPort();
return TelnetTest(domain, port);
};
@@ -95,7 +95,7 @@ const getCurrentPort = () => {
// 运行全部测试
async function runAllTests() {
const domain = getCurrentDomain();
// 检查是否有域名
if (!domain) {
message.error("请输入域名");
@@ -107,8 +107,6 @@ async function runAllTests() {
// 通过组件引用调用测试方法
try {
await Promise.allSettled([domainResolveRef.value?.test(), pingTestRef.value?.test(), telnetTestRef.value?.test()]);
message.success("所有测试已完成");
} catch (error) {
message.error("部分测试执行失败请查看详细结果");
} finally {

View File

@@ -19,14 +19,8 @@
<!-- 本地IP -->
<div class="info-item">
<div class="info-label">本地IP:</div>
<div v-if="serverInfo.localIP" class="info-value">
<a-list item-layout="horizontal" :data-source="serverInfo.localIP">
<template #renderItem="{ item }">
<a-list-item>
<a-list-item-meta description="{{ item }}" />
</a-list-item>
</template>
</a-list>
<div v-if="serverInfo.localIP && serverInfo.localIP.length > 0" class="info-value">
<a-tag v-for="ip in serverInfo.localIP" :key="ip" type="info" color="blue">{{ ip }}</a-tag>
</div>
<div v-else class="info-empty">暂无信息</div>
</div>
@@ -34,8 +28,8 @@
<!-- 外网IP -->
<div class="info-item">
<div class="info-label">外网IP:</div>
<div v-if="serverInfo.publicIP" class="info-value">
{{ serverInfo.publicIP }}
<div v-if="serverInfo.publicIP && serverInfo.publicIP.length > 0" class="info-value">
<a-tag v-for="ip in serverInfo.publicIP" :key="ip" type="info" color="green">{{ ip }}</a-tag>
</div>
<div v-else class="info-empty">暂无信息</div>
</div>
@@ -44,7 +38,7 @@
<div class="info-item">
<div class="info-label">DNS服务器:</div>
<div v-if="serverInfo.dnsServers && serverInfo.dnsServers.length > 0" class="info-value">
{{ serverInfo.dnsServers.join(", ") }}
<a-tag v-for="dns in serverInfo.dnsServers" :key="dns" type="info" color="cyan">{{ dns }}</a-tag>
</div>
<div v-else class="info-empty">暂无信息</div>
</div>
@@ -60,7 +54,7 @@ import { GetServerInfo } from "./api";
// 服务器信息类型
interface ServerInfo {
localIP?: string[];
publicIP?: string;
publicIP?: string[];
dnsServers?: string[];
}

View File

@@ -6,7 +6,7 @@
<div class="nettest-container">
<!-- 服务端信息 -->
<server-info-card />
<!-- 测试区域 -->
<div class="test-areas">
<!-- 用户输入域名测试 -->

View File

@@ -88,6 +88,7 @@ export default ({ command, mode }) => {
host: "0.0.0.0",
port: 3008,
fs: devServerFs,
allowedHosts: ["localhost", "127.0.0.1", "yfy.docmirror.cn"],
proxy: {
// with options
"/api": {

View File

@@ -42,7 +42,7 @@ export class NetTestService {
// 判断测试是否成功
const success = this.isWindows()
? output.includes('端口连接成功')
: output.includes('succeeded') || output.includes('open');
: output.includes('Connected to');
// 处理结果
return {
@@ -55,8 +55,8 @@ export class NetTestService {
return {
success: false,
message: 'Telnet测试执行失败',
testLog: error instanceof Error ? error.message : String(error),
error: error instanceof Error ? error.message : String(error)
testLog: error.stdout || error.stderr || error?.message || String(error),
error: error.stderr || error?.message || String(error),
};
}
}
@@ -133,7 +133,7 @@ export class NetTestService {
});
// 判断测试是否成功
const success = output.includes('Address:') || output.includes('IN A') ||
const success = output.includes('Address:') || output.includes('IN A') || output.includes('IN AAAA') ||
(this.isWindows() && output.includes('Name:'));
return {
@@ -153,27 +153,29 @@ export class NetTestService {
}
async getLocalIP(): Promise<string> {
async getLocalIP(): Promise<string[]> {
try {
const output = await utils.sp.spawn({
cmd: 'ip a | grep \'inet \' | grep -v \'127.0.0.1\' | awk \'{print $2}\' | cut -d/ -f1',
logger: undefined
});
return output.trim();
// 去除 inet 前缀
let ips = output.trim().replace(/inet /g, '');
return ips.split('\n').filter(ip => ip.length > 0);
} catch (error) {
return error instanceof Error ? error.message : String(error);
return [error instanceof Error ? error.message : String(error)];
}
}
async getPublicIP(): Promise<string> {
async getPublicIP(): Promise<string[]> {
try {
const res = await http.request({
url:"https://ipinfo.io/ip",
method:"GET",
})
return res
return[res]
} catch (error) {
return error instanceof Error ? error.message : String(error);
return [error instanceof Error ? error.message : String(error)]
}
}
@@ -215,8 +217,8 @@ export class NetTestService {
async serverInfo(): Promise<any> {
const res = {
localIP: '',
publicIP: '',
localIP: [],
publicIP: [],
dnsServers: [],
}

673
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff