testLanguageServiceHost.ts•2.25 kB
import * as ts from 'typescript'
import { existsSync } from 'fs'
/**
* Create a memory-efficient language service host for tests
* This host limits type loading to reduce memory usage
*/
export function createTestLanguageServiceHost(
projectPath: string,
parsedConfig: ts.ParsedCommandLine,
files: Map<string, string>
): ts.LanguageServiceHost {
const fileVersions = new Map<string, number>()
// Initialize file versions
for (const file of parsedConfig.fileNames) {
files.set(file, '')
fileVersions.set(file, 0)
}
return {
getScriptFileNames: () => Array.from(files.keys()),
getScriptVersion: (fileName) => fileVersions.get(fileName)?.toString() || '0',
getScriptSnapshot: (fileName) => {
// Skip loading type definitions from node_modules in tests
if (fileName.includes('node_modules') && fileName.endsWith('.d.ts')) {
// Only allow essential Node.js types
if (!fileName.includes('@types/node')) {
return undefined
}
}
if (!existsSync(fileName)) {
return undefined
}
const content = ts.sys.readFile(fileName)
return content ? ts.ScriptSnapshot.fromString(content) : undefined
},
getCurrentDirectory: () => projectPath,
getCompilationSettings: () => ({
...parsedConfig.options,
// Override settings to reduce memory usage in tests
skipLibCheck: true,
skipDefaultLibCheck: true,
noLib: true,
types: [],
typeRoots: [],
}),
getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options),
fileExists: (fileName) => {
// Prevent loading unnecessary files
if (fileName.includes('node_modules') && !fileName.includes('@types/node')) {
return false
}
return ts.sys.fileExists(fileName)
},
readFile: ts.sys.readFile,
readDirectory: ts.sys.readDirectory,
directoryExists: ts.sys.directoryExists,
getDirectories: ts.sys.getDirectories,
}
}