codehere 0.2.2 → 0.3.0-rc.10
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 +88 -68
- package/dist/domain/entities/task.js +4 -4
- package/dist/error-handler.js +4 -9
- package/dist/index.js +261 -1224
- package/dist/infrastructure/config/product-context.js +7 -6
- package/dist/infrastructure/hooks/claude-sdk-hook.js +348 -72
- package/dist/infrastructure/observability/execution-tracer.js +11 -6
- package/dist/infrastructure/orchestration/agent-adapter.js +13 -0
- package/dist/infrastructure/orchestration/agent-installer.js +101 -0
- package/dist/infrastructure/orchestration/agents-config-seed.js +56 -0
- package/dist/infrastructure/orchestration/aider-adapter.js +319 -0
- package/dist/infrastructure/orchestration/artifacts-extractor.js +175 -0
- package/dist/infrastructure/orchestration/claude-code-adapter.js +352 -0
- package/dist/infrastructure/orchestration/codex-adapter.js +310 -0
- package/dist/infrastructure/orchestration/conductor-adapter.js +340 -0
- package/dist/infrastructure/orchestration/generic-cli-adapter.js +553 -0
- package/dist/infrastructure/orchestration/opencode-adapter.js +275 -0
- package/dist/infrastructure/orchestration/progress-aggregator.js +189 -0
- package/dist/infrastructure/orchestration/readiness.js +106 -0
- package/dist/infrastructure/orchestration/session-manager.js +278 -0
- package/dist/infrastructure/orchestration/session-persistence.js +109 -0
- package/dist/infrastructure/protocols/mcp-helpers.js +10 -30
- package/dist/infrastructure/protocols/mcp-server-impl.js +359 -21
- package/dist/infrastructure/protocols/probe-port.js +36 -0
- package/dist/infrastructure/protocols/ui-page.js +1827 -0
- package/dist/infrastructure/security/file-collection.js +115 -0
- package/dist/infrastructure/security/trust-scorer.js +301 -56
- package/dist/infrastructure/storage/task-repository.js +8 -7
- package/dist/monitoring.js +9 -38
- package/dist/presentation/cli/commands/help-command.js +96 -139
- package/dist/presentation/cli/commands/hook-command.js +17 -24
- package/dist/presentation/cli/commands/report-command.js +59 -72
- package/dist/presentation/cli/commands/setup-command.js +4 -4
- package/dist/presentation/cli/commands/status-command.js +321 -30
- package/dist/presentation/cli/commands/trust-command.js +84 -72
- package/dist/presentation/cli/error-display.js +17 -21
- package/dist/presentation/cli/repl.js +474 -0
- package/dist/ui.js +11 -11
- package/package.json +24 -62
- package/dist/agents/base.js +0 -101
- package/dist/agents/orchestrator-model-driven.js +0 -141
- package/dist/agents/react-orchestrator-agent.js +0 -54
- package/dist/application/agents/execution-agent.js +0 -508
- package/dist/application/agents/multi-agent-orchestrator.js +0 -295
- package/dist/application/agents/planning-agent.js +0 -433
- package/dist/application/agents/validation-agent.js +0 -317
- package/dist/application/architectures/plan-and-act.js +0 -242
- package/dist/application/index.js +0 -12
- package/dist/application/services/agent-factory.js +0 -28
- package/dist/application/services/dependency-container.js +0 -596
- package/dist/application/services/git-context-service.js +0 -83
- package/dist/application/services/intelligent-router.js +0 -934
- package/dist/application/services/tool-executor-service.js +0 -94
- package/dist/application/use-cases/ask-question-use-case.js +0 -338
- package/dist/application/use-cases/edit-file-use-case.js +0 -830
- package/dist/application/use-cases/explain-file-use-case.js +0 -50
- package/dist/application/use-cases/index-codebase-use-case.js +0 -113
- package/dist/application/use-cases/planning-use-case.js +0 -276
- package/dist/application/use-cases/react-orchestration-use-case.js +0 -329
- package/dist/application/use-cases/reflexion-use-case.js +0 -30
- package/dist/application/workflows/deterministic-workflows.js +0 -189
- package/dist/ast-parser.js +0 -331
- package/dist/cache.js +0 -180
- package/dist/chat.js +0 -251
- package/dist/code-analysis.js +0 -327
- package/dist/context.js +0 -187
- package/dist/docs.js +0 -146
- package/dist/domain/entities/code-chunk.js +0 -6
- package/dist/domain/entities/decision.js +0 -9
- package/dist/domain/entities/edit.js +0 -6
- package/dist/domain/entities/knowledge-node.js +0 -9
- package/dist/domain/entities/knowledge-preservation.js +0 -10
- package/dist/domain/entities/memory.js +0 -6
- package/dist/domain/entities/pattern.js +0 -7
- package/dist/domain/entities/plan.js +0 -6
- package/dist/domain/entities/query.js +0 -6
- package/dist/domain/errors/embeddings-not-found-error.js +0 -13
- package/dist/domain/index.js +0 -19
- package/dist/domain/interfaces/ai-service.interface.js +0 -6
- package/dist/domain/interfaces/code-analyzer.interface.js +0 -6
- package/dist/domain/interfaces/decision-repository.interface.js +0 -9
- package/dist/domain/interfaces/embedding-repository.interface.js +0 -6
- package/dist/domain/interfaces/knowledge-graph-repository.interface.js +0 -9
- package/dist/domain/interfaces/knowledge-preservation-repository.interface.js +0 -8
- package/dist/domain/interfaces/memory-repository.interface.js +0 -6
- package/dist/domain/interfaces/pattern-repository.interface.js +0 -6
- package/dist/domain/interfaces/verification-service.interface.js +0 -6
- package/dist/domain/services/cross-team-pattern-sharing.js +0 -125
- package/dist/domain/services/decision-recorder.js +0 -223
- package/dist/domain/services/decision-retriever.js +0 -133
- package/dist/domain/services/environment-mode-manager.js +0 -22
- package/dist/domain/services/graded-memory-activation.js +0 -69
- package/dist/domain/services/knowledge-access.js +0 -132
- package/dist/domain/services/knowledge-extractor.js +0 -247
- package/dist/domain/services/knowledge-graph-builder.js +0 -268
- package/dist/domain/services/knowledge-graph-query.js +0 -187
- package/dist/domain/services/memory-retriever.js +0 -82
- package/dist/domain/services/memory-synthesizer.js +0 -91
- package/dist/domain/services/pattern-extractor.js +0 -442
- package/dist/domain/services/query-intent-classifier.js +0 -140
- package/dist/domain/services/react-loop.js +0 -186
- package/dist/domain/services/risk-tier-detector.js +0 -78
- package/dist/edit.js +0 -319
- package/dist/embed.js +0 -459
- package/dist/formatter.js +0 -168
- package/dist/git.js +0 -198
- package/dist/infrastructure/ai/cohere-ai-service.js +0 -607
- package/dist/infrastructure/ai/command-r-evaluation.js +0 -206
- package/dist/infrastructure/ai/model-config.js +0 -84
- package/dist/infrastructure/ai/provider-ai-service.js +0 -477
- package/dist/infrastructure/cache/embedding-cache.js +0 -175
- package/dist/infrastructure/cache/query-result-cache.js +0 -66
- package/dist/infrastructure/cache/response-cache.js +0 -48
- package/dist/infrastructure/cache/security-scan-cache.js +0 -47
- package/dist/infrastructure/chunking/ast-code-chunker.js +0 -19
- package/dist/infrastructure/chunking/code-aware-chunker.js +0 -397
- package/dist/infrastructure/context/context-compressor.js +0 -329
- package/dist/infrastructure/context/conversation-context.js +0 -128
- package/dist/infrastructure/context/session-manager.js +0 -94
- package/dist/infrastructure/cost/cost-tracker.js +0 -360
- package/dist/infrastructure/file-scanner/file-scanner.js +0 -106
- package/dist/infrastructure/governance/nist-ai-rmf.js +0 -292
- package/dist/infrastructure/governance/policy-as-code.js +0 -258
- package/dist/infrastructure/governance/prompt-to-code-lineage.js +0 -239
- package/dist/infrastructure/index.js +0 -7
- package/dist/infrastructure/observability/prompt-versioner.js +0 -145
- package/dist/infrastructure/protocols/a2a-metadata.js +0 -137
- package/dist/infrastructure/protocols/a2a-protocol.js +0 -314
- package/dist/infrastructure/protocols/mcp-oauth.js +0 -184
- package/dist/infrastructure/protocols/mcp-server.js +0 -333
- package/dist/infrastructure/protocols/streaming-handler.js +0 -103
- package/dist/infrastructure/providers/cohere-provider.js +0 -444
- package/dist/infrastructure/providers/fake-provider.js +0 -130
- package/dist/infrastructure/providers/local-llm-provider.js +0 -330
- package/dist/infrastructure/providers/model-config.types.js +0 -9
- package/dist/infrastructure/providers/model-provider.interface.js +0 -8
- package/dist/infrastructure/providers/openai-provider.js +0 -413
- package/dist/infrastructure/providers/openrouter-provider.js +0 -399
- package/dist/infrastructure/providers/operation-provider-resolver.js +0 -105
- package/dist/infrastructure/providers/provider-config-loader.js +0 -120
- package/dist/infrastructure/providers/provider-registry.js +0 -88
- package/dist/infrastructure/safety/pattern-detector.js +0 -133
- package/dist/infrastructure/security/ai-sast-scanner.js +0 -290
- package/dist/infrastructure/security/docker-sandbox.js +0 -178
- package/dist/infrastructure/security/enhanced-security-gate.js +0 -151
- package/dist/infrastructure/security/license-scanner.js +0 -167
- package/dist/infrastructure/security/provider-bias-detector.js +0 -164
- package/dist/infrastructure/security/sandbox-executor.js +0 -64
- package/dist/infrastructure/serialization/toon-serializer.js +0 -119
- package/dist/infrastructure/storage/memory-stream-service.js +0 -204
- package/dist/infrastructure/storage/plan-repository.js +0 -96
- package/dist/infrastructure/storage/sqlite-decision-repository.js +0 -232
- package/dist/infrastructure/storage/sqlite-embedding-repository.js +0 -311
- package/dist/infrastructure/storage/sqlite-knowledge-graph-repository.js +0 -417
- package/dist/infrastructure/storage/sqlite-knowledge-preservation-repository.js +0 -230
- package/dist/infrastructure/storage/sqlite-memory-repository.js +0 -229
- package/dist/infrastructure/storage/sqlite-pattern-repository.js +0 -249
- package/dist/infrastructure/storage/task-helpers.js +0 -197
- package/dist/infrastructure/telemetry/telemetry-service.js +0 -167
- package/dist/infrastructure/ux/appropriate-friction.js +0 -213
- package/dist/infrastructure/ux/bi-directional-learning.js +0 -337
- package/dist/infrastructure/ux/capability-boundaries.js +0 -42
- package/dist/infrastructure/ux/comprehensive-formatter.js +0 -117
- package/dist/infrastructure/ux/contextual-feature-discovery.js +0 -10
- package/dist/infrastructure/ux/expectation-management.js +0 -327
- package/dist/infrastructure/ux/feature-discovery.js +0 -14
- package/dist/infrastructure/ux/feedback-prompt.js +0 -45
- package/dist/infrastructure/ux/hitl-validation.js +0 -297
- package/dist/infrastructure/ux/progress-indicator.js +0 -116
- package/dist/infrastructure/ux/progressive-disclosure.js +0 -236
- package/dist/infrastructure/ux/review-checkpoint.js +0 -72
- package/dist/infrastructure/ux/staged-feature-intro.js +0 -24
- package/dist/infrastructure/ux/stream-markdown.js +0 -151
- package/dist/infrastructure/ux/syntax-highlighter.js +0 -91
- package/dist/infrastructure/ux/team-standards.js +0 -196
- package/dist/infrastructure/ux/transparency.js +0 -71
- package/dist/infrastructure/validation/agent-feedback.js +0 -55
- package/dist/infrastructure/validation/agent-validation-helper.js +0 -137
- package/dist/infrastructure/validation/review-handler.js +0 -40
- package/dist/infrastructure/validation/summary-aggregator.js +0 -70
- package/dist/infrastructure/validation/summary-extractor.js +0 -45
- package/dist/infrastructure/validation/trace-summary.js +0 -52
- package/dist/infrastructure/verification/verification-service.js +0 -47
- package/dist/infrastructure/xai/attention-visualizer.js +0 -172
- package/dist/infrastructure/xai/cot-visualizer.js +0 -283
- package/dist/infrastructure/xai/decision-tree-log.js +0 -212
- package/dist/infrastructure/xai/interactive-xai.js +0 -260
- package/dist/infrastructure/xai/uncertainty-quantifier.js +0 -198
- package/dist/intelligent-retrieval.js +0 -272
- package/dist/intent/classifier.js +0 -2
- package/dist/intent/context.js +0 -2
- package/dist/iterative-refinement.js +0 -189
- package/dist/learning.js +0 -232
- package/dist/log.js +0 -31
- package/dist/migrate.js +0 -133
- package/dist/parallel-processor.js +0 -534
- package/dist/planner.js +0 -198
- package/dist/policy.js +0 -26
- package/dist/presentation/cli/commands/ask-command.js +0 -314
- package/dist/presentation/cli/commands/cost-command.js +0 -191
- package/dist/presentation/cli/commands/decision-command.js +0 -207
- package/dist/presentation/cli/commands/docs-command.js +0 -25
- package/dist/presentation/cli/commands/fix-command.js +0 -53
- package/dist/presentation/cli/commands/knowledge-command.js +0 -129
- package/dist/presentation/cli/commands/learning-dashboard-command.js +0 -183
- package/dist/presentation/cli/commands/models-command.js +0 -194
- package/dist/presentation/cli/commands/orchestrate-command.js +0 -207
- package/dist/presentation/cli/commands/plan-command.js +0 -246
- package/dist/presentation/cli/commands/product-command.js +0 -199
- package/dist/presentation/cli/commands/react-command.js +0 -181
- package/dist/presentation/cli/commands/review-command.js +0 -154
- package/dist/presentation/cli/commands/run-command.js +0 -188
- package/dist/presentation/cli/commands/smart-command.js +0 -395
- package/dist/presentation/cli/commands/suggest-command.js +0 -138
- package/dist/presentation/cli/commands/trace-command.js +0 -129
- package/dist/presentation/cli/commands/undo-command.js +0 -150
- package/dist/query-optimizer.js +0 -205
- package/dist/refactor.js +0 -116
- package/dist/review.js +0 -206
- package/dist/search.js +0 -163
- package/dist/session.js +0 -704
- package/dist/task-verification.js +0 -336
- package/dist/testgen.js +0 -166
- package/dist/token-optimizer.js +0 -277
- package/dist/tools/bash.js +0 -213
- package/dist/tools/edit.js +0 -235
- package/dist/tools/executor.js +0 -153
- package/dist/tools/git-tool.js +0 -292
- package/dist/tools/parser.js +0 -158
- package/dist/tools/registry.js +0 -302
- package/dist/tools/search.js +0 -100
- package/dist/types.js +0 -2
- package/dist/utils/check-api-status.js +0 -100
- package/dist/utils/diff-parser.js +0 -162
- package/dist/verification/backup.js +0 -259
- package/dist/verification/compiler.js +0 -264
- package/dist/verification/index.js +0 -273
- package/dist/verification/test-runner.js +0 -379
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unified Diff Parser
|
|
3
|
-
* Parses and applies unified diff patches to file content
|
|
4
|
-
*
|
|
5
|
-
* Handles standard unified diff format:
|
|
6
|
-
* --- a/filepath
|
|
7
|
-
* +++ b/filepath
|
|
8
|
-
* @@ -start,count +start,count @@
|
|
9
|
-
* -old line (remove)
|
|
10
|
-
* +new line (add)
|
|
11
|
-
* context line (keep)
|
|
12
|
-
*/
|
|
13
|
-
/**
|
|
14
|
-
* Apply a unified diff to file content
|
|
15
|
-
*/
|
|
16
|
-
export function applyUnifiedDiff(originalContent, diff) {
|
|
17
|
-
if (!diff || !diff.trim()) {
|
|
18
|
-
return originalContent;
|
|
19
|
-
}
|
|
20
|
-
// Clean diff - remove any markdown formatting
|
|
21
|
-
let cleanDiff = diff.trim();
|
|
22
|
-
// Extract the actual diff lines
|
|
23
|
-
const diffLines = cleanDiff.split('\n');
|
|
24
|
-
const originalLines = originalContent.split('\n');
|
|
25
|
-
const result = [];
|
|
26
|
-
let originalIndex = 0; // Current position in original file
|
|
27
|
-
let inHunk = false;
|
|
28
|
-
let hunkStartLine = 0; // Line number where hunk starts (1-based from diff)
|
|
29
|
-
let hunkOldLineCount = 0; // Number of old lines in this hunk
|
|
30
|
-
let hunkOldLinesProcessed = 0; // How many old lines we've processed
|
|
31
|
-
for (let i = 0; i < diffLines.length; i++) {
|
|
32
|
-
const line = diffLines[i];
|
|
33
|
-
// Skip header lines
|
|
34
|
-
if (line.startsWith('---') || line.startsWith('+++')) {
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
// Parse hunk header: @@ -start,count +start,count @@
|
|
38
|
-
const hunkMatch = line.match(/^@@\s+-(\d+)(?:,(\d+))?\s+\+(\d+)(?:,(\d+))?\s+@@/);
|
|
39
|
-
if (hunkMatch) {
|
|
40
|
-
// Finish previous hunk
|
|
41
|
-
if (inHunk) {
|
|
42
|
-
// Make sure we've processed all old lines from previous hunk
|
|
43
|
-
while (hunkOldLinesProcessed < hunkOldLineCount && originalIndex < originalLines.length) {
|
|
44
|
-
originalIndex++;
|
|
45
|
-
hunkOldLinesProcessed++;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
// Start new hunk
|
|
49
|
-
inHunk = true;
|
|
50
|
-
hunkStartLine = parseInt(hunkMatch[1], 10); // 1-based line number
|
|
51
|
-
hunkOldLineCount = parseInt(hunkMatch[2] || '0', 10);
|
|
52
|
-
hunkOldLinesProcessed = 0;
|
|
53
|
-
// Copy all lines from original up to (but not including) the hunk start
|
|
54
|
-
// hunkStartLine is 1-based, originalIndex is 0-based
|
|
55
|
-
while (originalIndex < hunkStartLine - 1 && originalIndex < originalLines.length) {
|
|
56
|
-
result.push(originalLines[originalIndex]);
|
|
57
|
-
originalIndex++;
|
|
58
|
-
}
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
if (!inHunk) {
|
|
62
|
-
continue; // Skip lines outside hunks
|
|
63
|
-
}
|
|
64
|
-
// Process hunk content
|
|
65
|
-
if (line.startsWith('-')) {
|
|
66
|
-
// Remove line: skip this line from original
|
|
67
|
-
if (originalIndex < originalLines.length) {
|
|
68
|
-
originalIndex++;
|
|
69
|
-
hunkOldLinesProcessed++;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
else if (line.startsWith('+')) {
|
|
73
|
-
// Add line: add new line to result
|
|
74
|
-
result.push(line.substring(1));
|
|
75
|
-
// Don't increment originalIndex or hunkOldLinesProcessed for additions
|
|
76
|
-
}
|
|
77
|
-
else if (line.startsWith(' ')) {
|
|
78
|
-
// Context line: keep from original
|
|
79
|
-
if (originalIndex < originalLines.length) {
|
|
80
|
-
result.push(originalLines[originalIndex]);
|
|
81
|
-
originalIndex++;
|
|
82
|
-
hunkOldLinesProcessed++;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
else if (line.trim() === '') {
|
|
86
|
-
// Empty line - preserve if it's part of the diff structure
|
|
87
|
-
// But don't add it if we're in the middle of processing
|
|
88
|
-
if (hunkOldLinesProcessed < hunkOldLineCount) {
|
|
89
|
-
// This might be a continuation, skip it
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
// Check if hunk is complete
|
|
94
|
-
if (hunkOldLinesProcessed >= hunkOldLineCount) {
|
|
95
|
-
inHunk = false;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
// Copy all remaining lines from original
|
|
99
|
-
while (originalIndex < originalLines.length) {
|
|
100
|
-
result.push(originalLines[originalIndex]);
|
|
101
|
-
originalIndex++;
|
|
102
|
-
}
|
|
103
|
-
return result.join('\n');
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Fallback: Try multiple strategies to apply the edit
|
|
107
|
-
* Now optimized for complete file content (preferred) or unified diff
|
|
108
|
-
*/
|
|
109
|
-
export function applyEditFallback(originalContent, diff) {
|
|
110
|
-
if (!diff || !diff.trim()) {
|
|
111
|
-
return originalContent;
|
|
112
|
-
}
|
|
113
|
-
// Clean the diff
|
|
114
|
-
let cleanDiff = diff.trim();
|
|
115
|
-
// Strategy 1: Extract from markdown code blocks
|
|
116
|
-
const codeBlockMatch = cleanDiff.match(/```(?:\w+)?\n([\s\S]*?)\n```/);
|
|
117
|
-
if (codeBlockMatch) {
|
|
118
|
-
cleanDiff = codeBlockMatch[1].trim();
|
|
119
|
-
}
|
|
120
|
-
// Strategy 2: Check if it's a complete file (no diff markers)
|
|
121
|
-
const hasDiffMarkers = cleanDiff.includes('---') || cleanDiff.includes('+++') || cleanDiff.includes('@@');
|
|
122
|
-
// If no diff markers and substantial content, treat as complete file
|
|
123
|
-
if (!hasDiffMarkers) {
|
|
124
|
-
// Verify it looks like code (has common patterns)
|
|
125
|
-
const looksLikeCode = cleanDiff.includes('function') ||
|
|
126
|
-
cleanDiff.includes('class') ||
|
|
127
|
-
cleanDiff.includes('import') ||
|
|
128
|
-
cleanDiff.includes('export') ||
|
|
129
|
-
cleanDiff.includes('const') ||
|
|
130
|
-
cleanDiff.includes('async');
|
|
131
|
-
if (looksLikeCode && cleanDiff.length > 100) {
|
|
132
|
-
// Likely complete file content
|
|
133
|
-
return cleanDiff;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
// Strategy 3: Try unified diff parsing if it has diff markers
|
|
137
|
-
if (hasDiffMarkers) {
|
|
138
|
-
try {
|
|
139
|
-
const result = applyUnifiedDiff(originalContent, cleanDiff);
|
|
140
|
-
// Basic sanity check
|
|
141
|
-
if (result && result.length > 0 && result !== originalContent) {
|
|
142
|
-
// Verify it's not just the diff itself
|
|
143
|
-
if (!result.startsWith('---') && !result.startsWith('+++')) {
|
|
144
|
-
return result;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
catch (error) {
|
|
149
|
-
if (process.env.CODEHERE_DEBUG === '1')
|
|
150
|
-
console.warn('[DiffParser] Unified diff parsing failed:', error);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
// Strategy 4: Last resort - if it's substantial content, use it
|
|
154
|
-
if (cleanDiff.length > 200 && !cleanDiff.startsWith('---') && !cleanDiff.startsWith('+++')) {
|
|
155
|
-
return cleanDiff;
|
|
156
|
-
}
|
|
157
|
-
// Strategy 5: If all else fails, return original (safer than broken code)
|
|
158
|
-
if (process.env.CODEHERE_DEBUG === '1')
|
|
159
|
-
console.warn('[DiffParser] Could not parse diff, returning original content');
|
|
160
|
-
return originalContent;
|
|
161
|
-
}
|
|
162
|
-
//# sourceMappingURL=diff-parser.js.map
|
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* File Backup and Rollback Module
|
|
3
|
-
* Creates backups before edits and enables rollback on verification failure
|
|
4
|
-
*/
|
|
5
|
-
import { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync, readdirSync, statSync } from 'fs';
|
|
6
|
-
import { join, dirname, basename } from 'path';
|
|
7
|
-
import { executionTracer } from '../infrastructure/observability/execution-tracer.js';
|
|
8
|
-
const BACKUP_DIR = '.codehere/backups';
|
|
9
|
-
const MAX_BACKUPS = 5; // Keep last 5 backups per file
|
|
10
|
-
/**
|
|
11
|
-
* Create backup of file before editing
|
|
12
|
-
*/
|
|
13
|
-
export async function backupFile(filepath) {
|
|
14
|
-
try {
|
|
15
|
-
// Read original file
|
|
16
|
-
if (!existsSync(filepath)) {
|
|
17
|
-
throw new Error(`File not found: ${filepath}`);
|
|
18
|
-
}
|
|
19
|
-
const originalContent = readFileSync(filepath, 'utf-8');
|
|
20
|
-
// Create backup directory
|
|
21
|
-
const projectDir = findProjectRoot(filepath) || dirname(filepath);
|
|
22
|
-
const backupDir = join(projectDir, BACKUP_DIR);
|
|
23
|
-
if (!existsSync(backupDir)) {
|
|
24
|
-
mkdirSync(backupDir, { recursive: true });
|
|
25
|
-
}
|
|
26
|
-
// Generate backup filename with timestamp
|
|
27
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
28
|
-
const filename = basename(filepath);
|
|
29
|
-
const backupPath = join(backupDir, `${filename}.${timestamp}.backup`);
|
|
30
|
-
// Write backup
|
|
31
|
-
writeFileSync(backupPath, originalContent, 'utf-8');
|
|
32
|
-
// Link backup to current run for traceability
|
|
33
|
-
const runId = executionTracer.getCurrentRunId();
|
|
34
|
-
if (runId) {
|
|
35
|
-
executionTracer.trace({
|
|
36
|
-
operationType: 'file_operation',
|
|
37
|
-
operationName: 'backup',
|
|
38
|
-
input: { filepath },
|
|
39
|
-
output: { backupPath },
|
|
40
|
-
metadata: {
|
|
41
|
-
runId,
|
|
42
|
-
filepath,
|
|
43
|
-
timestamp: new Date().toISOString(),
|
|
44
|
-
},
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
// Clean up old backups for this file
|
|
48
|
-
await cleanupOldBackups(backupDir, filename);
|
|
49
|
-
return backupPath;
|
|
50
|
-
}
|
|
51
|
-
catch (error) {
|
|
52
|
-
throw new Error(`Failed to create backup: ${error instanceof Error ? error.message : String(error)}`);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Restore file from backup
|
|
57
|
-
*/
|
|
58
|
-
export async function rollbackFile(filepath, backupPath) {
|
|
59
|
-
try {
|
|
60
|
-
// If no backup path provided, find most recent backup
|
|
61
|
-
if (!backupPath) {
|
|
62
|
-
const latestBackup = await findLatestBackup(filepath);
|
|
63
|
-
if (!latestBackup) {
|
|
64
|
-
throw new Error(`No backup found for file: ${filepath}`);
|
|
65
|
-
}
|
|
66
|
-
backupPath = latestBackup;
|
|
67
|
-
}
|
|
68
|
-
// Verify backup exists
|
|
69
|
-
if (!existsSync(backupPath)) {
|
|
70
|
-
throw new Error(`Backup file not found: ${backupPath}`);
|
|
71
|
-
}
|
|
72
|
-
// Read backup content
|
|
73
|
-
const backupContent = readFileSync(backupPath, 'utf-8');
|
|
74
|
-
// Restore original file
|
|
75
|
-
writeFileSync(filepath, backupContent, 'utf-8');
|
|
76
|
-
// Trace rollback operation
|
|
77
|
-
const runId = executionTracer.getCurrentRunId();
|
|
78
|
-
if (runId) {
|
|
79
|
-
executionTracer.trace({
|
|
80
|
-
operationType: 'file_operation',
|
|
81
|
-
operationName: 'rollback',
|
|
82
|
-
input: { filepath, backupPath },
|
|
83
|
-
output: { restored: true },
|
|
84
|
-
metadata: {
|
|
85
|
-
runId,
|
|
86
|
-
filepath,
|
|
87
|
-
backupPath,
|
|
88
|
-
timestamp: new Date().toISOString(),
|
|
89
|
-
},
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
catch (error) {
|
|
94
|
-
throw new Error(`Failed to rollback file: ${error instanceof Error ? error.message : String(error)}`);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Find latest backup for a file
|
|
99
|
-
*/
|
|
100
|
-
export async function findLatestBackup(filepath) {
|
|
101
|
-
try {
|
|
102
|
-
const projectDir = findProjectRoot(filepath) || dirname(filepath);
|
|
103
|
-
const backupDir = join(projectDir, BACKUP_DIR);
|
|
104
|
-
if (!existsSync(backupDir)) {
|
|
105
|
-
return null;
|
|
106
|
-
}
|
|
107
|
-
const filename = basename(filepath);
|
|
108
|
-
const files = readdirSync(backupDir)
|
|
109
|
-
.filter(file => file.startsWith(`${filename}.`) && file.endsWith('.backup'))
|
|
110
|
-
.map(file => join(backupDir, file))
|
|
111
|
-
.filter(file => existsSync(file));
|
|
112
|
-
if (files.length === 0) {
|
|
113
|
-
return null;
|
|
114
|
-
}
|
|
115
|
-
// Sort by modification time (newest first)
|
|
116
|
-
files.sort((a, b) => {
|
|
117
|
-
const statA = statSync(a);
|
|
118
|
-
const statB = statSync(b);
|
|
119
|
-
return statB.mtime.getTime() - statA.mtime.getTime();
|
|
120
|
-
});
|
|
121
|
-
return files[0]; // Return most recent backup
|
|
122
|
-
}
|
|
123
|
-
catch (error) {
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* List all backups for a file
|
|
129
|
-
*/
|
|
130
|
-
export async function listBackups(filepath) {
|
|
131
|
-
try {
|
|
132
|
-
const projectDir = findProjectRoot(filepath) || dirname(filepath);
|
|
133
|
-
const backupDir = join(projectDir, BACKUP_DIR);
|
|
134
|
-
if (!existsSync(backupDir)) {
|
|
135
|
-
return [];
|
|
136
|
-
}
|
|
137
|
-
const filename = basename(filepath);
|
|
138
|
-
const files = readdirSync(backupDir)
|
|
139
|
-
.filter(file => file.startsWith(`${filename}.`) && file.endsWith('.backup'))
|
|
140
|
-
.map(file => {
|
|
141
|
-
const backupPath = join(backupDir, file);
|
|
142
|
-
if (!existsSync(backupPath)) {
|
|
143
|
-
return null;
|
|
144
|
-
}
|
|
145
|
-
const stat = statSync(backupPath);
|
|
146
|
-
const timestampMatch = file.match(/\.([^.]+)\.backup$/);
|
|
147
|
-
let timestamp;
|
|
148
|
-
if (timestampMatch) {
|
|
149
|
-
// Timestamp format: 2025-12-02T00-10-46-506Z (dashes instead of colons)
|
|
150
|
-
// Convert to ISO format: 2025-12-02T00:10:46.506Z
|
|
151
|
-
const timestampStr = timestampMatch[1];
|
|
152
|
-
// Replace dashes with colons, but keep date part dashes
|
|
153
|
-
// Format: YYYY-MM-DDTHH-MM-SS-MMMZ
|
|
154
|
-
// Convert: YYYY-MM-DDTHH:MM:SS.MMMZ
|
|
155
|
-
const isoStr = timestampStr
|
|
156
|
-
.replace(/T(\d{2})-(\d{2})-(\d{2})-(\d{3})Z$/, 'T$1:$2:$3.$4Z');
|
|
157
|
-
try {
|
|
158
|
-
timestamp = new Date(isoStr);
|
|
159
|
-
// Validate date
|
|
160
|
-
if (isNaN(timestamp.getTime())) {
|
|
161
|
-
timestamp = stat.mtime; // Fallback to file mtime
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
catch {
|
|
165
|
-
timestamp = stat.mtime; // Fallback to file mtime
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
timestamp = stat.mtime;
|
|
170
|
-
}
|
|
171
|
-
return {
|
|
172
|
-
backupPath,
|
|
173
|
-
originalPath: filepath,
|
|
174
|
-
timestamp,
|
|
175
|
-
};
|
|
176
|
-
})
|
|
177
|
-
.filter((info) => info !== null);
|
|
178
|
-
// Sort by timestamp (newest first)
|
|
179
|
-
files.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());
|
|
180
|
-
return files;
|
|
181
|
-
}
|
|
182
|
-
catch (error) {
|
|
183
|
-
return [];
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Clean up old backups (keep only MAX_BACKUPS most recent)
|
|
188
|
-
*/
|
|
189
|
-
async function cleanupOldBackups(backupDir, filename) {
|
|
190
|
-
try {
|
|
191
|
-
const files = readdirSync(backupDir)
|
|
192
|
-
.filter(file => file.startsWith(`${filename}.`) && file.endsWith('.backup'))
|
|
193
|
-
.map(file => join(backupDir, file))
|
|
194
|
-
.filter(file => existsSync(file));
|
|
195
|
-
if (files.length <= MAX_BACKUPS) {
|
|
196
|
-
return; // No cleanup needed
|
|
197
|
-
}
|
|
198
|
-
// Sort by modification time (oldest first)
|
|
199
|
-
files.sort((a, b) => {
|
|
200
|
-
const statA = statSync(a);
|
|
201
|
-
const statB = statSync(b);
|
|
202
|
-
return statA.mtime.getTime() - statB.mtime.getTime();
|
|
203
|
-
});
|
|
204
|
-
// Delete oldest backups
|
|
205
|
-
const toDelete = files.slice(0, files.length - MAX_BACKUPS);
|
|
206
|
-
for (const file of toDelete) {
|
|
207
|
-
try {
|
|
208
|
-
unlinkSync(file);
|
|
209
|
-
}
|
|
210
|
-
catch {
|
|
211
|
-
// Ignore deletion errors
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
catch (error) {
|
|
216
|
-
// Ignore cleanup errors - don't fail if cleanup fails
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* Delete all backups for a file
|
|
221
|
-
*/
|
|
222
|
-
export async function deleteAllBackups(filepath) {
|
|
223
|
-
try {
|
|
224
|
-
const backups = await listBackups(filepath);
|
|
225
|
-
for (const backup of backups) {
|
|
226
|
-
try {
|
|
227
|
-
if (existsSync(backup.backupPath)) {
|
|
228
|
-
unlinkSync(backup.backupPath);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
catch {
|
|
232
|
-
// Ignore deletion errors
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
catch (error) {
|
|
237
|
-
// Ignore cleanup errors
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* Find project root (where package.json or .git is)
|
|
242
|
-
*/
|
|
243
|
-
function findProjectRoot(filepath) {
|
|
244
|
-
let currentDir = dirname(filepath);
|
|
245
|
-
const root = currentDir.split(/[/\\]/)[0];
|
|
246
|
-
while (currentDir !== root) {
|
|
247
|
-
if (existsSync(join(currentDir, 'package.json')) ||
|
|
248
|
-
existsSync(join(currentDir, '.git'))) {
|
|
249
|
-
return currentDir;
|
|
250
|
-
}
|
|
251
|
-
const parentDir = dirname(currentDir);
|
|
252
|
-
if (parentDir === currentDir) {
|
|
253
|
-
break;
|
|
254
|
-
}
|
|
255
|
-
currentDir = parentDir;
|
|
256
|
-
}
|
|
257
|
-
return null;
|
|
258
|
-
}
|
|
259
|
-
//# sourceMappingURL=backup.js.map
|
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Compilation Verification Module
|
|
3
|
-
* Verifies TypeScript and JavaScript code compiles/syntax checks correctly
|
|
4
|
-
*/
|
|
5
|
-
import { readFileSync, existsSync } from 'fs';
|
|
6
|
-
import { join, dirname, extname } from 'path';
|
|
7
|
-
import { execSync } from 'child_process';
|
|
8
|
-
import { mkdirSync, writeFileSync, unlinkSync } from 'fs';
|
|
9
|
-
import { tmpdir } from 'os';
|
|
10
|
-
/**
|
|
11
|
-
* Verify code compilation based on file type
|
|
12
|
-
*/
|
|
13
|
-
export async function verifyCompilation(filepath, code, options = {}) {
|
|
14
|
-
const ext = extname(filepath).toLowerCase();
|
|
15
|
-
// Use provided code or read from file
|
|
16
|
-
const codeToCheck = code || (existsSync(filepath) ? readFileSync(filepath, 'utf-8') : '');
|
|
17
|
-
if (!codeToCheck) {
|
|
18
|
-
return {
|
|
19
|
-
success: false,
|
|
20
|
-
errors: ['No code provided and file does not exist'],
|
|
21
|
-
warnings: [],
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
// Route to appropriate verifier
|
|
25
|
-
if (ext === '.ts' || ext === '.tsx') {
|
|
26
|
-
return await verifyTypeScriptCompilation(filepath, codeToCheck, options);
|
|
27
|
-
}
|
|
28
|
-
else if (ext === '.js' || ext === '.jsx') {
|
|
29
|
-
return await verifyJavaScriptSyntax(filepath, codeToCheck, options);
|
|
30
|
-
}
|
|
31
|
-
// Unknown file type - skip verification
|
|
32
|
-
return {
|
|
33
|
-
success: true,
|
|
34
|
-
errors: [],
|
|
35
|
-
warnings: [`Unknown file type ${ext}, skipping compilation check`],
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Verify TypeScript compilation
|
|
40
|
-
*/
|
|
41
|
-
async function verifyTypeScriptCompilation(filepath, code, options = {}) {
|
|
42
|
-
const errors = [];
|
|
43
|
-
const warnings = [];
|
|
44
|
-
const timeout = options.timeout || 30000; // 30 seconds default
|
|
45
|
-
const skipLibCheck = options.skipLibCheck !== false; // Default to true
|
|
46
|
-
try {
|
|
47
|
-
// Create temporary file for checking
|
|
48
|
-
const tmpDir = join(tmpdir(), 'codehere-verification');
|
|
49
|
-
if (!existsSync(tmpDir)) {
|
|
50
|
-
mkdirSync(tmpDir, { recursive: true });
|
|
51
|
-
}
|
|
52
|
-
const tmpFile = join(tmpDir, `check-${Date.now()}.ts`);
|
|
53
|
-
writeFileSync(tmpFile, code, 'utf-8');
|
|
54
|
-
try {
|
|
55
|
-
// Build tsc command
|
|
56
|
-
const tscArgs = [
|
|
57
|
-
'--noEmit',
|
|
58
|
-
skipLibCheck ? '--skipLibCheck' : '',
|
|
59
|
-
'--strict',
|
|
60
|
-
`"${tmpFile}"`,
|
|
61
|
-
].filter(Boolean).join(' ');
|
|
62
|
-
// Try to find tsconfig.json in project root
|
|
63
|
-
const projectDir = findProjectRoot(filepath);
|
|
64
|
-
const hasTsConfig = projectDir && (existsSync(join(projectDir, 'tsconfig.json')) ||
|
|
65
|
-
existsSync(join(projectDir, 'tsconfig.base.json')));
|
|
66
|
-
let command;
|
|
67
|
-
if (hasTsConfig && projectDir) {
|
|
68
|
-
// Use project tsconfig.json
|
|
69
|
-
command = `cd "${projectDir}" && npx tsc ${tscArgs}`;
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
// Use standalone file check
|
|
73
|
-
command = `npx tsc ${tscArgs}`;
|
|
74
|
-
}
|
|
75
|
-
const result = execSync(command, {
|
|
76
|
-
encoding: 'utf-8',
|
|
77
|
-
stdio: 'pipe',
|
|
78
|
-
timeout,
|
|
79
|
-
cwd: projectDir || dirname(filepath),
|
|
80
|
-
});
|
|
81
|
-
// If execution succeeded with no output, compilation passed
|
|
82
|
-
if (!result || result.trim().length === 0) {
|
|
83
|
-
return { success: true, errors: [], warnings: [] };
|
|
84
|
-
}
|
|
85
|
-
// Parse output for errors and warnings (enhanced pattern detection)
|
|
86
|
-
const lines = result.split('\n');
|
|
87
|
-
for (const line of lines) {
|
|
88
|
-
const trimmedLine = line.trim();
|
|
89
|
-
// Enhanced error detection patterns
|
|
90
|
-
if (trimmedLine.includes('error TS') ||
|
|
91
|
-
trimmedLine.match(/error\s+TS\d+/i) ||
|
|
92
|
-
trimmedLine.includes('Cannot find') ||
|
|
93
|
-
trimmedLine.includes('is not defined') ||
|
|
94
|
-
trimmedLine.includes('has no exported member') ||
|
|
95
|
-
trimmedLine.includes('Property') && trimmedLine.includes('does not exist') ||
|
|
96
|
-
trimmedLine.includes('Type') && trimmedLine.includes('is not assignable')) {
|
|
97
|
-
errors.push(trimmedLine);
|
|
98
|
-
}
|
|
99
|
-
else if (trimmedLine.includes('warning TS') || trimmedLine.match(/warning\s+TS\d+/i)) {
|
|
100
|
-
warnings.push(trimmedLine);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
return {
|
|
104
|
-
success: errors.length === 0,
|
|
105
|
-
errors,
|
|
106
|
-
warnings,
|
|
107
|
-
output: result,
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
finally {
|
|
111
|
-
// Clean up temp file
|
|
112
|
-
try {
|
|
113
|
-
if (existsSync(tmpFile)) {
|
|
114
|
-
unlinkSync(tmpFile);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
catch {
|
|
118
|
-
// Ignore cleanup errors
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
catch (error) {
|
|
123
|
-
// execSync throws on non-zero exit code
|
|
124
|
-
const output = error.stdout || error.stderr || error.message || '';
|
|
125
|
-
const errorOutput = String(output);
|
|
126
|
-
// Parse error output (enhanced pattern detection)
|
|
127
|
-
const lines = errorOutput.split('\n');
|
|
128
|
-
for (const line of lines) {
|
|
129
|
-
const trimmedLine = line.trim();
|
|
130
|
-
// Enhanced error detection patterns
|
|
131
|
-
if (trimmedLine.includes('error TS') ||
|
|
132
|
-
trimmedLine.match(/error\s+TS\d+/i) ||
|
|
133
|
-
trimmedLine.includes('Cannot find') ||
|
|
134
|
-
trimmedLine.includes('is not defined') ||
|
|
135
|
-
trimmedLine.includes('has no exported member') ||
|
|
136
|
-
trimmedLine.includes('Property') && trimmedLine.includes('does not exist') ||
|
|
137
|
-
trimmedLine.includes('Type') && trimmedLine.includes('is not assignable') ||
|
|
138
|
-
trimmedLine.includes('Module') && trimmedLine.includes('has no exported member')) {
|
|
139
|
-
errors.push(trimmedLine);
|
|
140
|
-
}
|
|
141
|
-
else if (trimmedLine.includes('warning TS') || trimmedLine.match(/warning\s+TS\d+/i)) {
|
|
142
|
-
warnings.push(trimmedLine);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
// If no structured errors found, try to extract meaningful error patterns
|
|
146
|
-
if (errors.length === 0) {
|
|
147
|
-
// Look for common error patterns in output
|
|
148
|
-
const errorPatterns = [
|
|
149
|
-
/(?:error|Error)[:\s]+(.+)/i,
|
|
150
|
-
/(?:failed|Failed)[:\s]+(.+)/i,
|
|
151
|
-
/(?:cannot|Cannot)[:\s]+(.+)/i,
|
|
152
|
-
/(?:undefined|Undefined)[:\s]+(.+)/i,
|
|
153
|
-
];
|
|
154
|
-
let foundError = false;
|
|
155
|
-
for (const pattern of errorPatterns) {
|
|
156
|
-
const match = errorOutput.match(pattern);
|
|
157
|
-
if (match && match[1]) {
|
|
158
|
-
errors.push(`TypeScript compilation error: ${match[1].trim().substring(0, 200)}`);
|
|
159
|
-
foundError = true;
|
|
160
|
-
break;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
if (!foundError) {
|
|
164
|
-
errors.push(`TypeScript compilation failed: ${errorOutput.substring(0, 500)}`);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
// Check for timeout
|
|
168
|
-
if (error.signal === 'SIGTERM' || errorOutput.includes('timeout')) {
|
|
169
|
-
errors.push('Compilation check timed out');
|
|
170
|
-
}
|
|
171
|
-
// Check if tsc is available
|
|
172
|
-
if (errorOutput.includes('command not found') || errorOutput.includes('Cannot find module')) {
|
|
173
|
-
warnings.push('TypeScript compiler (tsc) not found. Install it with: npm install -D typescript');
|
|
174
|
-
// Don't fail if tsc is not installed - this is a warning, not an error
|
|
175
|
-
return {
|
|
176
|
-
success: true, // Allow to proceed if compiler not available
|
|
177
|
-
errors: [],
|
|
178
|
-
warnings: ['TypeScript compiler not available, skipping compilation check'],
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
return {
|
|
182
|
-
success: false,
|
|
183
|
-
errors,
|
|
184
|
-
warnings,
|
|
185
|
-
output: errorOutput,
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Verify JavaScript syntax
|
|
191
|
-
*/
|
|
192
|
-
async function verifyJavaScriptSyntax(filepath, code, options = {}) {
|
|
193
|
-
const errors = [];
|
|
194
|
-
const warnings = [];
|
|
195
|
-
try {
|
|
196
|
-
// Syntax check: write to temp file and use node --check (parse-only, no execution)
|
|
197
|
-
const tmpFile = join(tmpdir(), `codehere-syntax-${Date.now()}.js`);
|
|
198
|
-
try {
|
|
199
|
-
writeFileSync(tmpFile, code, 'utf-8');
|
|
200
|
-
execSync(`node --check "${tmpFile}"`, { stdio: 'pipe' });
|
|
201
|
-
}
|
|
202
|
-
catch (parseError) {
|
|
203
|
-
const errorMsg = parseError instanceof Error ? parseError.message : String(parseError);
|
|
204
|
-
const lineMatch = errorMsg.match(/line (\d+)/i) || errorMsg.match(/:(\d+):/);
|
|
205
|
-
const lineNum = lineMatch ? lineMatch[1] : '?';
|
|
206
|
-
errors.push(`Syntax error at line ${lineNum}: ${errorMsg}`);
|
|
207
|
-
return { success: false, errors, warnings };
|
|
208
|
-
}
|
|
209
|
-
finally {
|
|
210
|
-
try {
|
|
211
|
-
unlinkSync(tmpFile);
|
|
212
|
-
}
|
|
213
|
-
catch { /* ignore */ }
|
|
214
|
-
}
|
|
215
|
-
// Additional check: Try to parse as ES module
|
|
216
|
-
// This catches import/export syntax errors
|
|
217
|
-
try {
|
|
218
|
-
// Create temporary file and try to load it as module
|
|
219
|
-
// This is a lightweight check
|
|
220
|
-
if (code.includes('import ') || code.includes('export ')) {
|
|
221
|
-
// For ES modules, we'd need more sophisticated checking
|
|
222
|
-
// For now, syntax check is sufficient
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
catch (moduleError) {
|
|
226
|
-
warnings.push(`Module syntax warning: ${moduleError instanceof Error ? moduleError.message : String(moduleError)}`);
|
|
227
|
-
}
|
|
228
|
-
return {
|
|
229
|
-
success: true,
|
|
230
|
-
errors: [],
|
|
231
|
-
warnings,
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
catch (error) {
|
|
235
|
-
errors.push(`JavaScript syntax check failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
236
|
-
return {
|
|
237
|
-
success: false,
|
|
238
|
-
errors,
|
|
239
|
-
warnings,
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* Find project root (where package.json or tsconfig.json is)
|
|
245
|
-
*/
|
|
246
|
-
function findProjectRoot(filepath) {
|
|
247
|
-
let currentDir = dirname(filepath);
|
|
248
|
-
const root = currentDir.split(/[/\\]/)[0]; // Get filesystem root
|
|
249
|
-
// Walk up directory tree
|
|
250
|
-
while (currentDir !== root) {
|
|
251
|
-
if (existsSync(join(currentDir, 'package.json')) ||
|
|
252
|
-
existsSync(join(currentDir, 'tsconfig.json')) ||
|
|
253
|
-
existsSync(join(currentDir, 'tsconfig.base.json'))) {
|
|
254
|
-
return currentDir;
|
|
255
|
-
}
|
|
256
|
-
const parentDir = dirname(currentDir);
|
|
257
|
-
if (parentDir === currentDir) {
|
|
258
|
-
break; // Reached root
|
|
259
|
-
}
|
|
260
|
-
currentDir = parentDir;
|
|
261
|
-
}
|
|
262
|
-
return null;
|
|
263
|
-
}
|
|
264
|
-
//# sourceMappingURL=compiler.js.map
|