vibe-coder-mcp
Version:
Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.
166 lines (165 loc) • 5.55 kB
JavaScript
import resolve from 'resolve';
import * as path from 'path';
import logger from '../../../logger.js';
class LRUCache {
cache;
maxSize;
constructor(maxSize) {
this.cache = new Map();
this.maxSize = maxSize;
}
get(key) {
const value = this.cache.get(key);
if (value !== undefined) {
this.cache.delete(key);
this.cache.set(key, value);
}
return value;
}
set(key, value) {
if (this.cache.has(key)) {
this.cache.delete(key);
}
if (this.cache.size >= this.maxSize) {
const firstKey = this.cache.keys().next().value;
if (firstKey !== undefined) {
this.cache.delete(firstKey);
}
}
this.cache.set(key, value);
}
has(key) {
return this.cache.has(key);
}
clear() {
this.cache.clear();
}
get size() {
return this.cache.size;
}
keys() {
return this.cache.keys();
}
delete(key) {
return this.cache.delete(key);
}
}
const importCache = new LRUCache(1000);
export function resolveImport(importPath, options) {
if (isBuiltinModule(importPath)) {
return importPath;
}
const cacheKey = `${options.fromFile}:${importPath}:${options.language}`;
if (options.useCache !== false && importCache.has(cacheKey)) {
return importCache.get(cacheKey);
}
try {
if (isExternalPackage(importPath)) {
const packageName = getPackageName(importPath);
try {
const basedir = path.dirname(options.fromFile);
const resolvedPackage = resolve.sync(packageName, {
basedir,
preserveSymlinks: false
});
logger.debug({ packageName, resolvedPackage }, 'Package exists but specific import cannot be resolved');
return importPath;
}
catch (packageError) {
logger.debug({ err: packageError, packageName }, 'Package not found');
return importPath;
}
}
const basedir = path.dirname(options.fromFile);
const extensions = options.extensions || getDefaultExtensions(options.language);
const resolvedPath = resolve.sync(importPath, {
basedir,
extensions,
preserveSymlinks: false
});
let finalPath = resolvedPath;
if (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');
}
}
if (options.useCache !== false) {
importCache.set(cacheKey, finalPath);
}
return finalPath;
}
catch (error) {
logger.debug({ err: error, importPath, fromFile: options.fromFile }, 'Error resolving import');
return importPath;
}
}
export function clearImportCache() {
importCache.clear();
}
export function getImportCacheSize() {
return importCache.size;
}
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 getPackageName(moduleName) {
if (moduleName.startsWith('@')) {
const parts = moduleName.split('/');
if (parts.length >= 2) {
return `${parts[0]}/${parts[1]}`;
}
}
const parts = moduleName.split('/');
return parts[0];
}
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'];
}
}