vibe-coder-mcp
Version:
Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.
218 lines (217 loc) • 9.7 kB
JavaScript
import { getNodeText } from '../astAnalyzer.js';
import logger from '../../../logger.js';
export function isLikelyImport(node) {
try {
const text = node.text.toLowerCase();
return text.includes('import') ||
text.includes('require') ||
text.includes('from');
}
catch (error) {
logger.debug({ err: error, nodeType: node.type }, 'Error checking if node is likely an import');
return false;
}
}
export function tryExtractImportPath(node) {
try {
const text = node.text;
const importFromMatch = text.match(/from\s+['"]([^'"]+)['"]/);
if (importFromMatch && importFromMatch[1]) {
return importFromMatch[1];
}
const dynamicImportMatch = text.match(/import\s*\(\s*['"]([^'"]+)['"]\s*\)/);
if (dynamicImportMatch && dynamicImportMatch[1]) {
return dynamicImportMatch[1];
}
const requireMatch = text.match(/require\s*\(\s*['"]([^'"]+)['"]\s*\)/);
if (requireMatch && requireMatch[1]) {
return requireMatch[1];
}
return null;
}
catch (error) {
logger.debug({ err: error, nodeType: node.type }, 'Error extracting import path with regex');
return null;
}
}
export function extractJSImports(node, sourceCode) {
const imports = [];
try {
switch (node.type) {
case 'import_statement':
case 'import_declaration': {
const source = node.childForFieldName('source');
if (source && source.text) {
const path = source.text.replace(/['"`]/g, '');
imports.push({
path,
type: 'static',
isExternalPackage: !path.startsWith('.') && !path.startsWith('/'),
importedItems: extractImportedItemsFromES6Import(node, sourceCode),
startLine: node.startPosition.row + 1,
endLine: node.endPosition.row + 1
});
}
break;
}
case 'call_expression': {
const funcName = node.childForFieldName('function')?.text;
if (funcName === 'import') {
const args = node.childForFieldName('arguments');
const firstArg = args?.firstChild;
if (firstArg && firstArg.text) {
const path = firstArg.text.replace(/['"`]/g, '');
imports.push({
path,
type: 'dynamic',
isExternalPackage: !path.startsWith('.') && !path.startsWith('/'),
startLine: node.startPosition.row + 1,
endLine: node.endPosition.row + 1
});
}
}
else if (funcName === 'require') {
const args = node.childForFieldName('arguments');
const firstArg = args?.firstChild;
if (firstArg && firstArg.text) {
const path = firstArg.text.replace(/['"`]/g, '');
imports.push({
path,
type: 'commonjs',
isExternalPackage: !path.startsWith('.') && !path.startsWith('/'),
startLine: node.startPosition.row + 1,
endLine: node.endPosition.row + 1
});
}
}
break;
}
case 'variable_declaration': {
const declarator = node.childForFieldName('declarator');
const value = declarator?.childForFieldName('value');
if (value?.type === 'call_expression' &&
value.childForFieldName('function')?.text === 'require') {
const args = value.childForFieldName('arguments');
const firstArg = args?.firstChild;
if (firstArg && firstArg.text) {
const path = firstArg.text.replace(/['"`]/g, '');
imports.push({
path,
type: 'commonjs',
isExternalPackage: !path.startsWith('.') && !path.startsWith('/'),
startLine: node.startPosition.row + 1,
endLine: node.endPosition.row + 1
});
}
}
break;
}
}
if (imports.length === 0 && isLikelyImport(node)) {
const extractedPath = tryExtractImportPath(node);
if (extractedPath) {
imports.push({
path: extractedPath,
type: node.text.includes('import(') ? 'dynamic' :
node.text.includes('require(') ? 'commonjs' : 'extracted',
isExternalPackage: !extractedPath.startsWith('.') && !extractedPath.startsWith('/'),
startLine: node.startPosition.row + 1,
endLine: node.endPosition.row + 1
});
}
}
}
catch (error) {
logger.debug({ err: error, nodeType: node.type }, 'Error extracting JS/TS imports');
}
return imports;
}
export function extractImportedItemsFromES6Import(node, sourceCode) {
try {
const items = [];
if (node.type === 'import_statement' || node.type === 'import_declaration') {
const defaultSpecifier = node.childForFieldName('default');
if (defaultSpecifier) {
items.push({
name: getNodeText(defaultSpecifier, sourceCode),
isDefault: true,
isNamespace: false
});
}
const namedImports = node.childForFieldName('named_imports');
if (namedImports) {
for (let i = 0; i < namedImports.namedChildCount; i++) {
const specifier = namedImports.namedChild(i);
if (specifier) {
const importedName = specifier.childForFieldName('name');
const aliasName = specifier.childForFieldName('alias');
if (importedName) {
items.push({
name: getNodeText(importedName, sourceCode),
alias: aliasName ? getNodeText(aliasName, sourceCode) : undefined,
isDefault: false,
isNamespace: false
});
}
}
}
}
const namespaceImport = node.childForFieldName('namespace_import');
if (namespaceImport) {
const name = namespaceImport.childForFieldName('name');
if (name) {
items.push({
name: getNodeText(name, sourceCode),
isDefault: false,
isNamespace: true
});
}
}
const importClause = node.childForFieldName('import_clause');
if (importClause) {
const defaultImport = importClause.childForFieldName('default');
if (defaultImport) {
items.push({
name: getNodeText(defaultImport, sourceCode),
isDefault: true,
isNamespace: false
});
}
const namedImportsInClause = importClause.childForFieldName('named_imports');
if (namedImportsInClause && namedImportsInClause.namedChildCount > 0) {
for (let i = 0; i < namedImportsInClause.namedChildCount; i++) {
const specifier = namedImportsInClause.namedChild(i);
if (specifier) {
const importedName = specifier.childForFieldName('name');
const aliasName = specifier.childForFieldName('alias');
if (importedName) {
items.push({
name: getNodeText(importedName, sourceCode),
alias: aliasName ? getNodeText(aliasName, sourceCode) : undefined,
isDefault: false,
isNamespace: false
});
}
}
}
}
const namespaceImportInClause = importClause.childForFieldName('namespace_import');
if (namespaceImportInClause) {
const name = namespaceImportInClause.childForFieldName('name');
if (name) {
items.push({
name: getNodeText(name, sourceCode),
isDefault: false,
isNamespace: true
});
}
}
}
}
return items.length > 0 ? items : undefined;
}
catch (error) {
logger.debug({ err: error, nodeType: node.type }, 'Error extracting imported items from ES6 import');
return undefined;
}
}