@rayburst/cli 0.4.4 → 0.4.6
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.
|
@@ -434,15 +434,15 @@ function createRouterDecisionNode(sourceFilePath, gitHash, routeCount) {
|
|
|
434
434
|
};
|
|
435
435
|
}
|
|
436
436
|
function extractRoutePathFromFile(routeFilePath) {
|
|
437
|
-
let
|
|
438
|
-
if (
|
|
437
|
+
let path6 = routeFilePath.replace(/^src\/routes\//, "/").replace(/\.(tsx?|jsx?)$/, "").replace(/\/route$/, "").replace(/\/index$/, "");
|
|
438
|
+
if (path6 === "/__root") {
|
|
439
439
|
return "/";
|
|
440
440
|
}
|
|
441
|
-
|
|
442
|
-
if (
|
|
441
|
+
path6 = path6.replace(/\/\$([^/]+)/g, (_, param) => `/:${param}`);
|
|
442
|
+
if (path6 === "" || path6 === "/") {
|
|
443
443
|
return "/";
|
|
444
444
|
}
|
|
445
|
-
return
|
|
445
|
+
return path6;
|
|
446
446
|
}
|
|
447
447
|
function createConfigBasedEdges(sourceNode, targetFilePaths, nodeMap, edges, edgeType = "config", useRoutePathLabels = false) {
|
|
448
448
|
let edgesCreated = 0;
|
|
@@ -650,7 +650,7 @@ function traceConfigToComponentPaths(configObject, propertyName, projectPath, pr
|
|
|
650
650
|
}
|
|
651
651
|
return [];
|
|
652
652
|
}
|
|
653
|
-
function detectConfigBasedComponents(sourceFile, nodes, nodeMap, edges, projectPath, project, gitHash, externalNodeMap) {
|
|
653
|
+
function detectConfigBasedComponents(sourceFile, nodes, nodeMap, edges, projectPath, project, gitHash, externalNodeMap, usedIds, idCounters) {
|
|
654
654
|
let totalEdgesCreated = 0;
|
|
655
655
|
try {
|
|
656
656
|
const jsxElements = sourceFile.getDescendantsOfKind(SyntaxKind.JsxSelfClosingElement);
|
|
@@ -747,7 +747,18 @@ function detectConfigBasedComponents(sourceFile, nodes, nodeMap, edges, projectP
|
|
|
747
747
|
for (const routeFilePath of componentPaths) {
|
|
748
748
|
const routePath = extractRoutePathFromFile(routeFilePath);
|
|
749
749
|
const isDynamic = routePath.includes(":");
|
|
750
|
-
const
|
|
750
|
+
const routePathNormalized = routePath.replace(/[/:]/g, "_");
|
|
751
|
+
const decisionNodeName = `RouterDecision::decision::${routePathNormalized}`;
|
|
752
|
+
const routerIdParts = routerNode.id.split("::");
|
|
753
|
+
const sourceFilePath = routerIdParts[0];
|
|
754
|
+
const gitHash2 = routerIdParts[2];
|
|
755
|
+
const decisionNodeId = getUniqueNodeId(
|
|
756
|
+
sourceFilePath,
|
|
757
|
+
decisionNodeName,
|
|
758
|
+
gitHash2,
|
|
759
|
+
usedIds,
|
|
760
|
+
idCounters
|
|
761
|
+
);
|
|
751
762
|
const decisionNode = {
|
|
752
763
|
id: decisionNodeId,
|
|
753
764
|
type: "conditional",
|
|
@@ -879,7 +890,7 @@ async function analyzeProject(projectPath, projectId, onLog) {
|
|
|
879
890
|
log(` Analyzing config-based components...`);
|
|
880
891
|
let totalConfigEdges = 0;
|
|
881
892
|
for (const sourceFile of sourceFiles) {
|
|
882
|
-
const configEdges = detectConfigBasedComponents(sourceFile, nodes, nodeMap, edges, projectPath, project, gitHash, externalNodeMap);
|
|
893
|
+
const configEdges = detectConfigBasedComponents(sourceFile, nodes, nodeMap, edges, projectPath, project, gitHash, externalNodeMap, usedIds, idCounters);
|
|
883
894
|
totalConfigEdges += configEdges;
|
|
884
895
|
}
|
|
885
896
|
if (totalConfigEdges > 0) {
|
|
@@ -933,8 +944,25 @@ async function analyzeProject(projectPath, projectId, onLog) {
|
|
|
933
944
|
edges
|
|
934
945
|
};
|
|
935
946
|
log(" Checking for changed files vs remote...");
|
|
936
|
-
const
|
|
937
|
-
log(` Found ${
|
|
947
|
+
const allChangedFiles = getChangedFilesVsRemote(projectPath);
|
|
948
|
+
log(` Found ${allChangedFiles.length} changed files`);
|
|
949
|
+
const changedFiles = allChangedFiles.filter((filePath) => {
|
|
950
|
+
return !filePath.includes("node_modules") && !filePath.includes(".test.") && !filePath.includes(".spec.") && (filePath.endsWith(".ts") || filePath.endsWith(".tsx") || filePath.endsWith(".js") || filePath.endsWith(".jsx"));
|
|
951
|
+
});
|
|
952
|
+
log(` Filtered to ${changedFiles.length} analyzed source files`);
|
|
953
|
+
const changedFilesMetadata = [];
|
|
954
|
+
for (const filePath of changedFiles) {
|
|
955
|
+
try {
|
|
956
|
+
const stats = fs.statSync(filePath);
|
|
957
|
+
changedFilesMetadata.push({
|
|
958
|
+
filePath,
|
|
959
|
+
lastModified: stats.mtimeMs
|
|
960
|
+
// Unix timestamp in milliseconds
|
|
961
|
+
});
|
|
962
|
+
} catch (error) {
|
|
963
|
+
log(` Warning: Could not get stats for ${filePath}`);
|
|
964
|
+
}
|
|
965
|
+
}
|
|
938
966
|
const result = {
|
|
939
967
|
project: projectMetadata,
|
|
940
968
|
branches: [branchMetadata],
|
|
@@ -945,6 +973,9 @@ async function analyzeProject(projectPath, projectId, onLog) {
|
|
|
945
973
|
logs,
|
|
946
974
|
changedFilesVsRemote: changedFiles.length > 0 ? {
|
|
947
975
|
[branchId]: changedFiles
|
|
976
|
+
} : void 0,
|
|
977
|
+
changedFilesMetadata: changedFilesMetadata.length > 0 ? {
|
|
978
|
+
[branchId]: changedFilesMetadata
|
|
948
979
|
} : void 0
|
|
949
980
|
};
|
|
950
981
|
return result;
|
|
@@ -1893,6 +1924,8 @@ function getEdgeChanges(oldEdge, newEdge) {
|
|
|
1893
1924
|
|
|
1894
1925
|
// src/vite-plugin.ts
|
|
1895
1926
|
import chalk2 from "chalk";
|
|
1927
|
+
import * as fs3 from "fs";
|
|
1928
|
+
import * as path5 from "path";
|
|
1896
1929
|
function rayburstPlugin(options = {}) {
|
|
1897
1930
|
const {
|
|
1898
1931
|
enabled = process.env.CI !== "true",
|
|
@@ -1902,6 +1935,41 @@ function rayburstPlugin(options = {}) {
|
|
|
1902
1935
|
let config;
|
|
1903
1936
|
let debounceTimer = null;
|
|
1904
1937
|
let isAnalyzing = false;
|
|
1938
|
+
let lastGitState = null;
|
|
1939
|
+
let gitPollInterval = null;
|
|
1940
|
+
const checkGitState = (projectPath) => {
|
|
1941
|
+
try {
|
|
1942
|
+
const gitDir = path5.join(projectPath, ".git");
|
|
1943
|
+
if (!fs3.existsSync(gitDir)) {
|
|
1944
|
+
return false;
|
|
1945
|
+
}
|
|
1946
|
+
const headPath = path5.join(gitDir, "HEAD");
|
|
1947
|
+
if (!fs3.existsSync(headPath)) {
|
|
1948
|
+
return false;
|
|
1949
|
+
}
|
|
1950
|
+
const headContent = fs3.readFileSync(headPath, "utf-8").trim();
|
|
1951
|
+
let gitState = headContent;
|
|
1952
|
+
if (headContent.startsWith("ref: ")) {
|
|
1953
|
+
const refPath = headContent.substring(5);
|
|
1954
|
+
const fullRefPath = path5.join(gitDir, refPath);
|
|
1955
|
+
if (fs3.existsSync(fullRefPath)) {
|
|
1956
|
+
const refContent = fs3.readFileSync(fullRefPath, "utf-8").trim();
|
|
1957
|
+
gitState = `${headContent}:${refContent}`;
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
if (lastGitState === null) {
|
|
1961
|
+
lastGitState = gitState;
|
|
1962
|
+
return false;
|
|
1963
|
+
}
|
|
1964
|
+
if (lastGitState !== gitState) {
|
|
1965
|
+
lastGitState = gitState;
|
|
1966
|
+
return true;
|
|
1967
|
+
}
|
|
1968
|
+
return false;
|
|
1969
|
+
} catch (error) {
|
|
1970
|
+
return false;
|
|
1971
|
+
}
|
|
1972
|
+
};
|
|
1905
1973
|
const runAnalysis = async (triggerFile) => {
|
|
1906
1974
|
if (isAnalyzing) return;
|
|
1907
1975
|
isAnalyzing = true;
|
|
@@ -1980,6 +2048,24 @@ function rayburstPlugin(options = {}) {
|
|
|
1980
2048
|
server.watcher.on("change", handleFileChange);
|
|
1981
2049
|
server.watcher.on("add", handleFileChange);
|
|
1982
2050
|
server.watcher.on("unlink", handleFileChange);
|
|
2051
|
+
const gitHeadPath = path5.join(config.root, ".git", "HEAD");
|
|
2052
|
+
if (fs3.existsSync(gitHeadPath)) {
|
|
2053
|
+
server.watcher.add(gitHeadPath);
|
|
2054
|
+
const handleGitChange = (changedPath) => {
|
|
2055
|
+
if (changedPath === gitHeadPath || changedPath.includes(".git/refs/heads/")) {
|
|
2056
|
+
console.log(chalk2.dim("[Rayburst] Git state changed, re-analyzing..."));
|
|
2057
|
+
runAnalysis("git-event");
|
|
2058
|
+
}
|
|
2059
|
+
};
|
|
2060
|
+
server.watcher.on("change", handleGitChange);
|
|
2061
|
+
checkGitState(config.root);
|
|
2062
|
+
gitPollInterval = setInterval(() => {
|
|
2063
|
+
if (checkGitState(config.root)) {
|
|
2064
|
+
console.log(chalk2.dim("[Rayburst] Git state changed (poll), re-analyzing..."));
|
|
2065
|
+
runAnalysis("git-poll");
|
|
2066
|
+
}
|
|
2067
|
+
}, 5e3);
|
|
2068
|
+
}
|
|
1983
2069
|
return () => {
|
|
1984
2070
|
server.watcher.off("change", handleFileChange);
|
|
1985
2071
|
server.watcher.off("add", handleFileChange);
|
|
@@ -1987,6 +2073,9 @@ function rayburstPlugin(options = {}) {
|
|
|
1987
2073
|
if (debounceTimer) {
|
|
1988
2074
|
clearTimeout(debounceTimer);
|
|
1989
2075
|
}
|
|
2076
|
+
if (gitPollInterval) {
|
|
2077
|
+
clearInterval(gitPollInterval);
|
|
2078
|
+
}
|
|
1990
2079
|
};
|
|
1991
2080
|
}
|
|
1992
2081
|
};
|
package/dist/index.js
CHANGED
package/dist/vite-plugin.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rayburst/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.6",
|
|
4
4
|
"description": "Rayburst - Automatic code analysis for TypeScript/JavaScript projects via Vite plugin",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"zod": "^4.2.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@rayburst/types": "^0.1.
|
|
50
|
+
"@rayburst/types": "^0.1.8",
|
|
51
51
|
"@types/node": "^25.0.2",
|
|
52
52
|
"tsup": "^8.5.1",
|
|
53
53
|
"typescript": "^5.9.3",
|