|
@@ -0,0 +1,103 @@
|
|
|
+const chokidar = require("chokidar");
|
|
|
+const { exec } = require("child_process");
|
|
|
+const path = require("path")
|
|
|
+
|
|
|
+exports.parseK6StdoutTable = function (text) {
|
|
|
+ const keysToKeep = new Set([
|
|
|
+ "checks_total",
|
|
|
+ "checks_succeeded",
|
|
|
+ "checks_failed",
|
|
|
+ "browser_data_received",
|
|
|
+ "browser_data_sent",
|
|
|
+ "browser_http_req_duration",
|
|
|
+ "browser_http_req_failed",
|
|
|
+ "browser_web_vital_cls",
|
|
|
+ "browser_web_vital_fcp",
|
|
|
+ "browser_web_vital_ttfb",
|
|
|
+ "checks",
|
|
|
+ "data_received",
|
|
|
+ "data_sent",
|
|
|
+ "iteration_duration",
|
|
|
+ "iterations",
|
|
|
+ "vus",
|
|
|
+ "vus_max",
|
|
|
+ ]);
|
|
|
+
|
|
|
+ const lines = text.split("\n");
|
|
|
+ const result = {};
|
|
|
+
|
|
|
+ for (let line of lines) {
|
|
|
+ line = line.replace(/^[✓×\s]+/, ""); // 去掉开头 ✓ × 空格
|
|
|
+
|
|
|
+ if (!line.includes(":")) continue;
|
|
|
+
|
|
|
+ let [keyPart, valPart] = line.split(":");
|
|
|
+ if (!valPart) continue;
|
|
|
+
|
|
|
+ const key = keyPart.trim().replace(/\.+$/, "");
|
|
|
+ if (!keysToKeep.has(key)) continue;
|
|
|
+
|
|
|
+ valPart = valPart.trim();
|
|
|
+
|
|
|
+ if (/(\w+\()?=/.test(valPart)) {
|
|
|
+ const stats = {};
|
|
|
+ const regex = /([^\s=]+)=([^\s]+)/g;
|
|
|
+ let match;
|
|
|
+ while ((match = regex.exec(valPart)) !== null) {
|
|
|
+ stats[match[1]] = match[2];
|
|
|
+ }
|
|
|
+ result[key] = stats;
|
|
|
+ } else {
|
|
|
+ const parts = valPart.split(/\s+/);
|
|
|
+
|
|
|
+ if (parts.length === 4 && parts[2].endsWith("/s")) {
|
|
|
+ result[key] = {
|
|
|
+ value: parts[0] + " " + parts[1],
|
|
|
+ rate: parts[2] + " " + parts[3],
|
|
|
+ };
|
|
|
+ } else if (parts.length === 2 && parts[1].endsWith("/s")) {
|
|
|
+ result[key] = {
|
|
|
+ value: parts[0],
|
|
|
+ rate: parts[1],
|
|
|
+ };
|
|
|
+ } else {
|
|
|
+ result[key] = valPart;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+};
|
|
|
+
|
|
|
+exports.watchClient = () => {
|
|
|
+ const watchPath = path.join(__dirname, '../client/src');
|
|
|
+
|
|
|
+ // 初始化 watcher
|
|
|
+ const watcher = chokidar.watch(watchPath, {
|
|
|
+ ignored: /(^|[\/\\])\../, // 忽略隐藏文件
|
|
|
+ persistent: true,
|
|
|
+ });
|
|
|
+
|
|
|
+ // 添加事件监听
|
|
|
+ watcher
|
|
|
+ .on("add", (path) => runScript(`新增文件:${path}`))
|
|
|
+ .on("change", (path) => runScript(`文件修改:${path}`))
|
|
|
+ .on("unlink", (path) => runScript(`删除文件:${path}`));
|
|
|
+
|
|
|
+ // 你想在文件变更后执行的脚本(例如执行某个命令)
|
|
|
+ function runScript(changeInfo) {
|
|
|
+ console.log(`[触发] ${changeInfo}`);
|
|
|
+
|
|
|
+ // 例如执行 build 脚本或 shell 命令
|
|
|
+ exec("cd ../client && npm run build", (error, stdout, stderr) => {
|
|
|
+ if (error) {
|
|
|
+ console.error(`执行出错: ${error.message}`);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (stderr) {
|
|
|
+ console.error(`stderr: ${stderr}`);
|
|
|
+ }
|
|
|
+ console.log(`stdout: ${stdout}`);
|
|
|
+ });
|
|
|
+ }
|
|
|
+};
|