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
View File
@@ -1,2 +1,6 @@
link-workspace-packages=deep link-workspace-packages=deep
prefer-workspace-packages=true 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
+4 -4
View File
@@ -10,8 +10,8 @@
"type": "node", "type": "node",
"request": "launch", "request": "launch",
"cwd": "${workspaceFolder}/packages/ui/certd-client", "cwd": "${workspaceFolder}/packages/ui/certd-client",
"runtimeExecutable": "npm", "runtimeExecutable": "pnpm",
"runtimeArgs": ["run", "dev"], "runtimeArgs": ["dev"],
"console": "integratedTerminal", "console": "integratedTerminal",
"internalConsoleOptions": "neverOpen" "internalConsoleOptions": "neverOpen"
}, },
@@ -20,8 +20,8 @@
"type": "node", "type": "node",
"request": "launch", "request": "launch",
"cwd": "${workspaceFolder}/packages/ui/certd-server", "cwd": "${workspaceFolder}/packages/ui/certd-server",
"runtimeExecutable": "npm", "runtimeExecutable": "pnpm",
"runtimeArgs": ["run", "dev"], "runtimeArgs": ["dev"],
"console": "integratedTerminal", "console": "integratedTerminal",
"internalConsoleOptions": "neverOpen" "internalConsoleOptions": "neverOpen"
}, },
+3
View File
@@ -11,9 +11,12 @@
git clone https://github.com/certd/certd --depth=1 git clone https://github.com/certd/certd --depth=1
# git checkout v1.x.x # 当v2主干分支代码无法正常启动时,可以尝试此命令,1.x.x换成最新版本号 # git checkout v1.x.x # 当v2主干分支代码无法正常启动时,可以尝试此命令,1.x.x换成最新版本号
cd certd cd certd
# 启动服务 # 启动服务
./start.sh ./start.sh
``` ```
>如果是windows,请先安装`git for windows` ,然后右键,选择`open git bash here`打开终端,再执行`./start.sh`命令 >如果是windows,请先安装`git for windows` ,然后右键,选择`open git bash here`打开终端,再执行`./start.sh`命令
+16 -12
View File
@@ -1,7 +1,9 @@
//转换为import //转换为import
//@ts-ignore
import childProcess from "child_process"; import childProcess from "child_process";
import { safePromise } from "./util.promise.js"; import { safePromise } from "./util.promise.js";
import { ILogger, logger } from "./util.log.js"; import { ILogger, logger } from "./util.log.js";
//@ts-ignore
import iconv from "iconv-lite"; import iconv from "iconv-lite";
export type ExecOption = { export type ExecOption = {
cmd: string | string[]; cmd: string | string[];
@@ -28,12 +30,13 @@ async function exec(opts: ExecOption): Promise<string> {
cmd, cmd,
{ {
env: { env: {
//@ts-ignore
...process.env, ...process.env,
...opts.env, ...opts.env,
}, },
...opts.options, ...opts.options,
}, },
(error, stdout, stderr) => { (error: any, stdout: { toString: (arg0: string) => any }, stderr: any) => {
if (error) { if (error) {
log.error(`exec error: ${error}`); log.error(`exec error: ${error}`);
reject(error); reject(error);
@@ -57,6 +60,7 @@ export type SpawnOption = {
}; };
function isWindows() { function isWindows() {
// @ts-ignore
return process.platform === "win32"; return process.platform === "win32";
} }
function convert(buffer: any) { function convert(buffer: any) {
@@ -94,39 +98,39 @@ async function spawn(opts: SpawnOption): Promise<string> {
const ls = childProcess.spawn(cmd, { const ls = childProcess.spawn(cmd, {
shell: true, shell: true,
env: { env: {
//@ts-ignore
...process.env, ...process.env,
...opts.env, ...opts.env,
}, },
...opts.options, ...opts.options,
}); });
ls.stdout.on("data", data => { ls.stdout.on("data", (data: string) => {
data = convert(data); data = convert(data);
log.info(`stdout: ${data}`); log.info(`stdout: ${data}`);
stdout += data; stdout += data;
}); });
ls.stderr.on("data", data => { ls.stderr.on("data", (data: string) => {
data = convert(data); data = convert(data);
log.warn(`stderr: ${data}`); log.warn(`stderr: ${data}`);
stderr += data; stderr += data;
}); });
ls.on("error", error => { ls.on("error", (error: any) => {
log.error(`child process error: ${error}`); log.error(`child process error: ${error}`);
const e = error; //@ts-ignore
// @ts-ignore error.stderr = stderr;
e.stderr = stderr; //@ts-ignore
// @ts-ignore error.stdout = stdout;
e.stdout = stdout;
reject(error); reject(error);
}); });
ls.on("close", (code: number) => { ls.on("close", (code: number) => {
if (code !== 0) { if (code !== 0) {
log.error(`child process exited with code ${code}`); log.error(`child process exited with code ${code}`);
const e = new Error(stderr || `return ${code}`); const e = new Error(stderr || "return " + code);
// @ts-ignore //@ts-ignore
e.stderr = stderr; e.stderr = stderr;
// @ts-ignore //@ts-ignore
e.stdout = stdout; e.stdout = stdout;
reject(e); reject(e);
} else { } else {
@@ -31,7 +31,6 @@
"devDependencies": { "devDependencies": {
"@types/chai": "^4.3.3", "@types/chai": "^4.3.3",
"@types/mocha": "^10.0.0", "@types/mocha": "^10.0.0",
"@types/psl": "^1.1.3",
"@typescript-eslint/eslint-plugin": "^8.26.1", "@typescript-eslint/eslint-plugin": "^8.26.1",
"@typescript-eslint/parser": "^8.26.1", "@typescript-eslint/parser": "^8.26.1",
"chai": "^4.3.6", "chai": "^4.3.6",
-1
View File
@@ -41,7 +41,6 @@
"devDependencies": { "devDependencies": {
"@types/chai": "^4.3.3", "@types/chai": "^4.3.3",
"@types/mocha": "^10.0.0", "@types/mocha": "^10.0.0",
"@types/psl": "^1.1.3",
"@typescript-eslint/eslint-plugin": "^8.26.1", "@typescript-eslint/eslint-plugin": "^8.26.1",
"@typescript-eslint/parser": "^8.26.1", "@typescript-eslint/parser": "^8.26.1",
"chai": "^4.3.6", "chai": "^4.3.6",
@@ -107,8 +107,6 @@ async function runAllTests() {
// 通过组件引用调用测试方法 // 通过组件引用调用测试方法
try { try {
await Promise.allSettled([domainResolveRef.value?.test(), pingTestRef.value?.test(), telnetTestRef.value?.test()]); await Promise.allSettled([domainResolveRef.value?.test(), pingTestRef.value?.test(), telnetTestRef.value?.test()]);
message.success("所有测试已完成");
} catch (error) { } catch (error) {
message.error("部分测试执行失败请查看详细结果"); message.error("部分测试执行失败请查看详细结果");
} finally { } finally {
@@ -19,14 +19,8 @@
<!-- 本地IP --> <!-- 本地IP -->
<div class="info-item"> <div class="info-item">
<div class="info-label">本地IP:</div> <div class="info-label">本地IP:</div>
<div v-if="serverInfo.localIP" class="info-value"> <div v-if="serverInfo.localIP && serverInfo.localIP.length > 0" class="info-value">
<a-list item-layout="horizontal" :data-source="serverInfo.localIP"> <a-tag v-for="ip in serverInfo.localIP" :key="ip" type="info" color="blue">{{ ip }}</a-tag>
<template #renderItem="{ item }">
<a-list-item>
<a-list-item-meta description="{{ item }}" />
</a-list-item>
</template>
</a-list>
</div> </div>
<div v-else class="info-empty">暂无信息</div> <div v-else class="info-empty">暂无信息</div>
</div> </div>
@@ -34,8 +28,8 @@
<!-- 外网IP --> <!-- 外网IP -->
<div class="info-item"> <div class="info-item">
<div class="info-label">外网IP:</div> <div class="info-label">外网IP:</div>
<div v-if="serverInfo.publicIP" class="info-value"> <div v-if="serverInfo.publicIP && serverInfo.publicIP.length > 0" class="info-value">
{{ serverInfo.publicIP }} <a-tag v-for="ip in serverInfo.publicIP" :key="ip" type="info" color="green">{{ ip }}</a-tag>
</div> </div>
<div v-else class="info-empty">暂无信息</div> <div v-else class="info-empty">暂无信息</div>
</div> </div>
@@ -44,7 +38,7 @@
<div class="info-item"> <div class="info-item">
<div class="info-label">DNS服务器:</div> <div class="info-label">DNS服务器:</div>
<div v-if="serverInfo.dnsServers && serverInfo.dnsServers.length > 0" class="info-value"> <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>
<div v-else class="info-empty">暂无信息</div> <div v-else class="info-empty">暂无信息</div>
</div> </div>
@@ -60,7 +54,7 @@ import { GetServerInfo } from "./api";
// 服务器信息类型 // 服务器信息类型
interface ServerInfo { interface ServerInfo {
localIP?: string[]; localIP?: string[];
publicIP?: string; publicIP?: string[];
dnsServers?: string[]; dnsServers?: string[];
} }
+1
View File
@@ -88,6 +88,7 @@ export default ({ command, mode }) => {
host: "0.0.0.0", host: "0.0.0.0",
port: 3008, port: 3008,
fs: devServerFs, fs: devServerFs,
allowedHosts: ["localhost", "127.0.0.1", "yfy.docmirror.cn"],
proxy: { proxy: {
// with options // with options
"/api": { "/api": {
@@ -42,7 +42,7 @@ export class NetTestService {
// 判断测试是否成功 // 判断测试是否成功
const success = this.isWindows() const success = this.isWindows()
? output.includes('端口连接成功') ? output.includes('端口连接成功')
: output.includes('succeeded') || output.includes('open'); : output.includes('Connected to');
// 处理结果 // 处理结果
return { return {
@@ -55,8 +55,8 @@ export class NetTestService {
return { return {
success: false, success: false,
message: 'Telnet测试执行失败', message: 'Telnet测试执行失败',
testLog: error instanceof Error ? error.message : String(error), testLog: error.stdout || error.stderr || error?.message || String(error),
error: error instanceof Error ? 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:')); (this.isWindows() && output.includes('Name:'));
return { return {
@@ -153,27 +153,29 @@ export class NetTestService {
} }
async getLocalIP(): Promise<string> { async getLocalIP(): Promise<string[]> {
try { try {
const output = await utils.sp.spawn({ const output = await utils.sp.spawn({
cmd: 'ip a | grep \'inet \' | grep -v \'127.0.0.1\' | awk \'{print $2}\' | cut -d/ -f1', cmd: 'ip a | grep \'inet \' | grep -v \'127.0.0.1\' | awk \'{print $2}\' | cut -d/ -f1',
logger: undefined logger: undefined
}); });
return output.trim(); // 去除 inet 前缀
let ips = output.trim().replace(/inet /g, '');
return ips.split('\n').filter(ip => ip.length > 0);
} catch (error) { } 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 { try {
const res = await http.request({ const res = await http.request({
url:"https://ipinfo.io/ip", url:"https://ipinfo.io/ip",
method:"GET", method:"GET",
}) })
return res return[res]
} catch (error) { } 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> { async serverInfo(): Promise<any> {
const res = { const res = {
localIP: '', localIP: [],
publicIP: '', publicIP: [],
dnsServers: [], dnsServers: [],
} }
+239 -434
View File
File diff suppressed because it is too large Load Diff