arcvision 0.2.12 โ†’ 0.2.15

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 (134) hide show
  1. package/ARCVISION_DIRECTORY_STRUCTURE.md +104 -0
  2. package/CLI_STRUCTURE.md +110 -0
  3. package/CONFIGURATION.md +119 -0
  4. package/IMPLEMENTATION_SUMMARY.md +99 -0
  5. package/README.md +149 -89
  6. package/architecture.authority.ledger.json +46 -0
  7. package/arcvision-0.2.3.tgz +0 -0
  8. package/arcvision-0.2.4.tgz +0 -0
  9. package/arcvision-0.2.5.tgz +0 -0
  10. package/arcvision.context.diff.json +2181 -0
  11. package/arcvision.context.json +1021 -0
  12. package/arcvision.context.v1.json +2163 -0
  13. package/arcvision.context.v2.json +2173 -0
  14. package/arcvision_context/README.md +93 -0
  15. package/arcvision_context/architecture.authority.ledger.json +83 -0
  16. package/arcvision_context/arcvision.context.json +6884 -0
  17. package/debug-cycle-detection.js +56 -0
  18. package/dist/index.js +1626 -25
  19. package/docs/ENHANCED_ACCURACY_SAFETY_PROTOCOL.md +172 -0
  20. package/docs/accuracy-enhancement-artifacts/enhanced-validation-config.json +98 -0
  21. package/docs/acig-robustness-guide.md +164 -0
  22. package/docs/authoritative-gate-implementation.md +168 -0
  23. package/docs/cli-strengthening-summary.md +232 -0
  24. package/docs/invariant-system-summary.md +100 -0
  25. package/docs/invariant-system.md +112 -0
  26. package/generate_large_test.js +42 -0
  27. package/large_test_repo.json +1 -0
  28. package/output1.json +2163 -0
  29. package/output2.json +2163 -0
  30. package/package.json +46 -36
  31. package/scan_calcom_report.txt +0 -0
  32. package/scan_leafmint_report.txt +0 -0
  33. package/scan_output.txt +0 -0
  34. package/scan_trigger_report.txt +0 -0
  35. package/schema/arcvision_context_schema_v1.json +136 -1
  36. package/src/arcvision-guard.js +433 -0
  37. package/src/core/authority-core-detector.js +382 -0
  38. package/src/core/authority-ledger.js +300 -0
  39. package/src/core/blastRadius.js +299 -0
  40. package/src/core/call-resolver.js +196 -0
  41. package/src/core/change-evaluator.js +509 -0
  42. package/src/core/change-evaluator.js.backup +424 -0
  43. package/src/core/change-evaluator.ts +285 -0
  44. package/src/core/chunked-uploader.js +180 -0
  45. package/src/core/circular-dependency-detector.js +404 -0
  46. package/src/core/cli-error-handler.js +458 -0
  47. package/src/core/cli-validator.js +458 -0
  48. package/src/core/compression.js +64 -0
  49. package/src/core/context_builder.js +741 -0
  50. package/src/core/dependency-manager.js +134 -0
  51. package/src/core/di-detector.js +202 -0
  52. package/src/core/diff-analyzer.js +76 -0
  53. package/src/core/example-invariants.js +135 -0
  54. package/src/core/failure-mode-synthesizer.js +341 -0
  55. package/src/core/invariant-analyzer.js +294 -0
  56. package/src/core/invariant-detector.js +548 -0
  57. package/src/core/invariant-enforcer.js +171 -0
  58. package/src/core/invariant-evaluation-utils.js +172 -0
  59. package/src/core/invariant-hooks.js +152 -0
  60. package/src/core/invariant-integration-example.js +186 -0
  61. package/src/core/invariant-registry.js +298 -0
  62. package/src/core/invariant-registry.ts +100 -0
  63. package/src/core/invariant-types.js +66 -0
  64. package/src/core/invariants-index.js +88 -0
  65. package/src/core/method-tracker.js +170 -0
  66. package/src/core/override-handler.js +304 -0
  67. package/src/core/ownership-resolver.js +227 -0
  68. package/src/core/parser-enhanced.js +80 -0
  69. package/src/core/parser.js +610 -0
  70. package/src/core/path-resolver.js +240 -0
  71. package/src/core/pattern-matcher.js +246 -0
  72. package/src/core/progress-tracker.js +71 -0
  73. package/src/core/react-nextjs-detector.js +245 -0
  74. package/src/core/readme-generator.js +167 -0
  75. package/src/core/retry-handler.js +57 -0
  76. package/src/core/scanner.js +289 -0
  77. package/src/core/semantic-analyzer.js +204 -0
  78. package/src/core/structural-context-owner.js +442 -0
  79. package/src/core/symbol-indexer.js +164 -0
  80. package/src/core/tsconfig-utils.js +73 -0
  81. package/src/core/type-analyzer.js +272 -0
  82. package/src/core/watcher.js +18 -0
  83. package/src/core/workspace-scanner.js +88 -0
  84. package/src/engine/context_builder.js +280 -0
  85. package/src/engine/context_sorter.js +59 -0
  86. package/src/engine/context_validator.js +200 -0
  87. package/src/engine/id-generator.js +16 -0
  88. package/src/engine/pass1_facts.js +260 -0
  89. package/src/engine/pass2_semantics.js +333 -0
  90. package/src/engine/pass3_lifter.js +99 -0
  91. package/src/engine/pass4_signals.js +201 -0
  92. package/src/index.js +830 -0
  93. package/src/plugins/express-plugin.js +48 -0
  94. package/src/plugins/plugin-manager.js +58 -0
  95. package/src/plugins/react-plugin.js +54 -0
  96. package/temp_original.js +0 -0
  97. package/test/determinism-test.js +83 -0
  98. package/test-authoritative-context.js +53 -0
  99. package/test-real-authoritative-context.js +118 -0
  100. package/test-upload-enhancements.js +111 -0
  101. package/test_repos/allowed-clean-architecture/.arcvision/invariants.json +57 -0
  102. package/test_repos/allowed-clean-architecture/adapters/controllers/UserController.js +95 -0
  103. package/test_repos/allowed-clean-architecture/adapters/http/HttpServer.js +78 -0
  104. package/test_repos/allowed-clean-architecture/application/dtos/CreateUserRequest.js +37 -0
  105. package/test_repos/allowed-clean-architecture/application/services/UserService.js +61 -0
  106. package/test_repos/allowed-clean-architecture/arcvision_context/README.md +93 -0
  107. package/test_repos/allowed-clean-architecture/arcvision_context/arcvision.context.json +2796 -0
  108. package/test_repos/allowed-clean-architecture/domain/interfaces/UserRepository.js +25 -0
  109. package/test_repos/allowed-clean-architecture/domain/models/User.js +39 -0
  110. package/test_repos/allowed-clean-architecture/index.js +45 -0
  111. package/test_repos/allowed-clean-architecture/infrastructure/database/DatabaseConnection.js +56 -0
  112. package/test_repos/allowed-clean-architecture/infrastructure/repositories/InMemoryUserRepository.js +61 -0
  113. package/test_repos/allowed-clean-architecture/package.json +15 -0
  114. package/test_repos/blocked-legacy-monolith/.arcvision/invariants.json +78 -0
  115. package/test_repos/blocked-legacy-monolith/arcvision_context/README.md +93 -0
  116. package/test_repos/blocked-legacy-monolith/arcvision_context/arcvision.context.json +2882 -0
  117. package/test_repos/blocked-legacy-monolith/database/dbConnection.js +35 -0
  118. package/test_repos/blocked-legacy-monolith/index.js +38 -0
  119. package/test_repos/blocked-legacy-monolith/modules/emailService.js +31 -0
  120. package/test_repos/blocked-legacy-monolith/modules/paymentProcessor.js +37 -0
  121. package/test_repos/blocked-legacy-monolith/package.json +15 -0
  122. package/test_repos/blocked-legacy-monolith/shared/utils.js +19 -0
  123. package/test_repos/blocked-legacy-monolith/utils/helpers.js +23 -0
  124. package/test_repos/risky-microservices-concerns/.arcvision/invariants.json +69 -0
  125. package/test_repos/risky-microservices-concerns/arcvision_context/README.md +93 -0
  126. package/test_repos/risky-microservices-concerns/arcvision_context/arcvision.context.json +3070 -0
  127. package/test_repos/risky-microservices-concerns/common/utils.js +77 -0
  128. package/test_repos/risky-microservices-concerns/gateways/apiGateway.js +84 -0
  129. package/test_repos/risky-microservices-concerns/index.js +20 -0
  130. package/test_repos/risky-microservices-concerns/libs/deprecatedHelper.js +36 -0
  131. package/test_repos/risky-microservices-concerns/package.json +15 -0
  132. package/test_repos/risky-microservices-concerns/services/orderService.js +42 -0
  133. package/test_repos/risky-microservices-concerns/services/userService.js +48 -0
  134. package/verify_engine.js +116 -0
