mcp-code-context 3.5.3 → 3.6.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 (79) hide show
  1. package/CHANGELOG.md +57 -3
  2. package/INSTRUCTIONS.md +274 -0
  3. package/README.md +59 -6
  4. package/SECURITY.md +14 -14
  5. package/dist/src/core/cacheManager.d.ts +44 -0
  6. package/dist/src/core/cacheManager.js +255 -0
  7. package/dist/src/core/cacheManager.js.map +1 -0
  8. package/dist/src/core/engine.d.ts +1 -1
  9. package/dist/src/core/engine.js +1 -1
  10. package/dist/src/core/validator.d.ts +1 -1
  11. package/dist/src/core/validator.js +19 -7
  12. package/dist/src/core/validator.js.map +1 -1
  13. package/dist/src/index.d.ts +6 -1
  14. package/dist/src/index.js +197 -20
  15. package/dist/src/index.js.map +1 -1
  16. package/dist/src/operations/compress.d.ts +3 -1
  17. package/dist/src/operations/compress.js +47 -48
  18. package/dist/src/operations/compress.js.map +1 -1
  19. package/dist/src/operations/confirmationStore.d.ts +1 -1
  20. package/dist/src/operations/confirmationStore.js +1 -1
  21. package/dist/src/operations/read.d.ts +5 -1
  22. package/dist/src/operations/read.js +125 -64
  23. package/dist/src/operations/read.js.map +1 -1
  24. package/dist/src/operations/write.d.ts +2 -2
  25. package/dist/src/operations/write.js +83 -59
  26. package/dist/src/operations/write.js.map +1 -1
  27. package/dist/src/parsers/base.d.ts +1 -1
  28. package/dist/src/parsers/base.js +1 -1
  29. package/dist/src/parsers/dartTreeSitter.d.ts +1 -1
  30. package/dist/src/parsers/dartTreeSitter.js +1 -1
  31. package/dist/src/parsers/php.d.ts +1 -1
  32. package/dist/src/parsers/php.js +1 -1
  33. package/dist/src/parsers/python.d.ts +1 -1
  34. package/dist/src/parsers/python.js +1 -1
  35. package/dist/src/parsers/registry.d.ts +1 -1
  36. package/dist/src/parsers/registry.js +1 -1
  37. package/dist/src/parsers/typescript.d.ts +1 -1
  38. package/dist/src/parsers/typescript.js +1 -1
  39. package/dist/src/utils/auditLogger.d.ts +1 -1
  40. package/dist/src/utils/auditLogger.js +3 -2
  41. package/dist/src/utils/auditLogger.js.map +1 -1
  42. package/dist/src/utils/backupManager.d.ts +30 -9
  43. package/dist/src/utils/backupManager.js +75 -33
  44. package/dist/src/utils/backupManager.js.map +1 -1
  45. package/dist/src/utils/constants.d.ts +13 -2
  46. package/dist/src/utils/constants.js +21 -2
  47. package/dist/src/utils/constants.js.map +1 -1
  48. package/dist/src/utils/diff.d.ts +37 -7
  49. package/dist/src/utils/diff.js +91 -101
  50. package/dist/src/utils/diff.js.map +1 -1
  51. package/dist/src/utils/fileLock.d.ts +25 -50
  52. package/dist/src/utils/fileLock.js +66 -100
  53. package/dist/src/utils/fileLock.js.map +1 -1
  54. package/dist/src/utils/fileWalker.d.ts +28 -0
  55. package/dist/src/utils/fileWalker.js +57 -0
  56. package/dist/src/utils/fileWalker.js.map +1 -0
  57. package/dist/src/utils/fileWatcher.d.ts +23 -0
  58. package/dist/src/utils/fileWatcher.js +80 -0
  59. package/dist/src/utils/fileWatcher.js.map +1 -0
  60. package/dist/src/utils/fuzzySearch.d.ts +22 -0
  61. package/dist/src/utils/fuzzySearch.js +36 -0
  62. package/dist/src/utils/fuzzySearch.js.map +1 -0
  63. package/dist/src/utils/logger.d.ts +19 -0
  64. package/dist/src/utils/logger.js +50 -0
  65. package/dist/src/utils/logger.js.map +1 -0
  66. package/dist/src/utils/rateLimiter.d.ts +1 -1
  67. package/dist/src/utils/rateLimiter.js +1 -1
  68. package/dist/src/utils/safeRegex.d.ts +1 -1
  69. package/dist/src/utils/safeRegex.js +1 -1
  70. package/dist/src/utils/searchTools.d.ts +14 -0
  71. package/dist/src/utils/searchTools.js +94 -0
  72. package/dist/src/utils/searchTools.js.map +1 -0
  73. package/dist/src/utils/streaming.d.ts +1 -1
  74. package/dist/src/utils/streaming.js +1 -1
  75. package/dist/src/utils/telemetry.d.ts +1 -1
  76. package/dist/src/utils/telemetry.js +1 -1
  77. package/llms.txt +5 -5
  78. package/package.json +28 -10
  79. package/vitest.config.ts +37 -0
