mcp-code-context 2.2.0 → 2.4.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.
Files changed (132) hide show
  1. package/.io/RULES.md +12 -0
  2. package/CHANGELOG.md +114 -1
  3. package/README.md +28 -1
  4. package/dist/src/ast/writers/safeRename.d.ts +14 -0
  5. package/dist/src/ast/writers/safeRename.js +258 -0
  6. package/dist/src/ast/writers/safeRename.js.map +1 -0
  7. package/dist/src/ast/writers/symbolWriter.d.ts +2 -0
  8. package/dist/src/ast/writers/symbolWriter.js +9 -14
  9. package/dist/src/ast/writers/symbolWriter.js.map +1 -1
  10. package/dist/src/cache/astCache.d.ts +33 -0
  11. package/dist/src/cache/astCache.js +113 -0
  12. package/dist/src/cache/astCache.js.map +1 -0
  13. package/dist/src/handlers/readHandlers.d.ts +70 -0
  14. package/dist/src/handlers/readHandlers.js +431 -0
  15. package/dist/src/handlers/readHandlers.js.map +1 -0
  16. package/dist/src/handlers/utilHandlers.d.ts +31 -0
  17. package/dist/src/handlers/utilHandlers.js +69 -0
  18. package/dist/src/handlers/utilHandlers.js.map +1 -0
  19. package/dist/src/handlers/writeHandlers.d.ts +57 -0
  20. package/dist/src/handlers/writeHandlers.js +475 -0
  21. package/dist/src/handlers/writeHandlers.js.map +1 -0
  22. package/dist/src/index.d.ts +6 -143
  23. package/dist/src/index.js +77 -1091
  24. package/dist/src/index.js.map +1 -1
  25. package/dist/src/tools/searchCodePattern.d.ts +7 -2
  26. package/dist/src/tools/searchCodePattern.js +68 -4
  27. package/dist/src/tools/searchCodePattern.js.map +1 -1
  28. package/dist/src/utils/arrayUtils.d.ts +12 -0
  29. package/dist/src/utils/arrayUtils.js +27 -0
  30. package/dist/src/utils/arrayUtils.js.map +1 -0
  31. package/dist/src/utils/constants.d.ts +46 -0
  32. package/dist/src/utils/constants.js +112 -0
  33. package/dist/src/utils/constants.js.map +1 -0
  34. package/dist/src/utils/ignoreManager.d.ts +8 -0
  35. package/dist/src/utils/ignoreManager.js +49 -0
  36. package/dist/src/utils/ignoreManager.js.map +1 -1
  37. package/dist/src/utils/normalization.d.ts +49 -0
  38. package/dist/src/utils/normalization.js +173 -0
  39. package/dist/src/utils/normalization.js.map +1 -0
  40. package/dist/src/utils/projectRoot.d.ts +12 -5
  41. package/dist/src/utils/projectRoot.js +22 -20
  42. package/dist/src/utils/projectRoot.js.map +1 -1
  43. package/dist/src/utils/secureValidation.d.ts +15 -0
  44. package/dist/src/utils/secureValidation.js +41 -0
  45. package/dist/src/utils/secureValidation.js.map +1 -0
  46. package/dist/src/utils/transactionManager.d.ts +45 -0
  47. package/dist/src/utils/transactionManager.js +102 -0
  48. package/dist/src/utils/transactionManager.js.map +1 -0
  49. package/dist/src/utils/validation.d.ts +87 -0
  50. package/dist/src/utils/validation.js +231 -0
  51. package/dist/src/utils/validation.js.map +1 -0
  52. package/docs/ARCHITECTURE.md +300 -0
  53. package/docs/architecture/ADR-001-modular-handlers.md +119 -0
  54. package/llms.txt +10 -1
  55. package/package.json +5 -5
  56. package/AGENT_INSTRUCTIONS.md +0 -135
  57. package/DEPLOYMENT_INSTRUCTIONS.md +0 -110
  58. package/MEJORAS_PROPUESTAS.md +0 -324
  59. package/RELEASE_NOTES_v2.1.3.md +0 -78
  60. package/RELEASE_NOTES_v2.2.0.md +0 -286
  61. package/dist/src/tests/test-confirmation-flow.d.ts +0 -1
  62. package/dist/src/tests/test-confirmation-flow.js +0 -43
  63. package/dist/src/tests/test-confirmation-flow.js.map +0 -1
  64. package/dist/tests/debug-replace.d.ts +0 -1
  65. package/dist/tests/debug-replace.js +0 -17
  66. package/dist/tests/debug-replace.js.map +0 -1
  67. package/dist/tests/test-backup-system.d.ts +0 -7
  68. package/dist/tests/test-backup-system.js +0 -152
  69. package/dist/tests/test-backup-system.js.map +0 -1
  70. package/dist/tests/test-confirmation-flow.d.ts +0 -1
  71. package/dist/tests/test-confirmation-flow.js +0 -43
  72. package/dist/tests/test-confirmation-flow.js.map +0 -1
  73. package/dist/tests/test-dart.d.ts +0 -1
  74. package/dist/tests/test-dart.js +0 -242
  75. package/dist/tests/test-dart.js.map +0 -1
  76. package/dist/tests/test-new-tools.d.ts +0 -4
  77. package/dist/tests/test-new-tools.js +0 -147
  78. package/dist/tests/test-new-tools.js.map +0 -1
  79. package/dist/tests/test-php-ast.d.ts +0 -1
  80. package/dist/tests/test-php-ast.js +0 -152
  81. package/dist/tests/test-php-ast.js.map +0 -1
  82. package/dist/tests/test-php.d.ts +0 -1
  83. package/dist/tests/test-php.js +0 -234
  84. package/dist/tests/test-php.js.map +0 -1
  85. package/dist/tests/test-smoke.d.ts +0 -5
  86. package/dist/tests/test-smoke.js +0 -83
  87. package/dist/tests/test-smoke.js.map +0 -1
  88. package/dist/tests/writers/test-crlf-handling.d.ts +0 -4
  89. package/dist/tests/writers/test-crlf-handling.js +0 -73
  90. package/dist/tests/writers/test-crlf-handling.js.map +0 -1
  91. package/dist/tests/writers/test-write-smoke.d.ts +0 -9
  92. package/dist/tests/writers/test-write-smoke.js +0 -346
  93. package/dist/tests/writers/test-write-smoke.js.map +0 -1
  94. package/src/ast/dartCompressor.ts +0 -1013
  95. package/src/ast/phpCompressor.ts +0 -814
  96. package/src/ast/semanticCompressor.ts +0 -808
  97. package/src/ast/writers/dartWriter.ts +0 -648
  98. package/src/ast/writers/phpWriter.ts +0 -508
  99. package/src/ast/writers/pyWriter.ts +0 -446
  100. package/src/ast/writers/symbolWriter.ts +0 -277
  101. package/src/ast/writers/tsWriter.ts +0 -418
  102. package/src/index.ts +0 -1784
  103. package/src/tools/readFileLines.ts +0 -104
  104. package/src/tools/searchCodePattern.ts +0 -129
  105. package/src/utils/backupManager.ts +0 -141
  106. package/src/utils/confirmationCache.ts +0 -61
  107. package/src/utils/diffEngine.ts +0 -223
  108. package/src/utils/fuzzyMatch.ts +0 -86
  109. package/src/utils/ignoreManager.ts +0 -144
  110. package/src/utils/projectRoot.ts +0 -44
  111. package/tests/test-backup-system.ts +0 -174
  112. package/tests/test-confirmation-flow.ts +0 -49
  113. package/tests/test-dart.d.ts +0 -1
  114. package/tests/test-dart.js +0 -209
  115. package/tests/test-dart.js.map +0 -1
  116. package/tests/test-dart.ts +0 -265
  117. package/tests/test-new-tools.ts +0 -165
  118. package/tests/test-php-ast.d.ts +0 -1
  119. package/tests/test-php-ast.js +0 -152
  120. package/tests/test-php-ast.js.map +0 -1
  121. package/tests/test-php-ast.ts +0 -155
  122. package/tests/test-php.d.ts +0 -1
  123. package/tests/test-php.js +0 -234
  124. package/tests/test-php.js.map +0 -1
  125. package/tests/test-php.ts +0 -261
  126. package/tests/test-smoke.d.ts +0 -5
  127. package/tests/test-smoke.js +0 -83
  128. package/tests/test-smoke.js.map +0 -1
  129. package/tests/test-smoke.ts +0 -93
  130. package/tests/writers/test-crlf-handling.ts +0 -100
  131. package/tests/writers/test-write-smoke.ts +0 -568
  132. package/tsconfig.json +0 -19
