@noorm/marie-cli 0.1.0
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/JOY_ZONING.md +200 -0
- package/LICENSE.md +190 -0
- package/README.md +94 -0
- package/dist/cli-new/components/App.js +138 -0
- package/dist/cli-new/components/App.js.map +1 -0
- package/dist/cli-new/components/ApprovalDialog.js +31 -0
- package/dist/cli-new/components/ApprovalDialog.js.map +1 -0
- package/dist/cli-new/components/Banner.js +23 -0
- package/dist/cli-new/components/Banner.js.map +1 -0
- package/dist/cli-new/components/ChatArea.js +49 -0
- package/dist/cli-new/components/ChatArea.js.map +1 -0
- package/dist/cli-new/components/Header.js +20 -0
- package/dist/cli-new/components/Header.js.map +1 -0
- package/dist/cli-new/components/InputArea.js +97 -0
- package/dist/cli-new/components/InputArea.js.map +1 -0
- package/dist/cli-new/components/MessageBubble.js +114 -0
- package/dist/cli-new/components/MessageBubble.js.map +1 -0
- package/dist/cli-new/components/SessionSwitcher.js +46 -0
- package/dist/cli-new/components/SessionSwitcher.js.map +1 -0
- package/dist/cli-new/components/SetupWizard.js +283 -0
- package/dist/cli-new/components/SetupWizard.js.map +1 -0
- package/dist/cli-new/components/ToolCallDisplay.js +45 -0
- package/dist/cli-new/components/ToolCallDisplay.js.map +1 -0
- package/dist/cli-new/hooks/useGit.js +99 -0
- package/dist/cli-new/hooks/useGit.js.map +1 -0
- package/dist/cli-new/hooks/useMarie.js +249 -0
- package/dist/cli-new/hooks/useMarie.js.map +1 -0
- package/dist/cli-new/hooks/useSessions.js +75 -0
- package/dist/cli-new/hooks/useSessions.js.map +1 -0
- package/dist/cli-new/index.js +52 -0
- package/dist/cli-new/index.js.map +1 -0
- package/dist/cli-new/styles/theme.js +68 -0
- package/dist/cli-new/styles/theme.js.map +1 -0
- package/dist/cli-new/types/cli.js +2 -0
- package/dist/cli-new/types/cli.js.map +1 -0
- package/dist/extension.cjs +655 -0
- package/dist/monolith/adapters/CliMarieAdapter.js +72 -0
- package/dist/monolith/adapters/CliMarieAdapter.js.map +1 -0
- package/dist/monolith/adapters/VscodeMarieAdapter.js +81 -0
- package/dist/monolith/adapters/VscodeMarieAdapter.js.map +1 -0
- package/dist/monolith/cli/CliFileSystemPort.js +83 -0
- package/dist/monolith/cli/CliFileSystemPort.js.map +1 -0
- package/dist/monolith/cli/MarieToolDefinitionsCLI.js +438 -0
- package/dist/monolith/cli/MarieToolDefinitionsCLI.js.map +1 -0
- package/dist/monolith/cli/index.js +272 -0
- package/dist/monolith/cli/index.js.map +1 -0
- package/dist/monolith/cli/services/JoyAutomationServiceCLI.js +80 -0
- package/dist/monolith/cli/services/JoyAutomationServiceCLI.js.map +1 -0
- package/dist/monolith/cli/services/JoyServiceCLI.js +63 -0
- package/dist/monolith/cli/services/JoyServiceCLI.js.map +1 -0
- package/dist/monolith/cli/storage.js +119 -0
- package/dist/monolith/cli/storage.js.map +1 -0
- package/dist/monolith/domain/joy/JoyTools.js +513 -0
- package/dist/monolith/domain/joy/JoyTools.js.map +1 -0
- package/dist/monolith/domain/joy/RitualService.js +51 -0
- package/dist/monolith/domain/joy/RitualService.js.map +1 -0
- package/dist/monolith/domain/marie/MarieTypes.js +2 -0
- package/dist/monolith/domain/marie/MarieTypes.js.map +1 -0
- package/dist/monolith/infrastructure/ai/agents/MarieAscendant.js +230 -0
- package/dist/monolith/infrastructure/ai/agents/MarieAscendant.js.map +1 -0
- package/dist/monolith/infrastructure/ai/agents/MarieYOLO.js +207 -0
- package/dist/monolith/infrastructure/ai/agents/MarieYOLO.js.map +1 -0
- package/dist/monolith/infrastructure/ai/context/ContextArchiveService.js +129 -0
- package/dist/monolith/infrastructure/ai/context/ContextArchiveService.js.map +1 -0
- package/dist/monolith/infrastructure/ai/context/ContextManager.js +118 -0
- package/dist/monolith/infrastructure/ai/context/ContextManager.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/FileSystemPort.js +2 -0
- package/dist/monolith/infrastructure/ai/core/FileSystemPort.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/GhostPort.js +2 -0
- package/dist/monolith/infrastructure/ai/core/GhostPort.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieAscensionTypes.js +2 -0
- package/dist/monolith/infrastructure/ai/core/MarieAscensionTypes.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieEngine.js +590 -0
- package/dist/monolith/infrastructure/ai/core/MarieEngine.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieEventDispatcher.js +161 -0
- package/dist/monolith/infrastructure/ai/core/MarieEventDispatcher.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieLockManager.js +121 -0
- package/dist/monolith/infrastructure/ai/core/MarieLockManager.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieProgressTracker.js +256 -0
- package/dist/monolith/infrastructure/ai/core/MarieProgressTracker.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MariePulseService.js +67 -0
- package/dist/monolith/infrastructure/ai/core/MariePulseService.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieResponse.js +101 -0
- package/dist/monolith/infrastructure/ai/core/MarieResponse.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieSanitizer.js +86 -0
- package/dist/monolith/infrastructure/ai/core/MarieSanitizer.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieSession.js +202 -0
- package/dist/monolith/infrastructure/ai/core/MarieSession.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieStabilityMonitor.js +58 -0
- package/dist/monolith/infrastructure/ai/core/MarieStabilityMonitor.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieToolMender.js +127 -0
- package/dist/monolith/infrastructure/ai/core/MarieToolMender.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieToolProcessor.js +548 -0
- package/dist/monolith/infrastructure/ai/core/MarieToolProcessor.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/MarieYOLOTypes.js +2 -0
- package/dist/monolith/infrastructure/ai/core/MarieYOLOTypes.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/ReasoningBudget.js +125 -0
- package/dist/monolith/infrastructure/ai/core/ReasoningBudget.js.map +1 -0
- package/dist/monolith/infrastructure/ai/core/VscodeFileSystemPort.js +30 -0
- package/dist/monolith/infrastructure/ai/core/VscodeFileSystemPort.js.map +1 -0
- package/dist/monolith/infrastructure/ai/providers/AIProvider.js +2 -0
- package/dist/monolith/infrastructure/ai/providers/AIProvider.js.map +1 -0
- package/dist/monolith/infrastructure/ai/providers/AnthropicProvider.js +148 -0
- package/dist/monolith/infrastructure/ai/providers/AnthropicProvider.js.map +1 -0
- package/dist/monolith/infrastructure/ai/providers/CerebrasProvider.js +208 -0
- package/dist/monolith/infrastructure/ai/providers/CerebrasProvider.js.map +1 -0
- package/dist/monolith/infrastructure/ai/providers/OpenRouterProvider.js +404 -0
- package/dist/monolith/infrastructure/ai/providers/OpenRouterProvider.js.map +1 -0
- package/dist/monolith/infrastructure/ai/providers/OpenRouterStreamParser.js +283 -0
- package/dist/monolith/infrastructure/ai/providers/OpenRouterStreamParser.js.map +1 -0
- package/dist/monolith/infrastructure/config/ConfigService.js +398 -0
- package/dist/monolith/infrastructure/config/ConfigService.js.map +1 -0
- package/dist/monolith/infrastructure/services/MarieMemoryStore.js +140 -0
- package/dist/monolith/infrastructure/services/MarieMemoryStore.js.map +1 -0
- package/dist/monolith/infrastructure/tools/MarieToolDefinitions.js +1568 -0
- package/dist/monolith/infrastructure/tools/MarieToolDefinitions.js.map +1 -0
- package/dist/monolith/infrastructure/tools/PureStreamParser.js +147 -0
- package/dist/monolith/infrastructure/tools/PureStreamParser.js.map +1 -0
- package/dist/monolith/infrastructure/tools/SharedToolDefinitions.js +223 -0
- package/dist/monolith/infrastructure/tools/SharedToolDefinitions.js.map +1 -0
- package/dist/monolith/infrastructure/tools/ToolRegistry.js +29 -0
- package/dist/monolith/infrastructure/tools/ToolRegistry.js.map +1 -0
- package/dist/monolith/infrastructure/tools/ToolUtils.js +59 -0
- package/dist/monolith/infrastructure/tools/ToolUtils.js.map +1 -0
- package/dist/monolith/plumbing/analysis/CodeHealthService.js +146 -0
- package/dist/monolith/plumbing/analysis/CodeHealthService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/ComplexityService.js +43 -0
- package/dist/monolith/plumbing/analysis/ComplexityService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/DependencyService.js +51 -0
- package/dist/monolith/plumbing/analysis/DependencyService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/DiscoveryService.js +49 -0
- package/dist/monolith/plumbing/analysis/DiscoveryService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/JoyMapService.js +66 -0
- package/dist/monolith/plumbing/analysis/JoyMapService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/LintService.js +132 -0
- package/dist/monolith/plumbing/analysis/LintService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/MarieSentinelService.js +276 -0
- package/dist/monolith/plumbing/analysis/MarieSentinelService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/QualityGuardrailService.js +119 -0
- package/dist/monolith/plumbing/analysis/QualityGuardrailService.js.map +1 -0
- package/dist/monolith/plumbing/analysis/SurgicalMender.js +70 -0
- package/dist/monolith/plumbing/analysis/SurgicalMender.js.map +1 -0
- package/dist/monolith/plumbing/analysis/TestService.js +104 -0
- package/dist/monolith/plumbing/analysis/TestService.js.map +1 -0
- package/dist/monolith/plumbing/filesystem/FileService.js +406 -0
- package/dist/monolith/plumbing/filesystem/FileService.js.map +1 -0
- package/dist/monolith/plumbing/filesystem/PathResolver.js +26 -0
- package/dist/monolith/plumbing/filesystem/PathResolver.js.map +1 -0
- package/dist/monolith/plumbing/git/GitService.js +71 -0
- package/dist/monolith/plumbing/git/GitService.js.map +1 -0
- package/dist/monolith/plumbing/lsp/SymbolService.js +36 -0
- package/dist/monolith/plumbing/lsp/SymbolService.js.map +1 -0
- package/dist/monolith/plumbing/terminal/ProcessRegistry.js +31 -0
- package/dist/monolith/plumbing/terminal/ProcessRegistry.js.map +1 -0
- package/dist/monolith/plumbing/terminal/TerminalService.js +180 -0
- package/dist/monolith/plumbing/terminal/TerminalService.js.map +1 -0
- package/dist/monolith/plumbing/ui/DecorationService.js +54 -0
- package/dist/monolith/plumbing/ui/DecorationService.js.map +1 -0
- package/dist/monolith/plumbing/utils/ErrorUtils.js +11 -0
- package/dist/monolith/plumbing/utils/ErrorUtils.js.map +1 -0
- package/dist/monolith/plumbing/utils/JsonUtils.js +360 -0
- package/dist/monolith/plumbing/utils/JsonUtils.js.map +1 -0
- package/dist/monolith/plumbing/utils/PrefixTree.js +153 -0
- package/dist/monolith/plumbing/utils/PrefixTree.js.map +1 -0
- package/dist/monolith/plumbing/utils/RetryUtils.js +141 -0
- package/dist/monolith/plumbing/utils/RetryUtils.js.map +1 -0
- package/dist/monolith/plumbing/utils/StreamTagDetector.js +128 -0
- package/dist/monolith/plumbing/utils/StreamTagDetector.js.map +1 -0
- package/dist/monolith/plumbing/utils/StringUtils.js +97 -0
- package/dist/monolith/plumbing/utils/StringUtils.js.map +1 -0
- package/dist/monolith/plumbing/utils/TimeoutUtils.js +21 -0
- package/dist/monolith/plumbing/utils/TimeoutUtils.js.map +1 -0
- package/dist/monolith/runtime/MarieRuntime.js +354 -0
- package/dist/monolith/runtime/MarieRuntime.js.map +1 -0
- package/dist/monolith/runtime/RuntimeAdapterBase.js +59 -0
- package/dist/monolith/runtime/RuntimeAdapterBase.js.map +1 -0
- package/dist/monolith/runtime/providerFactory.js +11 -0
- package/dist/monolith/runtime/providerFactory.js.map +1 -0
- package/dist/monolith/runtime/types.js +2 -0
- package/dist/monolith/runtime/types.js.map +1 -0
- package/dist/monolith/services/HealthService.js +38 -0
- package/dist/monolith/services/HealthService.js.map +1 -0
- package/dist/monolith/services/JoyAutomationService.js +131 -0
- package/dist/monolith/services/JoyAutomationService.js.map +1 -0
- package/dist/monolith/services/JoyLogService.js +48 -0
- package/dist/monolith/services/JoyLogService.js.map +1 -0
- package/dist/monolith/services/JoyService.js +190 -0
- package/dist/monolith/services/JoyService.js.map +1 -0
- package/dist/monolith/services/MarieGhostService.js +168 -0
- package/dist/monolith/services/MarieGhostService.js.map +1 -0
- package/dist/monolith/services/MarieSCMProvider.js +41 -0
- package/dist/monolith/services/MarieSCMProvider.js.map +1 -0
- package/package.json +168 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import * as fs from "fs/promises";
|
|
2
|
+
import { getGratitudeMessage, getCelebrationMessage, } from "../../../prompts.js";
|
|
3
|
+
export function detectMigrationNeeds(filePath, content) {
|
|
4
|
+
const isPlumbing = filePath.includes("/plumbing/");
|
|
5
|
+
const isInfrastructure = filePath.includes("/infrastructure/");
|
|
6
|
+
const lowerContent = content.toLowerCase();
|
|
7
|
+
// If a plumbing file starts talking about "Entity", "User", "Order", it's leaking domain.
|
|
8
|
+
const domainKeywords = [
|
|
9
|
+
"entity",
|
|
10
|
+
"user",
|
|
11
|
+
"order",
|
|
12
|
+
"product",
|
|
13
|
+
"logic",
|
|
14
|
+
"business",
|
|
15
|
+
];
|
|
16
|
+
const domainMatch = domainKeywords.find((word) => lowerContent.includes(word));
|
|
17
|
+
if (isPlumbing && domainMatch) {
|
|
18
|
+
return {
|
|
19
|
+
shouldMigrate: true,
|
|
20
|
+
targetZone: "src/domain",
|
|
21
|
+
reason: `Found domain keyword '${domainMatch}' in plumbing. This file has evolved and deserves ascension.`,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (isInfrastructure &&
|
|
25
|
+
(lowerContent.includes("sql") || lowerContent.includes("fetch"))) {
|
|
26
|
+
// This is fine, infrastructure is for IO/Adapters.
|
|
27
|
+
}
|
|
28
|
+
return { shouldMigrate: false };
|
|
29
|
+
}
|
|
30
|
+
export async function checkCodeHealth(path) {
|
|
31
|
+
try {
|
|
32
|
+
const content = await fs.readFile(path, "utf-8");
|
|
33
|
+
const lines = content.split("\n");
|
|
34
|
+
const totalLines = lines.length;
|
|
35
|
+
const todos = (content.match(/TODO|FIXME/g) || []).length;
|
|
36
|
+
// Refined 'any' detection to include 'as any' and type casting
|
|
37
|
+
const anyRegex = /:\s*any\b|as\s+any\b|<\s*any\s*>/gi;
|
|
38
|
+
const anys = (content.match(anyRegex) || []).length;
|
|
39
|
+
const consoleLogs = (content.match(/console\.log/g) || []).length;
|
|
40
|
+
const blockComments = (content.match(/\/\*[\s\S]*?\*\//g) || []).filter((c) => c.split("\n").length > 2).length;
|
|
41
|
+
let maxDepth = 0;
|
|
42
|
+
lines.forEach((line) => {
|
|
43
|
+
const leadingWhitespace = line.match(/^\s*/)?.[0] || "";
|
|
44
|
+
const spaces = leadingWhitespace.length;
|
|
45
|
+
if (line.trim().length > 0) {
|
|
46
|
+
// Heuristic: handle both 2-space and 4-space indentation
|
|
47
|
+
const depth = Math.floor(spaces / 2);
|
|
48
|
+
if (depth > maxDepth)
|
|
49
|
+
maxDepth = depth;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
const filePath = path.replace(/\\/g, "/");
|
|
53
|
+
const zoningHealth = {
|
|
54
|
+
currentZone: "unknown",
|
|
55
|
+
isBackflowPresent: false,
|
|
56
|
+
illegalImports: [],
|
|
57
|
+
migrationNeed: { shouldMigrate: false },
|
|
58
|
+
};
|
|
59
|
+
if (filePath.includes("/domain/"))
|
|
60
|
+
zoningHealth.currentZone = "domain";
|
|
61
|
+
else if (filePath.includes("/infrastructure/"))
|
|
62
|
+
zoningHealth.currentZone = "infrastructure";
|
|
63
|
+
else if (filePath.includes("/plumbing/"))
|
|
64
|
+
zoningHealth.currentZone = "plumbing";
|
|
65
|
+
const imports = content.match(/import\s+.*\s+from\s+['"](.*)['"]*/g) || [];
|
|
66
|
+
imports.forEach((imp) => {
|
|
67
|
+
const match = imp.match(/from\s+['"](.*)['"]/);
|
|
68
|
+
if (!match)
|
|
69
|
+
return;
|
|
70
|
+
const importPath = match[1].toLowerCase();
|
|
71
|
+
// Downward Flow ONLY: Domain -> Infrastructure -> Plumbing
|
|
72
|
+
if (zoningHealth.currentZone === "plumbing") {
|
|
73
|
+
if (importPath.includes("/domain/") ||
|
|
74
|
+
importPath.includes("/infrastructure/")) {
|
|
75
|
+
zoningHealth.isBackflowPresent = true;
|
|
76
|
+
zoningHealth.illegalImports.push(imp);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else if (zoningHealth.currentZone === "infrastructure") {
|
|
80
|
+
if (importPath.includes("/domain/")) {
|
|
81
|
+
zoningHealth.isBackflowPresent = true;
|
|
82
|
+
zoningHealth.illegalImports.push(imp);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
zoningHealth.migrationNeed = detectMigrationNeeds(path, content);
|
|
87
|
+
let joyScore = 100;
|
|
88
|
+
const tips = [];
|
|
89
|
+
if (totalLines > 300) {
|
|
90
|
+
joyScore -= 10;
|
|
91
|
+
tips.push("• This file is growing large. Consider if it can be split to maintain focus.");
|
|
92
|
+
}
|
|
93
|
+
if (maxDepth > 5) {
|
|
94
|
+
joyScore -= 15;
|
|
95
|
+
tips.push("• Deep nesting detected. Can we simplify the logic to bring more clarity?");
|
|
96
|
+
}
|
|
97
|
+
if (todos > 0) {
|
|
98
|
+
joyScore -= todos * 2;
|
|
99
|
+
tips.push(`• ${todos} lingering TODOs. Each one is a small weight on our minds.`);
|
|
100
|
+
}
|
|
101
|
+
if (anys > 5) {
|
|
102
|
+
joyScore -= 10;
|
|
103
|
+
tips.push("• Frequent use of 'any' masks the true nature of our data.");
|
|
104
|
+
}
|
|
105
|
+
if (consoleLogs > 0) {
|
|
106
|
+
joyScore -= 5;
|
|
107
|
+
tips.push("• Console logs are whispers from development. They can be removed now.");
|
|
108
|
+
}
|
|
109
|
+
if (zoningHealth.isBackflowPresent) {
|
|
110
|
+
joyScore -= 20;
|
|
111
|
+
tips.push(`• ⚠️ **Zoning Violation**: This file imports from a higher conceptual zone. Respect the Downward Flow Law.`);
|
|
112
|
+
}
|
|
113
|
+
joyScore = Math.max(0, Math.min(100, joyScore));
|
|
114
|
+
let joyStatus = "Developing";
|
|
115
|
+
if (joyScore === 100)
|
|
116
|
+
joyStatus = getCelebrationMessage();
|
|
117
|
+
else
|
|
118
|
+
joyStatus = getGratitudeMessage();
|
|
119
|
+
if (tips.length === 0 && joyScore === 100) {
|
|
120
|
+
tips.push("• Perfection. This file sparks pure joy!");
|
|
121
|
+
}
|
|
122
|
+
else if (tips.length === 0) {
|
|
123
|
+
tips.push("• Looks good, just minor energetic tweaks needed.");
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
path,
|
|
127
|
+
lines: totalLines,
|
|
128
|
+
todos,
|
|
129
|
+
anys,
|
|
130
|
+
maxDepth,
|
|
131
|
+
joyScore,
|
|
132
|
+
clutter: {
|
|
133
|
+
consoleLogs,
|
|
134
|
+
commentedBlocks: blockComments,
|
|
135
|
+
},
|
|
136
|
+
joyStatus,
|
|
137
|
+
tips,
|
|
138
|
+
zoningHealth,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
console.error("Error checking code health:", error);
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=CodeHealthService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodeHealthService.js","sourceRoot":"","sources":["../../../../src/monolith/plumbing/analysis/CodeHealthService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as fs from "fs/promises";
|
|
2
|
+
/**
|
|
3
|
+
* Quantifies "Clutter" and code quality to help Marie maintain a high-integrity Garden.
|
|
4
|
+
*/
|
|
5
|
+
export class ComplexityService {
|
|
6
|
+
/**
|
|
7
|
+
* Heuristically analyzes a file for complexity.
|
|
8
|
+
*/
|
|
9
|
+
static async analyze(filePath) {
|
|
10
|
+
try {
|
|
11
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
12
|
+
const lines = content.split("\n");
|
|
13
|
+
const loc = lines.length;
|
|
14
|
+
// Simple heuristic for cyclomatic complexity: count control flow keywords
|
|
15
|
+
const controlFlowMatch = content.match(/\b(if|else if|for|while|case|catch|&&|\|\||!=|==|!==|===)\b/g);
|
|
16
|
+
const complexity = (controlFlowMatch?.length || 0) + 1;
|
|
17
|
+
let clutterLevel = "Clean";
|
|
18
|
+
const suggestions = [];
|
|
19
|
+
if (complexity > 20 || loc > 300) {
|
|
20
|
+
clutterLevel = "Toxic";
|
|
21
|
+
suggestions.push("This module is significantly cluttered. Consider decomposing into smaller 'Sprouts'.");
|
|
22
|
+
}
|
|
23
|
+
else if (complexity > 10 || loc > 150) {
|
|
24
|
+
clutterLevel = "Tangled";
|
|
25
|
+
suggestions.push("The logic is starting to tangle. A refactor ('Bloom') is recommended.");
|
|
26
|
+
}
|
|
27
|
+
else if (complexity > 5) {
|
|
28
|
+
clutterLevel = "Sparking";
|
|
29
|
+
suggestions.push("The code is healthy but keep an eye on control flow depth.");
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
cyclomaticComplexity: complexity,
|
|
33
|
+
loc,
|
|
34
|
+
clutterLevel,
|
|
35
|
+
suggestions,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
throw new Error(`Failed to analyze complexity for ${filePath}: ${error}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=ComplexityService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComplexityService.js","sourceRoot":"","sources":["../../../../src/monolith/plumbing/analysis/ComplexityService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AASlC;;GAEG;AACH,MAAM,OAAO,iBAAiB;IAC5B;;OAEG;IACI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,QAAgB;QAC1C,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACrD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC;YAEzB,0EAA0E;YAC1E,MAAM,gBAAgB,GAAG,OAAO,CAAC,KAAK,CACpC,8DAA8D,CAC/D,CAAC;YACF,MAAM,UAAU,GAAG,CAAC,gBAAgB,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YAEvD,IAAI,YAAY,GAAsC,OAAO,CAAC;YAC9D,MAAM,WAAW,GAAa,EAAE,CAAC;YAEjC,IAAI,UAAU,GAAG,EAAE,IAAI,GAAG,GAAG,GAAG,EAAE,CAAC;gBACjC,YAAY,GAAG,OAAO,CAAC;gBACvB,WAAW,CAAC,IAAI,CACd,sFAAsF,CACvF,CAAC;YACJ,CAAC;iBAAM,IAAI,UAAU,GAAG,EAAE,IAAI,GAAG,GAAG,GAAG,EAAE,CAAC;gBACxC,YAAY,GAAG,SAAS,CAAC;gBACzB,WAAW,CAAC,IAAI,CACd,uEAAuE,CACxE,CAAC;YACJ,CAAC;iBAAM,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;gBAC1B,YAAY,GAAG,UAAU,CAAC;gBAC1B,WAAW,CAAC,IAAI,CACd,4DAA4D,CAC7D,CAAC;YACJ,CAAC;YAED,OAAO;gBACL,oBAAoB,EAAE,UAAU;gBAChC,GAAG;gBACH,YAAY;gBACZ,WAAW;aACZ,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,oCAAoC,QAAQ,KAAK,KAAK,EAAE,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { readFile } from "../filesystem/FileService.js";
|
|
2
|
+
export class DependencyService {
|
|
3
|
+
/**
|
|
4
|
+
* Extracts imports and exports from a file to map its structural network.
|
|
5
|
+
*/
|
|
6
|
+
static async getFileNetwork(filePath) {
|
|
7
|
+
try {
|
|
8
|
+
const content = await readFile(filePath);
|
|
9
|
+
// Heuristic regex patterns for ESM imports and exports
|
|
10
|
+
const importRegex = /import\s+(?:.*?\s+from\s+)?['"](.*?)['"]/g;
|
|
11
|
+
const exportRegex = /export\s+(?:const|class|function|type|interface|enum|default)\s+(\w+)/g;
|
|
12
|
+
const imports = [];
|
|
13
|
+
const exports = [];
|
|
14
|
+
let match;
|
|
15
|
+
while ((match = importRegex.exec(content)) !== null) {
|
|
16
|
+
imports.push(match[1]);
|
|
17
|
+
}
|
|
18
|
+
while ((match = exportRegex.exec(content)) !== null) {
|
|
19
|
+
exports.push(match[1]);
|
|
20
|
+
}
|
|
21
|
+
let result = `# File Network: ${filePath.split("/").pop()}\n\n`;
|
|
22
|
+
result += `## 📥 Imports (Dependencies)\n`;
|
|
23
|
+
if (imports.length > 0) {
|
|
24
|
+
imports.forEach((i) => (result += `- \`${i}\`\n`));
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
result += `*None detected (Self-contained logic)*\n`;
|
|
28
|
+
}
|
|
29
|
+
result += `\n## 📤 Exports (Offerings)\n`;
|
|
30
|
+
if (exports.length > 0) {
|
|
31
|
+
exports.forEach((e) => (result += `- \`${e}\`\n`));
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
result += `*None detected (Internal consumer)*\n`;
|
|
35
|
+
}
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
throw new Error(`Failed to map network for ${filePath}: ${error}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* STABILITY: Circular Dependency Guard
|
|
44
|
+
* Detects if two files depend on each other, which can cause initialization death spirals.
|
|
45
|
+
*/
|
|
46
|
+
static async checkCircularity(fileA, fileB) {
|
|
47
|
+
// Placeholder for future graph analysis
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=DependencyService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DependencyService.js","sourceRoot":"","sources":["../../../../src/monolith/plumbing/analysis/DependencyService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAExD,MAAM,OAAO,iBAAiB;IAC5B;;OAEG;IACI,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,QAAgB;QACjD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAEzC,uDAAuD;YACvD,MAAM,WAAW,GAAG,2CAA2C,CAAC;YAChE,MAAM,WAAW,GACf,wEAAwE,CAAC;YAE3E,MAAM,OAAO,GAAa,EAAE,CAAC;YAC7B,MAAM,OAAO,GAAa,EAAE,CAAC;YAE7B,IAAI,KAAK,CAAC;YACV,OAAO,CAAC,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;gBACpD,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACzB,CAAC;YACD,OAAO,CAAC,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;gBACpD,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACzB,CAAC;YAED,IAAI,MAAM,GAAG,mBAAmB,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC;YAEhE,MAAM,IAAI,gCAAgC,CAAC;YAC3C,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACvB,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;YACrD,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,0CAA0C,CAAC;YACvD,CAAC;YAED,MAAM,IAAI,+BAA+B,CAAC;YAC1C,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACvB,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;YACrD,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,uCAAuC,CAAC;YACpD,CAAC;YAED,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,6BAA6B,QAAQ,KAAK,KAAK,EAAE,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;IAED;;;OAGG;IACI,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAClC,KAAa,EACb,KAAa;QAEb,wCAAwC;QACxC,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as fs from "fs/promises";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
export class DiscoveryService {
|
|
4
|
+
/**
|
|
5
|
+
* Returns a recursive, tree-like overview of a folder's structure.
|
|
6
|
+
*/
|
|
7
|
+
static async getFolderTree(folderPath, maxDepth = 3) {
|
|
8
|
+
try {
|
|
9
|
+
const rootName = path.basename(folderPath);
|
|
10
|
+
let result = `# Folder Structure: ${rootName}\n\n`;
|
|
11
|
+
result += await this.generateTree(folderPath, "", 0, maxDepth);
|
|
12
|
+
return result;
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
throw new Error(`Failed to generate folder tree for ${folderPath}: ${error}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
static async generateTree(dir, indent, currentDepth, maxDepth) {
|
|
19
|
+
if (currentDepth > maxDepth)
|
|
20
|
+
return "";
|
|
21
|
+
let result = "";
|
|
22
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
23
|
+
// Sort: directories first, then files
|
|
24
|
+
const sortedEntries = entries.sort((a, b) => {
|
|
25
|
+
if (a.isDirectory() && !b.isDirectory())
|
|
26
|
+
return -1;
|
|
27
|
+
if (!a.isDirectory() && b.isDirectory())
|
|
28
|
+
return 1;
|
|
29
|
+
return a.name.localeCompare(b.name);
|
|
30
|
+
});
|
|
31
|
+
// Filter first to get accurate isLast calculation
|
|
32
|
+
const visibleEntries = sortedEntries.filter((e) => !e.name.startsWith(".") &&
|
|
33
|
+
e.name !== "node_modules" &&
|
|
34
|
+
e.name !== "dist" &&
|
|
35
|
+
e.name !== "out");
|
|
36
|
+
for (let i = 0; i < visibleEntries.length; i++) {
|
|
37
|
+
const entry = visibleEntries[i];
|
|
38
|
+
const isLast = i === visibleEntries.length - 1;
|
|
39
|
+
const prefix = isLast ? "└── " : "├── ";
|
|
40
|
+
const nextIndent = indent + (isLast ? " " : "│ ");
|
|
41
|
+
result += `${indent}${prefix}${entry.name}${entry.isDirectory() ? "/" : ""}\n`;
|
|
42
|
+
if (entry.isDirectory()) {
|
|
43
|
+
result += await this.generateTree(path.join(dir, entry.name), nextIndent, currentDepth + 1, maxDepth);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=DiscoveryService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscoveryService.js","sourceRoot":"","sources":["../../../../src/monolith/plumbing/analysis/DiscoveryService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,MAAM,OAAO,gBAAgB;IAC3B;;OAEG;IACI,MAAM,CAAC,KAAK,CAAC,aAAa,CAC/B,UAAkB,EAClB,WAAmB,CAAC;QAEpB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YAC3C,IAAI,MAAM,GAAG,uBAAuB,QAAQ,MAAM,CAAC;YACnD,MAAM,IAAI,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,EAAE,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;YAC/D,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,sCAAsC,UAAU,KAAK,KAAK,EAAE,CAC7D,CAAC;QACJ,CAAC;IACH,CAAC;IAEO,MAAM,CAAC,KAAK,CAAC,YAAY,CAC/B,GAAW,EACX,MAAc,EACd,YAAoB,EACpB,QAAgB;QAEhB,IAAI,YAAY,GAAG,QAAQ;YAAE,OAAO,EAAE,CAAC;QAEvC,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAE/D,sCAAsC;QACtC,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAC1C,IAAI,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE;gBAAE,OAAO,CAAC,CAAC,CAAC;YACnD,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,WAAW,EAAE;gBAAE,OAAO,CAAC,CAAC;YAClD,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,kDAAkD;QAClD,MAAM,cAAc,GAAG,aAAa,CAAC,MAAM,CACzC,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YACvB,CAAC,CAAC,IAAI,KAAK,cAAc;YACzB,CAAC,CAAC,IAAI,KAAK,MAAM;YACjB,CAAC,CAAC,IAAI,KAAK,KAAK,CACnB,CAAC;QAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/C,MAAM,KAAK,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;YAChC,MAAM,MAAM,GAAG,CAAC,KAAK,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC;YAC/C,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;YACxC,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAEvD,MAAM,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;YAE/E,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,MAAM,IAAI,MAAM,IAAI,CAAC,YAAY,CAC/B,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,EAC1B,UAAU,EACV,YAAY,GAAG,CAAC,EAChB,QAAQ,CACT,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as fs from "fs/promises";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { checkCodeHealth } from "./CodeHealthService.js";
|
|
4
|
+
/**
|
|
5
|
+
* Generates a project-wide "Joy Map" to help Marie prioritize tidying.
|
|
6
|
+
*/
|
|
7
|
+
export class JoyMapService {
|
|
8
|
+
static async generate(workspaceRoot) {
|
|
9
|
+
const srcPath = path.join(workspaceRoot, "src");
|
|
10
|
+
const files = await this.findTsFiles(srcPath);
|
|
11
|
+
const results = [];
|
|
12
|
+
let totalScore = 0;
|
|
13
|
+
// Limit scan to 50 files for performance
|
|
14
|
+
const targetFiles = files.slice(0, 50);
|
|
15
|
+
for (const file of targetFiles) {
|
|
16
|
+
try {
|
|
17
|
+
const health = await checkCodeHealth(file);
|
|
18
|
+
results.push({
|
|
19
|
+
path: path.relative(workspaceRoot, file),
|
|
20
|
+
joyScore: health.joyScore,
|
|
21
|
+
clutterLevel: health.joyScore < 60
|
|
22
|
+
? "Toxic"
|
|
23
|
+
: health.joyScore < 80
|
|
24
|
+
? "Tangled"
|
|
25
|
+
: "Clean",
|
|
26
|
+
});
|
|
27
|
+
totalScore += health.joyScore;
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
console.error(`Failed to scan ${file}`, e);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const averageScore = targetFiles.length > 0
|
|
34
|
+
? Math.floor(totalScore / targetFiles.length)
|
|
35
|
+
: 100;
|
|
36
|
+
const hotspots = results
|
|
37
|
+
.sort((a, b) => a.joyScore - b.joyScore)
|
|
38
|
+
.filter((r) => r.joyScore < 70)
|
|
39
|
+
.slice(0, 5);
|
|
40
|
+
return {
|
|
41
|
+
overallJoyScore: averageScore,
|
|
42
|
+
totalFilesScanned: targetFiles.length,
|
|
43
|
+
hotspots,
|
|
44
|
+
summary: `The project has an average Joy Score of ${averageScore}. ` +
|
|
45
|
+
(hotspots.length > 0
|
|
46
|
+
? `We found ${hotspots.length} hotspots that need immediate attention.`
|
|
47
|
+
: "The Garden is looking pristine! ✨"),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
static async findTsFiles(dir) {
|
|
51
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
52
|
+
const files = await Promise.all(entries.map(async (entry) => {
|
|
53
|
+
const res = path.resolve(dir, entry.name);
|
|
54
|
+
if (entry.isDirectory()) {
|
|
55
|
+
if (entry.name === "node_modules" || entry.name.startsWith("."))
|
|
56
|
+
return [];
|
|
57
|
+
return this.findTsFiles(res);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
return res.endsWith(".ts") || res.endsWith(".tsx") ? [res] : [];
|
|
61
|
+
}
|
|
62
|
+
}));
|
|
63
|
+
return files.flat();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=JoyMapService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JoyMapService.js","sourceRoot":"","sources":["../../../../src/monolith/plumbing/analysis/JoyMapService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { exec } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
const execAsync = promisify(exec);
|
|
5
|
+
export class LintService {
|
|
6
|
+
/**
|
|
7
|
+
* Executes a lint command and parses the output into structured LintError objects.
|
|
8
|
+
*/
|
|
9
|
+
static async runLint(cwd, command = "npm run lint") {
|
|
10
|
+
try {
|
|
11
|
+
const { stdout, stderr } = await execAsync(command, { cwd });
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
catch (e) {
|
|
15
|
+
const output = (e.stdout || "") + (e.stderr || "");
|
|
16
|
+
return this.parseLintOutput(output, cwd);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Performs targeted linting on a specific file.
|
|
21
|
+
* Attempts to detect the best tool (ESLint, TSC) for the job.
|
|
22
|
+
*/
|
|
23
|
+
static async runLintOnFile(cwd, filePath) {
|
|
24
|
+
const relativePath = path.isAbsolute(filePath) ? path.relative(cwd, filePath) : filePath;
|
|
25
|
+
// 1. Try ESLint first if it's a TS/JS file
|
|
26
|
+
if (/\.(ts|js|tsx|jsx)$/.test(relativePath)) {
|
|
27
|
+
try {
|
|
28
|
+
// Try to use the project's own lint script if it supports passing files,
|
|
29
|
+
// otherwise use npx eslint directly.
|
|
30
|
+
const { stdout, stderr } = await execAsync(`npx eslint "${relativePath}" --format stylish`, { cwd });
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
const output = (e.stdout || "") + (e.stderr || "");
|
|
35
|
+
const errors = this.parseLintOutput(output, cwd);
|
|
36
|
+
if (errors.length > 0)
|
|
37
|
+
return errors;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// 2. Fallback to full project lint if targeted failed or was unavailable
|
|
41
|
+
return this.runLint(cwd);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Attempts to automatically fix lint errors in a file.
|
|
45
|
+
*/
|
|
46
|
+
static async fixFile(cwd, filePath) {
|
|
47
|
+
const relativePath = path.isAbsolute(filePath) ? path.relative(cwd, filePath) : filePath;
|
|
48
|
+
if (/\.(ts|js|tsx|jsx)$/.test(relativePath)) {
|
|
49
|
+
try {
|
|
50
|
+
// Prefer npm run lint:fix if available, but ESLint --fix is more precise for single files
|
|
51
|
+
const { stdout } = await execAsync(`npx eslint "${relativePath}" --fix`, { cwd });
|
|
52
|
+
return { success: true, output: stdout };
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
55
|
+
return { success: false, output: (e.stdout || "") + (e.stderr || "") };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return { success: false, output: "Auto-fix not supported for this file type." };
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Parses various lint output formats (ESLint, TSC).
|
|
62
|
+
*/
|
|
63
|
+
static parseLintOutput(output, cwd) {
|
|
64
|
+
const errors = [];
|
|
65
|
+
const lines = output.split("\n");
|
|
66
|
+
let currentFile = "";
|
|
67
|
+
for (const line of lines) {
|
|
68
|
+
// ESLint stylish file header
|
|
69
|
+
const fileMatch = line.match(/^(\/[^ ]+|\w:[\/][^ ]+)$/);
|
|
70
|
+
if (fileMatch) {
|
|
71
|
+
currentFile = fileMatch[1];
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
// ESLint stylish error line
|
|
75
|
+
const errorMatch = line.match(/^\s+(\d+):(\d+)\s+(error|warning)\s+(.+?)\s+([a-z0-9\-/]+|)$/i);
|
|
76
|
+
if (errorMatch && currentFile) {
|
|
77
|
+
errors.push({
|
|
78
|
+
file: path.relative(cwd, currentFile),
|
|
79
|
+
line: parseInt(errorMatch[1]),
|
|
80
|
+
column: parseInt(errorMatch[2]),
|
|
81
|
+
severity: errorMatch[3].toLowerCase(),
|
|
82
|
+
message: errorMatch[4].trim(),
|
|
83
|
+
ruleId: errorMatch[5] || undefined,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
// TSC format
|
|
87
|
+
const tscMatch = line.match(/^(.+)\((\d+),(\d+)\): (error|warning) (TS\d+): (.+)$/);
|
|
88
|
+
if (tscMatch) {
|
|
89
|
+
errors.push({
|
|
90
|
+
file: tscMatch[1],
|
|
91
|
+
line: parseInt(tscMatch[2]),
|
|
92
|
+
column: parseInt(tscMatch[3]),
|
|
93
|
+
severity: tscMatch[4].toLowerCase(),
|
|
94
|
+
ruleId: tscMatch[5],
|
|
95
|
+
message: tscMatch[6].trim(),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
// Generic unix format
|
|
99
|
+
const genericMatch = line.match(/^([^:]+):(\d+):(\d+): (error|warning): (.+)$/);
|
|
100
|
+
if (genericMatch) {
|
|
101
|
+
errors.push({
|
|
102
|
+
file: genericMatch[1],
|
|
103
|
+
line: parseInt(genericMatch[2]),
|
|
104
|
+
column: parseInt(genericMatch[3]),
|
|
105
|
+
severity: genericMatch[4].toLowerCase(),
|
|
106
|
+
message: genericMatch[5].trim(),
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return errors;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Heuristically suggests a fix for common lint errors.
|
|
114
|
+
*/
|
|
115
|
+
static suggestFix(error) {
|
|
116
|
+
const msg = error.message.toLowerCase();
|
|
117
|
+
if (msg.includes("unused") || msg.includes("is defined but never used")) {
|
|
118
|
+
return `Remove unused declaration or prefix with underscore.`;
|
|
119
|
+
}
|
|
120
|
+
if (msg.includes("missing semicolon") || msg.includes("extra semicolon")) {
|
|
121
|
+
return `Add or remove semicolon.`;
|
|
122
|
+
}
|
|
123
|
+
if (msg.includes("prefer-const") || msg.includes("should be a const")) {
|
|
124
|
+
return `Change 'let' to 'const'.`;
|
|
125
|
+
}
|
|
126
|
+
if (msg.includes("no-var") || msg.includes("unexpected var")) {
|
|
127
|
+
return `Change 'var' to 'let' or 'const'.`;
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=LintService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LintService.js","sourceRoot":"","sources":["../../../../src/monolith/plumbing/analysis/LintService.ts"],"names":[],"mappings":"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"}
|