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.
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,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 };