@@ -1,18 +1,92 @@
1
1
  /**
2
- * Diff Engine - v3.5.3
3
- * LCS-based unified diff with memory safety cap
2
+ * Diff Utilities - v3.6.0
3
+ * Uses diff-match-patch for efficient diffing
4
4
  */
5
- const MAX_DIFF_LINES = 5000;
5
+ import DiffMatchPatch from 'diff-match-patch';
6
+ import { DIFF_MAX_FILE_LINES } from './constants.js';
7
+ const dmp = new DiffMatchPatch();
8
+ const COMPACT_DIFF_THRESHOLD = 2048;
6
9
  /**
7
- * Longest Common Subsequence algorithm
10
+ * Generates a unified diff using Myers algorithm.
11
+ * Falls back to simple diff for files exceeding line limit.
12
+ *
13
+ * @param oldText - Original file content
14
+ * @param newText - Modified file content
15
+ * @returns Unified diff in patch format
8
16
  */
9
- function lcs(a, b) {
10
- const m = a.length;
11
- const n = b.length;
12
- const dp = Array(m + 1).fill(0).map(() => Array(n + 1).fill(0));
17
+ export function generateUnifiedDiff(oldText, newText) {
18
+ const oldLines = oldText.split('\n');
19
+ const newLines = newText.split('\n');
20
+ if (oldLines.length > DIFF_MAX_FILE_LINES || newLines.length > DIFF_MAX_FILE_LINES) {
21
+ return generateSimpleDiff(oldText, newText);
22
+ }
23
+ const diffs = dmp.diff_main(oldText, newText);
24
+ dmp.diff_cleanupSemantic(diffs);
25
+ const patch = dmp.patch_make(oldText, diffs);
26
+ return dmp.patch_toText(patch);
27
+ }
28
+ /**
29
+ * Generates a simple diff summary for large files.
30
+ *
31
+ * @param oldText - Original file content
32
+ * @param newText - Modified file content
33
+ * @returns Simple line count summary
34
+ */
35
+ export function generateSimpleDiff(oldText, newText) {
36
+ const oldLines = oldText.split('\n');
37
+ const newLines = newText.split('\n');
38
+ return `File too large for detailed diff.
39
+ Old: ${oldLines.length} lines
40
+ New: ${newLines.length} lines
41
+ Changed: ${Math.abs(oldLines.length - newLines.length)} lines`;
42
+ }
43
+ /**
44
+ * Generates a compact diff showing only changes (no context).
45
+ *
46
+ * @param oldText - Original file content
47
+ * @param newText - Modified file content
48
+ * @returns Compact diff with + and - prefixes
49
+ */
50
+ export function generateCompactDiff(oldText, newText) {
51
+ const diffs = dmp.diff_main(oldText, newText);
52
+ dmp.diff_cleanupSemantic(diffs);
53
+ const compactLines = [];
54
+ for (const [op, text] of diffs) {
55
+ if (op === 0)
56
+ continue;
57
+ const prefix = op === 1 ? '+ ' : '- ';
58
+ const lines = text.split('\n').filter(line => line.trim().length > 0);
59
+ for (const line of lines) {
60
+ compactLines.push(prefix + line);
61
+ }
62
+ }
63
+ return compactLines.join('\n');
64
+ }
65
+ /**
66
+ * Automatically selects compact or full diff based on size.
67
+ *
68
+ * @param oldText - Original file content
69
+ * @param newText - Modified file content
70
+ * @returns Compact diff if full diff exceeds threshold, otherwise full diff
71
+ */
72
+ export function generateSmartDiff(oldText, newText) {
73
+ const fullDiff = generateUnifiedDiff(oldText, newText);
74
+ if (fullDiff.length > COMPACT_DIFF_THRESHOLD) {
75
+ return generateCompactDiff(oldText, newText);
76
+ }
77
+ return fullDiff;
78
+ }
79
+ export function lcs(lines1, lines2) {
80
+ const m = lines1.length;
81
+ const n = lines2.length;
82
+ if (m === 0 || n === 0)
83
+ return [];
84
+ if (m > DIFF_MAX_FILE_LINES || n > DIFF_MAX_FILE_LINES)
85
+ return [];
86
+ const dp = Array(m + 1).fill(null).map(() => Array(n + 1).fill(0));
13
87
  for (let i = 1; i <= m; i++) {
14
88
  for (let j = 1; j <= n; j++) {
15
- if (a[i - 1] === b[j - 1]) {
89
+ if (lines1[i - 1] === lines2[j - 1]) {
16
90
  dp[i][j] = dp[i - 1][j - 1] + 1;
17
91
  }
18
92
  else {
@@ -20,105 +94,21 @@ function lcs(a, b) {
20
94
  }
21
95
  }
22
96
  }
23
- return dp;
24
- }
25
- /**
26
- * Generate unified diff using LCS algorithm
27
- * Falls back to simple diff for large files to prevent OOM
28
- */
29
- export function generateUnifiedDiff(oldContent, newContent, contextLines = 3) {
30
- const oldLines = oldContent.split('\n');
31
- const newLines = newContent.split('\n');
32
- // SAFETY: Fall back to simple diff for large files (LCS is O(n*m) memory)
33
- if (oldLines.length > MAX_DIFF_LINES || newLines.length > MAX_DIFF_LINES) {
34
- return generateSimpleDiff(oldContent, newContent);
35
- }
36
- const dp = lcs(oldLines, newLines);
37
- const diff = [];
38
- // Backtrack to find differences
39
- let i = oldLines.length;
40
- let j = newLines.length;
41
- while (i > 0 || j > 0) {
42
- if (i > 0 && j > 0 && oldLines[i - 1] === newLines[j - 1]) {
43
- diff.unshift({ type: 'context', content: oldLines[i - 1], lineNumber: i });
97
+ const result = [];
98
+ let i = m, j = n;
99
+ while (i > 0 && j > 0) {
100
+ if (lines1[i - 1] === lines2[j - 1]) {
101
+ result.unshift(lines1[i - 1]);
44
102
  i--;
45
103
  j--;
46
104
  }
47
- else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
48
- diff.unshift({ type: 'add', content: newLines[j - 1], lineNumber: j });
49
- j--;
50
- }
51
- else if (i > 0 && (j === 0 || dp[i][j - 1] < dp[i - 1][j])) {
52
- diff.unshift({ type: 'remove', content: oldLines[i - 1], lineNumber: i });
105
+ else if (dp[i - 1][j] > dp[i][j - 1]) {
53
106
  i--;
54
107
  }
55
- }
56
- // Format output with context
57
- const output = [];
58
- let inHunk = false;
59
- let contextCount = 0;
60
- for (let idx = 0; idx < diff.length; idx++) {
61
- const line = diff[idx];
62
- if (line.type === 'context') {
63
- if (inHunk) {
64
- contextCount++;
65
- if (contextCount <= contextLines) {
66
- output.push(` ${line.content}`);
67
- }
68
- else {
69
- inHunk = false;
70
- contextCount = 0;
71
- }
72
- }
73
- else {
74
- // Check if change is coming
75
- const hasChangeAhead = diff.slice(idx, idx + contextLines + 1)
76
- .some(l => l.type !== 'context');
77
- if (hasChangeAhead) {
78
- output.push(` ${line.content}`);
79
- }
80
- }
81
- }
82
- else {
83
- if (!inHunk) {
84
- // Add context before change
85
- const contextBefore = diff.slice(Math.max(0, idx - contextLines), idx)
86
- .filter(l => l.type === 'context');
87
- contextBefore.forEach(l => output.push(` ${l.content}`));
88
- }
89
- inHunk = true;
90
- contextCount = 0;
91
- if (line.type === 'add') {
92
- output.push(`+ ${line.content}`);
93
- }
94
- else {
95
- output.push(`- ${line.content}`);
96
- }
97
- }
98
- }
99
- return output.join('\n');
100
- }
101
- /**
102
- * Simple line-by-line diff (O(n) memory fallback for large files)
103
- */
104
- export function generateSimpleDiff(oldContent, newContent) {
105
- const oldLines = oldContent.split('\n');
106
- const newLines = newContent.split('\n');
107
- const diff = [];
108
- const maxLen = Math.max(oldLines.length, newLines.length);
109
- for (let i = 0; i < maxLen; i++) {
110
- const oldLine = oldLines[i];
111
- const newLine = newLines[i];
112
- if (oldLine === newLine) {
113
- diff.push(` ${oldLine || ''}`);
114
- }
115
108
  else {
116
- if (oldLine !== undefined)
117
- diff.push(`- ${oldLine}`);
118
- if (newLine !== undefined)
119
- diff.push(`+ ${newLine}`);
109
+ j--;
120
110
  }
121
111
  }
122
- return diff.join('\n');
112
+ return result;
123
113
  }
124
114
  //# sourceMappingURL=diff.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../../src/utils/diff.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../../src/utils/diff.ts"],"names":[],"mappings":"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"}
@@ -1,63 +1,38 @@
1
1
  /**
2
- * File Lock Manager - v3.5.3
3
- * Prevents concurrent writes to same file
2
+ * File Lock Manager - v3.6.0
3
+ * Filesystem-based locks for multi-process safety
4
+ */
5
+ /**
6
+ * Manages filesystem-based locks for multi-process safety.
7
+ * Locks are stored in OS temp directory to prevent conflicts.
4
8
  */
5
- interface LockInfo {
6
- clientId: string;
7
- operation: string;
8
- timestamp: number;
9
- timeout: NodeJS.Timeout;
10
- }
11
9
  export declare class FileLockManager {
12
- private locks;
13
- private readonly lockTimeout;
14
- constructor(lockTimeoutMs?: number);
15
- /**
16
- * Acquire lock on file
17
- */
18
- acquireLock(filePath: string, clientId: string, operation: string): Promise<{
19
- acquired: boolean;
20
- error?: string;
21
- lockedBy?: string;
22
- }>;
23
- /**
24
- * Release lock on file
25
- */
26
- releaseLock(filePath: string, clientId: string): boolean;
10
+ private lockDir;
11
+ private activeLocks;
27
12
  /**
28
- * Check if file is locked
13
+ * Creates a new FileLockManager instance.
14
+ * Initializes lock directory in OS temp with project-specific hash.
29
15
  */
30
- isLocked(filePath: string): boolean;
16
+ constructor();
31
17
  /**
32
- * Get lock info
18
+ * Acquires an exclusive lock on a file.
19
+ *
20
+ * @param filePath - Absolute path to file to lock
21
+ * @param timeoutMs - Stale lock timeout in milliseconds (default: 30000)
22
+ * @returns Release function to unlock the file
23
+ * @throws Error if lock cannot be acquired after retries
33
24
  */
34
- getLockInfo(filePath: string): LockInfo | null;
25
+ acquireLock(filePath: string, timeoutMs?: number): Promise<() => Promise<void>>;
35
26
  /**
36
- * Force release lock (admin only)
27
+ * Checks if a file is currently locked.
28
+ *
29
+ * @param filePath - Absolute path to file
30
+ * @returns True if file is locked, false otherwise
37
31
  */
38
- forceRelease(filePath: string): boolean;
32
+ isLocked(filePath: string): Promise<boolean>;
39
33
  /**
40
- * Release all locks for client
34
+ * Releases all active locks managed by this instance.
41
35
  */
42
- releaseAllForClient(clientId: string): number;
43
- /**
44
- * Get all active locks
45
- */
46
- getActiveLocks(): Array<{
47
- path: string;
48
- info: LockInfo;
49
- }>;
50
- /**
51
- * Clear all locks
52
- */
53
- clearAll(): void;
54
- /**
55
- * Normalize path for consistent comparison
56
- */
57
- private normalizePath;
36
+ releaseAll(): Promise<void>;
58
37
  }
59
- /**
60
- * Global lock manager instance
61
- */
62
38
  export declare const globalLockManager: FileLockManager;
63
- export {};
@@ -1,123 +1,89 @@
1
1
  /**
2
- * File Lock Manager - v3.5.3
3
- * Prevents concurrent writes to same file
2
+ * File Lock Manager - v3.6.0
3
+ * Filesystem-based locks for multi-process safety
4
+ */
5
+ import lockfile from 'proper-lockfile';
6
+ import { tmpdir } from 'os';
7
+ import { mkdirSync, existsSync } from 'fs';
8
+ import path from 'path';
9
+ import crypto from 'crypto';
10
+ import { LOCK_TIMEOUT_MS, LOCK_RETRY_COUNT, LOCK_RETRY_MIN_MS, LOCK_RETRY_MAX_MS, LOCK_RETRY_FACTOR, HASH_LENGTH } from './constants.js';
11
+ /**
12
+ * Manages filesystem-based locks for multi-process safety.
13
+ * Locks are stored in OS temp directory to prevent conflicts.
4
14
  */
5
15
  export class FileLockManager {
6
- locks = new Map();
7
- lockTimeout;
8
- constructor(lockTimeoutMs = 30000) {
9
- this.lockTimeout = lockTimeoutMs;
10
- }
16
+ lockDir;
17
+ activeLocks = new Map();
11
18
  /**
12
- * Acquire lock on file
19
+ * Creates a new FileLockManager instance.
20
+ * Initializes lock directory in OS temp with project-specific hash.
13
21
  */
14
- async acquireLock(filePath, clientId, operation) {
15
- const normalizedPath = this.normalizePath(filePath);
16
- const existingLock = this.locks.get(normalizedPath);
17
- if (existingLock) {
18
- return {
19
- acquired: false,
20
- error: `File locked by ${existingLock.operation} (client: ${existingLock.clientId})`,
21
- lockedBy: existingLock.clientId,
22
- };
22
+ constructor() {
23
+ const projectHash = crypto.createHash('md5')
24
+ .update(process.cwd())
25
+ .digest('hex')
26
+ .substring(0, HASH_LENGTH);
27
+ this.lockDir = path.join(tmpdir(), `mcp-locks-${projectHash}`);
28
+ if (!existsSync(this.lockDir)) {
29
+ mkdirSync(this.lockDir, { recursive: true });
23
30
  }
24
- // Create lock with auto-release timeout
25
- const timeout = setTimeout(() => {
26
- this.releaseLock(filePath, clientId);
27
- console.warn(`⚠️ Lock auto-released for ${normalizedPath} (timeout)`);
28
- }, this.lockTimeout);
29
- this.locks.set(normalizedPath, {
30
- clientId,
31
- operation,
32
- timestamp: Date.now(),
33
- timeout,
34
- });
35
- return { acquired: true };
36
31
  }
37
32
  /**
38
- * Release lock on file
33
+ * Acquires an exclusive lock on a file.
34
+ *
35
+ * @param filePath - Absolute path to file to lock
36
+ * @param timeoutMs - Stale lock timeout in milliseconds (default: 30000)
37
+ * @returns Release function to unlock the file
38
+ * @throws Error if lock cannot be acquired after retries
39
39
  */
40
- releaseLock(filePath, clientId) {
41
- const normalizedPath = this.normalizePath(filePath);
42
- const lock = this.locks.get(normalizedPath);
43
- if (!lock) {
44
- return false; // No lock exists
40
+ async acquireLock(filePath, timeoutMs = LOCK_TIMEOUT_MS) {
41
+ const normalizedPath = path.resolve(filePath);
42
+ try {
43
+ const release = await lockfile.lock(normalizedPath, {
44
+ stale: timeoutMs,
45
+ retries: {
46
+ retries: LOCK_RETRY_COUNT,
47
+ minTimeout: LOCK_RETRY_MIN_MS,
48
+ maxTimeout: LOCK_RETRY_MAX_MS,
49
+ factor: LOCK_RETRY_FACTOR
50
+ },
51
+ lockfilePath: path.join(this.lockDir, `${crypto.createHash('md5').update(normalizedPath).digest('hex')}.lock`)
52
+ });
53
+ this.activeLocks.set(normalizedPath, release);
54
+ return async () => {
55
+ await release();
56
+ this.activeLocks.delete(normalizedPath);
57
+ };
45
58
  }
46
- if (lock.clientId !== clientId) {
47
- return false; // Lock owned by different client
59
+ catch (error) {
60
+ throw new Error(`Failed to acquire lock for "${filePath}": ${error.message || String(error)}`);
48
61
  }
49
- clearTimeout(lock.timeout);
50
- this.locks.delete(normalizedPath);
51
- return true;
52
- }
53
- /**
54
- * Check if file is locked
55
- */
56
- isLocked(filePath) {
57
- const normalizedPath = this.normalizePath(filePath);
58
- return this.locks.has(normalizedPath);
59
- }
60
- /**
61
- * Get lock info
62
- */
63
- getLockInfo(filePath) {
64
- const normalizedPath = this.normalizePath(filePath);
65
- return this.locks.get(normalizedPath) || null;
66
62
  }
67
63
  /**
68
- * Force release lock (admin only)
64
+ * Checks if a file is currently locked.
65
+ *
66
+ * @param filePath - Absolute path to file
67
+ * @returns True if file is locked, false otherwise
69
68
  */
70
- forceRelease(filePath) {
71
- const normalizedPath = this.normalizePath(filePath);
72
- const lock = this.locks.get(normalizedPath);
73
- if (lock) {
74
- clearTimeout(lock.timeout);
75
- this.locks.delete(normalizedPath);
76
- return true;
69
+ async isLocked(filePath) {
70
+ const normalizedPath = path.resolve(filePath);
71
+ try {
72
+ const lockfilePath = path.join(this.lockDir, `${crypto.createHash('md5').update(normalizedPath).digest('hex')}.lock`);
73
+ return await lockfile.check(normalizedPath, { lockfilePath });
77
74
  }
78
- return false;
79
- }
80
- /**
81
- * Release all locks for client
82
- */
83
- releaseAllForClient(clientId) {
84
- let count = 0;
85
- for (const [path, lock] of this.locks.entries()) {
86
- if (lock.clientId === clientId) {
87
- clearTimeout(lock.timeout);
88
- this.locks.delete(path);
89
- count++;
90
- }
75
+ catch {
76
+ return false;
91
77
  }
92
- return count;
93
- }
94
- /**
95
- * Get all active locks
96
- */
97
- getActiveLocks() {
98
- return Array.from(this.locks.entries()).map(([path, info]) => ({
99
- path,
100
- info,
101
- }));
102
78
  }
103
79
  /**
104
- * Clear all locks
80
+ * Releases all active locks managed by this instance.
105
81
  */
106
- clearAll() {
107
- for (const lock of this.locks.values()) {
108
- clearTimeout(lock.timeout);
109
- }
110
- this.locks.clear();
111
- }
112
- /**
113
- * Normalize path for consistent comparison
114
- */
115
- normalizePath(filePath) {
116
- return filePath.replace(/\\/g, '/').toLowerCase();
82
+ async releaseAll() {
83
+ const releases = Array.from(this.activeLocks.values());
84
+ await Promise.all(releases.map(release => release()));
85
+ this.activeLocks.clear();
117
86
  }
118
87
  }
119
- /**
120
- * Global lock manager instance
121
- */
122
88
  export const globalLockManager = new FileLockManager();
123
89
  //# sourceMappingURL=fileLock.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fileLock.js","sourceRoot":"","sources":["../../../src/utils/fileLock.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,MAAM,OAAO,eAAe;IAClB,KAAK,GAA0B,IAAI,GAAG,EAAE,CAAC;IAChC,WAAW,CAAS;IAErC,YAAY,gBAAwB,KAAK;QACvC,IAAI,CAAC,WAAW,GAAG,aAAa,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CACf,QAAgB,EAChB,QAAgB,EAChB,SAAiB;QAEjB,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACpD,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAEpD,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO;gBACL,QAAQ,EAAE,KAAK;gBACf,KAAK,EAAE,kBAAkB,YAAY,CAAC,SAAS,aAAa,YAAY,CAAC,QAAQ,GAAG;gBACpF,QAAQ,EAAE,YAAY,CAAC,QAAQ;aAChC,CAAC;QACJ,CAAC;QAED,wCAAwC;QACxC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACrC,OAAO,CAAC,IAAI,CAAC,8BAA8B,cAAc,YAAY,CAAC,CAAC;QACzE,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAErB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,EAAE;YAC7B,QAAQ;YACR,SAAS;YACT,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,OAAO;SACR,CAAC,CAAC;QAEH,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,QAAgB,EAAE,QAAgB;QAC5C,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAE5C,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,KAAK,CAAC,CAAC,iBAAiB;QACjC,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC/B,OAAO,KAAK,CAAC,CAAC,iCAAiC;QACjD,CAAC;QAED,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,QAAgB;QACvB,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACxC,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,QAAgB;QAC1B,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,IAAI,CAAC;IAChD,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,QAAgB;QAC3B,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAE5C,IAAI,IAAI,EAAE,CAAC;YACT,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC3B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;YAClC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,mBAAmB,CAAC,QAAgB;QAClC,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YAChD,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBAC/B,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC3B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACxB,KAAK,EAAE,CAAC;YACV,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;YAC7D,IAAI;YACJ,IAAI;SACL,CAAC,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YACvC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED;;OAEG;IACK,aAAa,CAAC,QAAgB;QACpC,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IACpD,CAAC;CACF;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"fileLock.js","sourceRoot":"","sources":["../../../src/utils/fileLock.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * File Walker Utility - v3.6.0
3
+ * Centralized directory traversal with filtering
4
+ */
5
+ export interface WalkOptions {
6
+ /** Extensions to include (e.g., [".ts", ".js"]) */
7
+ extensions?: readonly string[];
8
+ /** Directories to exclude (e.g., ["node_modules", ".git"]) */
9
+ excludeDirs?: readonly string[];
10
+ /** Maximum files to collect (prevents OOM) */
11
+ maxFiles?: number;
12
+ /** Maximum total size in bytes (prevents OOM) */
13
+ maxSize?: number;
14
+ /** Callback for each file found */
15
+ onFile?: (filePath: string) => Promise<void> | void;
16
+ }
17
+ /**
18
+ * Recursively walks a directory tree with filtering options.
19
+ * Supports extension filtering, directory exclusion, and size/count limits.
20
+ *
21
+ * @param dir - Root directory to walk
22
+ * @param options - Filtering and callback options
23
+ * @param state - Internal state for tracking counts (do not pass manually)
24
+ */
25
+ export declare function walkDir(dir: string, options?: WalkOptions, state?: {
26
+ fileCount: number;
27
+ totalSize: number;
28
+ }): Promise<void>;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * File Walker Utility - v3.6.0
3
+ * Centralized directory traversal with filtering
4
+ */
5
+ import * as fs from "node:fs/promises";
6
+ import * as path from "node:path";
7
+ /**
8
+ * Recursively walks a directory tree with filtering options.
9
+ * Supports extension filtering, directory exclusion, and size/count limits.
10
+ *
11
+ * @param dir - Root directory to walk
12
+ * @param options - Filtering and callback options
13
+ * @param state - Internal state for tracking counts (do not pass manually)
14
+ */
15
+ export async function walkDir(dir, options = {}, state = { fileCount: 0, totalSize: 0 }) {
16
+ // Check limits
17
+ if (options.maxFiles && state.fileCount >= options.maxFiles)
18
+ return;
19
+ if (options.maxSize && state.totalSize >= options.maxSize)
20
+ return;
21
+ const entries = await fs.readdir(dir, { withFileTypes: true });
22
+ for (const entry of entries) {
23
+ // Check limits again in loop
24
+ if (options.maxFiles && state.fileCount >= options.maxFiles)
25
+ break;
26
+ if (options.maxSize && state.totalSize >= options.maxSize)
27
+ break;
28
+ const fullPath = path.join(dir, entry.name);
29
+ if (entry.isDirectory()) {
30
+ // Recurse if not excluded
31
+ if (!options.excludeDirs || !options.excludeDirs.includes(entry.name)) {
32
+ await walkDir(fullPath, options, state);
33
+ }
34
+ }
35
+ else if (entry.isFile()) {
36
+ // Check extension filter
37
+ if (options.extensions) {
38
+ const ext = path.extname(entry.name);
39
+ if (!options.extensions.includes(ext))
40
+ continue;
41
+ }
42
+ // Update size tracking
43
+ if (options.maxSize) {
44
+ const stat = await fs.stat(fullPath);
45
+ if (state.totalSize + stat.size > options.maxSize)
46
+ break;
47
+ state.totalSize += stat.size;
48
+ }
49
+ // Increment count and invoke callback
50
+ state.fileCount++;
51
+ if (options.onFile) {
52
+ await options.onFile(fullPath);
53
+ }
54
+ }
55
+ }
56
+ }
57
+ //# sourceMappingURL=fileWalker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileWalker.js","sourceRoot":"","sources":["../../../src/utils/fileWalker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAelC;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,GAAW,EACX,UAAuB,EAAE,EACzB,QAAkD,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE;IAEhF,eAAe;IACf,IAAI,OAAO,CAAC,QAAQ,IAAI,KAAK,CAAC,SAAS,IAAI,OAAO,CAAC,QAAQ;QAAE,OAAO;IACpE,IAAI,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC,SAAS,IAAI,OAAO,CAAC,OAAO;QAAE,OAAO;IAElE,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAE/D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,6BAA6B;QAC7B,IAAI,OAAO,CAAC,QAAQ,IAAI,KAAK,CAAC,SAAS,IAAI,OAAO,CAAC,QAAQ;YAAE,MAAM;QACnE,IAAI,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC,SAAS,IAAI,OAAO,CAAC,OAAO;YAAE,MAAM;QAEjE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAE5C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,0BAA0B;YAC1B,IAAI,CAAC,OAAO,CAAC,WAAW,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtE,MAAM,OAAO,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1B,yBAAyB;YACzB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;gBACvB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACrC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC;oBAAE,SAAS;YAClD,CAAC;YAED,uBAAuB;YACvB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACpB,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACrC,IAAI,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,OAAO;oBAAE,MAAM;gBACzD,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC,IAAI,CAAC;YAC/B,CAAC;YAED,sCAAsC;YACtC,KAAK,CAAC,SAAS,EAAE,CAAC;YAClB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACnB,MAAM,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}