vibe-coder-mcp
Version:
Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.
225 lines (224 loc) • 8.87 kB
JavaScript
import resolve from 'resolve';
import * as path from 'path';
import * as fs from 'fs';
import logger from '../../../logger.js';
export function resolveImport(importPath, options) {
if (options.includeAbsolutePath !== true) {
return resolveImportLegacy(importPath, options);
}
if (isBuiltinModule(importPath)) {
return { relativePath: importPath };
}
if (isExternalPackage(importPath)) {
return { relativePath: importPath };
}
try {
const basedir = path.dirname(options.fromFile);
const extensions = options.extensions || getDefaultExtensions(options.language);
let resolvedPath = null;
try {
try {
resolvedPath = resolve.sync(importPath, {
basedir,
extensions,
preserveSymlinks: false
});
logger.debug({
importPath,
resolvedPath,
securityExpanded: true
}, 'Resolved import path with expanded security boundary');
}
catch (expandedError) {
logger.debug({ err: expandedError, importPath, basedir }, 'Error resolving import with expanded boundary');
try {
const potentialPath = path.resolve(basedir, importPath);
for (const ext of extensions) {
const fullPath = `${potentialPath}${ext}`;
if (fs.existsSync(fullPath)) {
resolvedPath = fullPath;
logger.debug({
importPath,
resolvedPath,
method: 'direct-fs'
}, 'Resolved import path with direct filesystem check');
break;
}
}
if (!resolvedPath) {
throw new Error('Could not resolve with direct filesystem check');
}
}
catch (directError) {
logger.debug({ err: directError, importPath, basedir }, 'Error resolving import with direct filesystem check');
resolvedPath = resolve.sync(importPath, {
basedir,
extensions,
preserveSymlinks: false
});
}
}
let relativePath = importPath;
if (options.projectRoot && resolvedPath.startsWith(options.projectRoot)) {
relativePath = path.relative(options.projectRoot, resolvedPath);
relativePath = relativePath.replace(/\\/g, '/');
if (!relativePath.startsWith('./') && !relativePath.startsWith('../')) {
relativePath = `./${relativePath}`;
}
logger.debug({
originalPath: importPath,
resolvedPath,
relativePath,
projectRoot: options.projectRoot
}, 'Resolved import path relative to project root');
}
else {
logger.debug({
originalPath: importPath,
resolvedPath,
projectRoot: options.projectRoot
}, 'Resolved import path is outside project root');
}
return {
relativePath,
absolutePath: resolvedPath
};
}
catch (error) {
logger.debug({ err: error, importPath, fromFile: options.fromFile }, 'Error resolving absolute path');
return {
relativePath: importPath
};
}
}
catch (error) {
logger.debug({ err: error, importPath, fromFile: options.fromFile }, 'Error in import resolution');
return { relativePath: importPath };
}
}
export function clearImportCache() {
}
export function getImportCacheSize() {
return 0;
}
function resolveImportLegacy(importPath, options) {
if (isBuiltinModule(importPath)) {
return importPath;
}
if (isExternalPackage(importPath)) {
return importPath;
}
try {
const basedir = path.dirname(options.fromFile);
const extensions = options.extensions || getDefaultExtensions(options.language);
let resolvedPath = null;
try {
resolvedPath = resolve.sync(importPath, {
basedir,
extensions,
preserveSymlinks: false
});
logger.debug({
importPath,
resolvedPath,
securityExpanded: true
}, 'Resolved import path with expanded security boundary');
}
catch (expandedError) {
logger.debug({ err: expandedError, importPath, basedir }, 'Error resolving import with expanded boundary');
try {
const potentialPath = path.resolve(basedir, importPath);
let found = false;
for (const ext of extensions) {
const fullPath = `${potentialPath}${ext}`;
if (fs.existsSync(fullPath)) {
resolvedPath = fullPath;
found = true;
logger.debug({
importPath,
resolvedPath,
method: 'direct-fs'
}, 'Resolved import path with direct filesystem check');
break;
}
}
if (!found) {
throw new Error('Could not resolve with direct filesystem check');
}
}
catch (directError) {
logger.debug({ err: directError, importPath, basedir }, 'Error resolving import with direct filesystem check');
resolvedPath = resolve.sync(importPath, {
basedir,
extensions,
preserveSymlinks: false
});
}
}
let finalPath = importPath;
if (resolvedPath && options.projectRoot) {
if (resolvedPath.startsWith(options.projectRoot)) {
finalPath = path.relative(options.projectRoot, resolvedPath);
finalPath = finalPath.replace(/\\/g, '/');
if (!finalPath.startsWith('./') && !finalPath.startsWith('../')) {
finalPath = `./${finalPath}`;
}
logger.debug({
originalPath: importPath,
resolvedPath,
finalPath,
projectRoot: options.projectRoot
}, 'Resolved import path relative to project root');
}
else {
logger.debug({
originalPath: importPath,
resolvedPath,
projectRoot: options.projectRoot
}, 'Resolved import path is outside project root');
}
}
return finalPath;
}
catch (error) {
logger.debug({ err: error, importPath, fromFile: options.fromFile }, 'Error resolving import');
return importPath;
}
}
function isBuiltinModule(moduleName) {
const builtinModules = [
'assert', 'buffer', 'child_process', 'cluster', 'console', 'constants',
'crypto', 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'https',
'module', 'net', 'os', 'path', 'perf_hooks', 'process', 'punycode',
'querystring', 'readline', 'repl', 'stream', 'string_decoder', 'timers',
'tls', 'tty', 'url', 'util', 'v8', 'vm', 'wasi', 'worker_threads', 'zlib'
];
return builtinModules.includes(moduleName);
}
function isExternalPackage(moduleName) {
return !moduleName.startsWith('.') && !moduleName.startsWith('/') && !isBuiltinModule(moduleName);
}
function getDefaultExtensions(language) {
switch (language) {
case 'javascript':
return ['.js', '.json', '.node', '.mjs', '.cjs'];
case 'typescript':
return ['.ts', '.tsx', '.js', '.jsx', '.json', '.node'];
case 'python':
return ['.py', '.pyw', '.pyc', '.pyo', '.pyd'];
case 'java':
return ['.java', '.class', '.jar'];
case 'csharp':
return ['.cs', '.dll'];
case 'go':
return ['.go'];
case 'ruby':
return ['.rb', '.rake', '.gemspec'];
case 'rust':
return ['.rs'];
case 'php':
return ['.php'];
default:
return ['.js', '.json', '.node'];
}
}