@@ -0,0 +1,173 @@
1
+ /**
2
+ * normalization.ts — Code Normalization Utilities
3
+ *
4
+ * Centralizes line ending normalization and indentation logic
5
+ * to eliminate duplication across writer modules.
6
+ */
7
+ import { TS_INDENT, PHP_INDENT, PYTHON_INDENT } from "./constants.js";
8
+ // ─── Line Ending Normalization ──────────────────────────────────────
9
+ /**
10
+ * Normalize line endings to LF (\n) for consistent processing.
11
+ * Handles CRLF (\r\n), CR (\r), and mixed line endings.
12
+ *
13
+ * Why: Windows files use CRLF, which breaks brace-counting and line-based
14
+ * operations. Normalizing to LF ensures consistent behavior across platforms.
15
+ */
16
+ export function normalizeLineEndings(content) {
17
+ return content.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
18
+ }
19
+ // ─── Indentation Detection ──────────────────────────────────────────
20
+ /**
21
+ * Extract the leading whitespace from a line.
22
+ */
23
+ export function getIndent(line) {
24
+ const match = line.match(/^(\s*)/);
25
+ return match ? match[1] : "";
26
+ }
27
+ /**
28
+ * Measure the indentation level of a line (number of spaces/tabs).
29
+ */
30
+ export function measureIndent(line) {
31
+ const indent = getIndent(line);
32
+ // Convert tabs to 4 spaces for measurement
33
+ return indent.replace(/\t/g, " ").length;
34
+ }
35
+ /**
36
+ * Detect the predominant indentation style in a file.
37
+ * Returns the most common indentation string (e.g., " ", " ", "\t").
38
+ */
39
+ export function detectIndentStyle(content) {
40
+ const lines = content.split("\n");
41
+ const indents = new Map();
42
+ for (const line of lines) {
43
+ if (line.trim() === "")
44
+ continue;
45
+ const indent = getIndent(line);
46
+ if (indent.length === 0)
47
+ continue;
48
+ // Extract the base indent unit (first level of indentation)
49
+ const match = indent.match(/^(\s+)/);
50
+ if (match) {
51
+ const unit = match[1];
52
+ indents.set(unit, (indents.get(unit) || 0) + 1);
53
+ }
54
+ }
55
+ if (indents.size === 0)
56
+ return " "; // Default to 2 spaces
57
+ // Return the most common indent
58
+ let maxCount = 0;
59
+ let commonIndent = " ";
60
+ for (const [indent, count] of indents.entries()) {
61
+ if (count > maxCount) {
62
+ maxCount = count;
63
+ commonIndent = indent;
64
+ }
65
+ }
66
+ return commonIndent;
67
+ }
68
+ // ─── Code Reindentation ─────────────────────────────────────────────
69
+ /**
70
+ * Reindent code to match a target indentation level.
71
+ * Preserves relative indentation between lines.
72
+ *
73
+ * @param code - The code to reindent
74
+ * @param targetIndent - The base indentation to apply
75
+ * @param language - Optional language hint for default indent style
76
+ */
77
+ export function reindentCode(code, targetIndent, language) {
78
+ // Normalize line endings first
79
+ code = normalizeLineEndings(code);
80
+ const lines = code.split("\n");
81
+ if (lines.length === 0)
82
+ return code;
83
+ // Find minimum indentation (excluding empty lines)
84
+ let minIndent = Infinity;
85
+ for (const line of lines) {
86
+ if (line.trim() === "")
87
+ continue;
88
+ const indent = measureIndent(line);
89
+ if (indent < minIndent)
90
+ minIndent = indent;
91
+ }
92
+ if (minIndent === Infinity)
93
+ minIndent = 0;
94
+ // Apply target indentation while preserving relative indentation
95
+ return lines
96
+ .map((line) => {
97
+ if (line.trim() === "")
98
+ return "";
99
+ const currentIndent = measureIndent(line);
100
+ const relativeIndent = currentIndent - minIndent;
101
+ // Calculate how many indent units are needed
102
+ const indentUnit = getIndentUnit(language);
103
+ const indentUnitSize = indentUnit.length;
104
+ const numUnits = Math.floor(relativeIndent / indentUnitSize);
105
+ return targetIndent + indentUnit.repeat(numUnits) + line.trimStart();
106
+ })
107
+ .join("\n");
108
+ }
109
+ /**
110
+ * Get the standard indentation unit for a language.
111
+ */
112
+ function getIndentUnit(language) {
113
+ switch (language) {
114
+ case "dart":
115
+ case "typescript":
116
+ return TS_INDENT;
117
+ case "php":
118
+ return PHP_INDENT;
119
+ case "python":
120
+ return PYTHON_INDENT;
121
+ default:
122
+ return " "; // Default to 2 spaces
123
+ }
124
+ }
125
+ /**
126
+ * Reindent code for Python (indentation-aware language).
127
+ * Handles Python's strict indentation requirements.
128
+ */
129
+ export function reindentPython(code, targetIndent) {
130
+ code = normalizeLineEndings(code);
131
+ const lines = code.split("\n");
132
+ if (lines.length === 0)
133
+ return code;
134
+ let minIndent = Infinity;
135
+ for (const line of lines) {
136
+ if (line.trim() === "")
137
+ continue;
138
+ const indent = measureIndent(line);
139
+ if (indent < minIndent)
140
+ minIndent = indent;
141
+ }
142
+ if (minIndent === Infinity)
143
+ minIndent = 0;
144
+ return lines
145
+ .map((line) => {
146
+ if (line.trim() === "")
147
+ return "";
148
+ const currentIndent = measureIndent(line);
149
+ const relativeIndent = currentIndent - minIndent;
150
+ // Python uses 4-space indentation by convention
151
+ const numLevels = Math.floor(relativeIndent / 4);
152
+ return targetIndent + PYTHON_INDENT.repeat(numLevels) + line.trimStart();
153
+ })
154
+ .join("\n");
155
+ }
156
+ // ─── Whitespace Cleanup ─────────────────────────────────────────────
157
+ /**
158
+ * Remove excessive blank lines (more than 2 consecutive).
159
+ */
160
+ export function normalizeBlankLines(content) {
161
+ return content.replace(/\n{3,}/g, "\n\n");
162
+ }
163
+ /**
164
+ * Ensure file ends with a single newline (POSIX standard).
165
+ */
166
+ export function ensureTrailingNewline(content) {
167
+ if (!content.endsWith("\n")) {
168
+ return content + "\n";
169
+ }
170
+ // Remove multiple trailing newlines
171
+ return content.replace(/\n+$/, "\n");
172
+ }
173
+ //# sourceMappingURL=normalization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalization.js","sourceRoot":"","sources":["../../../src/utils/normalization.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,17 @@
1
1
  /**
2
- * projectRoot.ts — Project Root Discovery Utility
3
- *
4
- * Finds the root directory of a project by looking for common markers.
2
+ * Secure Project Root Detection
3
+ * Ensures all file operations are contained within project boundaries
5
4
  */
