arcvision 0.2.3 → 0.2.4

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.
@@ -1,343 +0,0 @@
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
- function parseFile(filePath) {
7
- const content = fs.readFileSync(filePath, 'utf-8');
8
- let ast;
9
-
10
- // Enhanced parser options with more comprehensive plugin support
11
- const parserOptions = {
12
- sourceType: 'unambiguous', // Auto-detect between script and module
13
- allowImportExportEverywhere: true,
14
- allowReturnOutsideFunction: true,
15
- allowSuperOutsideMethod: true,
16
- plugins: [
17
- 'jsx',
18
- 'typescript',
19
- 'decorators-legacy',
20
- 'classProperties',
21
- 'exportDefaultFrom',
22
- 'exportNamespaceFrom',
23
- 'dynamicImport',
24
- 'functionBind',
25
- 'nullishCoalescingOperator',
26
- 'optionalChaining',
27
- 'numericSeparator',
28
- 'bigInt',
29
- 'importMeta',
30
- 'asyncGenerators',
31
- 'optionalCatchBinding',
32
- 'throwExpressions',
33
- 'logicalAssignment',
34
- 'nullishCoalescingOperator',
35
- 'doExpressions',
36
- 'pipeOperator',
37
- 'recordAndTuple',
38
- 'moduleBlocks',
39
- 'topLevelAwait',
40
- 'v8intrinsic',
41
- 'partialApplication',
42
- 'regexpUnicodeSets',
43
- 'destructuringPrivate',
44
- 'decoratorAutoAccessors'
45
- ]
46
- };
47
-
48
- try {
49
- ast = parser.parse(content, parserOptions);
50
- } catch (error) {
51
- // Log the parsing error but don't throw - let the scanner continue
52
- console.warn(`⚠️ Failed to parse ${filePath}: ${error.message}`);
53
- // Return minimal metadata for files that can't be parsed
54
- return {
55
- id: filePath,
56
- imports: [],
57
- exports: [],
58
- functions: [],
59
- apiCalls: []
60
- };
61
- }
62
-
63
- const metadata = {
64
- id: filePath,
65
- imports: [],
66
- exports: [],
67
- functions: [],
68
- apiCalls: [],
69
- classes: [],
70
- variables: [],
71
- dependencies: []
72
- };
73
-
74
- traverse(ast, {
75
- ImportDeclaration({ node }) {
76
- const importSource = node.source.value;
77
- const specifiers = [];
78
-
79
- node.specifiers.forEach(spec => {
80
- if (spec.imported && spec.local) {
81
- // Named import: import { name as alias } from 'source'
82
- specifiers.push({
83
- imported: spec.imported.name || spec.imported.value,
84
- local: spec.local.name
85
- });
86
- } else if (spec.local) {
87
- // Default import: import name from 'source'
88
- specifiers.push({
89
- imported: 'default',
90
- local: spec.local.name
91
- });
92
- }
93
- });
94
-
95
- metadata.imports.push({
96
- source: importSource,
97
- specifiers: specifiers
98
- });
99
- },
100
- ImportExpression({ node }) {
101
- // Handle dynamic imports: import('module')
102
- if (node.source && node.source.type === 'StringLiteral') {
103
- metadata.imports.push({
104
- source: node.source.value,
105
- specifiers: [],
106
- dynamic: true
107
- });
108
- }
109
- },
110
- ExportNamedDeclaration({ node }) {
111
- // Handle export { X, Y, Z } from './file' statements
112
- if (node.source) {
113
- const specifiers = [];
114
- if (node.specifiers) {
115
- node.specifiers.forEach(spec => {
116
- specifiers.push({
117
- exported: spec.exported.name || spec.exported.value || spec.exported.value,
118
- local: spec.local ? spec.local.name : spec.exported.name || spec.exported.value
119
- });
120
- });
121
- }
122
-
123
- metadata.imports.push({
124
- source: node.source.value,
125
- specifiers: specifiers,
126
- type: 'export-from'
127
- });
128
- }
129
- // Handle export declarations without source (local exports)
130
- if (node.declaration) {
131
- if (node.declaration.type === 'FunctionDeclaration' && node.declaration.id) {
132
- metadata.exports.push({
133
- name: node.declaration.id.name,
134
- type: 'function',
135
- loc: node.declaration.loc
136
- });
137
- } else if (node.declaration.type === 'ClassDeclaration' && node.declaration.id) {
138
- metadata.exports.push({
139
- name: node.declaration.id.name,
140
- type: 'class',
141
- loc: node.declaration.loc
142
- });
143
- } else if (node.declaration.type === 'VariableDeclaration') {
144
- node.declaration.declarations.forEach(decl => {
145
- if (decl.id.name) {
146
- metadata.exports.push({
147
- name: decl.id.name,
148
- type: 'variable',
149
- loc: decl.loc
150
- });
151
- } else if (decl.id.type === 'ObjectPattern') {
152
- // Handle destructuring exports: export const { a, b } = obj
153
- decl.id.properties.forEach(prop => {
154
- if (prop.key.name) {
155
- metadata.exports.push({
156
- name: prop.key.name,
157
- type: 'variable',
158
- loc: prop.loc
159
- });
160
- }
161
- });
162
- } else if (decl.id.type === 'ArrayPattern') {
163
- // Handle array destructuring exports: export const [a, b] = arr
164
- decl.id.elements.forEach(element => {
165
- if (element && element.name) {
166
- metadata.exports.push({
167
- name: element.name,
168
- type: 'variable',
169
- loc: element.loc
170
- });
171
- }
172
- });
173
- }
174
- });
175
- }
176
- }
177
- },
178
- ExportAllDeclaration({ node }) {
179
- // Handle export * from './file' statements
180
- metadata.imports.push({
181
- source: node.source.value,
182
- specifiers: ['*'],
183
- type: 'export-all'
184
- });
185
- },
186
- ExportDefaultDeclaration({ node }) {
187
- let exportName = 'default';
188
-
189
- if (node.declaration) {
190
- if (node.declaration.type === 'FunctionDeclaration' && node.declaration.id) {
191
- exportName = node.declaration.id.name || 'default';
192
- } else if (node.declaration.type === 'ClassDeclaration' && node.declaration.id) {
193
- exportName = node.declaration.id.name || 'default';
194
- }
195
- }
196
-
197
- metadata.exports.push({
198
- name: exportName,
199
- type: 'default',
200
- loc: node.loc
201
- });
202
- },
203
- FunctionDeclaration({ node }) {
204
- if (node.id && node.id.name) {
205
- metadata.functions.push({
206
- name: node.id.name,
207
- params: node.params.map(p => {
208
- if (p.type === 'Identifier') {
209
- return p.name;
210
- } else if (p.type === 'ObjectPattern') {
211
- return 'ObjectPattern';
212
- } else if (p.type === 'ArrayPattern') {
213
- return 'ArrayPattern';
214
- } else {
215
- return '?';
216
- }
217
- }),
218
- loc: node.loc
219
- });
220
- }
221
- },
222
- FunctionExpression({ node }) {
223
- // Capture anonymous function assignments
224
- if (node.id && node.id.name) {
225
- metadata.functions.push({
226
- name: node.id.name,
227
- params: node.params.map(p => p.name || '?'),
228
- loc: node.loc
229
- });
230
- }
231
- },
232
- ArrowFunctionExpression({ node }) {
233
- // Capture arrow functions if they're part of variable declarations
234
- // This helps identify function definitions in modern JS
235
- },
236
- ClassDeclaration({ node }) {
237
- if (node.id && node.id.name) {
238
- metadata.classes.push({
239
- name: node.id.name,
240
- superClass: node.superClass ? node.superClass.name : null,
241
- loc: node.loc
242
- });
243
- }
244
- },
245
- VariableDeclaration({ node }) {
246
- node.declarations.forEach(decl => {
247
- if (decl.id.name) {
248
- metadata.variables.push({
249
- name: decl.id.name,
250
- type: 'variable',
251
- loc: decl.loc
252
- });
253
- } else if (decl.id.type === 'ObjectPattern') {
254
- // Handle destructuring: const { a, b } = obj
255
- decl.id.properties.forEach(prop => {
256
- if (prop.key && prop.key.name) {
257
- metadata.variables.push({
258
- name: prop.key.name,
259
- type: 'destructured',
260
- loc: prop.loc
261
- });
262
- }
263
- });
264
- } else if (decl.id.type === 'ArrayPattern') {
265
- // Handle array destructuring: const [a, b] = arr
266
- decl.id.elements.forEach((element, index) => {
267
- if (element && element.name) {
268
- metadata.variables.push({
269
- name: element.name,
270
- type: 'destructured',
271
- loc: element.loc
272
- });
273
- }
274
- });
275
- }
276
- });
277
- },
278
- CallExpression({ node }) {
279
- if (node.callee.name === 'fetch') {
280
- const arg = node.arguments[0];
281
- metadata.apiCalls.push({
282
- type: 'fetch',
283
- url: arg && arg.type === 'StringLiteral' ? arg.value : 'dynamic',
284
- loc: node.loc
285
- });
286
- }
287
- if (node.callee.name === 'require' && node.arguments.length > 0) {
288
- const sourceArg = node.arguments[0];
289
- if (sourceArg && sourceArg.type === 'StringLiteral') {
290
- metadata.imports.push({
291
- source: sourceArg.value,
292
- specifiers: [],
293
- type: 'require'
294
- });
295
- }
296
- }
297
- // Handle other common API calls
298
- if (node.callee.type === 'MemberExpression' &&
299
- node.callee.object &&
300
- node.callee.object.name === 'axios') {
301
- metadata.apiCalls.push({
302
- type: 'axios',
303
- method: node.callee.property.name,
304
- loc: node.loc
305
- });
306
- }
307
-
308
- // Handle other common import patterns like import() in function calls
309
- if (node.callee.type === 'Import' && node.arguments.length > 0) {
310
- const sourceArg = node.arguments[0];
311
- if (sourceArg && sourceArg.type === 'StringLiteral') {
312
- metadata.imports.push({
313
- source: sourceArg.value,
314
- specifiers: [],
315
- type: 'dynamic-import'
316
- });
317
- }
318
- }
319
- },
320
-
321
- VariableDeclarator({ node }) {
322
- // Handle import assignments like: const { something } = require('module')
323
- if (node.init && node.init.type === 'CallExpression' &&
324
- node.init.callee.name === 'require' &&
325
- node.init.arguments.length > 0 &&
326
- node.init.arguments[0].type === 'StringLiteral') {
327
- metadata.imports.push({
328
- source: node.init.arguments[0].value,
329
- specifiers: [],
330
- type: 'require-assignment'
331
- });
332
- }
333
- },
334
-
335
- MemberExpression({ node }) {
336
- // Additional member expression handling for complex import patterns
337
- }
338
- });
339
-
340
- return metadata;
341
- }
342
-
343
- module.exports = { parseFile };
@@ -1,174 +0,0 @@
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, barrel files, and implicit extensions
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
- * @returns {string|null} The resolved absolute file path or null if not found
12
- */
13
- function resolveImport(importPath, importerPath, projectRoot, tsconfig) {
14
- // If it's an absolute path or URL, skip resolution
15
- if (importPath.startsWith('http://') || importPath.startsWith('https://') ||
16
- importPath.startsWith('data:') || importPath.startsWith('file:')) {
17
- return null;
18
- }
19
-
20
- // Handle relative imports
21
- if (importPath.startsWith('.')) {
22
- // Resolve relative to importer
23
- let resolvedPath = path.resolve(path.dirname(importerPath), importPath);
24
-
25
- // Try with various extensions in order of preference
26
- const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.json'];
27
- for (const ext of extensions) {
28
- if (fs.existsSync(resolvedPath + ext)) {
29
- return resolvedPath + ext;
30
- }
31
- }
32
-
33
- // Try as directory with index files
34
- const indexFiles = ['index.ts', 'index.tsx', 'index.js', 'index.jsx', 'index.json'];
35
- for (const idxFile of indexFiles) {
36
- const indexPath = path.join(resolvedPath, idxFile);
37
- if (fs.existsSync(indexPath)) {
38
- return indexPath;
39
- }
40
- }
41
-
42
- // If original path exists as-is
43
- if (fs.existsSync(resolvedPath)) {
44
- return resolvedPath;
45
- }
46
-
47
- return null;
48
- }
49
-
50
- // Handle path aliases (like @/components/, ~/utils/, etc.)
51
- if (tsconfig && tsconfig.paths) {
52
- const paths = tsconfig.paths;
53
-
54
- // Sort aliases by length (descending) to match longer patterns first
55
- const sortedAliases = Object.keys(paths).sort((a, b) => b.length - a.length);
56
-
57
- for (const aliasPattern of sortedAliases) {
58
- const aliasTargets = paths[aliasPattern];
59
-
60
- // Handle pattern like "@/*" -> ["./src/*"]
61
- if (aliasPattern.includes('*')) {
62
- const patternBase = aliasPattern.replace(/\*.*$/, '');
63
-
64
- if (importPath.startsWith(patternBase)) {
65
- const suffix = importPath.substring(patternBase.length);
66
-
67
- for (const target of aliasTargets) {
68
- const targetBase = target.replace(/\*.*$/, '');
69
- const targetPath = path.resolve(projectRoot, path.join(targetBase, suffix));
70
-
71
- // Try with extensions
72
- const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.json'];
73
- for (const ext of extensions) {
74
- if (fs.existsSync(targetPath + ext)) {
75
- return targetPath + ext;
76
- }
77
- }
78
-
79
- // Try as directory with index files
80
- const indexFiles = ['index.ts', 'index.tsx', 'index.js', 'index.jsx', 'index.json'];
81
- for (const idxFile of indexFiles) {
82
- const indexPath = path.join(targetPath, idxFile);
83
- if (fs.existsSync(indexPath)) {
84
- return indexPath;
85
- }
86
- }
87
-
88
- // Try exact path
89
- if (fs.existsSync(targetPath)) {
90
- return targetPath;
91
- }
92
- }
93
- }
94
- } else {
95
- // Handle exact match patterns
96
- if (importPath === aliasPattern || importPath.startsWith(aliasPattern + '/')) {
97
- for (const target of aliasTargets) {
98
- let targetPath = path.resolve(projectRoot, target);
99
-
100
- // If importPath is longer than the alias pattern, add the remaining part
101
- if (importPath.length > aliasPattern.length) {
102
- const remainingPath = importPath.substring(aliasPattern.length);
103
- targetPath = path.join(targetPath, remainingPath);
104
- }
105
-
106
- // Try with extensions
107
- const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.json'];
108
- for (const ext of extensions) {
109
- if (fs.existsSync(targetPath + ext)) {
110
- return targetPath + ext;
111
- }
112
- }
113
-
114
- // Try as directory with index files
115
- const indexFiles = ['index.ts', 'index.tsx', 'index.js', 'index.jsx', 'index.json'];
116
- for (const idxFile of indexFiles) {
117
- const indexPath = path.join(targetPath, idxFile);
118
- if (fs.existsSync(indexPath)) {
119
- return indexPath;
120
- }
121
- }
122
-
123
- // Try exact path
124
- if (fs.existsSync(targetPath)) {
125
- return targetPath;
126
- }
127
- }
128
- }
129
- }
130
- }
131
- }
132
-
133
- // Handle baseUrl if configured
134
- if (tsconfig && tsconfig.baseUrl && !importPath.startsWith('.')) {
135
- let resolvedPath = path.resolve(projectRoot, tsconfig.baseUrl, importPath);
136
-
137
- // Try with extensions
138
- const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.json'];
139
- for (const ext of extensions) {
140
- if (fs.existsSync(resolvedPath + ext)) {
141
- return resolvedPath + ext;
142
- }
143
- }
144
-
145
- // Try as directory with index files
146
- const indexFiles = ['index.ts', 'index.tsx', 'index.js', 'index.jsx', 'index.json'];
147
- for (const idxFile of indexFiles) {
148
- const indexPath = path.join(resolvedPath, idxFile);
149
- if (fs.existsSync(indexPath)) {
150
- return indexPath;
151
- }
152
- }
153
-
154
- // Try exact path
155
- if (fs.existsSync(resolvedPath)) {
156
- return resolvedPath;
157
- }
158
- }
159
-
160
- // Handle node_modules resolution
161
- if (!importPath.startsWith('.')) {
162
- // Check if it's a node module
163
- try {
164
- const resolved = require.resolve(importPath, { paths: [path.dirname(importerPath)] });
165
- return resolved;
166
- } catch (e) {
167
- // If require.resolve fails, it's not a node module
168
- }
169
- }
170
-
171
- return null;
172
- }
173
-
174
- module.exports = { resolveImport };