thuban 0.3.2 → 0.3.3

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.
@@ -0,0 +1,64 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ function collectFiles(dir, ignorePatterns = []) {
5
+ const defaultIgnore = ['node_modules', '.git', 'dist', 'build', '.next', '__pycache__', '.venv', 'venv', 'coverage', '.cache', '.turbo'];
6
+ const allIgnore = [...defaultIgnore, ...ignorePatterns];
7
+ const extensions = ['.js', '.ts', '.jsx', '.tsx', '.mjs', '.cjs', '.py', '.pyw', '.go', '.rs', '.java', '.kt', '.cs', '.php', '.rb', '.json'];
8
+ const maxFileSize = 1024 * 1024;
9
+ const maxFiles = 50000;
10
+ const files = [];
11
+ const visitedPaths = new Set(); // Track real paths to handle symlinks
12
+
13
+ function walk(currentDir) {
14
+ if (files.length >= maxFiles) return;
15
+ let entries;
16
+ try {
17
+ entries = fs.readdirSync(currentDir, { withFileTypes: true });
18
+ } catch (error) {
19
+ return;
20
+ }
21
+
22
+ for (const entry of entries) {
23
+ if (files.length >= maxFiles) return;
24
+ if (allIgnore.some(pattern => entry.name === pattern || entry.name.match(pattern))) continue;
25
+ const fullPath = path.join(currentDir, entry.name);
26
+
27
+ // Handle symlinks — resolve and skip if already visited or points outside
28
+ if (entry.isSymbolicLink()) {
29
+ try {
30
+ const realPath = fs.realpathSync(fullPath);
31
+ if (visitedPaths.has(realPath)) continue;
32
+ visitedPaths.add(realPath);
33
+ const stat = fs.statSync(fullPath); // follow symlink
34
+ if (stat.isDirectory()) {
35
+ walk(fullPath);
36
+ } else if (stat.isFile() && extensions.some(ext => entry.name.endsWith(ext))) {
37
+ if (stat.size > 0 && stat.size <= maxFileSize) files.push(fullPath);
38
+ }
39
+ } catch {
40
+ continue; // Broken symlink — skip
41
+ }
42
+ continue;
43
+ }
44
+
45
+ if (entry.isDirectory()) {
46
+ walk(fullPath);
47
+ } else if (entry.isFile() && extensions.some(ext => entry.name.endsWith(ext))) {
48
+ try {
49
+ const stat = fs.statSync(fullPath);
50
+ if (stat.size > 0 && stat.size <= maxFileSize) files.push(fullPath);
51
+ } catch (error) {
52
+ // Skip files we can't stat
53
+ }
54
+ }
55
+ }
56
+ }
57
+
58
+ walk(dir);
59
+ return files;
60
+ }
61
+
62
+ module.exports = {
63
+ collectFiles,
64
+ };