6
5
  /**
7
- * Find the project root by walking up from a file path.
8
- * Returns undefined if no root marker is found.
6
+ * Find project root by walking up from a file path
7
+ * Returns undefined if no root marker found
9
8
  */
10
9
  export declare function findProjectRoot(filePath: string): string | undefined;
10
+ /**
11
+ * Validate that a file path is within project boundaries
12
+ * MANDATORY for all write operations
13
+ */
14
+ export declare function enforceProjectBoundary(filePath: string, projectRoot: string): {
15
+ valid: boolean;
16
+ error?: string;
17
+ };
@@ -1,28 +1,13 @@
1
1
  /**
2
- * projectRoot.ts — Project Root Discovery Utility
3
- *
4
- * Finds the root directory of a project by looking for common markers.
2
+ * Secure Project Root Detection
3
+ * Ensures all file operations are contained within project boundaries
5
4
  */
6
5
  import * as fs from "node:fs";
7
6
  import * as path from "node:path";
8
- const ROOT_MARKERS = [
9
- "package.json",
10
- ".git",
11
- "pyproject.toml",
12
- "setup.py",
13
- "Cargo.toml",
14
- "go.mod",
15
- "pom.xml",
16
- "build.gradle",
17
- "CMakeLists.txt",
18
- ".gitignore",
19
- "Gemfile",
20
- "composer.json",
21
- "pubspec.yaml",
22
- ];
7
+ const ROOT_MARKERS = ["package.json", ".git", "pubspec.yaml", "pyproject.toml", "Cargo.toml"];
23
8
  /**
24
- * Find the project root by walking up from a file path.
25
- * Returns undefined if no root marker is found.
9
+ * Find project root by walking up from a file path
10
+ * Returns undefined if no root marker found
26
11
  */
