qat-cli 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli.js +1319 -1233
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +308 -129
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +128 -120
- package/dist/index.d.ts +128 -120
- package/dist/index.js +307 -128
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1047,12 +1047,36 @@ import_handlebars.default.registerHelper("propTestValue", (prop) => {
|
|
|
1047
1047
|
};
|
|
1048
1048
|
return map[prop.type] || "'test-value'";
|
|
1049
1049
|
});
|
|
1050
|
+
function resolveImportPath(testType, targetPath) {
|
|
1051
|
+
if (!targetPath) return targetPath;
|
|
1052
|
+
const testDirMap = {
|
|
1053
|
+
unit: "tests/unit",
|
|
1054
|
+
component: "tests/component",
|
|
1055
|
+
e2e: "tests/e2e",
|
|
1056
|
+
api: "tests/api",
|
|
1057
|
+
visual: "tests/visual",
|
|
1058
|
+
performance: "tests/e2e"
|
|
1059
|
+
};
|
|
1060
|
+
const testDir = testDirMap[testType];
|
|
1061
|
+
if (!testDir) return targetPath;
|
|
1062
|
+
if (targetPath.startsWith("../") || targetPath.startsWith("./../")) {
|
|
1063
|
+
return targetPath;
|
|
1064
|
+
}
|
|
1065
|
+
const depth = testDir.split("/").length;
|
|
1066
|
+
const prefix = "../".repeat(depth);
|
|
1067
|
+
let cleanPath = targetPath.replace(/^\.\//, "");
|
|
1068
|
+
if (!cleanPath.endsWith(".vue")) {
|
|
1069
|
+
cleanPath = cleanPath.replace(/\.(ts|js|tsx|jsx)$/, "");
|
|
1070
|
+
}
|
|
1071
|
+
return `${prefix}${cleanPath}`;
|
|
1072
|
+
}
|
|
1050
1073
|
function registerTemplate(type, templateContent) {
|
|
1051
1074
|
customTemplates.set(type, templateContent);
|
|
1052
1075
|
}
|
|
1053
1076
|
function renderTemplate(type, context) {
|
|
1054
1077
|
const templateContent = loadTemplate(type);
|
|
1055
1078
|
const template = import_handlebars.default.compile(templateContent);
|
|
1079
|
+
const resolvedTarget = resolveImportPath(type, context.target);
|
|
1056
1080
|
const fullContext = {
|
|
1057
1081
|
vueVersion: 3,
|
|
1058
1082
|
typescript: true,
|
|
@@ -1073,6 +1097,8 @@ function renderTemplate(type, context) {
|
|
|
1073
1097
|
requiredProps: [],
|
|
1074
1098
|
optionalProps: [],
|
|
1075
1099
|
...context,
|
|
1100
|
+
// 使用计算后的正确路径
|
|
1101
|
+
target: resolvedTarget,
|
|
1076
1102
|
framework: context.framework || "vue",
|
|
1077
1103
|
camelName: context.camelName || toCamelCase(context.name),
|
|
1078
1104
|
pascalName: context.pascalName || toPascalCase(context.name)
|
|
@@ -1715,12 +1741,23 @@ function generateHTMLReport(data) {
|
|
|
1715
1741
|
// src/runners/vitest-runner.ts
|
|
1716
1742
|
var import_node_child_process = require("child_process");
|
|
1717
1743
|
var import_node_path6 = __toESM(require("path"), 1);
|
|
1744
|
+
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
1745
|
+
var import_node_os = __toESM(require("os"), 1);
|
|
1746
|
+
var isVerbose = () => process.env.QAT_VERBOSE === "true";
|
|
1747
|
+
function debug(label, ...args) {
|
|
1748
|
+
if (isVerbose()) {
|
|
1749
|
+
console.log(`\x1B[90m [debug:${label}]\x1B[0m`, ...args);
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1718
1752
|
async function runVitest(options) {
|
|
1719
1753
|
const startTime = Date.now();
|
|
1720
1754
|
const args = buildVitestArgs(options);
|
|
1755
|
+
debug("vitest", "\u547D\u4EE4\u53C2\u6570:", args.join(" "));
|
|
1721
1756
|
try {
|
|
1722
1757
|
const result = await execVitest(args);
|
|
1723
1758
|
const endTime = Date.now();
|
|
1759
|
+
debug("vitest", `\u89E3\u6790\u7ED3\u679C: ${result.suites.length} \u4E2A\u5957\u4EF6, ${result.suites.reduce((s, su) => s + su.tests.length, 0)} \u4E2A\u7528\u4F8B`);
|
|
1760
|
+
debug("vitest", "\u89E3\u6790\u65B9\u5F0F:", result.parseMethod);
|
|
1724
1761
|
return {
|
|
1725
1762
|
type: options.type,
|
|
1726
1763
|
status: result.success ? "passed" : "failed",
|
|
@@ -1763,14 +1800,14 @@ function buildVitestArgs(options) {
|
|
|
1763
1800
|
if (options.files && options.files.length > 0) {
|
|
1764
1801
|
args.push(...options.files);
|
|
1765
1802
|
} else {
|
|
1766
|
-
const
|
|
1767
|
-
unit:
|
|
1768
|
-
component:
|
|
1769
|
-
api:
|
|
1803
|
+
const pathMap = {
|
|
1804
|
+
unit: "tests/unit/**/*.test.ts",
|
|
1805
|
+
component: "tests/component/**/*.test.ts",
|
|
1806
|
+
api: "tests/api/**/*.test.ts"
|
|
1770
1807
|
};
|
|
1771
|
-
const
|
|
1772
|
-
if (
|
|
1773
|
-
args.push(
|
|
1808
|
+
const testPattern = pathMap[options.type];
|
|
1809
|
+
if (testPattern) {
|
|
1810
|
+
args.push(testPattern);
|
|
1774
1811
|
}
|
|
1775
1812
|
}
|
|
1776
1813
|
if (options.coverage) {
|
|
@@ -1785,12 +1822,11 @@ function buildVitestArgs(options) {
|
|
|
1785
1822
|
return args;
|
|
1786
1823
|
}
|
|
1787
1824
|
async function execVitest(args) {
|
|
1788
|
-
const
|
|
1789
|
-
const fs9 = await import("fs");
|
|
1790
|
-
const tmpFile = import_node_path6.default.join(os.tmpdir(), `qat-vitest-result-${Date.now()}.json`);
|
|
1825
|
+
const tmpFile = import_node_path6.default.join(import_node_os.default.tmpdir(), `qat-vitest-result-${Date.now()}.json`);
|
|
1791
1826
|
const argsWithOutput = [...args, "--outputFile", tmpFile];
|
|
1792
1827
|
return new Promise((resolve, reject) => {
|
|
1793
1828
|
const npx = process.platform === "win32" ? "npx.cmd" : "npx";
|
|
1829
|
+
debug("vitest", "\u6267\u884C\u547D\u4EE4:", npx, argsWithOutput.join(" "));
|
|
1794
1830
|
const child = (0, import_node_child_process.execFile)(npx, argsWithOutput, {
|
|
1795
1831
|
cwd: process.cwd(),
|
|
1796
1832
|
env: { ...process.env, FORCE_COLOR: "0", NO_COLOR: "1" },
|
|
@@ -1798,85 +1834,113 @@ async function execVitest(args) {
|
|
|
1798
1834
|
shell: true
|
|
1799
1835
|
}, (error, stdout, stderr) => {
|
|
1800
1836
|
const rawOutput = stdout || stderr || "";
|
|
1837
|
+
const exitCode = error && "code" in error ? error.code : 0;
|
|
1838
|
+
debug("vitest", `\u9000\u51FA\u7801: ${exitCode}`);
|
|
1839
|
+
debug("vitest", `stdout \u957F\u5EA6: ${stdout?.length || 0}, stderr \u957F\u5EA6: ${stderr?.length || 0}`);
|
|
1801
1840
|
let jsonResult = null;
|
|
1802
1841
|
try {
|
|
1803
|
-
if (
|
|
1804
|
-
jsonResult =
|
|
1805
|
-
|
|
1842
|
+
if (import_node_fs6.default.existsSync(tmpFile)) {
|
|
1843
|
+
jsonResult = import_node_fs6.default.readFileSync(tmpFile, "utf-8");
|
|
1844
|
+
debug("vitest", `\u4ECE\u4E34\u65F6\u6587\u4EF6\u8BFB\u53D6\u5230 JSON (${jsonResult.length} \u5B57\u7B26)`);
|
|
1845
|
+
debug("vitest", "JSON \u524D 500 \u5B57\u7B26:", jsonResult.substring(0, 500));
|
|
1846
|
+
import_node_fs6.default.unlinkSync(tmpFile);
|
|
1847
|
+
} else {
|
|
1848
|
+
debug("vitest", "\u4E34\u65F6\u6587\u4EF6\u4E0D\u5B58\u5728:", tmpFile);
|
|
1806
1849
|
}
|
|
1807
|
-
} catch {
|
|
1850
|
+
} catch (e) {
|
|
1851
|
+
debug("vitest", "\u4E34\u65F6\u6587\u4EF6\u8BFB\u53D6\u5931\u8D25:", e instanceof Error ? e.message : String(e));
|
|
1808
1852
|
}
|
|
1809
1853
|
if (jsonResult) {
|
|
1810
1854
|
try {
|
|
1811
|
-
const parsed =
|
|
1812
|
-
|
|
1855
|
+
const parsed = parseVitestJSON(jsonResult);
|
|
1856
|
+
debug("vitest", "\u4ECE\u4E34\u65F6\u6587\u4EF6\u89E3\u6790\u6210\u529F:", parsed.suites.length, "\u4E2A\u5957\u4EF6");
|
|
1857
|
+
resolve({ ...parsed, rawOutput, parseMethod: "outputFile-JSON" });
|
|
1813
1858
|
return;
|
|
1814
|
-
} catch {
|
|
1859
|
+
} catch (e) {
|
|
1860
|
+
debug("vitest", "\u4E34\u65F6\u6587\u4EF6 JSON \u89E3\u6790\u5931\u8D25:", e instanceof Error ? e.message : String(e));
|
|
1815
1861
|
}
|
|
1816
1862
|
}
|
|
1863
|
+
debug("vitest", "\u5C1D\u8BD5\u4ECE stdout \u63D0\u53D6 JSON...");
|
|
1817
1864
|
try {
|
|
1818
|
-
const parsed =
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1865
|
+
const parsed = parseFromStdout(rawOutput);
|
|
1866
|
+
debug("vitest", "\u4ECE stdout \u89E3\u6790\u6210\u529F:", parsed.suites.length, "\u4E2A\u5957\u4EF6");
|
|
1867
|
+
resolve({ ...parsed, rawOutput, parseMethod: "stdout-JSON" });
|
|
1868
|
+
return;
|
|
1869
|
+
} catch (e) {
|
|
1870
|
+
debug("vitest", "stdout JSON \u89E3\u6790\u5931\u8D25:", e instanceof Error ? e.message : String(e));
|
|
1871
|
+
}
|
|
1872
|
+
debug("vitest", "\u5C1D\u8BD5\u4ECE\u6587\u672C\u8F93\u51FA\u89E3\u6790...");
|
|
1873
|
+
if (rawOutput) {
|
|
1874
|
+
const parsed = parseVitestTextOutput(rawOutput, !!error);
|
|
1875
|
+
debug("vitest", "\u6587\u672C\u89E3\u6790\u7ED3\u679C:", parsed.suites.length, "\u4E2A\u5957\u4EF6");
|
|
1876
|
+
resolve({ ...parsed, rawOutput, parseMethod: "text-fallback" });
|
|
1877
|
+
return;
|
|
1828
1878
|
}
|
|
1879
|
+
if (error && error.message.includes("ENOENT")) {
|
|
1880
|
+
reject(new Error("\u672A\u627E\u5230 vitest\uFF0C\u8BF7\u786E\u4FDD\u5DF2\u5B89\u88C5: npm install -D vitest"));
|
|
1881
|
+
return;
|
|
1882
|
+
}
|
|
1883
|
+
debug("vitest", "\u6240\u6709\u89E3\u6790\u65B9\u5F0F\u5747\u5931\u8D25\uFF0C\u8FD4\u56DE\u7A7A\u7ED3\u679C");
|
|
1884
|
+
resolve({ success: !error, suites: [], rawOutput, parseMethod: "none" });
|
|
1829
1885
|
});
|
|
1830
1886
|
child.on("error", (err) => {
|
|
1831
1887
|
try {
|
|
1832
|
-
|
|
1888
|
+
import_node_fs6.default.unlinkSync(tmpFile);
|
|
1833
1889
|
} catch {
|
|
1834
1890
|
}
|
|
1835
1891
|
reject(new Error(`Vitest \u6267\u884C\u5931\u8D25: ${err.message}`));
|
|
1836
1892
|
});
|
|
1837
1893
|
});
|
|
1838
1894
|
}
|
|
1839
|
-
function
|
|
1895
|
+
function parseVitestJSON(jsonStr) {
|
|
1840
1896
|
const data = JSON.parse(jsonStr);
|
|
1841
1897
|
const suites = [];
|
|
1898
|
+
debug("vitest-json", "JSON \u9876\u5C42\u5B57\u6BB5:", Object.keys(data).join(", "));
|
|
1842
1899
|
if (data.testResults && Array.isArray(data.testResults)) {
|
|
1900
|
+
debug("vitest-json", `testResults \u6570\u91CF: ${data.testResults.length}`);
|
|
1843
1901
|
for (const fileResult of data.testResults) {
|
|
1902
|
+
const suiteTests = parseTestResults(fileResult);
|
|
1903
|
+
suites.push({
|
|
1904
|
+
name: import_node_path6.default.basename(fileResult.name || "unknown"),
|
|
1905
|
+
file: fileResult.name || "unknown",
|
|
1906
|
+
type: "unit",
|
|
1907
|
+
status: mapVitestStatus(fileResult.status),
|
|
1908
|
+
duration: fileResult.duration || 0,
|
|
1909
|
+
tests: suiteTests
|
|
1910
|
+
});
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
if (suites.length === 0 && data.numTotalTests !== void 0) {
|
|
1914
|
+
debug("vitest-json", `\u4F7F\u7528\u6C47\u603B\u683C\u5F0F: total=${data.numTotalTests}, passed=${data.numPassedTests}`);
|
|
1915
|
+
suites.push({
|
|
1916
|
+
name: "Vitest Results",
|
|
1917
|
+
file: "unknown",
|
|
1918
|
+
type: "unit",
|
|
1919
|
+
status: data.numFailedTests > 0 ? "failed" : "passed",
|
|
1920
|
+
duration: 0,
|
|
1921
|
+
tests: buildTestsFromSummary(data)
|
|
1922
|
+
});
|
|
1923
|
+
}
|
|
1924
|
+
if (suites.length === 0 && data.suites && Array.isArray(data.suites)) {
|
|
1925
|
+
debug("vitest-json", `suites \u6570\u91CF: ${data.suites.length}`);
|
|
1926
|
+
for (const suiteData of data.suites) {
|
|
1844
1927
|
const suiteTests = [];
|
|
1845
|
-
const
|
|
1846
|
-
for (const assertion of assertions) {
|
|
1928
|
+
for (const test of suiteData.tests || []) {
|
|
1847
1929
|
suiteTests.push({
|
|
1848
|
-
name:
|
|
1849
|
-
file:
|
|
1850
|
-
status: mapVitestStatus(
|
|
1851
|
-
duration:
|
|
1852
|
-
error:
|
|
1930
|
+
name: test.name || test.title || "unknown",
|
|
1931
|
+
file: test.file || suiteData.file || "unknown",
|
|
1932
|
+
status: mapVitestStatus(test.status || test.result?.status),
|
|
1933
|
+
duration: test.duration || test.result?.duration || 0,
|
|
1934
|
+
error: test.result?.errors?.[0] ? { message: test.result.errors[0].message || String(test.result.errors[0]) } : void 0,
|
|
1853
1935
|
retries: 0
|
|
1854
1936
|
});
|
|
1855
1937
|
}
|
|
1856
|
-
if (suiteTests.length === 0 && fileResult.numPassingTests !== void 0) {
|
|
1857
|
-
const counts = [
|
|
1858
|
-
{ n: fileResult.numPassingTests || 0, s: "passed" },
|
|
1859
|
-
{ n: fileResult.numFailingTests || 0, s: "failed" },
|
|
1860
|
-
{ n: fileResult.numPendingTests || 0, s: "skipped" }
|
|
1861
|
-
];
|
|
1862
|
-
for (const { n, s } of counts) {
|
|
1863
|
-
for (let i = 0; i < n; i++) {
|
|
1864
|
-
suiteTests.push({
|
|
1865
|
-
name: `${s} test ${i + 1}`,
|
|
1866
|
-
file: fileResult.name || "unknown",
|
|
1867
|
-
status: s,
|
|
1868
|
-
duration: 0,
|
|
1869
|
-
retries: 0
|
|
1870
|
-
});
|
|
1871
|
-
}
|
|
1872
|
-
}
|
|
1873
|
-
}
|
|
1874
1938
|
suites.push({
|
|
1875
|
-
name:
|
|
1876
|
-
file:
|
|
1939
|
+
name: suiteData.name || "unknown",
|
|
1940
|
+
file: suiteData.file || "unknown",
|
|
1877
1941
|
type: "unit",
|
|
1878
|
-
status:
|
|
1879
|
-
duration:
|
|
1942
|
+
status: suiteTests.some((t) => t.status === "failed") ? "failed" : "passed",
|
|
1943
|
+
duration: 0,
|
|
1880
1944
|
tests: suiteTests
|
|
1881
1945
|
});
|
|
1882
1946
|
}
|
|
@@ -1885,58 +1949,101 @@ function parseVitestJSONResult(jsonStr) {
|
|
|
1885
1949
|
if (data.coverageMap) {
|
|
1886
1950
|
coverage = extractCoverage(data.coverageMap);
|
|
1887
1951
|
}
|
|
1888
|
-
|
|
1952
|
+
if (!coverage && data.coverage && typeof data.coverage === "object") {
|
|
1953
|
+
const cov = data.coverage;
|
|
1954
|
+
const totals = cov.totals || cov;
|
|
1955
|
+
const getVal = (key) => {
|
|
1956
|
+
const v = totals[key];
|
|
1957
|
+
return typeof v === "number" ? v : typeof v === "object" && v !== null && "pct" in v ? v.pct / 100 : 0;
|
|
1958
|
+
};
|
|
1959
|
+
coverage = {
|
|
1960
|
+
lines: getVal("lines"),
|
|
1961
|
+
statements: getVal("statements"),
|
|
1962
|
+
functions: getVal("functions"),
|
|
1963
|
+
branches: getVal("branches")
|
|
1964
|
+
};
|
|
1965
|
+
}
|
|
1966
|
+
const success = data.success !== false ? data.numFailedTests !== void 0 ? data.numFailedTests === 0 : suites.every((s) => s.status !== "failed") : false;
|
|
1889
1967
|
return { success, suites, coverage };
|
|
1890
1968
|
}
|
|
1891
|
-
function
|
|
1892
|
-
const
|
|
1893
|
-
|
|
1894
|
-
|
|
1969
|
+
function parseTestResults(fileResult) {
|
|
1970
|
+
const tests = [];
|
|
1971
|
+
const assertions = fileResult.assertionResults || fileResult.tests || [];
|
|
1972
|
+
for (const assertion of assertions) {
|
|
1973
|
+
tests.push({
|
|
1974
|
+
name: assertion.title || assertion.fullName || assertion.name || "unknown",
|
|
1975
|
+
file: fileResult.name || "unknown",
|
|
1976
|
+
status: mapVitestStatus(assertion.status),
|
|
1977
|
+
duration: assertion.duration || 0,
|
|
1978
|
+
error: assertion.failureMessages?.length ? { message: assertion.failureMessages[0] } : assertion.failureMessage ? { message: assertion.failureMessage } : void 0,
|
|
1979
|
+
retries: 0
|
|
1980
|
+
});
|
|
1895
1981
|
}
|
|
1896
|
-
|
|
1982
|
+
if (tests.length === 0 && fileResult.numPassingTests !== void 0) {
|
|
1983
|
+
tests.push(...buildTestsFromSummary(fileResult));
|
|
1984
|
+
}
|
|
1985
|
+
return tests;
|
|
1986
|
+
}
|
|
1987
|
+
function buildTestsFromSummary(data) {
|
|
1988
|
+
const tests = [];
|
|
1989
|
+
const counts = [
|
|
1990
|
+
[data.numPassedTests || 0, "passed"],
|
|
1991
|
+
[data.numFailedTests || 0, "failed"],
|
|
1992
|
+
[data.numPendingTests || 0, "skipped"]
|
|
1993
|
+
];
|
|
1994
|
+
for (const [n, s] of counts) {
|
|
1995
|
+
for (let i = 0; i < n; i++) {
|
|
1996
|
+
tests.push({
|
|
1997
|
+
name: `${s} test ${i + 1}`,
|
|
1998
|
+
file: data.name || "unknown",
|
|
1999
|
+
status: s,
|
|
2000
|
+
duration: 0,
|
|
2001
|
+
retries: 0
|
|
2002
|
+
});
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
return tests;
|
|
2006
|
+
}
|
|
2007
|
+
function parseFromStdout(output) {
|
|
2008
|
+
const jsonMatch = output.match(/\{[\s\S]*"testResults"[\s\S]*\}/);
|
|
2009
|
+
if (jsonMatch) {
|
|
1897
2010
|
const data = JSON.parse(jsonMatch[0]);
|
|
1898
2011
|
const suites = [];
|
|
1899
2012
|
if (data.testResults && Array.isArray(data.testResults)) {
|
|
1900
2013
|
for (const fileResult of data.testResults) {
|
|
1901
|
-
|
|
1902
|
-
name: import_node_path6.default.basename(fileResult.name ||
|
|
2014
|
+
suites.push({
|
|
2015
|
+
name: import_node_path6.default.basename(fileResult.name || "unknown"),
|
|
1903
2016
|
file: fileResult.name || "unknown",
|
|
1904
2017
|
type: "unit",
|
|
1905
2018
|
status: mapVitestStatus(fileResult.status),
|
|
1906
2019
|
duration: fileResult.duration || 0,
|
|
1907
|
-
tests: (fileResult
|
|
1908
|
-
|
|
1909
|
-
file: fileResult.name || "unknown",
|
|
1910
|
-
status: mapVitestStatus(assertion.status),
|
|
1911
|
-
duration: assertion.duration || 0,
|
|
1912
|
-
error: assertion.failureMessages?.length ? { message: assertion.failureMessages[0] } : void 0,
|
|
1913
|
-
retries: 0
|
|
1914
|
-
}))
|
|
1915
|
-
};
|
|
1916
|
-
suites.push(suite);
|
|
2020
|
+
tests: parseTestResults(fileResult)
|
|
2021
|
+
});
|
|
1917
2022
|
}
|
|
1918
2023
|
}
|
|
1919
|
-
let coverage;
|
|
1920
|
-
if (data.coverageMap) {
|
|
1921
|
-
coverage = extractCoverage(data.coverageMap);
|
|
1922
|
-
}
|
|
1923
2024
|
const success = data.success !== false && suites.every((s) => s.status !== "failed");
|
|
2025
|
+
let coverage;
|
|
2026
|
+
if (data.coverageMap) coverage = extractCoverage(data.coverageMap);
|
|
1924
2027
|
return { success, suites, coverage };
|
|
1925
|
-
} catch {
|
|
1926
|
-
return parseVitestTextOutput(output, false);
|
|
1927
2028
|
}
|
|
2029
|
+
const anyJsonMatch = output.match(/\{[\s\S]*"numTotalTests"[\s\S]*\}/);
|
|
2030
|
+
if (anyJsonMatch) {
|
|
2031
|
+
return parseVitestJSON(anyJsonMatch[0]);
|
|
2032
|
+
}
|
|
2033
|
+
throw new Error("stdout \u4E2D\u672A\u627E\u5230\u6709\u6548 JSON");
|
|
1928
2034
|
}
|
|
1929
2035
|
function parseVitestTextOutput(output, hasError) {
|
|
1930
2036
|
const suites = [];
|
|
2037
|
+
debug("vitest-text", "\u6587\u672C\u8F93\u51FA\u524D 1000 \u5B57\u7B26:", output.substring(0, 1e3));
|
|
2038
|
+
const suiteRegex = /[✓✗×✕]\s+(.+\.test\.(ts|js)|.+\.spec\.(ts|js))\s*\((\d+)[^)]*\)/i;
|
|
2039
|
+
const lines = output.split("\n");
|
|
1931
2040
|
let totalPassed = 0;
|
|
1932
2041
|
let totalFailed = 0;
|
|
1933
|
-
const suiteRegex = /[✓✗×]\s+(.+\.test\.ts|.+\.spec\.ts)\s*\((\d+)\s+test/i;
|
|
1934
|
-
const lines = output.split("\n");
|
|
1935
2042
|
for (const line of lines) {
|
|
1936
2043
|
const match = line.match(suiteRegex);
|
|
1937
2044
|
if (match) {
|
|
1938
2045
|
const file = match[1];
|
|
1939
|
-
const testCount = parseInt(match[
|
|
2046
|
+
const testCount = parseInt(match[4], 10);
|
|
1940
2047
|
const isPassed = line.includes("\u2713");
|
|
1941
2048
|
if (isPassed) totalPassed += testCount;
|
|
1942
2049
|
else totalFailed += testCount;
|
|
@@ -1956,15 +2063,39 @@ function parseVitestTextOutput(output, hasError) {
|
|
|
1956
2063
|
});
|
|
1957
2064
|
}
|
|
1958
2065
|
}
|
|
2066
|
+
if (suites.length === 0) {
|
|
2067
|
+
const summaryMatch = output.match(/Tests\s+(\d+)\s+(passed|failed)/i);
|
|
2068
|
+
if (summaryMatch) {
|
|
2069
|
+
const count = parseInt(summaryMatch[1], 10);
|
|
2070
|
+
const status = summaryMatch[2].toLowerCase() === "passed" ? "passed" : "failed";
|
|
2071
|
+
suites.push({
|
|
2072
|
+
name: "Vitest Summary",
|
|
2073
|
+
file: "unknown",
|
|
2074
|
+
type: "unit",
|
|
2075
|
+
status,
|
|
2076
|
+
duration: 0,
|
|
2077
|
+
tests: Array.from({ length: count }, (_, i) => ({
|
|
2078
|
+
name: `test ${i + 1}`,
|
|
2079
|
+
file: "unknown",
|
|
2080
|
+
status,
|
|
2081
|
+
duration: 0,
|
|
2082
|
+
retries: 0
|
|
2083
|
+
}))
|
|
2084
|
+
});
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
debug("vitest-text", `\u89E3\u6790\u5230 ${suites.length} \u4E2A\u5957\u4EF6, ${totalPassed} \u901A\u8FC7, ${totalFailed} \u5931\u8D25`);
|
|
1959
2088
|
return {
|
|
1960
2089
|
success: !hasError || totalFailed === 0,
|
|
1961
2090
|
suites
|
|
1962
2091
|
};
|
|
1963
2092
|
}
|
|
1964
2093
|
function mapVitestStatus(status) {
|
|
2094
|
+
if (!status) return "pending";
|
|
1965
2095
|
switch (status) {
|
|
1966
2096
|
case "passed":
|
|
1967
2097
|
case "pass":
|
|
2098
|
+
case "done":
|
|
1968
2099
|
return "passed";
|
|
1969
2100
|
case "failed":
|
|
1970
2101
|
case "fail":
|
|
@@ -1972,6 +2103,7 @@ function mapVitestStatus(status) {
|
|
|
1972
2103
|
case "skipped":
|
|
1973
2104
|
case "skip":
|
|
1974
2105
|
case "pending":
|
|
2106
|
+
case "todo":
|
|
1975
2107
|
return "skipped";
|
|
1976
2108
|
default:
|
|
1977
2109
|
return "pending";
|
|
@@ -2658,8 +2790,13 @@ ${error.actual ? `\u5B9E\u9645\u503C: ${error.actual}` : ""}`;
|
|
|
2658
2790
|
6. \u5982\u679C\u6709 props/emits \u4FE1\u606F\uFF0C\u52A1\u5FC5\u9488\u5BF9\u6BCF\u4E2A prop \u548C emit \u751F\u6210\u6D4B\u8BD5`;
|
|
2659
2791
|
}
|
|
2660
2792
|
buildGenerateTestUserPrompt(req) {
|
|
2793
|
+
const importPath = this.computeTestImportPath(req.type, req.target);
|
|
2661
2794
|
let prompt = `\u8BF7\u4E3A\u4EE5\u4E0B\u6587\u4EF6\u751F\u6210${req.type}\u6D4B\u8BD5\u4EE3\u7801:
|
|
2662
2795
|
\u76EE\u6807\u6587\u4EF6: ${req.target}
|
|
2796
|
+
\u6D4B\u8BD5\u6587\u4EF6\u5C06\u653E\u5728: ${this.getTestOutputDir(req.type)}/
|
|
2797
|
+
\u6B63\u786E\u7684 import \u8DEF\u5F84: ${importPath}
|
|
2798
|
+
|
|
2799
|
+
\u91CD\u8981\uFF1Aimport \u8BED\u53E5\u4E2D\u5FC5\u987B\u4F7F\u7528\u4E0A\u8FF0\u6B63\u786E\u7684\u76F8\u5BF9\u8DEF\u5F84 ${importPath}\uFF0C\u4E0D\u8981\u4F7F\u7528 ${req.target} \u6216\u5176\u4ED6\u8DEF\u5F84\uFF01
|
|
2663
2800
|
`;
|
|
2664
2801
|
if (req.analysis) {
|
|
2665
2802
|
prompt += "\n\u6E90\u7801\u5206\u6790\u7ED3\u679C:\n";
|
|
@@ -2709,6 +2846,46 @@ ${req.context}
|
|
|
2709
2846
|
}
|
|
2710
2847
|
return prompt;
|
|
2711
2848
|
}
|
|
2849
|
+
/**
|
|
2850
|
+
* 根据测试类型和源文件路径,计算从测试文件到源文件的正确相对导入路径
|
|
2851
|
+
*/
|
|
2852
|
+
computeTestImportPath(testType, targetPath) {
|
|
2853
|
+
if (!targetPath) return targetPath;
|
|
2854
|
+
const testDirMap = {
|
|
2855
|
+
unit: "tests/unit",
|
|
2856
|
+
component: "tests/component",
|
|
2857
|
+
e2e: "tests/e2e",
|
|
2858
|
+
api: "tests/api",
|
|
2859
|
+
visual: "tests/visual",
|
|
2860
|
+
performance: "tests/e2e"
|
|
2861
|
+
};
|
|
2862
|
+
const testDir = testDirMap[testType];
|
|
2863
|
+
if (!testDir) return targetPath;
|
|
2864
|
+
if (targetPath.startsWith("../") || targetPath.startsWith("./../")) {
|
|
2865
|
+
return targetPath;
|
|
2866
|
+
}
|
|
2867
|
+
const depth = testDir.split("/").length;
|
|
2868
|
+
const prefix = "../".repeat(depth);
|
|
2869
|
+
let cleanPath = targetPath.replace(/^\.\//, "");
|
|
2870
|
+
if (!cleanPath.endsWith(".vue")) {
|
|
2871
|
+
cleanPath = cleanPath.replace(/\.(ts|js|tsx|jsx)$/, "");
|
|
2872
|
+
}
|
|
2873
|
+
return `${prefix}${cleanPath}`;
|
|
2874
|
+
}
|
|
2875
|
+
/**
|
|
2876
|
+
* 获取测试输出目录
|
|
2877
|
+
*/
|
|
2878
|
+
getTestOutputDir(testType) {
|
|
2879
|
+
const dirMap = {
|
|
2880
|
+
unit: "tests/unit",
|
|
2881
|
+
component: "tests/component",
|
|
2882
|
+
e2e: "tests/e2e",
|
|
2883
|
+
api: "tests/api",
|
|
2884
|
+
visual: "tests/visual",
|
|
2885
|
+
performance: "tests/e2e"
|
|
2886
|
+
};
|
|
2887
|
+
return dirMap[testType] || "tests/unit";
|
|
2888
|
+
}
|
|
2712
2889
|
parseGenerateTestResponse(content) {
|
|
2713
2890
|
const codeBlockMatch = content.match(/```(?:typescript|ts|javascript|js)?\s*\n([\s\S]*?)```/);
|
|
2714
2891
|
const code = codeBlockMatch ? codeBlockMatch[1].trim() : content.replace(/^(?:```[\s\S]*?\n)?/, "").replace(/\n?```$/, "").trim();
|
|
@@ -2737,10 +2914,12 @@ ISSUES: \u95EE\u9898\u5217\u8868\uFF08\u6BCF\u884C\u4E00\u4E2A\uFF0C\u683C\u5F0F
|
|
|
2737
2914
|
SUGGESTIONS: \u6539\u8FDB\u5EFA\u8BAE\u5217\u8868\uFF08\u6BCF\u884C\u4E00\u4E2A\uFF0C\u683C\u5F0F "- \u5EFA\u8BAE\u63CF\u8FF0"\uFF09`;
|
|
2738
2915
|
}
|
|
2739
2916
|
buildReviewTestUserPrompt(req) {
|
|
2917
|
+
const importPath = this.computeTestImportPath(req.testType, req.target);
|
|
2740
2918
|
let prompt = `\u8BF7\u5BA1\u67E5\u4EE5\u4E0B\u6D4B\u8BD5\u7528\u4F8B\u662F\u5426\u4E0E\u6E90\u7801\u8D34\u5207\u4E14\u51C6\u786E\u3002
|
|
2741
2919
|
|
|
2742
2920
|
\u88AB\u6D4B\u6587\u4EF6: ${req.target}
|
|
2743
2921
|
\u6D4B\u8BD5\u7C7B\u578B: ${req.testType}
|
|
2922
|
+
\u6B63\u786E\u7684 import \u8DEF\u5F84\u5E94\u4E3A: ${importPath}\uFF08\u6D4B\u8BD5\u6587\u4EF6\u4F4D\u4E8E ${this.getTestOutputDir(req.testType)}/\uFF09
|
|
2744
2923
|
|
|
2745
2924
|
--- \u6E90\u7801\u5185\u5BB9 ---
|
|
2746
2925
|
\`\`\`typescript
|
|
@@ -2908,7 +3087,7 @@ async function testAIConnection(config) {
|
|
|
2908
3087
|
}
|
|
2909
3088
|
|
|
2910
3089
|
// src/services/mock-server.ts
|
|
2911
|
-
var
|
|
3090
|
+
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
2912
3091
|
var import_node_path8 = __toESM(require("path"), 1);
|
|
2913
3092
|
var serverState = {
|
|
2914
3093
|
running: false,
|
|
@@ -2921,18 +3100,18 @@ function getMockServerState() {
|
|
|
2921
3100
|
}
|
|
2922
3101
|
async function loadMockRoutes(routesDir) {
|
|
2923
3102
|
const absDir = import_node_path8.default.resolve(process.cwd(), routesDir);
|
|
2924
|
-
if (!
|
|
3103
|
+
if (!import_node_fs7.default.existsSync(absDir)) {
|
|
2925
3104
|
return [];
|
|
2926
3105
|
}
|
|
2927
3106
|
const routes = [];
|
|
2928
|
-
const entries =
|
|
3107
|
+
const entries = import_node_fs7.default.readdirSync(absDir, { withFileTypes: true });
|
|
2929
3108
|
for (const entry of entries) {
|
|
2930
3109
|
if (!entry.isFile()) continue;
|
|
2931
3110
|
const filePath = import_node_path8.default.join(absDir, entry.name);
|
|
2932
3111
|
const ext = import_node_path8.default.extname(entry.name);
|
|
2933
3112
|
try {
|
|
2934
3113
|
if (ext === ".json") {
|
|
2935
|
-
const content =
|
|
3114
|
+
const content = import_node_fs7.default.readFileSync(filePath, "utf-8");
|
|
2936
3115
|
const parsed = JSON.parse(content);
|
|
2937
3116
|
if (Array.isArray(parsed)) {
|
|
2938
3117
|
routes.push(...parsed);
|
|
@@ -3124,11 +3303,11 @@ function generateMockRouteTemplate(name) {
|
|
|
3124
3303
|
}
|
|
3125
3304
|
function initMockRoutesDir(routesDir) {
|
|
3126
3305
|
const absDir = import_node_path8.default.resolve(process.cwd(), routesDir);
|
|
3127
|
-
if (!
|
|
3128
|
-
|
|
3306
|
+
if (!import_node_fs7.default.existsSync(absDir)) {
|
|
3307
|
+
import_node_fs7.default.mkdirSync(absDir, { recursive: true });
|
|
3129
3308
|
}
|
|
3130
3309
|
const examplePath = import_node_path8.default.join(absDir, "example.json");
|
|
3131
|
-
if (!
|
|
3310
|
+
if (!import_node_fs7.default.existsSync(examplePath)) {
|
|
3132
3311
|
const exampleRoutes = [
|
|
3133
3312
|
{
|
|
3134
3313
|
method: "GET",
|
|
@@ -3152,24 +3331,24 @@ function initMockRoutesDir(routesDir) {
|
|
|
3152
3331
|
}
|
|
3153
3332
|
}
|
|
3154
3333
|
];
|
|
3155
|
-
|
|
3334
|
+
import_node_fs7.default.writeFileSync(examplePath, JSON.stringify(exampleRoutes, null, 2), "utf-8");
|
|
3156
3335
|
}
|
|
3157
3336
|
}
|
|
3158
3337
|
|
|
3159
3338
|
// src/services/visual.ts
|
|
3160
|
-
var
|
|
3339
|
+
var import_node_fs8 = __toESM(require("fs"), 1);
|
|
3161
3340
|
var import_node_path9 = __toESM(require("path"), 1);
|
|
3162
3341
|
var import_pixelmatch = __toESM(require("pixelmatch"), 1);
|
|
3163
3342
|
var import_pngjs = require("pngjs");
|
|
3164
3343
|
function compareImages(baselinePath, currentPath, diffOutputPath, threshold = 0.1) {
|
|
3165
|
-
if (!
|
|
3344
|
+
if (!import_node_fs8.default.existsSync(baselinePath)) {
|
|
3166
3345
|
throw new Error(`\u57FA\u7EBF\u56FE\u7247\u4E0D\u5B58\u5728: ${baselinePath}`);
|
|
3167
3346
|
}
|
|
3168
|
-
if (!
|
|
3347
|
+
if (!import_node_fs8.default.existsSync(currentPath)) {
|
|
3169
3348
|
throw new Error(`\u5F53\u524D\u56FE\u7247\u4E0D\u5B58\u5728: ${currentPath}`);
|
|
3170
3349
|
}
|
|
3171
|
-
const baseline = import_pngjs.PNG.sync.read(
|
|
3172
|
-
const current = import_pngjs.PNG.sync.read(
|
|
3350
|
+
const baseline = import_pngjs.PNG.sync.read(import_node_fs8.default.readFileSync(baselinePath));
|
|
3351
|
+
const current = import_pngjs.PNG.sync.read(import_node_fs8.default.readFileSync(currentPath));
|
|
3173
3352
|
if (baseline.width !== current.width || baseline.height !== current.height) {
|
|
3174
3353
|
return {
|
|
3175
3354
|
passed: false,
|
|
@@ -3198,10 +3377,10 @@ function compareImages(baselinePath, currentPath, diffOutputPath, threshold = 0.
|
|
|
3198
3377
|
let diffPath;
|
|
3199
3378
|
if (diffPixels > 0) {
|
|
3200
3379
|
const diffDir = import_node_path9.default.dirname(diffOutputPath);
|
|
3201
|
-
if (!
|
|
3202
|
-
|
|
3380
|
+
if (!import_node_fs8.default.existsSync(diffDir)) {
|
|
3381
|
+
import_node_fs8.default.mkdirSync(diffDir, { recursive: true });
|
|
3203
3382
|
}
|
|
3204
|
-
|
|
3383
|
+
import_node_fs8.default.writeFileSync(diffOutputPath, import_pngjs.PNG.sync.write(diff));
|
|
3205
3384
|
diffPath = diffOutputPath;
|
|
3206
3385
|
}
|
|
3207
3386
|
return {
|
|
@@ -3215,14 +3394,14 @@ function compareImages(baselinePath, currentPath, diffOutputPath, threshold = 0.
|
|
|
3215
3394
|
};
|
|
3216
3395
|
}
|
|
3217
3396
|
function createBaseline(currentPath, baselinePath) {
|
|
3218
|
-
if (!
|
|
3397
|
+
if (!import_node_fs8.default.existsSync(currentPath)) {
|
|
3219
3398
|
throw new Error(`\u5F53\u524D\u622A\u56FE\u4E0D\u5B58\u5728: ${currentPath}`);
|
|
3220
3399
|
}
|
|
3221
3400
|
const baselineDir = import_node_path9.default.dirname(baselinePath);
|
|
3222
|
-
if (!
|
|
3223
|
-
|
|
3401
|
+
if (!import_node_fs8.default.existsSync(baselineDir)) {
|
|
3402
|
+
import_node_fs8.default.mkdirSync(baselineDir, { recursive: true });
|
|
3224
3403
|
}
|
|
3225
|
-
|
|
3404
|
+
import_node_fs8.default.copyFileSync(currentPath, baselinePath);
|
|
3226
3405
|
return baselinePath;
|
|
3227
3406
|
}
|
|
3228
3407
|
function updateBaseline(currentPath, baselinePath) {
|
|
@@ -3230,69 +3409,69 @@ function updateBaseline(currentPath, baselinePath) {
|
|
|
3230
3409
|
}
|
|
3231
3410
|
function updateAllBaselines(currentDir, baselineDir) {
|
|
3232
3411
|
const updated = [];
|
|
3233
|
-
if (!
|
|
3412
|
+
if (!import_node_fs8.default.existsSync(currentDir)) {
|
|
3234
3413
|
return updated;
|
|
3235
3414
|
}
|
|
3236
|
-
const files =
|
|
3415
|
+
const files = import_node_fs8.default.readdirSync(currentDir).filter((f) => f.endsWith(".png"));
|
|
3237
3416
|
for (const file of files) {
|
|
3238
3417
|
const currentPath = import_node_path9.default.join(currentDir, file);
|
|
3239
3418
|
const baselinePath = import_node_path9.default.join(baselineDir, file);
|
|
3240
3419
|
const baselineDirAbs = import_node_path9.default.dirname(baselinePath);
|
|
3241
|
-
if (!
|
|
3242
|
-
|
|
3420
|
+
if (!import_node_fs8.default.existsSync(baselineDirAbs)) {
|
|
3421
|
+
import_node_fs8.default.mkdirSync(baselineDirAbs, { recursive: true });
|
|
3243
3422
|
}
|
|
3244
|
-
|
|
3423
|
+
import_node_fs8.default.copyFileSync(currentPath, baselinePath);
|
|
3245
3424
|
updated.push(file);
|
|
3246
3425
|
}
|
|
3247
3426
|
return updated;
|
|
3248
3427
|
}
|
|
3249
3428
|
function cleanBaselines(baselineDir) {
|
|
3250
|
-
if (!
|
|
3429
|
+
if (!import_node_fs8.default.existsSync(baselineDir)) {
|
|
3251
3430
|
return 0;
|
|
3252
3431
|
}
|
|
3253
|
-
const files =
|
|
3432
|
+
const files = import_node_fs8.default.readdirSync(baselineDir).filter((f) => f.endsWith(".png"));
|
|
3254
3433
|
let count = 0;
|
|
3255
3434
|
for (const file of files) {
|
|
3256
|
-
|
|
3435
|
+
import_node_fs8.default.unlinkSync(import_node_path9.default.join(baselineDir, file));
|
|
3257
3436
|
count++;
|
|
3258
3437
|
}
|
|
3259
3438
|
return count;
|
|
3260
3439
|
}
|
|
3261
3440
|
function cleanDiffs(diffDir) {
|
|
3262
|
-
if (!
|
|
3441
|
+
if (!import_node_fs8.default.existsSync(diffDir)) {
|
|
3263
3442
|
return 0;
|
|
3264
3443
|
}
|
|
3265
|
-
const files =
|
|
3444
|
+
const files = import_node_fs8.default.readdirSync(diffDir).filter((f) => f.endsWith(".png"));
|
|
3266
3445
|
let count = 0;
|
|
3267
3446
|
for (const file of files) {
|
|
3268
|
-
|
|
3447
|
+
import_node_fs8.default.unlinkSync(import_node_path9.default.join(diffDir, file));
|
|
3269
3448
|
count++;
|
|
3270
3449
|
}
|
|
3271
3450
|
return count;
|
|
3272
3451
|
}
|
|
3273
3452
|
function listBaselines(baselineDir) {
|
|
3274
|
-
if (!
|
|
3453
|
+
if (!import_node_fs8.default.existsSync(baselineDir)) {
|
|
3275
3454
|
return [];
|
|
3276
3455
|
}
|
|
3277
|
-
return
|
|
3456
|
+
return import_node_fs8.default.readdirSync(baselineDir).filter((f) => f.endsWith(".png")).sort();
|
|
3278
3457
|
}
|
|
3279
3458
|
function listDiffs(diffDir) {
|
|
3280
|
-
if (!
|
|
3459
|
+
if (!import_node_fs8.default.existsSync(diffDir)) {
|
|
3281
3460
|
return [];
|
|
3282
3461
|
}
|
|
3283
|
-
return
|
|
3462
|
+
return import_node_fs8.default.readdirSync(diffDir).filter((f) => f.endsWith(".png")).sort();
|
|
3284
3463
|
}
|
|
3285
3464
|
function compareDirectories(baselineDir, currentDir, diffDir, threshold = 0.1) {
|
|
3286
3465
|
const results = [];
|
|
3287
|
-
if (!
|
|
3466
|
+
if (!import_node_fs8.default.existsSync(currentDir)) {
|
|
3288
3467
|
return results;
|
|
3289
3468
|
}
|
|
3290
|
-
const currentFiles =
|
|
3469
|
+
const currentFiles = import_node_fs8.default.readdirSync(currentDir).filter((f) => f.endsWith(".png"));
|
|
3291
3470
|
for (const file of currentFiles) {
|
|
3292
3471
|
const currentPath = import_node_path9.default.join(currentDir, file);
|
|
3293
3472
|
const baselinePath = import_node_path9.default.join(baselineDir, file);
|
|
3294
3473
|
const diffPath = import_node_path9.default.join(diffDir, file);
|
|
3295
|
-
if (!
|
|
3474
|
+
if (!import_node_fs8.default.existsSync(baselinePath)) {
|
|
3296
3475
|
createBaseline(currentPath, baselinePath);
|
|
3297
3476
|
results.push({
|
|
3298
3477
|
passed: true,
|
|
@@ -3324,14 +3503,14 @@ function compareDirectories(baselineDir, currentDir, diffDir, threshold = 0.1) {
|
|
|
3324
3503
|
}
|
|
3325
3504
|
|
|
3326
3505
|
// src/services/source-analyzer.ts
|
|
3327
|
-
var
|
|
3506
|
+
var import_node_fs9 = __toESM(require("fs"), 1);
|
|
3328
3507
|
var import_node_path10 = __toESM(require("path"), 1);
|
|
3329
3508
|
function analyzeFile(filePath) {
|
|
3330
3509
|
const absolutePath = import_node_path10.default.resolve(process.cwd(), filePath);
|
|
3331
|
-
if (!
|
|
3510
|
+
if (!import_node_fs9.default.existsSync(absolutePath)) {
|
|
3332
3511
|
return { filePath, exports: [], apiCalls: [] };
|
|
3333
3512
|
}
|
|
3334
|
-
const content =
|
|
3513
|
+
const content = import_node_fs9.default.readFileSync(absolutePath, "utf-8");
|
|
3335
3514
|
const ext = import_node_path10.default.extname(filePath);
|
|
3336
3515
|
const result = {
|
|
3337
3516
|
filePath,
|
|
@@ -3686,13 +3865,13 @@ function cleanTemplateUrl(url) {
|
|
|
3686
3865
|
}
|
|
3687
3866
|
function scanAPICalls(srcDir) {
|
|
3688
3867
|
const absDir = import_node_path10.default.resolve(process.cwd(), srcDir);
|
|
3689
|
-
if (!
|
|
3868
|
+
if (!import_node_fs9.default.existsSync(absDir)) {
|
|
3690
3869
|
return [];
|
|
3691
3870
|
}
|
|
3692
3871
|
const allCalls = [];
|
|
3693
3872
|
const seen = /* @__PURE__ */ new Set();
|
|
3694
3873
|
function walk(dir) {
|
|
3695
|
-
const entries =
|
|
3874
|
+
const entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
|
|
3696
3875
|
for (const entry of entries) {
|
|
3697
3876
|
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist") continue;
|
|
3698
3877
|
const fullPath = import_node_path10.default.join(dir, entry.name);
|
|
@@ -3700,7 +3879,7 @@ function scanAPICalls(srcDir) {
|
|
|
3700
3879
|
walk(fullPath);
|
|
3701
3880
|
} else if (entry.isFile() && /\.(ts|js|vue|mjs)$/.test(entry.name)) {
|
|
3702
3881
|
try {
|
|
3703
|
-
const content =
|
|
3882
|
+
const content = import_node_fs9.default.readFileSync(fullPath, "utf-8");
|
|
3704
3883
|
const calls = extractAPICalls(content, import_node_path10.default.relative(process.cwd(), fullPath));
|
|
3705
3884
|
for (const call of calls) {
|
|
3706
3885
|
const key = `${call.method}:${call.url}`;
|