arcvision 0.2.14 → 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.
- package/ARCVISION_DIRECTORY_STRUCTURE.md +104 -0
- package/CLI_STRUCTURE.md +110 -0
- package/CONFIGURATION.md +119 -0
- package/IMPLEMENTATION_SUMMARY.md +99 -0
- package/README.md +149 -89
- package/architecture.authority.ledger.json +46 -0
- package/arcvision-0.2.3.tgz +0 -0
- package/arcvision-0.2.4.tgz +0 -0
- package/arcvision-0.2.5.tgz +0 -0
- package/arcvision.context.diff.json +2181 -0
- package/arcvision.context.json +1021 -0
- package/arcvision.context.v1.json +2163 -0
- package/arcvision.context.v2.json +2173 -0
- package/arcvision_context/README.md +93 -0
- package/arcvision_context/architecture.authority.ledger.json +83 -0
- package/arcvision_context/arcvision.context.json +6884 -0
- package/debug-cycle-detection.js +56 -0
- package/dist/index.js +1626 -25
- package/docs/ENHANCED_ACCURACY_SAFETY_PROTOCOL.md +172 -0
- package/docs/accuracy-enhancement-artifacts/enhanced-validation-config.json +98 -0
- package/docs/acig-robustness-guide.md +164 -0
- package/docs/authoritative-gate-implementation.md +168 -0
- package/docs/cli-strengthening-summary.md +232 -0
- package/docs/invariant-system-summary.md +100 -0
- package/docs/invariant-system.md +112 -0
- package/generate_large_test.js +42 -0
- package/large_test_repo.json +1 -0
- package/output1.json +2163 -0
- package/output2.json +2163 -0
- package/package.json +46 -36
- package/scan_calcom_report.txt +0 -0
- package/scan_leafmint_report.txt +0 -0
- package/scan_output.txt +0 -0
- package/scan_trigger_report.txt +0 -0
- package/schema/arcvision_context_schema_v1.json +136 -1
- package/src/arcvision-guard.js +433 -0
- package/src/core/authority-core-detector.js +382 -0
- package/src/core/authority-ledger.js +300 -0
- package/src/core/blastRadius.js +299 -0
- package/src/core/call-resolver.js +196 -0
- package/src/core/change-evaluator.js +509 -0
- package/src/core/change-evaluator.js.backup +424 -0
- package/src/core/change-evaluator.ts +285 -0
- package/src/core/chunked-uploader.js +180 -0
- package/src/core/circular-dependency-detector.js +404 -0
- package/src/core/cli-error-handler.js +458 -0
- package/src/core/cli-validator.js +458 -0
- package/src/core/compression.js +64 -0
- package/src/core/context_builder.js +741 -0
- package/src/core/dependency-manager.js +134 -0
- package/src/core/di-detector.js +202 -0
- package/src/core/diff-analyzer.js +76 -0
- package/src/core/example-invariants.js +135 -0
- package/src/core/failure-mode-synthesizer.js +341 -0
- package/src/core/invariant-analyzer.js +294 -0
- package/src/core/invariant-detector.js +548 -0
- package/src/core/invariant-enforcer.js +171 -0
- package/src/core/invariant-evaluation-utils.js +172 -0
- package/src/core/invariant-hooks.js +152 -0
- package/src/core/invariant-integration-example.js +186 -0
- package/src/core/invariant-registry.js +298 -0
- package/src/core/invariant-registry.ts +100 -0
- package/src/core/invariant-types.js +66 -0
- package/src/core/invariants-index.js +88 -0
- package/src/core/method-tracker.js +170 -0
- package/src/core/override-handler.js +304 -0
- package/src/core/ownership-resolver.js +227 -0
- package/src/core/parser-enhanced.js +80 -0
- package/src/core/parser.js +610 -0
- package/src/core/path-resolver.js +240 -0
- package/src/core/pattern-matcher.js +246 -0
- package/src/core/progress-tracker.js +71 -0
- package/src/core/react-nextjs-detector.js +245 -0
- package/src/core/readme-generator.js +167 -0
- package/src/core/retry-handler.js +57 -0
- package/src/core/scanner.js +289 -0
- package/src/core/semantic-analyzer.js +204 -0
- package/src/core/structural-context-owner.js +442 -0
- package/src/core/symbol-indexer.js +164 -0
- package/src/core/tsconfig-utils.js +73 -0
- package/src/core/type-analyzer.js +272 -0
- package/src/core/watcher.js +18 -0
- package/src/core/workspace-scanner.js +88 -0
- package/src/engine/context_builder.js +280 -0
- package/src/engine/context_sorter.js +59 -0
- package/src/engine/context_validator.js +200 -0
- package/src/engine/id-generator.js +16 -0
- package/src/engine/pass1_facts.js +260 -0
- package/src/engine/pass2_semantics.js +333 -0
- package/src/engine/pass3_lifter.js +99 -0
- package/src/engine/pass4_signals.js +201 -0
- package/src/index.js +830 -0
- package/src/plugins/express-plugin.js +48 -0
- package/src/plugins/plugin-manager.js +58 -0
- package/src/plugins/react-plugin.js +54 -0
- package/temp_original.js +0 -0
- package/test/determinism-test.js +83 -0
- package/test-authoritative-context.js +53 -0
- package/test-real-authoritative-context.js +118 -0
- package/test-upload-enhancements.js +111 -0
- package/test_repos/allowed-clean-architecture/.arcvision/invariants.json +57 -0
- package/test_repos/allowed-clean-architecture/adapters/controllers/UserController.js +95 -0
- package/test_repos/allowed-clean-architecture/adapters/http/HttpServer.js +78 -0
- package/test_repos/allowed-clean-architecture/application/dtos/CreateUserRequest.js +37 -0
- package/test_repos/allowed-clean-architecture/application/services/UserService.js +61 -0
- package/test_repos/allowed-clean-architecture/arcvision_context/README.md +93 -0
- package/test_repos/allowed-clean-architecture/arcvision_context/arcvision.context.json +2796 -0
- package/test_repos/allowed-clean-architecture/domain/interfaces/UserRepository.js +25 -0
- package/test_repos/allowed-clean-architecture/domain/models/User.js +39 -0
- package/test_repos/allowed-clean-architecture/index.js +45 -0
- package/test_repos/allowed-clean-architecture/infrastructure/database/DatabaseConnection.js +56 -0
- package/test_repos/allowed-clean-architecture/infrastructure/repositories/InMemoryUserRepository.js +61 -0
- package/test_repos/allowed-clean-architecture/package.json +15 -0
- package/test_repos/blocked-legacy-monolith/.arcvision/invariants.json +78 -0
- package/test_repos/blocked-legacy-monolith/arcvision_context/README.md +93 -0
- package/test_repos/blocked-legacy-monolith/arcvision_context/arcvision.context.json +2882 -0
- package/test_repos/blocked-legacy-monolith/database/dbConnection.js +35 -0
- package/test_repos/blocked-legacy-monolith/index.js +38 -0
- package/test_repos/blocked-legacy-monolith/modules/emailService.js +31 -0
- package/test_repos/blocked-legacy-monolith/modules/paymentProcessor.js +37 -0
- package/test_repos/blocked-legacy-monolith/package.json +15 -0
- package/test_repos/blocked-legacy-monolith/shared/utils.js +19 -0
- package/test_repos/blocked-legacy-monolith/utils/helpers.js +23 -0
- package/test_repos/risky-microservices-concerns/.arcvision/invariants.json +69 -0
- package/test_repos/risky-microservices-concerns/arcvision_context/README.md +93 -0
- package/test_repos/risky-microservices-concerns/arcvision_context/arcvision.context.json +3070 -0
- package/test_repos/risky-microservices-concerns/common/utils.js +77 -0
- package/test_repos/risky-microservices-concerns/gateways/apiGateway.js +84 -0
- package/test_repos/risky-microservices-concerns/index.js +20 -0
- package/test_repos/risky-microservices-concerns/libs/deprecatedHelper.js +36 -0
- package/test_repos/risky-microservices-concerns/package.json +15 -0
- package/test_repos/risky-microservices-concerns/services/orderService.js +42 -0
- package/test_repos/risky-microservices-concerns/services/userService.js +48 -0
- package/verify_engine.js +116 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Parser Wrapper
|
|
3
|
+
*
|
|
4
|
+
* Wraps the existing parser and adds enhanced metadata extraction
|
|
5
|
+
* using all the new analyzer modules.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { parseFile: originalParseFile } = require('./parser');
|
|
9
|
+
const { detectDependencyInjection } = require('./di-detector');
|
|
10
|
+
const { trackMethodCalls } = require('./method-tracker');
|
|
11
|
+
const { analyzeTypeDependencies } = require('./type-analyzer');
|
|
12
|
+
const { detectReactNextJSPatterns } = require('./react-nextjs-detector');
|
|
13
|
+
const fs = require('fs');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Enhanced parseFile that includes all new analysis
|
|
17
|
+
* @param {string} filePath - Path to file to parse
|
|
18
|
+
* @returns {Object} Enhanced metadata
|
|
19
|
+
*/
|
|
20
|
+
function parseFileEnhanced(filePath) {
|
|
21
|
+
// Get basic metadata from original parser
|
|
22
|
+
const metadata = originalParseFile(filePath);
|
|
23
|
+
|
|
24
|
+
// If parsing failed, return as-is
|
|
25
|
+
if (!metadata.ast) {
|
|
26
|
+
return metadata;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const ast = metadata.ast;
|
|
30
|
+
const fileContent = fs.readFileSync(filePath, 'utf-8');
|
|
31
|
+
|
|
32
|
+
// Skip enhanced analysis for markdown files
|
|
33
|
+
if (filePath.endsWith('.md')) {
|
|
34
|
+
// Remove AST from final metadata to reduce memory usage
|
|
35
|
+
delete metadata.ast;
|
|
36
|
+
return metadata;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Apply all new analyzers
|
|
40
|
+
try {
|
|
41
|
+
// Dependency Injection detection
|
|
42
|
+
const diPatterns = detectDependencyInjection(ast);
|
|
43
|
+
metadata.constructorInjections = diPatterns.constructorInjections || [];
|
|
44
|
+
metadata.contextUsages = diPatterns.contextUsages || [];
|
|
45
|
+
metadata.hookDependencies = diPatterns.hookDependencies || [];
|
|
46
|
+
|
|
47
|
+
// Method call tracking
|
|
48
|
+
const callTracking = trackMethodCalls(ast, metadata.imports);
|
|
49
|
+
metadata.functionCalls = callTracking.functionCalls || [];
|
|
50
|
+
metadata.constructorCalls = callTracking.constructorCalls || [];
|
|
51
|
+
metadata.methodCalls = callTracking.methodCalls || [];
|
|
52
|
+
|
|
53
|
+
// Type dependency analysis
|
|
54
|
+
const typeDeps = analyzeTypeDependencies(ast);
|
|
55
|
+
metadata.typeImports = typeDeps.typeImports || [];
|
|
56
|
+
metadata.interfaceDependencies = typeDeps.interfaceDependencies || [];
|
|
57
|
+
metadata.genericDependencies = typeDeps.genericDependencies || [];
|
|
58
|
+
|
|
59
|
+
// React/Next.js pattern detection
|
|
60
|
+
const reactPatterns = detectReactNextJSPatterns(ast, fileContent, filePath);
|
|
61
|
+
metadata.componentUsage = reactPatterns.componentUsages || [];
|
|
62
|
+
metadata.serverClientBoundaries = reactPatterns.boundaries || {};
|
|
63
|
+
metadata.apiDependencies = reactPatterns.apiDependencies || [];
|
|
64
|
+
metadata.middlewareDependencies = reactPatterns.middlewareDependencies || [];
|
|
65
|
+
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.warn(`⚠️ Enhanced analysis failed for ${filePath}: ${error.message}`);
|
|
68
|
+
// Continue with basic metadata if enhanced analysis fails
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Remove AST from final metadata to reduce memory usage
|
|
72
|
+
delete metadata.ast;
|
|
73
|
+
|
|
74
|
+
return metadata;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
module.exports = {
|
|
78
|
+
parseFile: parseFileEnhanced,
|
|
79
|
+
parseFileBasic: originalParseFile
|
|
80
|
+
};
|
|
@@ -0,0 +1,610 @@
|
|
|
1
|
+
const parser = require('@babel/parser');
|
|
2
|
+
const traverse = require('@babel/traverse').default;
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
// File content cache to avoid repeated disk reads
|
|
7
|
+
const fileContentCache = new Map();
|
|
8
|
+
|
|
9
|
+
function parseFile(filePath) {
|
|
10
|
+
let content;
|
|
11
|
+
|
|
12
|
+
// Check cache first
|
|
13
|
+
if (fileContentCache.has(filePath)) {
|
|
14
|
+
const cached = fileContentCache.get(filePath);
|
|
15
|
+
try {
|
|
16
|
+
const stat = fs.statSync(filePath);
|
|
17
|
+
if (cached.mtime && stat.mtimeMs <= cached.mtime) {
|
|
18
|
+
// Cache is still valid, use cached content
|
|
19
|
+
content = cached.content;
|
|
20
|
+
} else {
|
|
21
|
+
// Cache is stale, read fresh content and update cache
|
|
22
|
+
content = fs.readFileSync(filePath, 'utf-8');
|
|
23
|
+
fileContentCache.set(filePath, {
|
|
24
|
+
content: content,
|
|
25
|
+
mtime: stat.mtimeMs
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
} catch (statError) {
|
|
29
|
+
// If stat fails, fall back to reading file and caching
|
|
30
|
+
content = fs.readFileSync(filePath, 'utf-8');
|
|
31
|
+
try {
|
|
32
|
+
const stat = fs.statSync(filePath);
|
|
33
|
+
fileContentCache.set(filePath, {
|
|
34
|
+
content: content,
|
|
35
|
+
mtime: stat.mtimeMs
|
|
36
|
+
});
|
|
37
|
+
} catch (cacheError) {
|
|
38
|
+
// If caching fails, continue without cache
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
// File not in cache, read and add to cache
|
|
43
|
+
content = fs.readFileSync(filePath, 'utf-8');
|
|
44
|
+
try {
|
|
45
|
+
const stat = fs.statSync(filePath);
|
|
46
|
+
fileContentCache.set(filePath, {
|
|
47
|
+
content: content,
|
|
48
|
+
mtime: stat.mtimeMs
|
|
49
|
+
});
|
|
50
|
+
} catch (cacheError) {
|
|
51
|
+
// If caching fails, continue without cache
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let ast;
|
|
56
|
+
|
|
57
|
+
// Determine if this is a TypeScript declaration file
|
|
58
|
+
const isDeclarationFile = filePath.endsWith('.d.ts');
|
|
59
|
+
|
|
60
|
+
// Enhanced parser options with more comprehensive plugin support
|
|
61
|
+
const parserOptions = {
|
|
62
|
+
sourceType: 'unambiguous', // Auto-detect between script and module
|
|
63
|
+
allowImportExportEverywhere: true,
|
|
64
|
+
allowReturnOutsideFunction: true,
|
|
65
|
+
allowSuperOutsideMethod: true,
|
|
66
|
+
errorRecovery: true, // Allow parser to continue after errors
|
|
67
|
+
plugins: [
|
|
68
|
+
'jsx',
|
|
69
|
+
'typescript',
|
|
70
|
+
'decorators-legacy',
|
|
71
|
+
'classProperties',
|
|
72
|
+
'exportDefaultFrom',
|
|
73
|
+
'exportNamespaceFrom',
|
|
74
|
+
'dynamicImport',
|
|
75
|
+
'functionBind',
|
|
76
|
+
'nullishCoalescingOperator',
|
|
77
|
+
'optionalChaining',
|
|
78
|
+
'numericSeparator',
|
|
79
|
+
'bigInt',
|
|
80
|
+
'importMeta',
|
|
81
|
+
'asyncGenerators',
|
|
82
|
+
'optionalCatchBinding',
|
|
83
|
+
'throwExpressions',
|
|
84
|
+
'logicalAssignment',
|
|
85
|
+
'nullishCoalescingOperator',
|
|
86
|
+
'doExpressions',
|
|
87
|
+
'pipeOperator',
|
|
88
|
+
'recordAndTuple',
|
|
89
|
+
'moduleBlocks',
|
|
90
|
+
'topLevelAwait',
|
|
91
|
+
'v8intrinsic',
|
|
92
|
+
'partialApplication',
|
|
93
|
+
'regexpUnicodeSets',
|
|
94
|
+
'destructuringPrivate',
|
|
95
|
+
'decoratorAutoAccessors'
|
|
96
|
+
]
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// Add declaration file specific options if this is a declaration file
|
|
100
|
+
if (isDeclarationFile) {
|
|
101
|
+
parserOptions.plugins.push('typescript');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
ast = parser.parse(content, parserOptions);
|
|
106
|
+
} catch (error) {
|
|
107
|
+
// Try alternative parser options for files with complex syntax
|
|
108
|
+
const fallbackParserOptions = {
|
|
109
|
+
...parserOptions,
|
|
110
|
+
// Allow more flexible parsing
|
|
111
|
+
errorRecovery: true, // Allow parser to continue after errors
|
|
112
|
+
plugins: [
|
|
113
|
+
'jsx',
|
|
114
|
+
'typescript',
|
|
115
|
+
'decorators-legacy',
|
|
116
|
+
'classProperties',
|
|
117
|
+
'exportDefaultFrom',
|
|
118
|
+
'exportNamespaceFrom',
|
|
119
|
+
'dynamicImport',
|
|
120
|
+
'functionBind',
|
|
121
|
+
'nullishCoalescingOperator',
|
|
122
|
+
'optionalChaining',
|
|
123
|
+
'numericSeparator',
|
|
124
|
+
'bigInt',
|
|
125
|
+
'importMeta',
|
|
126
|
+
'asyncGenerators',
|
|
127
|
+
'optionalCatchBinding',
|
|
128
|
+
'throwExpressions',
|
|
129
|
+
'logicalAssignment',
|
|
130
|
+
'nullishCoalescingOperator',
|
|
131
|
+
'doExpressions',
|
|
132
|
+
'pipeOperator',
|
|
133
|
+
'recordAndTuple',
|
|
134
|
+
'moduleBlocks',
|
|
135
|
+
'topLevelAwait',
|
|
136
|
+
'v8intrinsic',
|
|
137
|
+
'partialApplication',
|
|
138
|
+
'regexpUnicodeSets',
|
|
139
|
+
'destructuringPrivate',
|
|
140
|
+
'decoratorAutoAccessors',
|
|
141
|
+
'typescript',
|
|
142
|
+
'decorators'
|
|
143
|
+
]
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// Add declaration file specific options
|
|
147
|
+
if (isDeclarationFile) {
|
|
148
|
+
fallbackParserOptions.plugins.push('typescript');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
try {
|
|
152
|
+
ast = parser.parse(content, fallbackParserOptions);
|
|
153
|
+
} catch (fallbackError) {
|
|
154
|
+
// If both attempts fail, try with even more lenient settings
|
|
155
|
+
const ultraFallbackParserOptions = {
|
|
156
|
+
sourceType: 'unambiguous',
|
|
157
|
+
allowImportExportEverywhere: true,
|
|
158
|
+
allowReturnOutsideFunction: true,
|
|
159
|
+
allowSuperOutsideMethod: true,
|
|
160
|
+
errorRecovery: true,
|
|
161
|
+
plugins: [
|
|
162
|
+
'typescript',
|
|
163
|
+
'jsx',
|
|
164
|
+
'decorators-legacy',
|
|
165
|
+
'classProperties',
|
|
166
|
+
'typescript',
|
|
167
|
+
'optionalChaining',
|
|
168
|
+
'nullishCoalescingOperator',
|
|
169
|
+
'logicalAssignment',
|
|
170
|
+
'numericSeparator',
|
|
171
|
+
'optionalCatchBinding',
|
|
172
|
+
'importMeta',
|
|
173
|
+
'functionBind',
|
|
174
|
+
'throwExpressions'
|
|
175
|
+
]
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// Add declaration file specific options
|
|
179
|
+
if (isDeclarationFile) {
|
|
180
|
+
ultraFallbackParserOptions.plugins.push('typescript');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
ast = parser.parse(content, ultraFallbackParserOptions);
|
|
185
|
+
} catch (ultraFallbackError) {
|
|
186
|
+
// If all attempts fail, collect error info for reporting but continue with minimal processing
|
|
187
|
+
const errorInfo = {
|
|
188
|
+
file: filePath,
|
|
189
|
+
error: error.message,
|
|
190
|
+
line: error.loc ? error.loc.line : 'unknown',
|
|
191
|
+
column: error.loc ? error.loc.column : 'unknown'
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
// Store error for later reporting instead of immediate console output
|
|
195
|
+
if (!global.parserErrors) {
|
|
196
|
+
global.parserErrors = [];
|
|
197
|
+
}
|
|
198
|
+
global.parserErrors.push(errorInfo);
|
|
199
|
+
|
|
200
|
+
// Return minimal metadata for files that can't be parsed
|
|
201
|
+
return {
|
|
202
|
+
id: filePath,
|
|
203
|
+
imports: [],
|
|
204
|
+
exports: [],
|
|
205
|
+
functions: [],
|
|
206
|
+
apiCalls: [],
|
|
207
|
+
potentialInvocations: extractPotentialLuaInvocations(content)
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const metadata = {
|
|
214
|
+
id: filePath,
|
|
215
|
+
ast: ast, // Include AST for enhanced analyzers
|
|
216
|
+
imports: [],
|
|
217
|
+
exports: [],
|
|
218
|
+
functions: [],
|
|
219
|
+
apiCalls: [],
|
|
220
|
+
classes: [],
|
|
221
|
+
variables: [],
|
|
222
|
+
types: [],
|
|
223
|
+
dependencies: []
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
traverse(ast, {
|
|
227
|
+
ImportDeclaration({ node }) {
|
|
228
|
+
const importSource = node.source.value;
|
|
229
|
+
const specifiers = [];
|
|
230
|
+
|
|
231
|
+
node.specifiers.forEach(spec => {
|
|
232
|
+
if (spec.imported && spec.local) {
|
|
233
|
+
// Named import: import { name as alias } from 'source'
|
|
234
|
+
specifiers.push({
|
|
235
|
+
imported: spec.imported.name || spec.imported.value,
|
|
236
|
+
local: spec.local.name
|
|
237
|
+
});
|
|
238
|
+
} else if (spec.local) {
|
|
239
|
+
// Default import: import name from 'source'
|
|
240
|
+
specifiers.push({
|
|
241
|
+
imported: 'default',
|
|
242
|
+
local: spec.local.name
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
metadata.imports.push({
|
|
248
|
+
source: importSource,
|
|
249
|
+
specifiers: specifiers
|
|
250
|
+
});
|
|
251
|
+
},
|
|
252
|
+
ImportExpression({ node }) {
|
|
253
|
+
// Handle dynamic imports: import('module')
|
|
254
|
+
if (node.source && node.source.type === 'StringLiteral') {
|
|
255
|
+
metadata.imports.push({
|
|
256
|
+
source: node.source.value,
|
|
257
|
+
specifiers: [],
|
|
258
|
+
dynamic: true
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
ExportNamedDeclaration({ node }) {
|
|
263
|
+
// Handle export { X, Y, Z } from './file' statements
|
|
264
|
+
if (node.source) {
|
|
265
|
+
const specifiers = [];
|
|
266
|
+
if (node.specifiers) {
|
|
267
|
+
node.specifiers.forEach(spec => {
|
|
268
|
+
specifiers.push({
|
|
269
|
+
exported: spec.exported.name || spec.exported.value || spec.exported.value,
|
|
270
|
+
local: spec.local ? spec.local.name : spec.exported.name || spec.exported.value
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
metadata.imports.push({
|
|
276
|
+
source: node.source.value,
|
|
277
|
+
specifiers: specifiers,
|
|
278
|
+
type: 'export-from'
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
// Handle export declarations without source (local exports)
|
|
282
|
+
if (node.declaration) {
|
|
283
|
+
if (node.declaration.type === 'FunctionDeclaration' && node.declaration.id) {
|
|
284
|
+
metadata.exports.push({
|
|
285
|
+
name: node.declaration.id.name,
|
|
286
|
+
type: 'function',
|
|
287
|
+
loc: node.declaration.loc
|
|
288
|
+
});
|
|
289
|
+
} else if (node.declaration.type === 'ClassDeclaration' && node.declaration.id) {
|
|
290
|
+
metadata.exports.push({
|
|
291
|
+
name: node.declaration.id.name,
|
|
292
|
+
type: 'class',
|
|
293
|
+
loc: node.declaration.loc
|
|
294
|
+
});
|
|
295
|
+
} else if (node.declaration.type === 'VariableDeclaration') {
|
|
296
|
+
node.declaration.declarations.forEach(decl => {
|
|
297
|
+
if (decl.id.name) {
|
|
298
|
+
metadata.exports.push({
|
|
299
|
+
name: decl.id.name,
|
|
300
|
+
type: 'variable',
|
|
301
|
+
loc: decl.loc
|
|
302
|
+
});
|
|
303
|
+
} else if (decl.id.type === 'ObjectPattern') {
|
|
304
|
+
// Handle destructuring exports: export const { a, b } = obj
|
|
305
|
+
decl.id.properties.forEach(prop => {
|
|
306
|
+
if (prop.key.name) {
|
|
307
|
+
metadata.exports.push({
|
|
308
|
+
name: prop.key.name,
|
|
309
|
+
type: 'variable',
|
|
310
|
+
loc: prop.loc
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
} else if (decl.id.type === 'ArrayPattern') {
|
|
315
|
+
// Handle array destructuring exports: export const [a, b] = arr
|
|
316
|
+
decl.id.elements.forEach(element => {
|
|
317
|
+
if (element && element.name) {
|
|
318
|
+
metadata.exports.push({
|
|
319
|
+
name: element.name,
|
|
320
|
+
type: 'variable',
|
|
321
|
+
loc: element.loc
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
} else if (node.declaration.type === 'TSInterfaceDeclaration' && node.declaration.id) {
|
|
328
|
+
metadata.exports.push({
|
|
329
|
+
name: node.declaration.id.name,
|
|
330
|
+
type: 'interface',
|
|
331
|
+
loc: node.declaration.loc
|
|
332
|
+
});
|
|
333
|
+
} else if (node.declaration.type === 'TSTypeAliasDeclaration' && node.declaration.id) {
|
|
334
|
+
metadata.exports.push({
|
|
335
|
+
name: node.declaration.id.name,
|
|
336
|
+
type: 'type',
|
|
337
|
+
loc: node.declaration.loc
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
},
|
|
342
|
+
ExportAllDeclaration({ node }) {
|
|
343
|
+
// Handle export * from './file' statements
|
|
344
|
+
metadata.imports.push({
|
|
345
|
+
source: node.source.value,
|
|
346
|
+
specifiers: ['*'],
|
|
347
|
+
type: 'export-all'
|
|
348
|
+
});
|
|
349
|
+
},
|
|
350
|
+
ExportDefaultDeclaration({ node }) {
|
|
351
|
+
let exportName = 'default';
|
|
352
|
+
|
|
353
|
+
if (node.declaration) {
|
|
354
|
+
if (node.declaration.type === 'FunctionDeclaration' && node.declaration.id) {
|
|
355
|
+
exportName = node.declaration.id.name || 'default';
|
|
356
|
+
} else if (node.declaration.type === 'ClassDeclaration' && node.declaration.id) {
|
|
357
|
+
exportName = node.declaration.id.name || 'default';
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
metadata.exports.push({
|
|
362
|
+
name: exportName,
|
|
363
|
+
type: 'default',
|
|
364
|
+
loc: node.loc
|
|
365
|
+
});
|
|
366
|
+
},
|
|
367
|
+
FunctionDeclaration({ node }) {
|
|
368
|
+
if (node.id && node.id.name) {
|
|
369
|
+
metadata.functions.push({
|
|
370
|
+
name: node.id.name,
|
|
371
|
+
params: node.params.map(p => {
|
|
372
|
+
if (p.type === 'Identifier') {
|
|
373
|
+
return p.name;
|
|
374
|
+
} else if (p.type === 'ObjectPattern') {
|
|
375
|
+
return 'ObjectPattern';
|
|
376
|
+
} else if (p.type === 'ArrayPattern') {
|
|
377
|
+
return 'ArrayPattern';
|
|
378
|
+
} else {
|
|
379
|
+
return '?';
|
|
380
|
+
}
|
|
381
|
+
}),
|
|
382
|
+
loc: node.loc
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
},
|
|
386
|
+
FunctionExpression({ node }) {
|
|
387
|
+
// Capture anonymous function assignments
|
|
388
|
+
if (node.id && node.id.name) {
|
|
389
|
+
metadata.functions.push({
|
|
390
|
+
name: node.id.name,
|
|
391
|
+
params: node.params.map(p => p.name || '?'),
|
|
392
|
+
loc: node.loc
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
},
|
|
396
|
+
ArrowFunctionExpression(path) {
|
|
397
|
+
// Capture arrow functions assigned to variables
|
|
398
|
+
const parent = path.parent;
|
|
399
|
+
if (parent.type === 'VariableDeclarator' && parent.id.type === 'Identifier') {
|
|
400
|
+
metadata.functions.push({
|
|
401
|
+
name: parent.id.name,
|
|
402
|
+
params: path.node.params.map(p => p.name || '?'),
|
|
403
|
+
loc: parent.loc
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
},
|
|
407
|
+
TSInterfaceDeclaration({ node }) {
|
|
408
|
+
if (node.id && node.id.name) {
|
|
409
|
+
metadata.types.push({
|
|
410
|
+
name: node.id.name,
|
|
411
|
+
kind: 'interface',
|
|
412
|
+
loc: node.loc
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
},
|
|
416
|
+
TSTypeAliasDeclaration({ node }) {
|
|
417
|
+
if (node.id && node.id.name) {
|
|
418
|
+
metadata.types.push({
|
|
419
|
+
name: node.id.name,
|
|
420
|
+
kind: 'type',
|
|
421
|
+
loc: node.loc
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
},
|
|
425
|
+
VariableDeclaration({ node }) {
|
|
426
|
+
node.declarations.forEach(decl => {
|
|
427
|
+
if (decl.id.name) {
|
|
428
|
+
const variableData = {
|
|
429
|
+
name: decl.id.name,
|
|
430
|
+
type: 'variable',
|
|
431
|
+
loc: decl.loc
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
// Capture properties of object literals
|
|
435
|
+
if (decl.init && decl.init.type === 'ObjectExpression') {
|
|
436
|
+
variableData.properties = decl.init.properties
|
|
437
|
+
.map(p => {
|
|
438
|
+
if (p.key && (p.key.name || p.key.value)) {
|
|
439
|
+
return {
|
|
440
|
+
name: p.key.name || p.key.value,
|
|
441
|
+
loc: p.loc
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
return null;
|
|
445
|
+
})
|
|
446
|
+
.filter(Boolean);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
metadata.variables.push(variableData);
|
|
450
|
+
} else if (decl.id.type === 'ObjectPattern') {
|
|
451
|
+
// Handle destructuring: const { a, b } = obj
|
|
452
|
+
decl.id.properties.forEach(prop => {
|
|
453
|
+
if (prop.key && prop.key.name) {
|
|
454
|
+
metadata.variables.push({
|
|
455
|
+
name: prop.key.name,
|
|
456
|
+
type: 'destructured',
|
|
457
|
+
loc: prop.loc
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
} else if (decl.id.type === 'ArrayPattern') {
|
|
462
|
+
// Handle array destructuring: const [a, b] = arr
|
|
463
|
+
decl.id.elements.forEach((element, index) => {
|
|
464
|
+
if (element && element.name) {
|
|
465
|
+
metadata.variables.push({
|
|
466
|
+
name: element.name,
|
|
467
|
+
type: 'destructured',
|
|
468
|
+
loc: element.loc
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
});
|
|
474
|
+
},
|
|
475
|
+
CallExpression({ node }) {
|
|
476
|
+
if (node.callee.name === 'fetch') {
|
|
477
|
+
const arg = node.arguments[0];
|
|
478
|
+
metadata.apiCalls.push({
|
|
479
|
+
type: 'fetch',
|
|
480
|
+
url: arg && arg.type === 'StringLiteral' ? arg.value : 'dynamic',
|
|
481
|
+
loc: node.loc
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
if (node.callee.name === 'require' && node.arguments.length > 0) {
|
|
485
|
+
const sourceArg = node.arguments[0];
|
|
486
|
+
if (sourceArg && sourceArg.type === 'StringLiteral') {
|
|
487
|
+
metadata.imports.push({
|
|
488
|
+
source: sourceArg.value,
|
|
489
|
+
specifiers: [],
|
|
490
|
+
type: 'require'
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
// Handle other common API calls
|
|
495
|
+
if (node.callee.type === 'MemberExpression' &&
|
|
496
|
+
node.callee.object &&
|
|
497
|
+
node.callee.object.name === 'axios') {
|
|
498
|
+
metadata.apiCalls.push({
|
|
499
|
+
type: 'axios',
|
|
500
|
+
method: node.callee.property.name,
|
|
501
|
+
loc: node.loc
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// Handle other common import patterns like import() in function calls
|
|
506
|
+
if (node.callee.type === 'Import' && node.arguments.length > 0) {
|
|
507
|
+
const sourceArg = node.arguments[0];
|
|
508
|
+
if (sourceArg && sourceArg.type === 'StringLiteral') {
|
|
509
|
+
metadata.imports.push({
|
|
510
|
+
source: sourceArg.value,
|
|
511
|
+
specifiers: [],
|
|
512
|
+
type: 'dynamic-import'
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
},
|
|
517
|
+
|
|
518
|
+
VariableDeclarator({ node }) {
|
|
519
|
+
// Handle import assignments like: const { something } = require('module')
|
|
520
|
+
if (node.init && node.init.type === 'CallExpression' &&
|
|
521
|
+
((node.init.callee.name === 'require') ||
|
|
522
|
+
(node.init.callee.property && node.init.callee.property.name === 'require') ||
|
|
523
|
+
(node.init.callee.type === 'MemberExpression' && node.init.callee.property.name === 'import')) &&
|
|
524
|
+
node.init.arguments.length > 0 &&
|
|
525
|
+
(node.init.arguments[0].type === 'StringLiteral' || node.init.arguments[0].type === 'TemplateLiteral')) {
|
|
526
|
+
|
|
527
|
+
// Extract the source from either StringLiteral or TemplateLiteral
|
|
528
|
+
let sourceValue = '';
|
|
529
|
+
if (node.init.arguments[0].type === 'StringLiteral') {
|
|
530
|
+
sourceValue = node.init.arguments[0].value;
|
|
531
|
+
} else if (node.init.arguments[0].type === 'TemplateLiteral') {
|
|
532
|
+
// For template literals, extract the quasis (static parts) and expressions
|
|
533
|
+
sourceValue = node.init.arguments[0].quasis.map(q => q.value.cooked).join('');
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
const specifiers = [];
|
|
537
|
+
if (node.id.type === 'ObjectPattern') {
|
|
538
|
+
node.id.properties.forEach(prop => {
|
|
539
|
+
const importedName = (prop.key && (prop.key.name || prop.key.value)) || null;
|
|
540
|
+
const localName = (prop.value && prop.value.name) || importedName;
|
|
541
|
+
if (importedName) {
|
|
542
|
+
specifiers.push({
|
|
543
|
+
imported: importedName,
|
|
544
|
+
local: localName
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
});
|
|
548
|
+
} else if (node.id.type === 'Identifier') {
|
|
549
|
+
specifiers.push({
|
|
550
|
+
imported: 'default',
|
|
551
|
+
local: node.id.name
|
|
552
|
+
});
|
|
553
|
+
} else if (node.id.type === 'ArrayPattern') {
|
|
554
|
+
// Handle array destructuring: const [a, b] = require('module')
|
|
555
|
+
node.id.elements.forEach((element, index) => {
|
|
556
|
+
if (element && element.name) {
|
|
557
|
+
specifiers.push({
|
|
558
|
+
imported: String(index),
|
|
559
|
+
local: element.name
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
metadata.imports.push({
|
|
566
|
+
source: sourceValue,
|
|
567
|
+
specifiers: specifiers,
|
|
568
|
+
type: 'require-assignment'
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
},
|
|
572
|
+
|
|
573
|
+
MemberExpression({ node }) {
|
|
574
|
+
// Additional member expression handling for complex import patterns
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
return metadata;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
function extractPotentialLuaInvocations(content) {
|
|
582
|
+
const invocations = [];
|
|
583
|
+
|
|
584
|
+
// Look for common Lua invocation patterns in the content
|
|
585
|
+
const patterns = [
|
|
586
|
+
/defineCommand\(\s*['"].*?['"]\s*,\s*\{[^}]*lua\s*:[^}]*(?:\.lua)?[^}]*\}/gi,
|
|
587
|
+
/defineCommand\(\s*[^,)]+\s*,\s*\{[^}]*lua\s*:[^}]*(?:\.lua)?[^}]*\}/gi,
|
|
588
|
+
/defineCommand\(\s*\{[^}]*lua\s*:[^}]*(?:\.lua)?[^}]*\}/gi,
|
|
589
|
+
/readFileSync\(['"].*\.lua['"].*\)/gi,
|
|
590
|
+
/require\(['"].*\.lua['"].*\)/gi,
|
|
591
|
+
/fs\.readFileSync\(['"].*\.lua['"].*\)/gi,
|
|
592
|
+
/loadScript\(['"].*\.lua['"].*\)/gi,
|
|
593
|
+
/loadLua\(['"].*\.lua['"].*\)/gi,
|
|
594
|
+
/load\(['"].*\.lua['"].*\)/gi
|
|
595
|
+
];
|
|
596
|
+
|
|
597
|
+
patterns.forEach(pattern => {
|
|
598
|
+
let match;
|
|
599
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
600
|
+
invocations.push({
|
|
601
|
+
pattern: match[0],
|
|
602
|
+
type: 'lua_invocation'
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
return invocations;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
module.exports = { parseFile };
|