"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getSolutionErrors = exports.makeSolutionBuilderHost = exports.makeWatchHost = exports.updateFileWithText = exports.makeServicesHost = void 0; const path = require("path"); const config_1 = require("./config"); const constants = require("./constants"); const instances_1 = require("./instances"); const resolver_1 = require("./resolver"); const utils_1 = require("./utils"); function makeResolversAndModuleResolutionHost(scriptRegex, loader, instance, fileExists, enableFileCaching) { const { compiler, compilerOptions, appendTsTsxSuffixesIfRequired, loaderOptions: { resolveModuleName: customResolveModuleName, resolveTypeReferenceDirective: customResolveTypeReferenceDirective, }, } = instance; const newLine = compilerOptions.newLine === constants.CarriageReturnLineFeedCode ? constants.CarriageReturnLineFeed : compilerOptions.newLine === constants.LineFeedCode ? constants.LineFeed : constants.EOL; // loader.context seems to work fine on Linux / Mac regardless causes problems for @types resolution on Windows for TypeScript < 2.3 const getCurrentDirectory = () => loader.context; // make a (sync) resolver that follows webpack's rules const resolveSync = (0, resolver_1.makeResolver)(loader._compiler.options); const moduleResolutionHost = { trace: logData => instance.log.log(logData), fileExists, readFile, realpath: compiler.sys.realpath && realpath, directoryExists, getCurrentDirectory, getDirectories, readDirectory, useCaseSensitiveFileNames: () => (0, utils_1.useCaseSensitiveFileNames)(compiler, instance.loaderOptions), getNewLine: () => newLine, getDefaultLibFileName: options => compiler.getDefaultLibFilePath(options), }; if (enableFileCaching) { addCache(moduleResolutionHost); } return makeResolvers(compiler, compilerOptions, moduleResolutionHost, customResolveTypeReferenceDirective, customResolveModuleName, resolveSync, appendTsTsxSuffixesIfRequired, scriptRegex, instance); function readFile(filePath, encoding) { return (instance.compiler.sys.readFile(filePath, encoding) || (0, utils_1.fsReadFile)(filePath, encoding)); } function directoryExists(directoryName) { return compiler.sys.directoryExists(directoryName); } function realpath(path) { return compiler.sys.realpath(path); } function getDirectories(path) { return compiler.sys.getDirectories(path); } function readDirectory(path, extensions, exclude, include, depth) { return compiler.sys.readDirectory(path, extensions, exclude, include, depth); } } /** * Create the TypeScript language service */ function makeServicesHost(scriptRegex, loader, instance, projectReferences) { const { compiler, compilerOptions, files, filePathKeyMapper } = instance; const { moduleResolutionHost, resolveModuleNames, resolveTypeReferenceDirectives, } = makeResolversAndModuleResolutionHost(scriptRegex, loader, instance, filePathToCheck => compiler.sys.fileExists(filePathToCheck) || (0, utils_1.fsReadFile)(filePathToCheck) !== undefined, instance.loaderOptions.experimentalFileCaching); const servicesHost = { getProjectVersion: () => `${instance.version}`, getProjectReferences: () => projectReferences, getScriptFileNames: () => [...files.values()] .map(({ fileName }) => fileName) .filter(filePath => filePath.match(scriptRegex)), getScriptVersion: (fileName) => { var _a; fileName = path.normalize(fileName); const key = filePathKeyMapper(fileName); const file = files.get(key); if (file) { return file.version.toString(); } const outputFileAndKey = (_a = instance.solutionBuilderHost) === null || _a === void 0 ? void 0 : _a.getOutputFileAndKeyFromReferencedProject(fileName); if (outputFileAndKey !== undefined) { instance.solutionBuilderHost.outputAffectingInstanceVersion.set(outputFileAndKey.key, true); } return outputFileAndKey && outputFileAndKey.outputFile ? outputFileAndKey.outputFile : ''; }, getScriptSnapshot: (fileName) => { // This is called any time TypeScript needs a file's text // We either load from memory or from disk fileName = path.normalize(fileName); const key = filePathKeyMapper(fileName); let file = files.get(key); if (file === undefined) { if (instance.solutionBuilderHost) { const outputFileAndKey = instance.solutionBuilderHost.getOutputFileTextAndKeyFromReferencedProject(fileName); if (outputFileAndKey !== undefined) { instance.solutionBuilderHost.outputAffectingInstanceVersion.set(outputFileAndKey.key, true); return outputFileAndKey && outputFileAndKey.text !== undefined ? compiler.ScriptSnapshot.fromString(outputFileAndKey.text) : undefined; } } const text = moduleResolutionHost.readFile(fileName); if (text === undefined) { return undefined; } file = { fileName, version: 0, text }; files.set(key, file); } return compiler.ScriptSnapshot.fromString(file.text); }, ...moduleResolutionHost, getCompilationSettings: () => compilerOptions, log: moduleResolutionHost.trace, // used for (/// ) see https://github.com/Realytics/fork-ts-checker-webpack-plugin/pull/250#issuecomment-485061329 resolveTypeReferenceDirectives, resolveModuleNames, getCustomTransformers: () => instance.transformers, }; return servicesHost; } exports.makeServicesHost = makeServicesHost; function makeResolvers(compiler, compilerOptions, moduleResolutionHost, customResolveTypeReferenceDirective, customResolveModuleName, resolveSync, appendTsTsxSuffixesIfRequired, scriptRegex, instance) { const resolveModuleName = makeResolveModuleName(compiler, compilerOptions, moduleResolutionHost, customResolveModuleName, instance); const resolveModuleNames = (moduleNames, containingFile, _reusedNames, redirectedReference, _, containingSourceFile) => { const resolvedModules = moduleNames.map(moduleName => resolveModule(resolveSync, resolveModuleName, appendTsTsxSuffixesIfRequired, scriptRegex, moduleName, containingFile, redirectedReference, containingSourceFile)); (0, utils_1.populateDependencyGraph)(resolvedModules, instance, containingFile); return resolvedModules; }; const resolveTypeReferenceDirective = makeResolveTypeReferenceDirective(compiler, compilerOptions, moduleResolutionHost, customResolveTypeReferenceDirective, instance); const resolveTypeReferenceDirectives = (typeDirectiveNames, containingFile, redirectedReference, options, containingFileMode // new impliedNodeFormat is accepted by compilerHost ) => typeDirectiveNames.map(directive => resolveTypeReferenceDirective(directive, containingFile, options, redirectedReference, containingFileMode).resolvedTypeReferenceDirective); return { resolveTypeReferenceDirectives, resolveModuleNames, moduleResolutionHost, }; } function createWatchFactory(filePathKeyMapper, compiler) { const watchedFiles = new Map(); const watchedDirectories = new Map(); const watchedDirectoriesRecursive = new Map(); return { watchedFiles, watchedDirectories, watchedDirectoriesRecursive, invokeFileWatcher, watchFile, watchDirectory, }; function invokeWatcherCallbacks(map, key, fileName, eventKind) { var _a; const callbacks = (_a = map.get(filePathKeyMapper(key))) === null || _a === void 0 ? void 0 : _a.callbacks; if (callbacks !== undefined && callbacks.length) { // The array copy is made to ensure that even if one of the callback removes the callbacks, // we dont miss any callbacks following it const cbs = callbacks.slice(); for (const cb of cbs) { cb(fileName, eventKind); } return true; } return false; } function invokeFileWatcher(fileName, eventKind) { fileName = path.normalize(fileName); let result = invokeWatcherCallbacks(watchedFiles, fileName, fileName, eventKind); if (eventKind !== compiler.FileWatcherEventKind.Changed) { const directory = path.dirname(fileName); result = invokeWatcherCallbacks(watchedDirectories, directory, fileName) || result; result = invokeRecursiveDirectoryWatcher(directory, fileName) || result; } return result; } ``; function invokeRecursiveDirectoryWatcher(directory, fileAddedOrRemoved) { directory = path.normalize(directory); let result = invokeWatcherCallbacks(watchedDirectoriesRecursive, directory, fileAddedOrRemoved); const basePath = path.dirname(directory); if (directory !== basePath) { result = invokeRecursiveDirectoryWatcher(basePath, fileAddedOrRemoved) || result; } return result; } function createWatcher(file, callbacks, callback) { const key = filePathKeyMapper(file); const existing = callbacks.get(key); if (existing === undefined) { callbacks.set(key, { fileName: path.normalize(file), callbacks: [callback], }); } else { existing.callbacks.push(callback); } return { close: () => { const existing = callbacks.get(key); if (existing !== undefined) { (0, utils_1.unorderedRemoveItem)(existing.callbacks, callback); if (!existing.callbacks.length) { callbacks.delete(key); } } }, }; } function watchFile(fileName, callback, _pollingInterval) { return createWatcher(fileName, watchedFiles, callback); } function watchDirectory(fileName, callback, recursive) { return createWatcher(fileName, recursive === true ? watchedDirectoriesRecursive : watchedDirectories, callback); } } function updateFileWithText(instance, key, filePath, text) { const nFilePath = path.normalize(filePath); const file = instance.files.get(key) || instance.otherFiles.get(key); if (file !== undefined) { const newText = text(nFilePath); if (newText !== file.text) { file.text = newText; file.version++; file.modifiedTime = new Date(); instance.version++; if (!instance.modifiedFiles) { instance.modifiedFiles = new Map(); } instance.modifiedFiles.set(key, true); if (instance.watchHost !== undefined) { instance.watchHost.invokeFileWatcher(nFilePath, instance.compiler.FileWatcherEventKind.Changed); } } } } exports.updateFileWithText = updateFileWithText; /** * Create the TypeScript Watch host */ function makeWatchHost(scriptRegex, loader, instance, projectReferences) { const { compiler, compilerOptions, files, otherFiles, filePathKeyMapper } = instance; const { watchFile, watchDirectory, invokeFileWatcher } = createWatchFactory(filePathKeyMapper, compiler); const { moduleResolutionHost, resolveModuleNames, resolveTypeReferenceDirectives, } = makeResolversAndModuleResolutionHost(scriptRegex, loader, instance, fileName => files.has(filePathKeyMapper(fileName)) || compiler.sys.fileExists(fileName), instance.loaderOptions.experimentalFileCaching); const watchHost = { rootFiles: getRootFileNames(), options: compilerOptions, ...moduleResolutionHost, readFile: readFileWithCachingText, watchFile: (fileName, callback, pollingInterval, options) => { var _a; const outputFileKey = (_a = instance.solutionBuilderHost) === null || _a === void 0 ? void 0 : _a.getOutputFileKeyFromReferencedProject(fileName); if (!outputFileKey || outputFileKey === filePathKeyMapper(fileName)) { return watchFile(fileName, callback, pollingInterval, options); } // Handle symlink to outputFile const outputFileName = instance.solutionBuilderHost.realpath(fileName); return watchFile(outputFileName, (_fileName, eventKind) => callback(fileName, eventKind), pollingInterval, options); }, watchDirectory, // used for (/// ) see https://github.com/Realytics/fork-ts-checker-webpack-plugin/pull/250#issuecomment-485061329 resolveTypeReferenceDirectives, resolveModuleNames, invokeFileWatcher, updateRootFileNames: () => { instance.changedFilesList = false; if (instance.watchOfFilesAndCompilerOptions !== undefined) { instance.watchOfFilesAndCompilerOptions.updateRootFileNames(getRootFileNames()); } }, createProgram: projectReferences === undefined ? compiler.createEmitAndSemanticDiagnosticsBuilderProgram : createBuilderProgramWithReferences, outputFiles: new Map(), }; return watchHost; function getRootFileNames() { return [...files.values()] .map(({ fileName }) => fileName) .filter(filePath => filePath.match(scriptRegex)); } function readFileWithCachingText(fileName, encoding) { var _a; fileName = path.normalize(fileName); const key = filePathKeyMapper(fileName); const file = files.get(key) || otherFiles.get(key); if (file !== undefined) { return file.text; } const text = moduleResolutionHost.readFile(fileName, encoding); if (text === undefined) { return undefined; } if (!((_a = instance.solutionBuilderHost) === null || _a === void 0 ? void 0 : _a.getOutputFileKeyFromReferencedProject(fileName))) { otherFiles.set(key, { fileName, version: 0, text }); } return text; } function createBuilderProgramWithReferences(rootNames, options, host, oldProgram, configFileParsingDiagnostics) { const program = compiler.createProgram({ rootNames: rootNames, options: options, host, oldProgram: oldProgram && oldProgram.getProgram(), configFileParsingDiagnostics, projectReferences, }); const builderProgramHost = host; return compiler.createEmitAndSemanticDiagnosticsBuilderProgram(program, builderProgramHost, oldProgram, configFileParsingDiagnostics); } } exports.makeWatchHost = makeWatchHost; const missingFileModifiedTime = new Date(0); function identity(x) { return x; } function toLowerCase(x) { return x.toLowerCase(); } const fileNameLowerCaseRegExp = /[^\u0130\u0131\u00DFa-z0-9\\/:\-_\. ]+/g; function toFileNameLowerCase(x) { return fileNameLowerCaseRegExp.test(x) ? x.replace(fileNameLowerCaseRegExp, toLowerCase) : x; } function createGetCanonicalFileName(instance) { return (0, utils_1.useCaseSensitiveFileNames)(instance.compiler, instance.loaderOptions) ? identity : toFileNameLowerCase; } function createModuleResolutionCache(instance, moduleResolutionHost) { const cache = instance.compiler.createModuleResolutionCache(moduleResolutionHost.getCurrentDirectory(), createGetCanonicalFileName(instance), instance.compilerOptions); // Add new API optional methods if (!cache.clear) { cache.clear = () => { cache.directoryToModuleNameMap.clear(); cache.moduleNameToDirectoryMap.clear(); }; } if (!cache.update) { cache.update = options => { if (!options.configFile) return; const ref = { sourceFile: options.configFile, commandLine: { options }, }; cache.directoryToModuleNameMap.setOwnMap(cache.directoryToModuleNameMap.getOrCreateMapOfCacheRedirects(ref)); cache.moduleNameToDirectoryMap.setOwnMap(cache.moduleNameToDirectoryMap.getOrCreateMapOfCacheRedirects(ref)); cache.directoryToModuleNameMap.setOwnOptions(options); cache.moduleNameToDirectoryMap.setOwnOptions(options); }; } return cache; } /** * Create the TypeScript Watch host */ function makeSolutionBuilderHost(scriptRegex, loader, instance) { const { compiler, loaderOptions: { transpileOnly }, filePathKeyMapper, } = instance; // loader.context seems to work fine on Linux / Mac regardless causes problems for @types resolution on Windows for TypeScript < 2.3 const formatDiagnosticHost = { getCurrentDirectory: compiler.sys.getCurrentDirectory, getCanonicalFileName: createGetCanonicalFileName(instance), getNewLine: () => compiler.sys.newLine, }; const diagnostics = { global: [], perFile: new Map(), transpileErrors: [], }; const reportDiagnostic = (d) => { if (transpileOnly) { const filePath = d.file ? filePathKeyMapper(d.file.fileName) : undefined; const last = diagnostics.transpileErrors[diagnostics.transpileErrors.length - 1]; if (diagnostics.transpileErrors.length && last[0] === filePath) { last[1].push(d); } else { diagnostics.transpileErrors.push([filePath, [d]]); } } else if (d.file) { const filePath = filePathKeyMapper(d.file.fileName); const existing = diagnostics.perFile.get(filePath); if (existing) { existing.push(d); } else { diagnostics.perFile.set(filePath, [d]); } } else { diagnostics.global.push(d); } instance.log.logInfo(compiler.formatDiagnostic(d, formatDiagnosticHost)); }; const reportSolutionBuilderStatus = (d) => instance.log.logInfo(compiler.formatDiagnostic(d, formatDiagnosticHost)); const reportWatchStatus = (d, newLine, _options) => instance.log.logInfo(`${compiler.flattenDiagnosticMessageText(d.messageText, compiler.sys.newLine)}${newLine + newLine}`); const outputFiles = new Map(); const inputFiles = new Map(); const writtenFiles = []; const outputAffectingInstanceVersion = new Map(); let timeoutId; const { resolveModuleNames, resolveTypeReferenceDirectives, moduleResolutionHost, } = makeResolversAndModuleResolutionHost(scriptRegex, loader, instance, fileName => { const filePathKey = filePathKeyMapper(fileName); return (instance.files.has(filePathKey) || instance.otherFiles.has(filePathKey) || compiler.sys.fileExists(fileName)); }, /*enableFileCaching*/ true); const configFileInfo = new Map(); const allWatches = []; const sysHost = compiler.createSolutionBuilderWithWatchHost(compiler.sys, compiler.createEmitAndSemanticDiagnosticsBuilderProgram, reportDiagnostic, reportSolutionBuilderStatus, reportWatchStatus); // Keeps track of the various `typescript.CustomTransformers` for each program that is created. const customTransformers = new Map(); // let lastBuilderProgram: typescript.CreateProgram | undefined = undefined; const solutionBuilderHost = { ...sysHost, ...moduleResolutionHost, createProgram: (rootNames, options, host, oldProgram, configFileParsingDiagnostics, projectReferences) => { var _a, _b, _c, _d; (_a = instance.moduleResolutionCache) === null || _a === void 0 ? void 0 : _a.update(options || {}); (_b = instance.typeReferenceResolutionCache) === null || _b === void 0 ? void 0 : _b.update(options || {}); const result = sysHost.createProgram(rootNames, options, host, oldProgram, configFileParsingDiagnostics, projectReferences); (_c = instance.typeReferenceResolutionCache) === null || _c === void 0 ? void 0 : _c.update(instance.compilerOptions); (_d = instance.moduleResolutionCache) === null || _d === void 0 ? void 0 : _d.update(instance.compilerOptions); if (options) { // The `configFilePath` is the same value that is used as the `project` parameter of // `getCustomtransformers` below. const project = options.configFilePath; if (typeof project === "string") { // Custom transformers need a reference to the `typescript.Program`, that reference is // unavailable during the the `getCustomTransformers` callback below. const transformers = (0, instances_1.getCustomTransformers)(instance.loaderOptions, result.getProgram(), result.getProgram); customTransformers.set(project, transformers); } } return result; }, resolveModuleNames, resolveTypeReferenceDirectives, diagnostics, ...createWatchFactory(filePathKeyMapper, compiler), getCustomTransformers: function (project) { return customTransformers.get(project); }, // Overrides writeFile: (name, text, writeByteOrderMark) => { var _a; const key = filePathKeyMapper(name); updateFileWithText(instance, key, name, () => text); const existing = ensureOutputFile(name); const hash = hashOutputText(text); outputFiles.set(key, hash); writtenFiles.push({ name, text, writeByteOrderMark: !!writeByteOrderMark, }); compiler.sys.writeFile(name, text, writeByteOrderMark); (_a = moduleResolutionHost.fileExistsCache) === null || _a === void 0 ? void 0 : _a.delete(name); if (outputAffectingInstanceVersion.has(key) && (!existing || existing !== hash)) { instance.version++; } if (instance.watchHost && !instance.files.has(key) && !instance.otherFiles.has(key)) { // If file wasnt updated in files or other files of instance, let watch host know of the change if (!existing) { instance.hasUnaccountedModifiedFiles = instance.watchHost.invokeFileWatcher(name, compiler.FileWatcherEventKind.Created) || instance.hasUnaccountedModifiedFiles; } else if (existing !== hash) { instance.hasUnaccountedModifiedFiles = instance.watchHost.invokeFileWatcher(name, compiler.FileWatcherEventKind.Changed) || instance.hasUnaccountedModifiedFiles; } } }, createDirectory: sysHost.createDirectory && (directory => { var _a; sysHost.createDirectory(directory); (_a = moduleResolutionHost.directoryExistsCache) === null || _a === void 0 ? void 0 : _a.delete(directory); }), afterProgramEmitAndDiagnostics: transpileOnly ? undefined : storeDtsFiles, setTimeout: (callback, _time, ...args) => { timeoutId = [callback, args]; return timeoutId; }, clearTimeout: _timeoutId => { timeoutId = undefined; }, getParsedCommandLine: file => { const config = (0, config_1.getParsedCommandLine)(compiler, instance.loaderOptions, file); configFileInfo.set(filePathKeyMapper(file), { config }); return config; }, writtenFiles, configFileInfo, outputAffectingInstanceVersion, getInputFileStamp, updateSolutionBuilderInputFile, getOutputFileKeyFromReferencedProject, getOutputFileAndKeyFromReferencedProject, getOutputFileTextAndKeyFromReferencedProject, getInputFileNameFromOutput: fileName => { const result = getInputFileNameFromOutput(fileName); return typeof result === 'string' ? result : undefined; }, getOutputFilesFromReferencedProjectInput, buildReferences, ensureAllReferenceTimestamps, clearCache, close, }; return solutionBuilderHost; function close() { allWatches.slice().forEach(w => w.close()); } function clearCache() { moduleResolutionHost.clearCache(); outputFiles.clear(); inputFiles.clear(); } function buildReferences() { if (!timeoutId) { ensureAllReferenceTimestamps(); return; } diagnostics.global.length = 0; diagnostics.perFile.clear(); diagnostics.transpileErrors.length = 0; while (timeoutId) { const [callback, args] = timeoutId; timeoutId = undefined; callback(...args); } ensureAllReferenceTimestamps(); } function ensureAllReferenceTimestamps() { if (inputFiles.size !== solutionBuilderHost.watchedFiles.size) { for (const { fileName, } of instance.solutionBuilderHost.watchedFiles.values()) { instance.solutionBuilderHost.getInputFileStamp(fileName); } } } function storeDtsFiles(builderProgram) { const program = builderProgram.getProgram(); for (const configInfo of configFileInfo.values()) { if (!configInfo.config || program.getRootFileNames() !== configInfo.config.fileNames || program.getCompilerOptions() !== configInfo.config.options || program.getProjectReferences() !== configInfo.config.projectReferences) { continue; } configInfo.dtsFiles = program .getSourceFiles() .map(file => path.resolve(file.fileName)) .filter(fileName => fileName.match(constants.dtsDtsxOrDtsDtsxMapRegex)); return; } } function getInputFileNameFromOutput(outputFileName) { const resolvedFileName = filePathKeyMapper(outputFileName); for (const configInfo of configFileInfo.values()) { ensureInputOutputInfo(configInfo); if (configInfo.outputFileNames) { for (const { inputFileName, outputNames, } of configInfo.outputFileNames.values()) { if (outputNames.some(outputName => resolvedFileName === filePathKeyMapper(outputName))) { return inputFileName; } } } if (configInfo.tsbuildInfoFile && filePathKeyMapper(configInfo.tsbuildInfoFile) === resolvedFileName) { return true; } } const realPath = solutionBuilderHost.realpath(outputFileName); return filePathKeyMapper(realPath) !== resolvedFileName ? getInputFileNameFromOutput(realPath) : undefined; } function ensureInputOutputInfo(configInfo) { if (configInfo.outputFileNames || !configInfo.config) { return; } configInfo.outputFileNames = new Map(); configInfo.config.fileNames.forEach(inputFile => configInfo.outputFileNames.set(filePathKeyMapper(inputFile), { inputFileName: path.resolve(inputFile), outputNames: (0, instances_1.getOutputFileNames)(instance, configInfo.config, inputFile), })); configInfo.tsbuildInfoFile = instance.compiler .getTsBuildInfoEmitOutputFilePath ? instance.compiler.getTsBuildInfoEmitOutputFilePath(configInfo.config.options) : // before api instance.compiler.getOutputPathForBuildInfo(configInfo.config.options); } function getOutputFileAndKeyFromReferencedProject(outputFileName) { const outputFile = ensureOutputFile(outputFileName); return outputFile !== undefined ? { key: getOutputFileKeyFromReferencedProject(outputFileName), outputFile, } : undefined; } function getOutputFileTextAndKeyFromReferencedProject(outputFileName) { const key = getOutputFileKeyFromReferencedProject(outputFileName); if (!key) { return undefined; } const file = writtenFiles.find(w => filePathKeyMapper(w.name) === key); if (file) { return { key, text: file.text }; } const outputFile = outputFiles.get(key); return { key, text: outputFile !== false ? compiler.sys.readFile(outputFileName) : undefined, }; } function getOutputFileKeyFromReferencedProject(outputFileName) { const key = filePathKeyMapper(outputFileName); if (outputFiles.has(key)) return key; const realKey = filePathKeyMapper(solutionBuilderHost.realpath(outputFileName)); if (realKey !== key && outputFiles.has(realKey)) return realKey; return getInputFileNameFromOutput(outputFileName) ? realKey : undefined; } function hashOutputText(text) { return compiler.sys.createHash ? compiler.sys.createHash(text) : text; } function ensureOutputFile(outputFileName) { const key = getOutputFileKeyFromReferencedProject(outputFileName); if (!key) { return undefined; } const outputFile = outputFiles.get(key); if (outputFile !== undefined) { return outputFile; } if (!getInputFileNameFromOutput(outputFileName)) { return undefined; } const text = compiler.sys.readFile(outputFileName); const hash = text === undefined ? false : hashOutputText(text); outputFiles.set(key, hash); return hash; } function getTypeScriptOutputFile(outputFileName) { const key = filePathKeyMapper(outputFileName); const writtenFile = writtenFiles.find(w => filePathKeyMapper(w.name) === key); if (writtenFile) return writtenFile; // Read from sys const text = compiler.sys.readFile(outputFileName); return text !== undefined ? { name: outputFileName, text, writeByteOrderMark: false, } : undefined; } function getOutputFilesFromReferencedProjectInput(inputFileName) { const resolvedFileName = filePathKeyMapper(inputFileName); for (const configInfo of configFileInfo.values()) { ensureInputOutputInfo(configInfo); if (configInfo.outputFileNames) { const result = configInfo.outputFileNames.get(resolvedFileName); if (result) { return result.outputNames .map(getTypeScriptOutputFile) .filter(output => !!output); } } } return []; } function getInputFileStamp(fileName) { const key = filePathKeyMapper(fileName); const existing = inputFiles.get(key); if (existing !== undefined) { return existing; } const time = compiler.sys.getModifiedTime(fileName) || missingFileModifiedTime; inputFiles.set(key, time); return time; } function updateSolutionBuilderInputFile(fileName) { const key = filePathKeyMapper(fileName); const existing = inputFiles.get(key) || missingFileModifiedTime; const newTime = compiler.sys.getModifiedTime(fileName) || missingFileModifiedTime; if (existing.getTime() === newTime.getTime()) { return; } const eventKind = existing == missingFileModifiedTime ? compiler.FileWatcherEventKind.Created : newTime === missingFileModifiedTime ? compiler.FileWatcherEventKind.Deleted : compiler.FileWatcherEventKind.Changed; solutionBuilderHost.invokeFileWatcher(fileName, eventKind); } } exports.makeSolutionBuilderHost = makeSolutionBuilderHost; function getSolutionErrors(instance, context) { const solutionErrors = []; if (instance.solutionBuilderHost && instance.solutionBuilderHost.diagnostics.transpileErrors.length) { instance.solutionBuilderHost.diagnostics.transpileErrors.forEach(([filePath, errors]) => solutionErrors.push(...(0, utils_1.formatErrors)(errors, instance.loaderOptions, instance.colors, instance.compiler, { file: filePath ? undefined : 'tsconfig.json' }, context))); } return solutionErrors; } exports.getSolutionErrors = getSolutionErrors; function makeResolveTypeReferenceDirective(compiler, compilerOptions, moduleResolutionHost, customResolveTypeReferenceDirective, instance) { var _a, _b; if (customResolveTypeReferenceDirective === undefined) { // Until the api is published if (compiler.createTypeReferenceDirectiveResolutionCache !== undefined && !instance.typeReferenceResolutionCache) { instance.typeReferenceResolutionCache = compiler.createTypeReferenceDirectiveResolutionCache(moduleResolutionHost.getCurrentDirectory(), createGetCanonicalFileName(instance), instance.compilerOptions, (_b = (_a = instance.moduleResolutionCache) === null || _a === void 0 ? void 0 : _a.getPackageJsonInfoCache) === null || _b === void 0 ? void 0 : _b.call(_a)); } return (typeDirectiveName, containingFile, options, redirectedReference, containingFileMode) => { // Copy-pasted from https://github.com/TypeStrong/ts-node/blob/9f789d0d91c6eba30ac7f7aad45194a23b44f159/src/resolver-functions.ts#L139 const nameIsString = typeof typeDirectiveName === 'string'; const mode = nameIsString ? undefined : compiler.getModeForFileReference(typeDirectiveName, containingFileMode); const strName = nameIsString ? typeDirectiveName : typeDirectiveName.fileName.toLowerCase(); return compiler.resolveTypeReferenceDirective(strName, containingFile, options, moduleResolutionHost, redirectedReference, undefined, mode); }; } return (directive, containingFile) => customResolveTypeReferenceDirective(directive, // unsure whether we should evolve this further containingFile, compilerOptions, moduleResolutionHost, compiler.resolveTypeReferenceDirective); } function isJsImplementationOfTypings(resolvedModule, tsResolution) { return (resolvedModule.resolvedFileName.endsWith('js') && /\.d\.ts$/.test(tsResolution.resolvedFileName)); } function resolveModule(resolveSync, resolveModuleName, appendTsTsxSuffixesIfRequired, scriptRegex, moduleName, containingFile, redirectedReference, containingSourceFile) { let resolutionResult; try { const originalFileName = resolveSync(path.normalize(path.dirname(containingFile)), moduleName); if (originalFileName) { const resolvedFileName = appendTsTsxSuffixesIfRequired(originalFileName); if (resolvedFileName.match(scriptRegex) !== null) { resolutionResult = { resolvedFileName, originalFileName }; } } } catch (e) { } const tsResolution = resolveModuleName(moduleName, containingFile, redirectedReference, containingSourceFile); if (tsResolution.resolvedModule !== undefined) { const resolvedFileName = path.normalize(tsResolution.resolvedModule.resolvedFileName); const tsResolutionResult = { ...tsResolution.resolvedModule, originalFileName: resolvedFileName, resolvedFileName, }; return resolutionResult === undefined || resolutionResult.resolvedFileName === tsResolutionResult.resolvedFileName || isJsImplementationOfTypings(resolutionResult, tsResolutionResult) ? tsResolutionResult : resolutionResult; } return resolutionResult; } function makeResolveModuleName(compiler, compilerOptions, moduleResolutionHost, customResolveModuleName, instance) { if (customResolveModuleName === undefined) { if (!instance.moduleResolutionCache) { instance.moduleResolutionCache = createModuleResolutionCache(instance, moduleResolutionHost); } return (moduleName, containingFileName, redirectedReference, containingFile) => compiler.resolveModuleName(moduleName, containingFileName, compilerOptions, moduleResolutionHost, instance.moduleResolutionCache, redirectedReference, containingFile === null || containingFile === void 0 ? void 0 : containingFile.impliedNodeFormat); } return (moduleName, containingFile) => customResolveModuleName(moduleName, containingFile, compilerOptions, moduleResolutionHost, compiler.resolveModuleName); } function addCache(host) { host.fileExists = createCache(host.fileExists, (host.fileExistsCache = new Map())); host.directoryExists = createCache(host.directoryExists, (host.directoryExistsCache = new Map())); host.realpath = host.realpath && createCache(host.realpath, (host.realpathCache = new Map())); host.clearCache = clearCache; function createCache(originalFunction, cache) { return function getCached(arg) { let res = cache.get(arg); if (res !== undefined) { return res; } res = originalFunction(arg); cache.set(arg, res); return res; }; } function clearCache() { var _a, _b, _c; (_a = host.fileExistsCache) === null || _a === void 0 ? void 0 : _a.clear(); (_b = host.directoryExistsCache) === null || _b === void 0 ? void 0 : _b.clear(); (_c = host.realpathCache) === null || _c === void 0 ? void 0 : _c.clear(); } } //# sourceMappingURL=servicesHost.js.map