27
12
  export function findProjectRoot(filePath) {
28
13
  let current = path.dirname(path.resolve(filePath));
@@ -37,4 +22,21 @@ export function findProjectRoot(filePath) {
37
22
  }
38
23
  return undefined;
39
24
  }
25
+ /**
26
+ * Validate that a file path is within project boundaries
27
+ * MANDATORY for all write operations
28
+ */
29
+ export function enforceProjectBoundary(filePath, projectRoot) {
30
+ const normalized = path.resolve(filePath);
31
+ const normalizedRoot = path.resolve(projectRoot);
32
+ const relative = path.relative(normalizedRoot, normalized);
33
+ // If relative path starts with .., it's outside the project root
34
+ if (relative.startsWith("..") || path.isAbsolute(relative)) {
35
+ return {
36
+ valid: false,
37
+ error: `Security: Path outside project root. File: ${normalized}, Root: ${normalizedRoot}`
38
+ };
39
+ }
40
+ return { valid: true };
41
+ }
40
42
  //# sourceMappingURL=projectRoot.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"projectRoot.js","sourceRoot":"","sources":["../../../src/utils/projectRoot.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,MAAM,YAAY,GAAG;IACnB,cAAc;IACd,MAAM;IACN,gBAAgB;IAChB,UAAU;IACV,YAAY;IACZ,QAAQ;IACR,SAAS;IACT,cAAc;IACd,gBAAgB;IAChB,YAAY;IACZ,SAAS;IACT,eAAe;IACf,cAAc;CACf,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IACnD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC;IAEtC,OAAO,OAAO,KAAK,IAAI,EAAE,CAAC;QACxB,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;YAClC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;gBAC9C,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;QACD,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