@@ -0,0 +1,240 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ /**
5
+ * Resolve an import path to its actual file location
6
+ * Handles relative paths, path aliases, workspace packages, and node_modules
7
+ * @param {string} importPath - The import path from the source code
8
+ * @param {string} importerPath - The path of the file doing the import
9
+ * @param {string} projectRoot - The root directory of the project
10
+ * @param {Object|null} tsconfig - Loaded tsconfig with compilerOptions
11
+ * @param {Map<string, string>|null} workspaceMap - Map of package names to their roots
12
+ * @param {Set<string>|null} fileSet - Cached set of all absolute file paths
13
+ * @returns {string|null} The resolved absolute file path or null if not found
14
+ */
15
+ function resolveImport(importPath, importerPath, projectRoot, tsconfig, workspaceMap, fileSet) {
16
+ // If it's an absolute path or URL, skip resolution
17
+ if (importPath.startsWith('http://') || importPath.startsWith('https://') ||
18
+ importPath.startsWith('data:') || importPath.startsWith('file:')) {
19
+ return null;
20
+ }
21
+
22
+ const exists = (p) => {
23
+ if (fileSet) return fileSet.has(p);
24
+ return fs.existsSync(p);
25
+ };
26
+
27
+ // Handle relative imports
28
+ if (importPath.startsWith('.')) {
29
+ // Resolve relative to importer
30
+ let resolvedPath = path.resolve(path.dirname(importerPath), importPath);
31
+
32
+ // Try with various extensions in order of preference
33
+ const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.json'];
34
+ for (const ext of extensions) {
35
+ if (exists(resolvedPath + ext)) {
36
+ return resolvedPath + ext;
37
+ }
38
+ }
39
+
40
+ // Try as directory with index files
41
+ const indexFiles = ['index.ts', 'index.tsx', 'index.js', 'index.jsx', 'index.json'];
42
+ for (const idxFile of indexFiles) {
43
+ const indexPath = path.join(resolvedPath, idxFile);
44
+ if (exists(indexPath)) {
45
+ return indexPath;
46
+ }
47
+ }
48
+
49
+ // If original path exists as-is
50
+ if (exists(resolvedPath)) {
51
+ return resolvedPath;
52
+ }
53
+
54
+ return null;
55
+ }
56
+
57
+ // Handle path aliases (like @/components/, ~/utils/, etc.)
58
+ if (tsconfig && tsconfig.paths) {
59
+ const paths = tsconfig.paths;
60
+
61
+ // Sort aliases by length (descending) to match longer patterns first
62
+ const sortedAliases = Object.keys(paths).sort((a, b) => b.length - a.length);
63
+
64
+ for (const aliasPattern of sortedAliases) {
65
+ const aliasTargets = paths[aliasPattern];
66
+
67
+ // Handle pattern like "@/*" -> ["./src/*"]
68
+ if (aliasPattern.includes('*')) {
69
+ const patternBase = aliasPattern.replace(/\*.*$/, '');
70
+
71
+ // Match if it's the exact base (e.g. "@/utils" matches "@/utils/*")
72
+ // OR if it starts with the base (e.g. "@/utils/foo" matches "@/utils/*")
73
+ if (importPath === patternBase.slice(0, -1) || importPath.startsWith(patternBase)) {
74
+ const suffix = importPath.length >= patternBase.length ?
75
+ importPath.substring(patternBase.length) : "";
76
+
77
+ for (const target of aliasTargets) {
78
+ const targetBase = target.replace(/\*.*$/, '');
79
+ const targetPath = path.resolve(projectRoot, path.join(targetBase, suffix));
80
+
81
+ // Try with extensions
82
+ const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.json'];
83
+ for (const ext of extensions) {
84
+ if (exists(targetPath + ext)) {
85
+ return targetPath + ext;
86
+ }
87
+ }
88
+
89
+ // Try as directory with index files
90
+ const indexFiles = ['index.ts', 'index.tsx', 'index.js', 'index.jsx', 'index.json'];
91
+ for (const idxFile of indexFiles) {
92
+ const indexPath = path.join(targetPath, idxFile);
93
+ if (exists(indexPath)) {
94
+ return indexPath;
95
+ }
96
+ }
97
+
98
+ // Try exact path
99
+ if (exists(targetPath)) {
100
+ return targetPath;
101
+ }
102
+ }
103
+ }
104
+ } else {
105
+ // Handle exact match patterns
106
+ if (importPath === aliasPattern || importPath.startsWith(aliasPattern + '/')) {
107
+ for (const target of aliasTargets) {
108
+ let targetPath = path.resolve(projectRoot, target);
109
+
110
+ // If importPath is longer than the alias pattern, add the remaining part
111
+ if (importPath.length > aliasPattern.length) {
112
+ const remainingPath = importPath.substring(aliasPattern.length);
113
+ targetPath = path.join(targetPath, remainingPath);
114
+ }
115
+
116
+ // Try with extensions
117
+ const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.json'];
118
+ for (const ext of extensions) {
119
+ if (exists(targetPath + ext)) {
120
+ return targetPath + ext;
121
+ }
122
+ }
123
+
124
+ // Try as directory with index files
125
+ const indexFiles = ['index.ts', 'index.tsx', 'index.js', 'index.jsx', 'index.json'];
126
+ for (const idxFile of indexFiles) {
127
+ const indexPath = path.join(targetPath, idxFile);
128
+ if (exists(indexPath)) {
129
+ return indexPath;
130
+ }
131
+ }
132
+
133
+ // Try exact path
134
+ if (exists(targetPath)) {
135
+ return targetPath;
136
+ }
137
+ }
138
+ }
139
+ }
140
+ }
141
+ }
142
+
143
+ // Handle baseUrl if configured
144
+ if (tsconfig && tsconfig.baseUrl && !importPath.startsWith('.')) {
145
+ let resolvedPath = path.resolve(projectRoot, tsconfig.baseUrl, importPath);
146
+
147
+ // Try with extensions
148
+ const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.json'];
149
+ for (const ext of extensions) {
150
+ if (exists(resolvedPath + ext)) {
151
+ return resolvedPath + ext;
152
+ }
153
+ }
154
+
155
+ // Try as directory with index files
156
+ const indexFiles = ['index.ts', 'index.tsx', 'index.js', 'index.jsx', 'index.json'];
157
+ for (const idxFile of indexFiles) {
158
+ const indexPath = path.join(resolvedPath, idxFile);
159
+ if (exists(indexPath)) {
160
+ return indexPath;
161
+ }
162
+ }
163
+
164
+ // Try exact path
165
+ if (exists(resolvedPath)) {
166
+ return resolvedPath;
167
+ }
168
+ }
169
+
170
+ // Handle Workspace Packages (Monorepo support)
171
+ if (workspaceMap && workspaceMap.has(importPath)) {
172
+ const packageRoot = workspaceMap.get(importPath);
173
+ // Look for entry point in package.json
174
+ try {
175
+ const pkgPath = path.join(packageRoot, 'package.json');
176
+ if (exists(pkgPath)) {
177
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
178
+ const mainFile = pkg.main || pkg.module || 'index.js';
179
+ const searchPath = path.join(packageRoot, mainFile);
180
+
181
+ // Use standard node resolution logic on the main file
182
+ const extensions = ['', '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.json'];
183
+ for (const ext of extensions) {
184
+ const p = searchPath + ext;
185
+ if (exists(p)) return p;
186
+ }
187
+ }
188
+ // If no package.json or main, try index
189
+ const indexFiles = ['index.ts', 'index.tsx', 'index.js', 'index.jsx'];
190
+ for (const idx of indexFiles) {
191
+ const p = path.join(packageRoot, idx);
192
+ if (exists(p)) return p;
193
+ }
194
+ } catch (e) {
195
+ // ignore
196
+ }
197
+ // Fallback to pure directory path if nothing else
198
+ return packageRoot;
199
+ }
200
+
201
+ // Handle Workspace Sub-paths (e.g. "my-pkg/utils")
202
+ if (workspaceMap) {
203
+ // Find longest matching package name
204
+ // This is O(N) but N is number of packages, usually small.
205
+ for (const [pkgName, pkgRoot] of workspaceMap.entries()) {
206
+ if (importPath.startsWith(pkgName + '/')) {
207
+ const suffix = importPath.substring(pkgName.length + 1);
208
+ const targetPath = path.join(pkgRoot, suffix);
209
+
210
+ const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.json', ''];
211
+ for (const ext of extensions) {
212
+ if (exists(targetPath + ext)) {
213
+ return targetPath + ext;
214
+ }
215
+ }
216
+ // Try as directory
217
+ const indexFiles = ['index.ts', 'index.tsx', 'index.js', 'index.jsx'];
218
+ for (const idx of indexFiles) {
219
+ const p = path.join(targetPath, idx);
220
+ if (exists(p)) return p;
221
+ }
222
+ }
223
+ }
224
+ }
225
+
226
+ // Handle node_modules resolution
227
+ if (!importPath.startsWith('.')) {
228
+ // Check if it's a node module
229
+ try {
230
+ const resolved = require.resolve(importPath, { paths: [path.dirname(importerPath)] });
231
+ return resolved;
232
+ } catch (e) {
233
+ // If require.resolve fails, it's not a node module
234
+ }
235
+ }
236
+
237
+ return null;
238
+ }
239
+
240
+ module.exports = { resolveImport };
@@ -0,0 +1,246 @@
1
+ /**
2
+ * Robust Pattern Matching Utility
3
+ * Provides resilient pattern matching with graceful fallbacks
4
+ */
5
+
6
+ const path = require('path');
7
+
8
+ class PatternMatcher {
9
+ constructor() {
10
+ this.minimatch = null;
11
+ this.initialized = false;
12
+ this.initMinimatch();
13
+ }
14
+
15
+ /**
16
+ * Initialize minimatch with error handling
17
+ */
18
+ initMinimatch() {
19
+ const { dependencyManager } = require('./dependency-manager');
20
+
21
+ this.minimatch = dependencyManager.safeImport('minimatch', null, { useCache: true });
22
+
23
+ if (this.minimatch) {
24
+ this.initialized = true;
25
+ console.log('โœ… Minimatch library initialized successfully');
26
+ } else {
27
+ console.warn('โš ๏ธ Minimatch library not available');
28
+ console.warn('โš ๏ธ Falling back to basic string matching');
29
+ this.minimatch = null;
30
+ this.initialized = false;
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Robust pattern matching with multiple fallback strategies
36
+ */
37
+ match(filePath, pattern, options = {}) {
38
+ // Validate inputs
39
+ if (!filePath || typeof filePath !== 'string') {
40
+ return false;
41
+ }
42
+
43
+ if (!pattern || typeof pattern !== 'string') {
44
+ return false;
45
+ }
46
+
47
+ // Try minimatch first if available
48
+ if (this.initialized && this.minimatch) {
49
+ try {
50
+ const matchOptions = {
51
+ matchBase: true,
52
+ dot: true,
53
+ ...options
54
+ };
55
+
56
+ return this.minimatch.minimatch(filePath, pattern, matchOptions);
57
+ } catch (error) {
58
+ console.warn(`โš ๏ธ Minimatch failed for pattern "${pattern}":`, error.message);
59
+ // Fall through to fallback methods
60
+ }
61
+ }
62
+
63
+ // Fallback 1: Basic glob matching (simple cases)
64
+ if (this.basicGlobMatch(filePath, pattern)) {
65
+ return true;
66
+ }
67
+
68
+ // Fallback 2: Path containment matching
69
+ if (this.pathContainmentMatch(filePath, pattern)) {
70
+ return true;
71
+ }
72
+
73
+ // Fallback 3: Extension matching
74
+ if (this.extensionMatch(filePath, pattern)) {
75
+ return true;
76
+ }
77
+
78
+ // Fallback 4: Exact filename matching
79
+ if (this.filenameMatch(filePath, pattern)) {
80
+ return true;
81
+ }
82
+
83
+ return false;
84
+ }
85
+
86
+ /**
87
+ * Match array of patterns against file path
88
+ */
89
+ matchAny(filePath, patterns, options = {}) {
90
+ if (!Array.isArray(patterns)) {
91
+ return false;
92
+ }
93
+
94
+ return patterns.some(pattern =>
95
+ this.match(filePath, pattern, options)
96
+ );
97
+ }
98
+
99
+ /**
100
+ * Match all patterns against file path
101
+ */
102
+ matchAll(filePath, patterns, options = {}) {
103
+ if (!Array.isArray(patterns)) {
104
+ return false;
105
+ }
106
+
107
+ return patterns.every(pattern =>
108
+ this.match(filePath, pattern, options)
109
+ );
110
+ }
111
+
112
+ /**
113
+ * Basic glob pattern matching for simple cases
114
+ */
115
+ basicGlobMatch(filePath, pattern) {
116
+ // Handle simple wildcards
117
+ if (pattern === '**/*') return true;
118
+ if (pattern === '*') return true;
119
+
120
+ // Handle extension patterns
121
+ if (pattern.startsWith('*.')) {
122
+ const ext = pattern.substring(1); // Remove *
123
+ return filePath.endsWith(ext);
124
+ }
125
+
126
+ // Handle directory patterns
127
+ if (pattern.endsWith('/**')) {
128
+ const dir = pattern.slice(0, -3); // Remove /**
129
+ return filePath.includes(dir);
130
+ }
131
+
132
+ // Handle simple contains
133
+ if (pattern.includes('*')) {
134
+ const parts = pattern.split('*');
135
+ let currentIndex = 0;
136
+
137
+ for (const part of parts) {
138
+ if (part === '') continue;
139
+ const foundIndex = filePath.indexOf(part, currentIndex);
140
+ if (foundIndex === -1) return false;
141
+ currentIndex = foundIndex + part.length;
142
+ }
143
+ return true;
144
+ }
145
+
146
+ return false;
147
+ }
148
+
149
+ /**
150
+ * Path containment matching
151
+ */
152
+ pathContainmentMatch(filePath, pattern) {
153
+ // Normalize paths for comparison
154
+ const normalizedFile = path.normalize(filePath).toLowerCase();
155
+ const normalizedPattern = path.normalize(pattern).toLowerCase();
156
+
157
+ // Check if pattern is contained in file path
158
+ return normalizedFile.includes(normalizedPattern);
159
+ }
160
+
161
+ /**
162
+ * Extension matching
163
+ */
164
+ extensionMatch(filePath, pattern) {
165
+ if (!pattern.includes('.')) return false;
166
+
167
+ const fileExt = path.extname(filePath).toLowerCase();
168
+ const patternExt = path.extname(pattern).toLowerCase();
169
+
170
+ return fileExt === patternExt;
171
+ }
172
+
173
+ /**
174
+ * Filename matching (basename comparison)
175
+ */
176
+ filenameMatch(filePath, pattern) {
177
+ const fileName = path.basename(filePath);
178
+ const patternName = path.basename(pattern);
179
+
180
+ // Exact match
181
+ if (fileName === patternName) return true;
182
+
183
+ // Case insensitive match
184
+ if (fileName.toLowerCase() === patternName.toLowerCase()) return true;
185
+
186
+ return false;
187
+ }
188
+
189
+ /**
190
+ * Get diagnostic information about matching capabilities
191
+ */
192
+ getDiagnostics() {
193
+ return {
194
+ minimatchAvailable: this.initialized,
195
+ minimatchVersion: this.minimatch ? require('minimatch/package.json').version : null,
196
+ fallbackMethods: [
197
+ 'basicGlobMatch',
198
+ 'pathContainmentMatch',
199
+ 'extensionMatch',
200
+ 'filenameMatch'
201
+ ]
202
+ };
203
+ }
204
+
205
+ /**
206
+ * Test pattern matching with sample data
207
+ */
208
+ testPatterns() {
209
+ const testCases = [
210
+ { file: 'src/components/Button.jsx', pattern: '**/*.jsx', expected: true },
211
+ { file: 'src/utils/helpers.js', pattern: '**/utils/**', expected: true },
212
+ { file: 'package.json', pattern: '*.json', expected: true },
213
+ { file: 'src/App.tsx', pattern: '**/*.{ts,tsx}', expected: true },
214
+ { file: 'README.md', pattern: 'README.*', expected: true }
215
+ ];
216
+
217
+ console.log('๐Ÿงช Pattern Matching Diagnostics:');
218
+ console.log('==============================');
219
+
220
+ const diagnostics = this.getDiagnostics();
221
+ console.log('Minimatch Available:', diagnostics.minimatchAvailable);
222
+ console.log('Fallback Methods:', diagnostics.fallbackMethods.length);
223
+
224
+ console.log('\n๐Ÿงช Test Results:');
225
+ let passed = 0;
226
+ let failed = 0;
227
+
228
+ testCases.forEach(({ file, pattern, expected }, index) => {
229
+ const result = this.match(file, pattern);
230
+ const status = result === expected ? 'โœ… PASS' : 'โŒ FAIL';
231
+
232
+ if (result === expected) passed++;
233
+ else failed++;
234
+
235
+ console.log(`${status} ${file} =~ ${pattern} (expected: ${expected}, got: ${result})`);
236
+ });
237
+
238
+ console.log(`\n๐Ÿ“Š Summary: ${passed}/${testCases.length} passed, ${failed} failed`);
239
+ return { passed, failed, total: testCases.length };
240
+ }
241
+ }
242
+
243
+ // Export singleton instance
244
+ const patternMatcher = new PatternMatcher();
245
+
246
+ module.exports = { PatternMatcher, patternMatcher };
@@ -0,0 +1,71 @@
1
+ const chalk = require('chalk');
2
+
3
+ class ProgressTracker {
4
+ constructor(totalSteps) {
5
+ this.totalSteps = totalSteps;
6
+ this.currentStep = 0;
7
+ this.startTime = Date.now();
8
+ }
9
+
10
+ update(step, message) {
11
+ this.currentStep = step;
12
+ const progress = (this.currentStep / this.totalSteps) * 100;
13
+ const elapsed = Date.now() - this.startTime;
14
+
15
+ // Format elapsed time
16
+ const elapsedSeconds = Math.floor(elapsed / 1000);
17
+ const minutes = Math.floor(elapsedSeconds / 60);
18
+ const seconds = elapsedSeconds % 60;
19
+
20
+ const timeString = `${minutes}:${seconds.toString().padStart(2, '0')}`;
21
+
22
+ console.log(
23
+ chalk.blue(`[${timeString}] `) +
24
+ chalk.yellow(`Progress: ${this.currentStep}/${this.totalSteps} (${Math.round(progress)}%) - ${message}`)
25
+ );
26
+ }
27
+
28
+ updateSimple(current, total, message) {
29
+ const progress = (current / total) * 100;
30
+ const elapsed = Date.now() - this.startTime;
31
+
32
+ // Format elapsed time
33
+ const elapsedSeconds = Math.floor(elapsed / 1000);
34
+ const minutes = Math.floor(elapsedSeconds / 60);
35
+ const seconds = elapsedSeconds % 60;
36
+
37
+ const timeString = `${minutes}:${seconds.toString().padStart(2, '0')}`;
38
+
39
+ console.log(
40
+ chalk.blue(`[${timeString}] `) +
41
+ chalk.yellow(`Progress: ${current}/${total} (${Math.round(progress)}%) - ${message}`)
42
+ );
43
+ }
44
+
45
+ complete(message = 'Operation completed') {
46
+ const elapsed = Date.now() - this.startTime;
47
+ const elapsedSeconds = Math.floor(elapsed / 1000);
48
+ const minutes = Math.floor(elapsedSeconds / 60);
49
+ const seconds = elapsedSeconds % 60;
50
+ const timeString = `${minutes}:${seconds.toString().padStart(2, '0')}`;
51
+
52
+ console.log(
53
+ chalk.green(`[${timeString}] โœ“ ${message}`)
54
+ );
55
+ }
56
+
57
+ estimateRemaining(current, total) {
58
+ const elapsed = Date.now() - this.startTime;
59
+ const progress = current / total;
60
+ const estimatedTotalTime = elapsed / progress;
61
+ const remainingTime = estimatedTotalTime - elapsed;
62
+
63
+ const remainingSeconds = Math.floor(remainingTime / 1000);
64
+ const minutes = Math.floor(remainingSeconds / 60);
65
+ const seconds = remainingSeconds % 60;
66
+
67
+ return `${minutes}:${seconds.toString().padStart(2, '0')}`;
68
+ }
69
+ }
70
+
71
+ module.exports = ProgressTracker;