1
+ {"version":3,"file":"projectRoot.js","sourceRoot":"","sources":["../../../src/utils/projectRoot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,MAAM,YAAY,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,gBAAgB,EAAE,YAAY,CAAC,CAAC;AAE9F;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IACnD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC;IAEtC,OAAO,OAAO,KAAK,IAAI,EAAE,CAAC;QACxB,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;YAClC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;gBAC9C,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;QACD,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,QAAgB,EAChB,WAAmB;IAEnB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;IAE3D,iEAAiE;IACjE,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3D,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,8CAA8C,UAAU,WAAW,cAAc,EAAE;SAC3F,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzB,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Secure validation helper for write operations
3
+ * Enforces project boundary checks
4
+ */
5
+ export interface SecureValidationResult {
6
+ valid: boolean;
7
+ resolvedPath?: string;
8
+ projectRoot?: string;
9
+ error?: string;
10
+ }
11
+ /**
12
+ * Validate file path with mandatory project boundary enforcement
13
+ * Use this for ALL write operations
14
+ */
15
+ export declare function validateFilePathSecure(filePath: string): SecureValidationResult;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Secure validation helper for write operations
3
+ * Enforces project boundary checks
4
+ */
5
+ import { validateFilePath } from "./validation.js";
6
+ import { findProjectRoot, enforceProjectBoundary } from "./projectRoot.js";
7
+ /**
8
+ * Validate file path with mandatory project boundary enforcement
9
+ * Use this for ALL write operations
10
+ */
11
+ export function validateFilePathSecure(filePath) {
12
+ const validation = validateFilePath(filePath);
13
+ if (!validation.valid) {
14
+ return {
15
+ valid: false,
16
+ error: validation.error
17
+ };
18
+ }
19
+ const resolvedPath = validation.normalizedPath;
20
+ // SECURITY: Enforce project boundary for write operations
21
+ const projectRoot = findProjectRoot(resolvedPath);
22
+ if (!projectRoot) {
23
+ return {
24
+ valid: false,
25
+ error: "Cannot determine project root. Ensure file is within a valid project."
26
+ };
27
+ }
28
+ const boundaryCheck = enforceProjectBoundary(resolvedPath, projectRoot);
29
+ if (!boundaryCheck.valid) {
30
+ return {
31
+ valid: false,
32
+ error: boundaryCheck.error
33
+ };
34
+ }
35
+ return {
36
+ valid: true,
37
+ resolvedPath,
38
+ projectRoot
39
+ };
40
+ }
41
+ //# sourceMappingURL=secureValidation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secureValidation.js","sourceRoot":"","sources":["../../../src/utils/secureValidation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAS3E;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,QAAgB;IACrD,MAAM,UAAU,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,UAAU,CAAC,KAAK;SACxB,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,UAAU,CAAC,cAAe,CAAC;IAEhD,0DAA0D;IAC1D,MAAM,WAAW,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC;IAClD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,uEAAuE;SAC/E,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,sBAAsB,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IACxE,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QACzB,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,aAAa,CAAC,KAAK;SAC3B,CAAC;IACJ,CAAC;IAED,OAAO;QACL,KAAK,EAAE,IAAI;QACX,YAAY;QACZ,WAAW;KACZ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Transaction Manager - Atomic Multi-File Operations
3
+ * Ensures all-or-nothing writes with automatic rollback on failure
4
+ */
5
+ export interface FileChange {
6
+ filePath: string;
7
+ newContent: string;
8
+ }
9
+ export declare class TransactionManager {
10
+ private staging;
11
+ private backedUpFiles;
12
+ /**
13
+ * Stage a file change for commit
14
+ */
15
+ stage(filePath: string, newContent: string): void;
16
+ /**
17
+ * Stage multiple file changes
18
+ */
19
+ stageMultiple(changes: FileChange[]): void;
20
+ /**
21
+ * Commit all staged changes atomically
22
+ * Creates backups first, then writes all files
23
+ * Rolls back automatically on any failure
24
+ */
25
+ commit(): Promise<{
26
+ success: boolean;
27
+ error?: string;
28
+ }>;
29
+ /**
30
+ * Rollback all changes by restoring from backups
31
+ */
32
+ rollback(): Promise<void>;
33
+ /**
34
+ * Clear staging area and backup tracking
35
+ */
36
+ clear(): void;
37
+ /**
38
+ * Get number of staged changes
39
+ */
40
+ get stagedCount(): number;
41
+ /**
42
+ * Get list of staged file paths
43
+ */
44
+ getStagedFiles(): string[];
45
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Transaction Manager - Atomic Multi-File Operations
3
+ * Ensures all-or-nothing writes with automatic rollback on failure
4
+ */
5
+ import * as fs from "node:fs";
6
+ import * as path from "node:path";
7
+ import { createBackup, restoreBackup } from "./backupManager.js";
8
+ export class TransactionManager {
9
+ staging = new Map();
10
+ backedUpFiles = new Set();
11
+ /**
12
+ * Stage a file change for commit
13
+ */
14
+ stage(filePath, newContent) {
15
+ const resolved = path.resolve(filePath);
16
+ this.staging.set(resolved, newContent);
17
+ }
18
+ /**
19
+ * Stage multiple file changes
20
+ */
21
+ stageMultiple(changes) {
22
+ for (const change of changes) {
23
+ this.stage(change.filePath, change.newContent);
24
+ }
25
+ }
26
+ /**
27
+ * Commit all staged changes atomically
28
+ * Creates backups first, then writes all files
29
+ * Rolls back automatically on any failure
30
+ */
31
+ async commit() {
32
+ if (this.staging.size === 0) {
33
+ return { success: true };
34
+ }
35
+ // Phase 1: Create backups
36
+ try {
37
+ for (const [filePath] of this.staging) {
38
+ createBackup(filePath);
39
+ this.backedUpFiles.add(filePath);
40
+ }
41
+ }
42
+ catch (error) {
43
+ await this.rollback();
44
+ return {
45
+ success: false,
46
+ error: `Backup failed: ${error instanceof Error ? error.message : String(error)}`
47
+ };
48
+ }
49
+ // Phase 2: Write all files
50
+ try {
51
+ for (const [filePath, content] of this.staging) {
52
+ await fs.promises.writeFile(filePath, content, "utf-8");
53
+ }
54
+ }
55
+ catch (error) {
56
+ await this.rollback();
57
+ return {
58
+ success: false,
59
+ error: `Write failed: ${error instanceof Error ? error.message : String(error)}`
60
+ };
61
+ }
62
+ // Phase 3: Validate (optional syntax check could go here)
63
+ // For now, we trust the write succeeded
64
+ this.clear();
65
+ return { success: true };
66
+ }
67
+ /**
68
+ * Rollback all changes by restoring from backups
69
+ */
70
+ async rollback() {
71
+ for (const filePath of this.backedUpFiles) {
72
+ try {
73
+ restoreBackup(filePath);
74
+ }
75
+ catch (error) {
76
+ // Log but continue rolling back other files
77
+ console.error(`Failed to restore ${filePath}:`, error);
78
+ }
79
+ }
80
+ this.clear();
81
+ }
82
+ /**
83
+ * Clear staging area and backup tracking
84
+ */
85
+ clear() {
86
+ this.staging.clear();
87
+ this.backedUpFiles.clear();
88
+ }
89
+ /**
90
+ * Get number of staged changes
91
+ */
92
+ get stagedCount() {
93
+ return this.staging.size;
94
+ }
95
+ /**
96
+ * Get list of staged file paths
97
+ */
98
+ getStagedFiles() {
99
+ return Array.from(this.staging.keys());
100
+ }
101
+ }
102
+ //# sourceMappingURL=transactionManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transactionManager.js","sourceRoot":"","sources":["../../../src/utils/transactionManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * validation.ts — Input Validation & Security
3
+ *
4
+ * Centralized validation logic to prevent security vulnerabilities:
5
+ * - Path traversal attacks
6
+ * - ReDoS (Regular Expression Denial of Service)
7
+ * - Injection attacks
8
+ * - Resource exhaustion
9
+ */
10
+ export interface PathValidationResult {
11
+ valid: boolean;
12
+ error?: string;
13
+ normalizedPath?: string;
14
+ }
15
+ /**
16
+ * Validate that a file path is safe and within allowed boundaries.
17
+ * Prevents path traversal attacks and access to sensitive system files.
18
+ *
19
+ * @param filePath - The path to validate
20
+ * @param projectRoot - Optional project root to enforce containment
21
+ */
22
+ export declare function validateFilePath(filePath: string, projectRoot?: string): PathValidationResult;
23
+ /**
24
+ * Validate that a directory path is safe for operations.
25
+ */
26
+ export declare function validateDirectoryPath(dirPath: string, projectRoot?: string): PathValidationResult;
27
+ export interface SymbolValidationResult {
28
+ valid: boolean;
29
+ error?: string;
30
+ }
31
+ /**
32
+ * Validate a symbol name to prevent ReDoS and injection attacks.
33
+ *
34
+ * @param symbolName - The symbol name to validate
35
+ */
36
+ export declare function validateSymbolName(symbolName: string): SymbolValidationResult;
37
+ export interface RegexValidationResult {
38
+ valid: boolean;
39
+ error?: string;
40
+ safeRegex?: RegExp;
41
+ }
42
+ /**
43
+ * Validate and sanitize a regex pattern to prevent ReDoS attacks.
44
+ *
45
+ * @param pattern - The regex pattern to validate
46
+ * @param flags - Optional regex flags
47
+ */
48
+ export declare function validateRegexPattern(pattern: string, flags?: string): RegexValidationResult;
49
+ /**
50
+ * Create a safe regex with timeout protection.
51
+ * Uses a simple timeout mechanism to prevent long-running regex operations.
52
+ *
53
+ * @param pattern - The regex pattern
54
+ * @param flags - Optional regex flags
55
+ * @param timeoutMs - Timeout in milliseconds (default: 1000ms)
56
+ */
57
+ export declare function createSafeRegex(pattern: string, flags?: string, timeoutMs?: number): RegExp;
58
+ export interface FileSizeValidationResult {
59
+ valid: boolean;
60
+ error?: string;
61
+ size?: number;
62
+ }
63
+ /**
64
+ * Validate that a file is not too large to process safely.
65
+ *
66
+ * @param filePath - Path to the file
67
+ */
68
+ export declare function validateFileSize(filePath: string): FileSizeValidationResult;
69
+ /**
70
+ * Check if file content contains null bytes (likely binary).
71
+ */
72
+ export declare function isBinaryContent(content: string): boolean;
73
+ /**
74
+ * Validate that file content is safe to process.
75
+ */
76
+ export declare function validateFileContent(content: string): SymbolValidationResult;
77
+ /**
78
+ * Validate multiple file paths at once.
79
+ * Returns only valid paths and collects errors.
80
+ */
81
+ export declare function validateFilePaths(filePaths: string[], projectRoot?: string): {
82
+ validPaths: string[];
83
+ errors: Array<{
84
+ path: string;
85
+ error: string;
86
+ }>;
87
+ };