This commit is contained in:
2022-07-21 03:28:35 +00:00
parent d7c883d6df
commit 51b34b0e1d
30103 changed files with 4152204 additions and 23 deletions
+4
View File
@@ -0,0 +1,4 @@
import * as webpack from 'webpack';
import { TSInstance } from './interfaces';
export declare function makeAfterCompile(instance: TSInstance, configFilePath: string | undefined): (compilation: webpack.compilation.Compilation, callback: () => void) => void;
//# sourceMappingURL=after-compile.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"after-compile.d.ts","sourceRoot":"","sources":["../src/after-compile.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAQnC,OAAO,EAGL,UAAU,EAGX,MAAM,cAAc,CAAC;AAQtB,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,UAAU,EACpB,cAAc,EAAE,MAAM,GAAG,SAAS,gFA8DnC"}
+256
View File
@@ -0,0 +1,256 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const constants = require("./constants");
const instances_1 = require("./instances");
const utils_1 = require("./utils");
function makeAfterCompile(instance, configFilePath) {
let getCompilerOptionDiagnostics = true;
let checkAllFilesForErrors = true;
return (compilation, callback) => {
// Don't add errors for child compilations
if (compilation.compiler.isChild()) {
callback();
return;
}
if (instance.loaderOptions.transpileOnly) {
provideAssetsFromSolutionBuilderHost(instance, compilation);
callback();
return;
}
removeTSLoaderErrors(compilation.errors);
provideCompilerOptionDiagnosticErrorsToWebpack(getCompilerOptionDiagnostics, compilation, instance, configFilePath);
getCompilerOptionDiagnostics = false;
const modules = determineModules(compilation);
const filesToCheckForErrors = determineFilesToCheckForErrors(checkAllFilesForErrors, instance);
checkAllFilesForErrors = false;
const filesWithErrors = new Map();
provideErrorsToWebpack(filesToCheckForErrors, filesWithErrors, compilation, modules, instance);
provideDeclarationFilesToWebpack(filesToCheckForErrors, instance, compilation);
provideTsBuildInfoFilesToWebpack(instance, compilation);
provideSolutionErrorsToWebpack(compilation, modules, instance);
provideAssetsFromSolutionBuilderHost(instance, compilation);
instance.filesWithErrors = filesWithErrors;
instance.modifiedFiles = undefined;
instance.projectsMissingSourceMaps = new Set();
callback();
};
}
exports.makeAfterCompile = makeAfterCompile;
/**
* handle compiler option errors after the first compile
*/
function provideCompilerOptionDiagnosticErrorsToWebpack(getCompilerOptionDiagnostics, compilation, instance, configFilePath) {
if (getCompilerOptionDiagnostics) {
const { languageService, loaderOptions, compiler, program } = instance;
const errorsToAdd = utils_1.formatErrors(program === undefined
? languageService.getCompilerOptionsDiagnostics()
: program.getOptionsDiagnostics(), loaderOptions, instance.colors, compiler, { file: configFilePath || 'tsconfig.json' }, compilation.compiler.context);
compilation.errors.push(...errorsToAdd);
}
}
/**
* build map of all modules based on normalized filename
* this is used for quick-lookup when trying to find modules
* based on filepath
*/
function determineModules(compilation) {
return compilation.modules.reduce((modules, module) => {
if (module.resource) {
const modulePath = path.normalize(module.resource);
const existingModules = modules.get(modulePath);
if (existingModules !== undefined) {
if (existingModules.indexOf(module) === -1) {
existingModules.push(module);
}
}
else {
modules.set(modulePath, [module]);
}
}
return modules;
}, new Map());
}
function determineFilesToCheckForErrors(checkAllFilesForErrors, instance) {
const { files, modifiedFiles, filesWithErrors, otherFiles } = instance;
// calculate array of files to check
const filesToCheckForErrors = new Map();
if (checkAllFilesForErrors) {
// check all files on initial run
for (const [filePath, file] of files) {
filesToCheckForErrors.set(filePath, file);
}
for (const [filePath, file] of otherFiles) {
filesToCheckForErrors.set(filePath, file);
}
}
else if (modifiedFiles !== null && modifiedFiles !== undefined) {
// check all modified files, and all dependants
for (const modifiedFileName of modifiedFiles.keys()) {
utils_1.collectAllDependants(instance.reverseDependencyGraph, modifiedFileName).forEach(fileName => {
const fileToCheckForErrors = files.get(fileName) || otherFiles.get(fileName);
filesToCheckForErrors.set(fileName, fileToCheckForErrors);
});
}
}
// re-check files with errors from previous build
if (filesWithErrors !== undefined) {
for (const [fileWithErrorName, fileWithErrors] of filesWithErrors) {
filesToCheckForErrors.set(fileWithErrorName, fileWithErrors);
}
}
return filesToCheckForErrors;
}
function provideErrorsToWebpack(filesToCheckForErrors, filesWithErrors, compilation, modules, instance) {
const { compiler, files, loaderOptions, compilerOptions, otherFiles } = instance;
const filePathRegex = compilerOptions.allowJs === true
? constants.dtsTsTsxJsJsxRegex
: constants.dtsTsTsxRegex;
// Im pretty sure this will never be undefined here
const program = utils_1.ensureProgram(instance);
for (const filePath of filesToCheckForErrors.keys()) {
if (filePath.match(filePathRegex) === null) {
continue;
}
const sourceFile = program && program.getSourceFile(filePath);
// If the source file is undefined, that probably means its actually part of an unbuilt project reference,
// which will have already produced a more useful error than the one we would get by proceeding here.
// If its undefined and were not using project references at all, I guess carry on so the user will
// get a useful error about which file was unexpectedly missing.
if (utils_1.isUsingProjectReferences(instance) && sourceFile === undefined) {
continue;
}
const errors = [];
if (program && sourceFile) {
errors.push(...program.getSyntacticDiagnostics(sourceFile), ...program
.getSemanticDiagnostics(sourceFile)
// Output file has not been built from source file - this message is redundant with
// program.getOptionsDiagnostics() separately added in instances.ts
.filter(({ code }) => code !== 6305));
}
if (errors.length > 0) {
const fileWithError = files.get(filePath) || otherFiles.get(filePath);
filesWithErrors.set(filePath, fileWithError);
}
// if we have access to a webpack module, use that
const associatedModules = modules.get(filePath);
if (associatedModules !== undefined) {
associatedModules.forEach(module => {
// remove any existing errors
removeTSLoaderErrors(module.errors);
// append errors
const formattedErrors = utils_1.formatErrors(errors, loaderOptions, instance.colors, compiler, { module }, compilation.compiler.context);
module.errors.push(...formattedErrors);
compilation.errors.push(...formattedErrors);
});
}
else {
// otherwise it's a more generic error
const formattedErrors = utils_1.formatErrors(errors, loaderOptions, instance.colors, compiler, { file: filePath }, compilation.compiler.context);
compilation.errors.push(...formattedErrors);
}
}
}
function provideSolutionErrorsToWebpack(compilation, modules, instance) {
if (!instance.solutionBuilderHost ||
!(instance.solutionBuilderHost.diagnostics.global.length ||
instance.solutionBuilderHost.diagnostics.perFile.size)) {
return;
}
const { compiler, loaderOptions, solutionBuilderHost: { diagnostics } } = instance;
for (const [filePath, perFileDiagnostics] of diagnostics.perFile) {
// if we have access to a webpack module, use that
const associatedModules = modules.get(filePath);
if (associatedModules !== undefined) {
associatedModules.forEach(module => {
// remove any existing errors
removeTSLoaderErrors(module.errors);
// append errors
const formattedErrors = utils_1.formatErrors(perFileDiagnostics, loaderOptions, instance.colors, compiler, { module }, compilation.compiler.context);
module.errors.push(...formattedErrors);
compilation.errors.push(...formattedErrors);
});
}
else {
// otherwise it's a more generic error
const formattedErrors = utils_1.formatErrors(perFileDiagnostics, loaderOptions, instance.colors, compiler, { file: filePath }, compilation.compiler.context);
compilation.errors.push(...formattedErrors);
}
}
// Add global solution errors
compilation.errors.push(...utils_1.formatErrors(diagnostics.global, instance.loaderOptions, instance.colors, instance.compiler, { file: 'tsconfig.json' }, compilation.compiler.context));
}
/**
* gather all declaration files from TypeScript and output them to webpack
*/
function provideDeclarationFilesToWebpack(filesToCheckForErrors, instance, compilation) {
for (const filePath of filesToCheckForErrors.keys()) {
if (filePath.match(constants.tsTsxRegex) === null) {
continue;
}
if (!instances_1.isReferencedFile(instance, filePath)) {
addDeclarationFilesAsAsset(instances_1.getEmitOutput(instance, filePath), compilation);
}
}
}
function addDeclarationFilesAsAsset(outputFiles, compilation, skipOutputFile) {
outputFilesToAsset(outputFiles, compilation, outputFile => skipOutputFile && skipOutputFile(outputFile)
? true
: !outputFile.name.match(constants.dtsDtsxOrDtsDtsxMapRegex));
}
function outputFileToAsset(outputFile, compilation) {
const assetPath = path.relative(compilation.compiler.outputPath, outputFile.name);
compilation.assets[assetPath] = {
source: () => outputFile.text,
size: () => outputFile.text.length
};
}
function outputFilesToAsset(outputFiles, compilation, skipOutputFile) {
for (const outputFile of outputFiles) {
if (!skipOutputFile || !skipOutputFile(outputFile)) {
outputFileToAsset(outputFile, compilation);
}
}
}
/**
* gather all .tsbuildinfo for the project
*/
function provideTsBuildInfoFilesToWebpack(instance, compilation) {
if (instance.watchHost) {
// Ensure emit is complete
instances_1.getEmitFromWatchHost(instance);
if (instance.watchHost.tsbuildinfo) {
outputFileToAsset(instance.watchHost.tsbuildinfo, compilation);
}
instance.watchHost.outputFiles.clear();
instance.watchHost.tsbuildinfo = undefined;
}
}
/**
* gather all solution builder assets
*/
function provideAssetsFromSolutionBuilderHost(instance, compilation) {
if (instance.solutionBuilderHost) {
// written files
outputFilesToAsset(instance.solutionBuilderHost.writtenFiles, compilation);
instance.solutionBuilderHost.writtenFiles.length = 0;
}
}
/**
* handle all other errors. The basic approach here to get accurate error
* reporting is to start with a "blank slate" each compilation and gather
* all errors from all files. Since webpack tracks errors in a module from
* compilation-to-compilation, and since not every module always runs through
* the loader, we need to detect and remove any pre-existing errors.
*/
function removeTSLoaderErrors(errors) {
let index = -1;
let length = errors.length;
while (++index < length) {
if (errors[index].loaderSource === 'ts-loader') {
errors.splice(index--, 1);
length--;
}
}
}
//# sourceMappingURL=after-compile.js.map
+11
View File
@@ -0,0 +1,11 @@
import * as typescript from 'typescript';
import { LoaderOptions } from './interfaces';
import * as logger from './logger';
export declare function getCompiler(loaderOptions: LoaderOptions, log: logger.Logger): {
compiler: typeof typescript | undefined;
compilerCompatible: boolean;
compilerDetailsLogMessage: string | undefined;
errorMessage: string | undefined;
};
export declare function getCompilerOptions(configParseResult: typescript.ParsedCommandLine): typescript.CompilerOptions;
//# sourceMappingURL=compilerSetup.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"compilerSetup.d.ts","sourceRoot":"","sources":["../src/compilerSetup.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,UAAU,MAAM,YAAY,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AAEnC,wBAAgB,WAAW,CAAC,aAAa,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM;;;;;EA+C3E;AAED,wBAAgB,kBAAkB,CAChC,iBAAiB,EAAE,UAAU,CAAC,iBAAiB,8BAyBhD"}
+65
View File
@@ -0,0 +1,65 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const semver = require("semver");
const typescript = require("typescript");
function getCompiler(loaderOptions, log) {
let compiler;
let errorMessage;
let compilerDetailsLogMessage;
let compilerCompatible = false;
try {
compiler = require(loaderOptions.compiler);
}
catch (e) {
errorMessage =
loaderOptions.compiler === 'typescript'
? 'Could not load TypeScript. Try installing with `yarn add typescript` or `npm install typescript`. If TypeScript is installed globally, try using `yarn link typescript` or `npm link typescript`.'
: `Could not load TypeScript compiler with NPM package name \`${loaderOptions.compiler}\`. Are you sure it is correctly installed?`;
}
if (errorMessage === undefined) {
compilerDetailsLogMessage = `ts-loader: Using ${loaderOptions.compiler}@${compiler.version}`;
compilerCompatible = false;
if (loaderOptions.compiler === 'typescript') {
if (compiler.version !== undefined &&
semver.gte(compiler.version, '2.4.1')) {
// don't log yet in this case, if a tsconfig.json exists we want to combine the message
compilerCompatible = true;
}
else {
log.logError(`${compilerDetailsLogMessage}. This version is incompatible with ts-loader. Please upgrade to the latest version of TypeScript.`);
}
}
else {
log.logWarning(`${compilerDetailsLogMessage}. This version may or may not be compatible with ts-loader.`);
}
}
return {
compiler,
compilerCompatible,
compilerDetailsLogMessage,
errorMessage
};
}
exports.getCompiler = getCompiler;
function getCompilerOptions(configParseResult) {
const compilerOptions = Object.assign({}, configParseResult.options, {
skipLibCheck: true,
suppressOutputPathCheck: true // This is why: https://github.com/Microsoft/TypeScript/issues/7363
});
// if `module` is not specified and not using ES6+ target, default to CJS module output
if (compilerOptions.module === undefined &&
(compilerOptions.target !== undefined &&
compilerOptions.target < typescript.ScriptTarget.ES2015)) {
compilerOptions.module = typescript.ModuleKind.CommonJS;
}
if (configParseResult.options.configFile) {
Object.defineProperty(compilerOptions, 'configFile', {
enumerable: false,
writable: false,
value: configParseResult.options.configFile
});
}
return compilerOptions;
}
exports.getCompilerOptions = getCompilerOptions;
//# sourceMappingURL=compilerSetup.js.map
+18
View File
@@ -0,0 +1,18 @@
import { Chalk } from 'chalk';
import * as typescript from 'typescript';
import * as webpack from 'webpack';
import { LoaderOptions, WebpackError } from './interfaces';
import * as logger from './logger';
interface ConfigFile {
config?: any;
error?: typescript.Diagnostic;
}
export declare function getConfigFile(compiler: typeof typescript, colors: Chalk, loader: webpack.loader.LoaderContext, loaderOptions: LoaderOptions, compilerCompatible: boolean, log: logger.Logger, compilerDetailsLogMessage: string): {
configFilePath: string | undefined;
configFile: ConfigFile;
configFileError: WebpackError | undefined;
};
export declare function getConfigParseResult(compiler: typeof typescript, configFile: ConfigFile, basePath: string, configFilePath: string | undefined, enableProjectReferences: boolean): typescript.ParsedCommandLine;
export declare function getParsedCommandLine(compiler: typeof typescript, loaderOptions: LoaderOptions, configFilePath: string): typescript.ParsedCommandLine | undefined;
export {};
//# sourceMappingURL=config.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAG9B,OAAO,KAAK,UAAU,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAGnC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AAGnC,UAAU,UAAU;IAClB,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,KAAK,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC;CAC/B;AAED,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,OAAO,UAAU,EAC3B,MAAM,EAAE,KAAK,EACb,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EACpC,aAAa,EAAE,aAAa,EAC5B,kBAAkB,EAAE,OAAO,EAC3B,GAAG,EAAE,MAAM,CAAC,MAAM,EAClB,yBAAyB,EAAE,MAAM;;;;EAuDlC;AAgDD,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,OAAO,UAAU,EAC3B,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,uBAAuB,EAAE,OAAO,gCAoBjC;AAKD,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,OAAO,UAAU,EAC3B,aAAa,EAAE,aAAa,EAC5B,cAAc,EAAE,MAAM,GACrB,UAAU,CAAC,iBAAiB,GAAG,SAAS,CAc1C"}
+107
View File
@@ -0,0 +1,107 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const semver = require("semver");
const compilerSetup_1 = require("./compilerSetup");
const utils_1 = require("./utils");
function getConfigFile(compiler, colors, loader, loaderOptions, compilerCompatible, log, compilerDetailsLogMessage) {
const configFilePath = findConfigFile(compiler, path.dirname(loader.resourcePath), loaderOptions.configFile);
let configFileError;
let configFile;
if (configFilePath !== undefined) {
if (compilerCompatible) {
log.logInfo(`${compilerDetailsLogMessage} and ${configFilePath}`);
}
else {
log.logInfo(`ts-loader: Using config file at ${configFilePath}`);
}
configFile = compiler.readConfigFile(configFilePath, compiler.sys.readFile);
if (configFile.error !== undefined) {
configFileError = utils_1.formatErrors([configFile.error], loaderOptions, colors, compiler, { file: configFilePath }, loader.context)[0];
}
}
else {
if (compilerCompatible) {
log.logInfo(compilerDetailsLogMessage);
}
configFile = {
config: {
compilerOptions: {},
files: []
}
};
}
if (configFileError === undefined) {
configFile.config.compilerOptions = Object.assign({}, configFile.config.compilerOptions, loaderOptions.compilerOptions);
}
return {
configFilePath,
configFile,
configFileError
};
}
exports.getConfigFile = getConfigFile;
/**
* Find a tsconfig file by name or by path.
* By name, the tsconfig.json is found using the same method as `tsc`, starting in the current
* directory and continuing up the parent directory chain.
* By path, the file will be found by resolving the given path relative to the requesting entry file.
*
* @param compiler The TypeScript compiler instance
* @param requestDirPath The directory in which the entry point requesting the tsconfig.json lies
* @param configFile The tsconfig file name to look for or a path to that file
* @return The absolute path to the tsconfig file, undefined if none was found.
*/
function findConfigFile(compiler, requestDirPath, configFile) {
// If `configFile` is an absolute path, return it right away
if (path.isAbsolute(configFile)) {
return compiler.sys.fileExists(configFile) ? configFile : undefined;
}
// If `configFile` is a relative path, resolve it.
// We define a relative path as: starts with
// one or two dots + a common directory delimiter
if (configFile.match(/^\.\.?(\/|\\)/) !== null) {
const resolvedPath = path.resolve(requestDirPath, configFile);
return compiler.sys.fileExists(resolvedPath) ? resolvedPath : undefined;
// If `configFile` is a file name, find it in the directory tree
}
else {
while (true) {
const fileName = path.join(requestDirPath, configFile);
if (compiler.sys.fileExists(fileName)) {
return fileName;
}
const parentPath = path.dirname(requestDirPath);
if (parentPath === requestDirPath) {
break;
}
requestDirPath = parentPath;
}
return undefined;
}
}
function getConfigParseResult(compiler, configFile, basePath, configFilePath, enableProjectReferences) {
const configParseResult = compiler.parseJsonConfigFileContent(configFile.config, compiler.sys, basePath);
if (!enableProjectReferences) {
configParseResult.projectReferences = undefined;
}
if (semver.gte(compiler.version, '3.5.0')) {
// set internal options.configFilePath flag on options to denote that we read this from a file
configParseResult.options = Object.assign({}, configParseResult.options, {
configFilePath
});
}
return configParseResult;
}
exports.getConfigParseResult = getConfigParseResult;
const extendedConfigCache = new Map();
function getParsedCommandLine(compiler, loaderOptions, configFilePath) {
const result = compiler.getParsedCommandLineOfConfigFile(configFilePath, loaderOptions.compilerOptions, Object.assign(Object.assign({}, compiler.sys), { onUnRecoverableConfigFileDiagnostic: () => { } // tslint:disable-line no-empty
}), extendedConfigCache);
if (result) {
result.options = compilerSetup_1.getCompilerOptions(result);
}
return result;
}
exports.getParsedCommandLine = getParsedCommandLine;
//# sourceMappingURL=config.js.map
+17
View File
@@ -0,0 +1,17 @@
export declare const EOL: string;
export declare const CarriageReturnLineFeed = "\r\n";
export declare const LineFeed = "\n";
export declare const CarriageReturnLineFeedCode = 0;
export declare const LineFeedCode = 1;
export declare const extensionRegex: RegExp;
export declare const tsxRegex: RegExp;
export declare const tsTsxRegex: RegExp;
export declare const dtsDtsxOrDtsDtsxMapRegex: RegExp;
export declare const dtsTsTsxRegex: RegExp;
export declare const dtsTsTsxJsJsxRegex: RegExp;
export declare const tsTsxJsJsxRegex: RegExp;
export declare const jsJsx: RegExp;
export declare const jsJsxMap: RegExp;
export declare const jsonRegex: RegExp;
export declare const nodeModules: RegExp;
//# sourceMappingURL=constants.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,GAAG,QAAS,CAAC;AAC1B,eAAO,MAAM,sBAAsB,SAAS,CAAC;AAC7C,eAAO,MAAM,QAAQ,OAAO,CAAC;AAE7B,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAC5C,eAAO,MAAM,YAAY,IAAI,CAAC;AAE9B,eAAO,MAAM,cAAc,QAAa,CAAC;AACzC,eAAO,MAAM,QAAQ,QAAY,CAAC;AAClC,eAAO,MAAM,UAAU,QAAe,CAAC;AACvC,eAAO,MAAM,wBAAwB,QAA0B,CAAC;AAChE,eAAO,MAAM,aAAa,QAAqB,CAAC;AAChD,eAAO,MAAM,kBAAkB,QAA8B,CAAC;AAC9D,eAAO,MAAM,eAAe,QAAqB,CAAC;AAClD,eAAO,MAAM,KAAK,QAAe,CAAC;AAClC,eAAO,MAAM,QAAQ,QAAoB,CAAC;AAC1C,eAAO,MAAM,SAAS,QAAa,CAAC;AACpC,eAAO,MAAM,WAAW,QAAkB,CAAC"}
+20
View File
@@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const os = require("os");
exports.EOL = os.EOL;
exports.CarriageReturnLineFeed = '\r\n';
exports.LineFeed = '\n';
exports.CarriageReturnLineFeedCode = 0;
exports.LineFeedCode = 1;
exports.extensionRegex = /\.[^.]+$/;
exports.tsxRegex = /\.tsx$/i;
exports.tsTsxRegex = /\.ts(x?)$/i;
exports.dtsDtsxOrDtsDtsxMapRegex = /\.d\.ts(x?)(\.map)?$/i;
exports.dtsTsTsxRegex = /(\.d)?\.ts(x?)$/i;
exports.dtsTsTsxJsJsxRegex = /((\.d)?\.ts(x?)|js(x?))$/i;
exports.tsTsxJsJsxRegex = /\.tsx?$|\.jsx?$/i;
exports.jsJsx = /\.js(x?)$/i;
exports.jsJsxMap = /\.js(x?)\.map$/i;
exports.jsonRegex = /\.json$/i;
exports.nodeModules = /node_modules/i;
//# sourceMappingURL=constants.js.map
+15
View File
@@ -0,0 +1,15 @@
import * as webpack from 'webpack';
import { LoaderOptions } from './interfaces';
/**
* The entry point for ts-loader
*/
declare function loader(this: webpack.loader.LoaderContext, contents: string): void;
export = loader;
/**
* expose public types via declaration merging
*/
declare namespace loader {
interface Options extends LoaderOptions {
}
}
//# sourceMappingURL=index.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAYnC,OAAO,EACL,aAAa,EAKd,MAAM,cAAc,CAAC;AAatB;;GAEG;AACH,iBAAS,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,QAAQ,EAAE,MAAM,QAcnE;AAisBD,SAAS,MAAM,CAAC;AAEhB;;GAEG;AAEH,kBAAU,MAAM,CAAC;IAEf,UAAiB,OAAQ,SAAQ,aAAa;KAAG;CAClD"}
+465
View File
@@ -0,0 +1,465 @@
"use strict";
const crypto = require("crypto");
const loaderUtils = require("loader-utils");
const path = require("path");
const constants = require("./constants");
const instances_1 = require("./instances");
const utils_1 = require("./utils");
const webpackInstances = [];
const loaderOptionsCache = {};
/**
* The entry point for ts-loader
*/
function loader(contents) {
// tslint:disable-next-line:no-unused-expression strict-boolean-expressions
this.cacheable && this.cacheable();
const callback = this.async();
const options = getLoaderOptions(this);
const instanceOrError = instances_1.getTypeScriptInstance(options, this);
if (instanceOrError.error !== undefined) {
callback(new Error(instanceOrError.error.message));
return;
}
const instance = instanceOrError.instance;
instances_1.buildSolutionReferences(instance, this);
successLoader(this, contents, callback, instance);
}
function successLoader(loaderContext, contents, callback, instance) {
instances_1.initializeInstance(loaderContext, instance);
instances_1.reportTranspileErrors(instance, loaderContext);
const rawFilePath = path.normalize(loaderContext.resourcePath);
const filePath = instance.loaderOptions.appendTsSuffixTo.length > 0 ||
instance.loaderOptions.appendTsxSuffixTo.length > 0
? utils_1.appendSuffixesIfMatch({
'.ts': instance.loaderOptions.appendTsSuffixTo,
'.tsx': instance.loaderOptions.appendTsxSuffixTo
}, rawFilePath)
: rawFilePath;
const fileVersion = updateFileInCache(instance.loaderOptions, filePath, contents, instance);
const referencedProject = utils_1.getAndCacheProjectReference(filePath, instance);
if (referencedProject !== undefined) {
const [relativeProjectConfigPath, relativeFilePath] = [
path.relative(loaderContext.rootContext, referencedProject.sourceFile.fileName),
path.relative(loaderContext.rootContext, filePath)
];
if (referencedProject.commandLine.options.outFile !== undefined) {
throw new Error(`The referenced project at ${relativeProjectConfigPath} is using ` +
`the outFile' option, which is not supported with ts-loader.`);
}
const jsFileName = utils_1.getAndCacheOutputJSFileName(filePath, referencedProject, instance);
const relativeJSFileName = path.relative(loaderContext.rootContext, jsFileName);
if (!instance.compiler.sys.fileExists(jsFileName)) {
throw new Error(`Could not find output JavaScript file for input ` +
`${relativeFilePath} (looked at ${relativeJSFileName}).\n` +
`The input file is part of a project reference located at ` +
`${relativeProjectConfigPath}, so ts-loader is looking for the ` +
'projects pre-built output on disk. Try running `tsc --build` ' +
'to build project references.');
}
// Since the output JS file is being read from disk instead of using the
// input TS file, we need to tell the loader that the compilation doesnt
// actually depend on the current file, but depends on the JS file instead.
loaderContext.clearDependencies();
loaderContext.addDependency(jsFileName);
utils_1.validateSourceMapOncePerProject(instance, loaderContext, jsFileName, referencedProject);
const mapFileName = jsFileName + '.map';
const outputText = instance.compiler.sys.readFile(jsFileName);
const sourceMapText = instance.compiler.sys.readFile(mapFileName);
makeSourceMapAndFinish(sourceMapText, outputText, filePath, contents, loaderContext, fileVersion, callback, instance);
}
else {
const { outputText, sourceMapText } = instance.loaderOptions.transpileOnly
? getTranspilationEmit(filePath, contents, instance, loaderContext)
: getEmit(rawFilePath, filePath, instance, loaderContext);
makeSourceMapAndFinish(sourceMapText, outputText, filePath, contents, loaderContext, fileVersion, callback, instance);
}
}
function makeSourceMapAndFinish(sourceMapText, outputText, filePath, contents, loaderContext, fileVersion, callback, instance) {
if (outputText === null || outputText === undefined) {
setModuleMeta(loaderContext, instance, fileVersion);
const additionalGuidance = instances_1.isReferencedFile(instance, filePath)
? ' The most common cause for this is having errors when building referenced projects.'
: !instance.loaderOptions.allowTsInNodeModules &&
filePath.indexOf('node_modules') !== -1
? ' By default, ts-loader will not compile .ts files in node_modules.\n' +
'You should not need to recompile .ts files there, but if you really want to, use the allowTsInNodeModules option.\n' +
'See: https://github.com/Microsoft/TypeScript/issues/12358'
: '';
callback(new Error(`TypeScript emitted no output for ${filePath}.${additionalGuidance}`), outputText, undefined);
return;
}
const { sourceMap, output } = makeSourceMap(sourceMapText, outputText, filePath, contents, loaderContext);
setModuleMeta(loaderContext, instance, fileVersion);
callback(null, output, sourceMap);
}
function setModuleMeta(loaderContext, instance, fileVersion) {
// _module.meta is not available inside happypack
if (!instance.loaderOptions.happyPackMode &&
loaderContext._module.buildMeta !== undefined) {
// Make sure webpack is aware that even though the emitted JavaScript may be the same as
// a previously cached version the TypeScript may be different and therefore should be
// treated as new
loaderContext._module.buildMeta.tsLoaderFileVersion = fileVersion;
}
}
/**
* Get a unique hash based on the contents of the options
* Hash is created from the values converted to strings
* Values which are functions (such as getCustomTransformers) are
* converted to strings by this code, which JSON.stringify would not do.
*/
function getOptionsHash(loaderOptions) {
const hash = crypto.createHash('sha256');
Object.values(loaderOptions).map((v) => {
if (v) {
hash.update(v.toString());
}
});
return hash.digest('hex').substring(0, 16);
}
/**
* either retrieves loader options from the cache
* or creates them, adds them to the cache and returns
*/
function getLoaderOptions(loaderContext) {
// differentiate the TypeScript instance based on the webpack instance
let webpackIndex = webpackInstances.indexOf(loaderContext._compiler);
if (webpackIndex === -1) {
webpackIndex = webpackInstances.push(loaderContext._compiler) - 1;
}
const loaderOptions = loaderUtils.getOptions(loaderContext) ||
{};
// If no instance name is given in the options, use the hash of the loader options
// In this way, if different options are given the instances will be different
const instanceName = webpackIndex +
'_' +
(loaderOptions.instance || 'default_' + getOptionsHash(loaderOptions));
if (!loaderOptionsCache.hasOwnProperty(instanceName)) {
loaderOptionsCache[instanceName] = new WeakMap();
}
const cache = loaderOptionsCache[instanceName];
if (cache.has(loaderOptions)) {
return cache.get(loaderOptions);
}
validateLoaderOptions(loaderOptions);
const options = makeLoaderOptions(instanceName, loaderOptions);
cache.set(loaderOptions, options);
return options;
}
const validLoaderOptions = [
'silent',
'logLevel',
'logInfoToStdOut',
'instance',
'compiler',
'context',
'configFile',
'transpileOnly',
'ignoreDiagnostics',
'errorFormatter',
'colors',
'compilerOptions',
'appendTsSuffixTo',
'appendTsxSuffixTo',
'onlyCompileBundledFiles',
'happyPackMode',
'getCustomTransformers',
'reportFiles',
'experimentalWatchApi',
'allowTsInNodeModules',
'experimentalFileCaching',
'projectReferences',
'resolveModuleName',
'resolveTypeReferenceDirective'
];
/**
* Validate the supplied loader options.
* At present this validates the option names only; in future we may look at validating the values too
* @param loaderOptions
*/
function validateLoaderOptions(loaderOptions) {
const loaderOptionKeys = Object.keys(loaderOptions);
// tslint:disable-next-line:prefer-for-of
for (let i = 0; i < loaderOptionKeys.length; i++) {
const option = loaderOptionKeys[i];
const isUnexpectedOption = validLoaderOptions.indexOf(option) === -1;
if (isUnexpectedOption) {
throw new Error(`ts-loader was supplied with an unexpected loader option: ${option}
Please take a look at the options you are supplying; the following are valid options:
${validLoaderOptions.join(' / ')}
`);
}
}
if (loaderOptions.context !== undefined &&
!path.isAbsolute(loaderOptions.context)) {
throw new Error(`Option 'context' has to be an absolute path. Given '${loaderOptions.context}'.`);
}
}
function makeLoaderOptions(instanceName, loaderOptions) {
const options = Object.assign({}, {
silent: false,
logLevel: 'WARN',
logInfoToStdOut: false,
compiler: 'typescript',
configFile: 'tsconfig.json',
context: undefined,
transpileOnly: false,
compilerOptions: {},
appendTsSuffixTo: [],
appendTsxSuffixTo: [],
transformers: {},
happyPackMode: false,
colors: true,
onlyCompileBundledFiles: false,
reportFiles: [],
// When the watch API usage stabilises look to remove this option and make watch usage the default behaviour when available
experimentalWatchApi: false,
allowTsInNodeModules: false,
experimentalFileCaching: true
}, loaderOptions);
options.ignoreDiagnostics = utils_1.arrify(options.ignoreDiagnostics).map(Number);
options.logLevel = options.logLevel.toUpperCase();
options.instance = instanceName;
// happypack can be used only together with transpileOnly mode
options.transpileOnly = options.happyPackMode ? true : options.transpileOnly;
return options;
}
/**
* Either add file to the overall files cache or update it in the cache when the file contents have changed
* Also add the file to the modified files
*/
function updateFileInCache(options, filePath, contents, instance) {
let fileWatcherEventKind;
// Update file contents
let file = instance.files.get(filePath);
if (file === undefined) {
file = instance.otherFiles.get(filePath);
if (file !== undefined) {
if (!instances_1.isReferencedFile(instance, filePath)) {
instance.otherFiles.delete(filePath);
instance.files.set(filePath, file);
instance.changedFilesList = true;
}
}
else {
if (instance.watchHost !== undefined ||
instance.solutionBuilderHost !== undefined) {
fileWatcherEventKind = instance.compiler.FileWatcherEventKind.Created;
}
file = { version: 0 };
if (!instances_1.isReferencedFile(instance, filePath)) {
instance.files.set(filePath, file);
instance.changedFilesList = true;
}
else {
instance.otherFiles.set(filePath, file);
}
}
}
if ((instance.watchHost !== undefined ||
instance.solutionBuilderHost !== undefined) &&
contents === undefined) {
fileWatcherEventKind = instance.compiler.FileWatcherEventKind.Deleted;
}
// filePath is a root file as it was passed to the loader. But it
// could have been found earlier as a dependency of another file. If
// that is the case, compiling this file changes the structure of
// the program and we need to increase the instance version.
//
// See https://github.com/TypeStrong/ts-loader/issues/943
if (!instances_1.isReferencedFile(instance, filePath) &&
!instance.rootFileNames.has(filePath) &&
// however, be careful not to add files from node_modules unless
// it is allowed by the options.
(options.allowTsInNodeModules || filePath.indexOf('node_modules') === -1)) {
instance.version++;
instance.rootFileNames.add(filePath);
}
if (file.text !== contents) {
file.version++;
file.text = contents;
file.modifiedTime = new Date();
instance.version++;
if ((instance.watchHost !== undefined ||
instance.solutionBuilderHost !== undefined) &&
fileWatcherEventKind === undefined) {
fileWatcherEventKind = instance.compiler.FileWatcherEventKind.Changed;
}
}
if (instance.watchHost !== undefined && fileWatcherEventKind !== undefined) {
instance.hasUnaccountedModifiedFiles = true;
instance.watchHost.invokeFileWatcher(filePath, fileWatcherEventKind);
instance.watchHost.invokeDirectoryWatcher(path.dirname(filePath), filePath);
}
if (instance.solutionBuilderHost !== undefined &&
fileWatcherEventKind !== undefined) {
instance.solutionBuilderHost.invokeFileWatcher(filePath, fileWatcherEventKind);
instance.solutionBuilderHost.invokeDirectoryWatcher(path.dirname(filePath), filePath);
}
// push this file to modified files hash.
if (!instance.modifiedFiles) {
instance.modifiedFiles = new Map();
}
instance.modifiedFiles.set(filePath, file);
return file.version;
}
function getEmit(rawFilePath, filePath, instance, loaderContext) {
const outputFiles = instances_1.getEmitOutput(instance, filePath);
loaderContext.clearDependencies();
loaderContext.addDependency(rawFilePath);
const dependencies = [];
const addDependency = (file) => {
file = path.resolve(file);
loaderContext.addDependency(file);
dependencies.push(file);
};
// Make this file dependent on *all* definition files in the program
if (!instances_1.isReferencedFile(instance, filePath)) {
for (const defFilePath of instance.files.keys()) {
if (defFilePath.match(constants.dtsDtsxOrDtsDtsxMapRegex) &&
// Remove the project reference d.ts as we are adding dependency for .ts later
// This removed extra build pass (resulting in new stats object in initial build)
(!instance.solutionBuilderHost ||
instance.solutionBuilderHost.getOutputFileFromReferencedProject(defFilePath) !== undefined)) {
addDependency(defFilePath);
}
}
}
// Additionally make this file dependent on all imported files
const fileDependencies = instance.dependencyGraph[filePath];
if (fileDependencies) {
for (const { resolvedFileName, originalFileName } of fileDependencies) {
const projectReference = utils_1.getAndCacheProjectReference(resolvedFileName, instance);
// In the case of dependencies that are part of a project reference,
// the real dependency that webpack should watch is the JS output file.
if (projectReference !== undefined) {
addDependency(utils_1.getAndCacheOutputJSFileName(resolvedFileName, projectReference, instance));
}
else {
addDependency(instances_1.getInputFileNameFromOutput(instance, path.resolve(resolvedFileName)) || originalFileName);
}
}
}
addDependenciesFromSolutionBuilder(instance, filePath, addDependency);
loaderContext._module.buildMeta.tsLoaderDefinitionFileVersions = dependencies.map(defFilePath => path.relative(loaderContext.rootContext, defFilePath) +
'@' +
(instance.files.get(defFilePath) ||
instance.otherFiles.get(defFilePath) || { version: '?' }).version);
return getOutputAndSourceMapFromOutputFiles(outputFiles);
}
function getOutputAndSourceMapFromOutputFiles(outputFiles) {
const outputFile = outputFiles
.filter(file => file.name.match(constants.jsJsx))
.pop();
const outputText = outputFile === undefined ? undefined : outputFile.text;
const sourceMapFile = outputFiles
.filter(file => file.name.match(constants.jsJsxMap))
.pop();
const sourceMapText = sourceMapFile === undefined ? undefined : sourceMapFile.text;
return { outputText, sourceMapText };
}
function addDependenciesFromSolutionBuilder(instance, filePath, addDependency) {
if (!instance.solutionBuilderHost) {
return;
}
// Add all the input files from the references as
const resolvedFilePath = path.resolve(filePath);
if (!instances_1.isReferencedFile(instance, filePath)) {
if (instance.configParseResult.fileNames.some(f => path.resolve(f) === resolvedFilePath)) {
addDependenciesFromProjectReferences(instance, path.resolve(instance.configFilePath), instance.configParseResult.projectReferences, addDependency);
}
return;
}
// Referenced file find the config for it
for (const [configFile, configInfo] of instance.solutionBuilderHost.configFileInfo.entries()) {
if (!configInfo.config ||
!configInfo.config.projectReferences ||
!configInfo.config.projectReferences.length) {
continue;
}
if (configInfo.outputFileNames) {
if (!configInfo.outputFileNames.has(resolvedFilePath)) {
continue;
}
}
else if (!configInfo.config.fileNames.some(f => path.resolve(f) === resolvedFilePath)) {
continue;
}
// Depend on all the dts files from the program
if (configInfo.dtsFiles) {
configInfo.dtsFiles.forEach(addDependency);
}
addDependenciesFromProjectReferences(instance, configFile, configInfo.config.projectReferences, addDependency);
break;
}
}
function addDependenciesFromProjectReferences(instance, configFile, projectReferences, addDependency) {
if (!projectReferences || !projectReferences.length) {
return;
}
// This is the config for the input file
const seenMap = new Map();
seenMap.set(configFile, true);
// Add dependencies to all the input files from the project reference files since building them
const queue = projectReferences.slice();
while (true) {
const currentRef = queue.pop();
if (!currentRef) {
break;
}
const refConfigFile = path.resolve(instance.compiler.resolveProjectReferencePath(currentRef));
if (seenMap.has(refConfigFile)) {
continue;
}
const refConfigInfo = instance.solutionBuilderHost.configFileInfo.get(refConfigFile);
if (!refConfigInfo) {
continue;
}
seenMap.set(refConfigFile, true);
if (refConfigInfo.config) {
refConfigInfo.config.fileNames.forEach(addDependency);
if (refConfigInfo.config.projectReferences) {
queue.push(...refConfigInfo.config.projectReferences);
}
}
}
}
/**
* Transpile file
*/
function getTranspilationEmit(fileName, contents, instance, loaderContext) {
if (instances_1.isReferencedFile(instance, fileName)) {
const outputFiles = instance.solutionBuilderHost.getOutputFilesFromReferencedProjectInput(fileName);
addDependenciesFromSolutionBuilder(instance, fileName, file => loaderContext.addDependency(path.resolve(file)));
return getOutputAndSourceMapFromOutputFiles(outputFiles);
}
const { outputText, sourceMapText, diagnostics } = instance.compiler.transpileModule(contents, {
compilerOptions: Object.assign(Object.assign({}, instance.compilerOptions), { rootDir: undefined }),
transformers: instance.transformers,
reportDiagnostics: true,
fileName
});
addDependenciesFromSolutionBuilder(instance, fileName, file => loaderContext.addDependency(path.resolve(file)));
// _module.errors is not available inside happypack - see https://github.com/TypeStrong/ts-loader/issues/336
if (!instance.loaderOptions.happyPackMode) {
const errors = utils_1.formatErrors(diagnostics, instance.loaderOptions, instance.colors, instance.compiler, { module: loaderContext._module }, loaderContext.context);
loaderContext._module.errors.push(...errors);
}
return { outputText, sourceMapText };
}
function makeSourceMap(sourceMapText, outputText, filePath, contents, loaderContext) {
if (sourceMapText === undefined) {
return { output: outputText, sourceMap: undefined };
}
return {
output: outputText.replace(/^\/\/# sourceMappingURL=[^\r\n]*/gm, ''),
sourceMap: Object.assign(JSON.parse(sourceMapText), {
sources: [loaderUtils.getRemainingRequest(loaderContext)],
file: filePath,
sourcesContent: [contents]
})
};
}
module.exports = loader;
//# sourceMappingURL=index.js.map
+24
View File
@@ -0,0 +1,24 @@
import * as typescript from 'typescript';
import * as webpack from 'webpack';
import { LoaderOptions, TSInstance, WebpackError } from './interfaces';
/**
* The loader is executed once for each file seen by webpack. However, we need to keep
* a persistent instance of TypeScript that contains all of the files in the program
* along with definition files and options. This function either creates an instance
* or returns the existing one. Multiple instances are possible by using the
* `instance` property.
*/
export declare function getTypeScriptInstance(loaderOptions: LoaderOptions, loader: webpack.loader.LoaderContext): {
instance?: TSInstance;
error?: WebpackError;
};
export declare function initializeInstance(loader: webpack.loader.LoaderContext, instance: TSInstance): void;
export declare function reportTranspileErrors(instance: TSInstance, loader: webpack.loader.LoaderContext): void;
export declare function buildSolutionReferences(instance: TSInstance, loader: webpack.loader.LoaderContext): void;
export declare function forEachResolvedProjectReference<T>(resolvedProjectReferences: readonly (typescript.ResolvedProjectReference | undefined)[] | undefined, cb: (resolvedProjectReference: typescript.ResolvedProjectReference) => T | undefined): T | undefined;
export declare function getOutputFileNames(instance: TSInstance, configFile: typescript.ParsedCommandLine, inputFileName: string): string[];
export declare function getInputFileNameFromOutput(instance: TSInstance, filePath: string): string | undefined;
export declare function isReferencedFile(instance: TSInstance, filePath: string): boolean;
export declare function getEmitFromWatchHost(instance: TSInstance, filePath?: string): typescript.OutputFile[] | undefined;
export declare function getEmitOutput(instance: TSInstance, filePath: string): typescript.OutputFile[];
//# sourceMappingURL=instances.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"instances.d.ts","sourceRoot":"","sources":["../src/instances.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,UAAU,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAMnC,OAAO,EACL,aAAa,EAGb,UAAU,EAEV,YAAY,EACb,MAAM,cAAc,CAAC;AAoBtB;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,GACnC;IAAE,QAAQ,CAAC,EAAE,UAAU,CAAC;IAAC,KAAK,CAAC,EAAE,YAAY,CAAA;CAAE,CA0BjD;AA4JD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EACpC,QAAQ,EAAE,UAAU,QAuHrB;AAgBD,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,UAAU,EACpB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,QAuBrC;AAED,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,UAAU,EACpB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,QAwBrC;AAuBD,wBAAgB,+BAA+B,CAAC,CAAC,EAC/C,yBAAyB,EACrB,SAAS,CAAC,UAAU,CAAC,wBAAwB,GAAG,SAAS,CAAC,EAAE,GAC5D,SAAS,EACb,EAAE,EAAE,CACF,wBAAwB,EAAE,UAAU,CAAC,wBAAwB,KAC1D,CAAC,GAAG,SAAS,GACjB,CAAC,GAAG,SAAS,CA8Bf;AA0ED,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,UAAU,EACpB,UAAU,EAAE,UAAU,CAAC,iBAAiB,EACxC,aAAa,EAAE,MAAM,GACpB,MAAM,EAAE,CAwCV;AAED,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,SAAS,CA2BpB;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,WAKtE;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,uCAoD3E;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,2BAwCnE"}
+445
View File
@@ -0,0 +1,445 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const chalk_1 = require("chalk");
const fs = require("fs");
const path = require("path");
const after_compile_1 = require("./after-compile");
const compilerSetup_1 = require("./compilerSetup");
const config_1 = require("./config");
const constants_1 = require("./constants");
const logger = require("./logger");
const servicesHost_1 = require("./servicesHost");
const utils_1 = require("./utils");
const watch_run_1 = require("./watch-run");
const instances = {};
/**
* The loader is executed once for each file seen by webpack. However, we need to keep
* a persistent instance of TypeScript that contains all of the files in the program
* along with definition files and options. This function either creates an instance
* or returns the existing one. Multiple instances are possible by using the
* `instance` property.
*/
function getTypeScriptInstance(loaderOptions, loader) {
if (instances.hasOwnProperty(loaderOptions.instance)) {
const instance = instances[loaderOptions.instance];
if (!instance.initialSetupPending) {
utils_1.ensureProgram(instance);
}
return { instance: instances[loaderOptions.instance] };
}
const colors = new chalk_1.default.constructor({ enabled: loaderOptions.colors });
const log = logger.makeLogger(loaderOptions, colors);
const compiler = compilerSetup_1.getCompiler(loaderOptions, log);
if (compiler.errorMessage !== undefined) {
return { error: utils_1.makeError(colors.red(compiler.errorMessage), undefined) };
}
return successfulTypeScriptInstance(loaderOptions, loader, log, colors, compiler.compiler, compiler.compilerCompatible, compiler.compilerDetailsLogMessage);
}
exports.getTypeScriptInstance = getTypeScriptInstance;
function successfulTypeScriptInstance(loaderOptions, loader, log, colors, compiler, compilerCompatible, compilerDetailsLogMessage) {
const configFileAndPath = config_1.getConfigFile(compiler, colors, loader, loaderOptions, compilerCompatible, log, compilerDetailsLogMessage);
if (configFileAndPath.configFileError !== undefined) {
const { message, file } = configFileAndPath.configFileError;
return {
error: utils_1.makeError(colors.red('error while reading tsconfig.json:' + constants_1.EOL + message), file)
};
}
const { configFilePath, configFile } = configFileAndPath;
const basePath = loaderOptions.context || path.dirname(configFilePath || '');
const configParseResult = config_1.getConfigParseResult(compiler, configFile, basePath, configFilePath, loaderOptions.projectReferences);
if (configParseResult.errors.length > 0 && !loaderOptions.happyPackMode) {
const errors = utils_1.formatErrors(configParseResult.errors, loaderOptions, colors, compiler, { file: configFilePath }, loader.context);
loader._module.errors.push(...errors);
return {
error: utils_1.makeError(colors.red('error while parsing tsconfig.json'), configFilePath)
};
}
const compilerOptions = compilerSetup_1.getCompilerOptions(configParseResult);
const rootFileNames = new Set();
const files = new Map();
const otherFiles = new Map();
const appendTsTsxSuffixesIfRequired = loaderOptions.appendTsSuffixTo.length > 0 ||
loaderOptions.appendTsxSuffixTo.length > 0
? (filePath) => utils_1.appendSuffixesIfMatch({
'.ts': loaderOptions.appendTsSuffixTo,
'.tsx': loaderOptions.appendTsxSuffixTo
}, filePath)
: (filePath) => filePath;
if (loaderOptions.transpileOnly) {
// quick return for transpiling
// we do need to check for any issues with TS options though
const transpileInstance = (instances[loaderOptions.instance] = {
compiler,
compilerOptions,
appendTsTsxSuffixesIfRequired,
loaderOptions,
rootFileNames,
files,
otherFiles,
version: 0,
program: undefined,
dependencyGraph: {},
reverseDependencyGraph: {},
transformers: {},
colors,
initialSetupPending: true,
reportTranspileErrors: true,
configFilePath,
configParseResult,
log
});
return { instance: transpileInstance };
}
// Load initial files (core lib files, any files specified in tsconfig.json)
let normalizedFilePath;
try {
const filesToLoad = loaderOptions.onlyCompileBundledFiles
? configParseResult.fileNames.filter(fileName => constants_1.dtsDtsxOrDtsDtsxMapRegex.test(fileName))
: configParseResult.fileNames;
filesToLoad.forEach(filePath => {
normalizedFilePath = path.normalize(filePath);
files.set(normalizedFilePath, {
text: fs.readFileSync(normalizedFilePath, 'utf-8'),
version: 0
});
rootFileNames.add(normalizedFilePath);
});
}
catch (exc) {
return {
error: utils_1.makeError(colors.red(`A file specified in tsconfig.json could not be found: ${normalizedFilePath}`), normalizedFilePath)
};
}
const instance = (instances[loaderOptions.instance] = {
compiler,
compilerOptions,
appendTsTsxSuffixesIfRequired,
loaderOptions,
rootFileNames,
files,
otherFiles,
languageService: null,
version: 0,
transformers: {},
dependencyGraph: {},
reverseDependencyGraph: {},
colors,
initialSetupPending: true,
configFilePath,
configParseResult,
log
});
return { instance };
}
function initializeInstance(loader, instance) {
if (!instance.initialSetupPending) {
return;
}
instance.initialSetupPending = false;
// same strategy as https://github.com/s-panferov/awesome-typescript-loader/pull/531/files
let { getCustomTransformers: customerTransformers } = instance.loaderOptions;
let getCustomTransformers = Function.prototype;
if (typeof customerTransformers === 'function') {
getCustomTransformers = customerTransformers;
}
else if (typeof customerTransformers === 'string') {
try {
customerTransformers = require(customerTransformers);
}
catch (err) {
throw new Error(`Failed to load customTransformers from "${instance.loaderOptions.getCustomTransformers}": ${err.message}`);
}
if (typeof customerTransformers !== 'function') {
throw new Error(`Custom transformers in "${instance.loaderOptions.getCustomTransformers}" should export a function, got ${typeof getCustomTransformers}`);
}
getCustomTransformers = customerTransformers;
}
if (instance.loaderOptions.transpileOnly) {
const program = (instance.program =
instance.configParseResult.projectReferences !== undefined
? instance.compiler.createProgram({
rootNames: instance.configParseResult.fileNames,
options: instance.configParseResult.options,
projectReferences: instance.configParseResult.projectReferences
})
: instance.compiler.createProgram([], instance.compilerOptions));
instance.transformers = getCustomTransformers(program);
// Setup watch run for solution building
if (instance.solutionBuilderHost) {
loader._compiler.hooks.afterCompile.tapAsync('ts-loader', after_compile_1.makeAfterCompile(instance, instance.configFilePath));
loader._compiler.hooks.watchRun.tapAsync('ts-loader', watch_run_1.makeWatchRun(instance, loader));
}
}
else {
if (!loader._compiler.hooks) {
throw new Error("You may be using an old version of webpack; please check you're using at least version 4");
}
if (instance.loaderOptions.experimentalWatchApi &&
instance.compiler.createWatchProgram) {
instance.log.logInfo('Using watch api');
// If there is api available for watch, use it instead of language service
instance.watchHost = servicesHost_1.makeWatchHost(getScriptRegexp(instance), loader, instance, instance.configParseResult.projectReferences);
instance.watchOfFilesAndCompilerOptions = instance.compiler.createWatchProgram(instance.watchHost);
instance.builderProgram = instance.watchOfFilesAndCompilerOptions.getProgram();
instance.program = instance.builderProgram.getProgram();
instance.transformers = getCustomTransformers(instance.program);
}
else {
instance.servicesHost = servicesHost_1.makeServicesHost(getScriptRegexp(instance), loader, instance, instance.loaderOptions.experimentalFileCaching, instance.configParseResult.projectReferences);
instance.languageService = instance.compiler.createLanguageService(instance.servicesHost.servicesHost, instance.compiler.createDocumentRegistry());
if (instance.servicesHost.clearCache !== null) {
loader._compiler.hooks.watchRun.tap('ts-loader', instance.servicesHost.clearCache);
}
instance.transformers = getCustomTransformers(instance.languageService.getProgram());
}
loader._compiler.hooks.afterCompile.tapAsync('ts-loader', after_compile_1.makeAfterCompile(instance, instance.configFilePath));
loader._compiler.hooks.watchRun.tapAsync('ts-loader', watch_run_1.makeWatchRun(instance, loader));
}
}
exports.initializeInstance = initializeInstance;
function getScriptRegexp(instance) {
// If resolveJsonModules is set, we should accept json files
if (instance.configParseResult.options.resolveJsonModule) {
// if allowJs is set then we should accept js(x) files
return instance.configParseResult.options.allowJs === true
? /\.tsx?$|\.json$|\.jsx?$/i
: /\.tsx?$|\.json$/i;
}
// if allowJs is set then we should accept js(x) files
return instance.configParseResult.options.allowJs === true
? /\.tsx?$|\.jsx?$/i
: /\.tsx?$/i;
}
function reportTranspileErrors(instance, loader) {
if (!instance.reportTranspileErrors) {
return;
}
instance.reportTranspileErrors = false;
// happypack does not have _module.errors - see https://github.com/TypeStrong/ts-loader/issues/336
if (!instance.loaderOptions.happyPackMode) {
const solutionErrors = servicesHost_1.getSolutionErrors(instance, loader.context);
const diagnostics = instance.program.getOptionsDiagnostics();
const errors = utils_1.formatErrors(diagnostics, instance.loaderOptions, instance.colors, instance.compiler, { file: instance.configFilePath || 'tsconfig.json' }, loader.context);
loader._module.errors.push(...solutionErrors, ...errors);
}
}
exports.reportTranspileErrors = reportTranspileErrors;
function buildSolutionReferences(instance, loader) {
if (!utils_1.supportsSolutionBuild(instance)) {
return;
}
if (!instance.solutionBuilderHost) {
// Use solution builder
instance.log.logInfo('Using SolutionBuilder api');
const scriptRegex = getScriptRegexp(instance);
instance.solutionBuilderHost = servicesHost_1.makeSolutionBuilderHost(scriptRegex, loader, instance);
instance.solutionBuilder = instance.compiler.createSolutionBuilderWithWatch(instance.solutionBuilderHost, instance.configParseResult.projectReferences.map(ref => ref.path), { verbose: true });
instance.solutionBuilder.build();
ensureAllReferences(instance);
}
else {
instance.solutionBuilderHost.buildReferences();
}
}
exports.buildSolutionReferences = buildSolutionReferences;
function ensureAllReferences(instance) {
// Return result from the json without errors so that the extra errors from config are digested here
for (const configInfo of instance.solutionBuilderHost.configFileInfo.values()) {
if (!configInfo.config) {
continue;
}
// Load all the input files
configInfo.config.fileNames.forEach(file => {
const resolvedFileName = path.resolve(file);
const existing = instance.otherFiles.get(resolvedFileName);
if (!existing) {
instance.otherFiles.set(resolvedFileName, {
version: 1,
text: instance.compiler.sys.readFile(file),
modifiedTime: instance.compiler.sys.getModifiedTime(file)
});
}
});
}
}
function forEachResolvedProjectReference(resolvedProjectReferences, cb) {
let seenResolvedRefs;
return worker(resolvedProjectReferences);
function worker(resolvedRefs) {
if (resolvedRefs) {
for (const resolvedRef of resolvedRefs) {
if (!resolvedRef) {
continue;
}
if (seenResolvedRefs &&
seenResolvedRefs.some(seenRef => seenRef === resolvedRef)) {
// ignore recursives
continue;
}
(seenResolvedRefs || (seenResolvedRefs = [])).push(resolvedRef);
const result = cb(resolvedRef) || worker(resolvedRef.references);
if (result) {
return result;
}
}
}
return undefined;
}
}
exports.forEachResolvedProjectReference = forEachResolvedProjectReference;
// This code is here as a temporary holder
function fileExtensionIs(fileName, ext) {
return fileName.endsWith(ext);
}
function rootDirOfOptions(instance, configFile) {
return (configFile.options.rootDir ||
instance.compiler.getDirectoryPath(configFile.options.configFilePath));
}
function getOutputPathWithoutChangingExt(instance, inputFileName, configFile, ignoreCase, outputDir) {
return outputDir
? instance.compiler.resolvePath(outputDir, instance.compiler.getRelativePathFromDirectory(rootDirOfOptions(instance, configFile), inputFileName, ignoreCase))
: inputFileName;
}
function getOutputJSFileName(instance, inputFileName, configFile, ignoreCase) {
if (configFile.options.emitDeclarationOnly) {
return undefined;
}
const isJsonFile = fileExtensionIs(inputFileName, '.json');
const outputFileName = instance.compiler.changeExtension(getOutputPathWithoutChangingExt(instance, inputFileName, configFile, ignoreCase, configFile.options.outDir), isJsonFile
? '.json'
: fileExtensionIs(inputFileName, '.tsx') &&
configFile.options.jsx === instance.compiler.JsxEmit.Preserve
? '.jsx'
: '.js');
return !isJsonFile ||
instance.compiler.comparePaths(inputFileName, outputFileName, configFile.options.configFilePath, ignoreCase) !== instance.compiler.Comparison.EqualTo
? outputFileName
: undefined;
}
function getOutputFileNames(instance, configFile, inputFileName) {
const ignoreCase = !instance.compiler.sys.useCaseSensitiveFileNames;
if (instance.compiler.getOutputFileNames) {
return instance.compiler.getOutputFileNames(configFile, inputFileName, ignoreCase);
}
const outputs = [];
const addOutput = (fileName) => fileName && outputs.push(fileName);
const js = getOutputJSFileName(instance, inputFileName, configFile, ignoreCase);
addOutput(js);
if (!fileExtensionIs(inputFileName, '.json')) {
if (js && configFile.options.sourceMap) {
addOutput(`${js}.map`);
}
if ((configFile.options.declaration || configFile.options.composite) &&
instance.compiler.hasTSFileExtension(inputFileName)) {
const dts = instance.compiler.getOutputDeclarationFileName(inputFileName, configFile, ignoreCase);
addOutput(dts);
if (configFile.options.declarationMap) {
addOutput(`${dts}.map`);
}
}
}
return outputs;
}
exports.getOutputFileNames = getOutputFileNames;
function getInputFileNameFromOutput(instance, filePath) {
if (filePath.match(constants_1.tsTsxRegex) && !fileExtensionIs(filePath, '.d.ts')) {
return undefined;
}
if (instance.solutionBuilderHost) {
return instance.solutionBuilderHost.getInputFileNameFromOutput(filePath);
}
const program = utils_1.ensureProgram(instance);
return (program &&
program.getResolvedProjectReferences &&
forEachResolvedProjectReference(program.getResolvedProjectReferences(), ({ commandLine }) => {
const { options, fileNames } = commandLine;
if (!options.outFile && !options.out) {
const input = fileNames.find(file => getOutputFileNames(instance, commandLine, file).find(name => path.resolve(name) === filePath));
return input && path.resolve(input);
}
return undefined;
}));
}
exports.getInputFileNameFromOutput = getInputFileNameFromOutput;
function isReferencedFile(instance, filePath) {
return (!!instance.solutionBuilderHost &&
!!instance.solutionBuilderHost.watchedFiles.get(filePath));
}
exports.isReferencedFile = isReferencedFile;
function getEmitFromWatchHost(instance, filePath) {
const program = utils_1.ensureProgram(instance);
const builderProgram = instance.builderProgram;
if (builderProgram && program) {
if (filePath) {
const existing = instance.watchHost.outputFiles.get(filePath);
if (existing) {
return existing;
}
}
const outputFiles = [];
const writeFile = (fileName, text, writeByteOrderMark) => {
if (fileName.endsWith('.tsbuildinfo')) {
instance.watchHost.tsbuildinfo = {
name: fileName,
writeByteOrderMark,
text
};
}
else {
outputFiles.push({ name: fileName, writeByteOrderMark, text });
}
};
const sourceFile = filePath ? program.getSourceFile(filePath) : undefined;
// Try emit Next file
while (true) {
const result = builderProgram.emitNextAffectedFile(writeFile,
/*cancellationToken*/ undefined,
/*emitOnlyDtsFiles*/ false, instance.transformers);
if (!result) {
break;
}
if (result.affected.fileName) {
instance.watchHost.outputFiles.set(path.resolve(result.affected.fileName), outputFiles.slice());
}
if (result.affected === sourceFile) {
return outputFiles;
}
}
}
return undefined;
}
exports.getEmitFromWatchHost = getEmitFromWatchHost;
function getEmitOutput(instance, filePath) {
if (fileExtensionIs(filePath, instance.compiler.Extension.Dts)) {
return [];
}
if (isReferencedFile(instance, filePath)) {
return instance.solutionBuilderHost.getOutputFilesFromReferencedProjectInput(filePath);
}
const program = utils_1.ensureProgram(instance);
if (program !== undefined) {
const sourceFile = program.getSourceFile(filePath);
const outputFiles = [];
const writeFile = (fileName, text, writeByteOrderMark) => outputFiles.push({ name: fileName, writeByteOrderMark, text });
// The source file will be undefined if its part of an unbuilt project reference
if (sourceFile !== undefined || !utils_1.isUsingProjectReferences(instance)) {
const outputFilesFromWatch = getEmitFromWatchHost(instance, filePath);
if (outputFilesFromWatch) {
return outputFilesFromWatch;
}
program.emit(sourceFile, writeFile,
/*cancellationToken*/ undefined,
/*emitOnlyDtsFiles*/ false, instance.transformers);
}
return outputFiles;
}
else {
// Emit Javascript
return instance.languageService.getProgram().getSourceFile(filePath) ===
undefined
? []
: instance.languageService.getEmitOutput(filePath).outputFiles;
}
}
exports.getEmitOutput = getEmitOutput;
//# sourceMappingURL=instances.js.map
+193
View File
@@ -0,0 +1,193 @@
export { ModuleResolutionHost, FormatDiagnosticsHost } from 'typescript';
import * as typescript from 'typescript';
import { Chalk } from 'chalk';
import * as logger from './logger';
export interface ErrorInfo {
code: number;
severity: Severity;
content: string;
file: string;
line: number;
character: number;
context: string;
}
export declare type FileLocation = {
line: number;
character: number;
};
export interface WebpackError {
module?: any;
file?: string;
message: string;
location?: FileLocation;
loaderSource: string;
}
export interface WebpackModule {
resource: string;
errors: WebpackError[];
buildMeta: {
tsLoaderFileVersion: number;
tsLoaderDefinitionFileVersions: string[];
};
}
export declare type ResolveSync = (context: string | undefined, path: string, moduleName: string) => string;
export declare type Action = () => void;
export interface ServiceHostWhichMayBeCacheable {
servicesHost: typescript.LanguageServiceHost;
clearCache: Action | null;
}
export interface WatchHost extends typescript.WatchCompilerHostOfFilesAndCompilerOptions<typescript.EmitAndSemanticDiagnosticsBuilderProgram> {
invokeFileWatcher(fileName: string, eventKind: typescript.FileWatcherEventKind): void;
invokeDirectoryWatcher(directory: string, fileAddedOrRemoved: string): void;
updateRootFileNames(): void;
outputFiles: Map<string, typescript.OutputFile[]>;
tsbuildinfo?: typescript.OutputFile;
}
export declare type WatchCallbacks<T> = Map<string, T[]>;
export interface WatchFactory {
watchedFiles: WatchCallbacks<typescript.FileWatcherCallback>;
watchedDirectories: WatchCallbacks<typescript.DirectoryWatcherCallback>;
watchedDirectoriesRecursive: WatchCallbacks<typescript.DirectoryWatcherCallback>;
invokeFileWatcher(fileName: string, eventKind: typescript.FileWatcherEventKind): void;
invokeDirectoryWatcher(directory: string, fileAddedOrRemoved: string): void;
/** Used to watch changes in source files, missing files needed to update the program or config file */
watchFile: typescript.WatchHost['watchFile'];
/** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */
watchDirectory: typescript.WatchHost['watchDirectory'];
}
export interface SolutionDiagnostics {
global: typescript.Diagnostic[];
perFile: Map<string, typescript.Diagnostic[]>;
transpileErrors: [string | undefined, typescript.Diagnostic[]][];
}
export interface SolutionBuilderWithWatchHost extends typescript.SolutionBuilderWithWatchHost<typescript.EmitAndSemanticDiagnosticsBuilderProgram>, WatchFactory {
diagnostics: SolutionDiagnostics;
writtenFiles: OutputFile[];
configFileInfo: Map<string, ConfigFileInfo>;
outputAffectingInstanceVersion: Map<string, true>;
getOutputFileFromReferencedProject(outputFileName: string): OutputFile | false | undefined;
getInputFileNameFromOutput(outputFileName: string): string | undefined;
getOutputFilesFromReferencedProjectInput(inputFileName: string): OutputFile[];
buildReferences(): void;
}
export interface ConfigFileInfo {
config: typescript.ParsedCommandLine | undefined;
outputFileNames?: Map<string, string[]>;
tsbuildInfoFile?: string;
dtsFiles?: string[];
}
export interface OutputFile extends typescript.OutputFile {
time: Date;
version: number;
}
export interface TSInstance {
compiler: typeof typescript;
compilerOptions: typescript.CompilerOptions;
/** Used for Vue for the most part */
appendTsTsxSuffixesIfRequired: (filePath: string) => string;
loaderOptions: LoaderOptions;
rootFileNames: Set<string>;
/**
* a cache of all the files
*/
files: TSFiles;
/**
* contains the modified files - cleared each time after-compile is called
*/
modifiedFiles?: TSFiles;
/**
* Paths to project references that are missing source maps.
* Cleared each time after-compile is called. Used to dedupe
* warnings about source maps during a single compilation.
*/
projectsMissingSourceMaps?: Set<string>;
servicesHost?: ServiceHostWhichMayBeCacheable;
languageService?: typescript.LanguageService | null;
version: number;
dependencyGraph: DependencyGraph;
reverseDependencyGraph: ReverseDependencyGraph;
filesWithErrors?: TSFiles;
transformers: typescript.CustomTransformers;
colors: Chalk;
otherFiles: TSFiles;
watchHost?: WatchHost;
watchOfFilesAndCompilerOptions?: typescript.WatchOfFilesAndCompilerOptions<typescript.EmitAndSemanticDiagnosticsBuilderProgram>;
builderProgram?: typescript.EmitAndSemanticDiagnosticsBuilderProgram;
program?: typescript.Program;
hasUnaccountedModifiedFiles?: boolean;
changedFilesList?: boolean;
reportTranspileErrors?: boolean;
solutionBuilderHost?: SolutionBuilderWithWatchHost;
solutionBuilder?: typescript.SolutionBuilder<typescript.EmitAndSemanticDiagnosticsBuilderProgram>;
configFilePath: string | undefined;
initialSetupPending: boolean;
configParseResult: typescript.ParsedCommandLine;
log: logger.Logger;
}
export interface LoaderOptionsCache {
[name: string]: WeakMap<LoaderOptions, LoaderOptions>;
}
export interface TSInstances {
[name: string]: TSInstance;
}
export interface DependencyGraph {
[file: string]: ResolvedModule[] | undefined;
}
export interface ReverseDependencyGraph {
[file: string]: {
[file: string]: boolean;
} | undefined;
}
export declare type LogLevel = 'INFO' | 'WARN' | 'ERROR';
export declare type ResolveModuleName = (moduleName: string, containingFile: string, compilerOptions: typescript.CompilerOptions, moduleResolutionHost: typescript.ModuleResolutionHost) => typescript.ResolvedModuleWithFailedLookupLocations;
export declare type CustomResolveModuleName = (moduleName: string, containingFile: string, compilerOptions: typescript.CompilerOptions, moduleResolutionHost: typescript.ModuleResolutionHost, parentResolver: ResolveModuleName) => typescript.ResolvedModuleWithFailedLookupLocations;
export declare type CustomResolveTypeReferenceDirective = (typeDirectiveName: string, containingFile: string, compilerOptions: typescript.CompilerOptions, moduleResolutionHost: typescript.ModuleResolutionHost, parentResolver: typeof typescript.resolveTypeReferenceDirective) => typescript.ResolvedTypeReferenceDirectiveWithFailedLookupLocations;
export interface LoaderOptions {
silent: boolean;
logLevel: LogLevel;
logInfoToStdOut: boolean;
instance: string;
compiler: string;
configFile: string;
context: string;
transpileOnly: boolean;
ignoreDiagnostics: number[];
reportFiles: string[];
errorFormatter: (message: ErrorInfo, colors: Chalk) => string;
onlyCompileBundledFiles: boolean;
colors: boolean;
compilerOptions: typescript.CompilerOptions;
appendTsSuffixTo: RegExp[];
appendTsxSuffixTo: RegExp[];
happyPackMode: boolean;
getCustomTransformers: string | ((program: typescript.Program) => typescript.CustomTransformers | undefined);
experimentalWatchApi: boolean;
allowTsInNodeModules: boolean;
experimentalFileCaching: boolean;
projectReferences: boolean;
resolveModuleName: CustomResolveModuleName;
resolveTypeReferenceDirective: CustomResolveTypeReferenceDirective;
}
export interface TSFile {
text?: string;
version: number;
modifiedTime?: Date;
projectReference?: {
/**
* Undefined here means weve already checked and confirmed there is no
* project reference for the file. Dont bother checking again.
*/
project?: typescript.ResolvedProjectReference;
outputFileName?: string;
};
}
/** where key is filepath */
export declare type TSFiles = Map<string, TSFile>;
export interface ResolvedModule {
originalFileName: string;
resolvedFileName: string;
resolvedModule?: ResolvedModule;
isExternalLibraryImport?: boolean;
}
export declare type Severity = 'error' | 'warning';
//# sourceMappingURL=interfaces.d.ts.map
File diff suppressed because one or more lines are too long
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=interfaces.js.map
+17
View File
@@ -0,0 +1,17 @@
import { Chalk } from 'chalk';
import { LoaderOptions } from './interfaces';
declare type LoggerFunc = (message: string) => void;
export interface Logger {
log: LoggerFunc;
logInfo: LoggerFunc;
logWarning: LoggerFunc;
logError: LoggerFunc;
}
export declare enum LogLevel {
INFO = 1,
WARN = 2,
ERROR = 3
}
export declare function makeLogger(loaderOptions: LoaderOptions, colors: Chalk): Logger;
export {};
//# sourceMappingURL=logger.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAE9B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAI7C,aAAK,UAAU,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAE5C,MAAM,WAAW,MAAM;IACrB,GAAG,EAAE,UAAU,CAAC;IAChB,OAAO,EAAE,UAAU,CAAC;IACpB,UAAU,EAAE,UAAU,CAAC;IACvB,QAAQ,EAAE,UAAU,CAAC;CACtB;AAED,oBAAY,QAAQ;IAClB,IAAI,IAAI;IACR,IAAI,IAAI;IACR,KAAK,IAAI;CACV;AAsDD,wBAAgB,UAAU,CACxB,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,KAAK,GACZ,MAAM,CAQR"}
+38
View File
@@ -0,0 +1,38 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const console_1 = require("console");
var LogLevel;
(function (LogLevel) {
LogLevel[LogLevel["INFO"] = 1] = "INFO";
LogLevel[LogLevel["WARN"] = 2] = "WARN";
LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
})(LogLevel = exports.LogLevel || (exports.LogLevel = {}));
const stderrConsole = new console_1.Console(process.stderr);
const stdoutConsole = new console_1.Console(process.stdout);
const doNothingLogger = (_message) => { };
const makeLoggerFunc = (loaderOptions) => loaderOptions.silent
? (_whereToLog, _message) => { }
: (whereToLog, message) =>
// tslint:disable-next-line:no-console
console.log.call(whereToLog, message);
const makeExternalLogger = (loaderOptions, logger) => (message) => logger(loaderOptions.logInfoToStdOut ? stdoutConsole : stderrConsole, message);
const makeLogInfo = (loaderOptions, logger, green) => LogLevel[loaderOptions.logLevel] <= LogLevel.INFO
? (message) => logger(loaderOptions.logInfoToStdOut ? stdoutConsole : stderrConsole, green(message))
: doNothingLogger;
const makeLogError = (loaderOptions, logger, red) => LogLevel[loaderOptions.logLevel] <= LogLevel.ERROR
? (message) => logger(stderrConsole, red(message))
: doNothingLogger;
const makeLogWarning = (loaderOptions, logger, yellow) => LogLevel[loaderOptions.logLevel] <= LogLevel.WARN
? (message) => logger(stderrConsole, yellow(message))
: doNothingLogger;
function makeLogger(loaderOptions, colors) {
const logger = makeLoggerFunc(loaderOptions);
return {
log: makeExternalLogger(loaderOptions, logger),
logInfo: makeLogInfo(loaderOptions, logger, colors.green),
logWarning: makeLogWarning(loaderOptions, logger, colors.yellow),
logError: makeLogError(loaderOptions, logger, colors.red)
};
}
exports.makeLogger = makeLogger;
//# sourceMappingURL=logger.js.map
+4
View File
@@ -0,0 +1,4 @@
import * as webpack from 'webpack';
import { ResolveSync } from './interfaces';
export declare function makeResolver(options: webpack.Configuration): ResolveSync;
//# sourceMappingURL=resolver.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAEnC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAK3C,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,GAAG,WAAW,CAExE"}
+9
View File
@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// tslint:disable-next-line:no-submodule-imports
const node = require('enhanced-resolve/lib/node');
function makeResolver(options) {
return node.create.sync(options.resolve);
}
exports.makeResolver = makeResolver;
//# sourceMappingURL=resolver.js.map
+18
View File
@@ -0,0 +1,18 @@
import * as typescript from 'typescript';
import * as webpack from 'webpack';
import { ServiceHostWhichMayBeCacheable, SolutionBuilderWithWatchHost, TSInstance, WatchHost, WebpackError } from './interfaces';
/**
* Create the TypeScript language service
*/
export declare function makeServicesHost(scriptRegex: RegExp, loader: webpack.loader.LoaderContext, instance: TSInstance, enableFileCaching: boolean, projectReferences?: ReadonlyArray<typescript.ProjectReference>): ServiceHostWhichMayBeCacheable;
export declare function updateFileWithText(instance: TSInstance, filePath: string, text: (nFilePath: string) => string): void;
/**
* Create the TypeScript Watch host
*/
export declare function makeWatchHost(scriptRegex: RegExp, loader: webpack.loader.LoaderContext, instance: TSInstance, projectReferences?: ReadonlyArray<typescript.ProjectReference>): WatchHost;
/**
* Create the TypeScript Watch host
*/
export declare function makeSolutionBuilderHost(scriptRegex: RegExp, loader: webpack.loader.LoaderContext, instance: TSInstance): SolutionBuilderWithWatchHost;
export declare function getSolutionErrors(instance: TSInstance, context: string): WebpackError[];
//# sourceMappingURL=servicesHost.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"servicesHost.d.ts","sourceRoot":"","sources":["../src/servicesHost.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,UAAU,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAKnC,OAAO,EAUL,8BAA8B,EAC9B,4BAA4B,EAG5B,UAAU,EAGV,SAAS,EACT,YAAY,EACb,MAAM,cAAc,CAAC;AAuBtB;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EACpC,QAAQ,EAAE,UAAU,EACpB,iBAAiB,EAAE,OAAO,EAC1B,iBAAiB,CAAC,EAAE,aAAa,CAAC,UAAU,CAAC,gBAAgB,CAAC,GAC7D,8BAA8B,CA6KhC;AA6LD,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,QA8BpC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EACpC,QAAQ,EAAE,UAAU,EACpB,iBAAiB,CAAC,EAAE,aAAa,CAAC,UAAU,CAAC,gBAAgB,CAAC,aA8J/D;AAMD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EACpC,QAAQ,EAAE,UAAU,GACnB,4BAA4B,CA4W9B;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,kBAqBtE"}
+687
View File
@@ -0,0 +1,687 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
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 readFileWithInstance(instance, filePath, encoding) {
if (instance.solutionBuilderHost) {
const outputFile = instance.solutionBuilderHost.getOutputFileFromReferencedProject(filePath);
if (outputFile !== undefined) {
return outputFile ? outputFile.text : undefined;
}
}
return (instance.compiler.sys.readFile(filePath, encoding) ||
utils_1.readFile(filePath, encoding));
}
/**
* Create the TypeScript language service
*/
function makeServicesHost(scriptRegex, loader, instance, enableFileCaching, projectReferences) {
const { compiler, compilerOptions, appendTsTsxSuffixesIfRequired, files, loaderOptions: { resolveModuleName: customResolveModuleName, resolveTypeReferenceDirective: customResolveTypeReferenceDirective } } = instance;
const newLine = compilerOptions.newLine === constants.CarriageReturnLineFeedCode
? constants.CarriageReturnLineFeed
: compilerOptions.newLine === constants.LineFeedCode
? constants.LineFeed
: constants.EOL;
// make a (sync) resolver that follows webpack's rules
const resolveSync = resolver_1.makeResolver(loader._compiler.options);
const readFileWithFallback = (filePath, encoding) => readFileWithInstance(instance, filePath, encoding);
const fileExists = (filePathToCheck) => {
if (instance.solutionBuilderHost) {
const outputFile = instance.solutionBuilderHost.getOutputFileFromReferencedProject(filePathToCheck);
if (outputFile !== undefined) {
return !!outputFile;
}
}
return (compiler.sys.fileExists(filePathToCheck) ||
utils_1.readFile(filePathToCheck) !== undefined);
};
let clearCache = null;
let moduleResolutionHost = {
fileExists,
readFile: readFileWithFallback,
realpath: compiler.sys.realpath,
directoryExists: compiler.sys.directoryExists,
getCurrentDirectory: compiler.sys.getCurrentDirectory,
getDirectories: compiler.sys.getDirectories
};
if (enableFileCaching) {
const cached = addCache(moduleResolutionHost);
clearCache = cached.clearCache;
moduleResolutionHost = cached.moduleResolutionHost;
}
// 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;
const resolvers = makeResolvers(compiler, compilerOptions, moduleResolutionHost, customResolveTypeReferenceDirective, customResolveModuleName, resolveSync, appendTsTsxSuffixesIfRequired, scriptRegex, instance);
const servicesHost = {
getProjectVersion: () => `${instance.version}`,
getProjectReferences: () => projectReferences,
getScriptFileNames: () => [...files.keys()].filter(filePath => filePath.match(scriptRegex)),
getScriptVersion: (fileName) => {
fileName = path.normalize(fileName);
const file = files.get(fileName);
if (file) {
return file.version.toString();
}
const outputFile = instance.solutionBuilderHost &&
instance.solutionBuilderHost.getOutputFileFromReferencedProject(fileName);
if (outputFile !== undefined) {
instance.solutionBuilderHost.outputAffectingInstanceVersion.set(path.resolve(fileName), true);
}
return outputFile ? outputFile.version.toString() : '';
},
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);
let file = files.get(fileName);
if (file === undefined) {
if (instance.solutionBuilderHost) {
const outputFile = instance.solutionBuilderHost.getOutputFileFromReferencedProject(fileName);
if (outputFile !== undefined) {
instance.solutionBuilderHost.outputAffectingInstanceVersion.set(path.resolve(fileName), true);
return outputFile
? compiler.ScriptSnapshot.fromString(outputFile.text)
: undefined;
}
}
const text = utils_1.readFile(fileName);
if (text === undefined) {
return undefined;
}
file = { version: 0, text };
files.set(fileName, file);
}
return compiler.ScriptSnapshot.fromString(file.text);
},
/**
* getDirectories is also required for full import and type reference completions.
* Without it defined, certain completions will not be provided
*/
getDirectories: compiler.sys.getDirectories,
/**
* For @types expansion, these two functions are needed.
*/
directoryExists: moduleResolutionHost.directoryExists,
useCaseSensitiveFileNames: () => compiler.sys.useCaseSensitiveFileNames,
realpath: moduleResolutionHost.realpath,
// The following three methods are necessary for @types resolution from TS 2.4.1 onwards see: https://github.com/Microsoft/TypeScript/issues/16772
fileExists: moduleResolutionHost.fileExists,
readFile: moduleResolutionHost.readFile,
readDirectory: compiler.sys.readDirectory,
getCurrentDirectory,
getCompilationSettings: () => compilerOptions,
getDefaultLibFileName: (options) => compiler.getDefaultLibFilePath(options),
getNewLine: () => newLine,
trace: instance.log.log,
log: instance.log.log,
// used for (/// <reference types="...">) see https://github.com/Realytics/fork-ts-checker-webpack-plugin/pull/250#issuecomment-485061329
resolveTypeReferenceDirectives: resolvers.resolveTypeReferenceDirectives,
resolveModuleNames: resolvers.resolveModuleNames,
getCustomTransformers: () => instance.transformers
};
return { servicesHost, clearCache };
}
exports.makeServicesHost = makeServicesHost;
function makeResolvers(compiler, compilerOptions, moduleResolutionHost, customResolveTypeReferenceDirective, customResolveModuleName, resolveSync, appendTsTsxSuffixesIfRequired, scriptRegex, instance) {
const resolveTypeReferenceDirective = makeResolveTypeReferenceDirective(compiler, compilerOptions, moduleResolutionHost, customResolveTypeReferenceDirective);
const resolveTypeReferenceDirectives = (typeDirectiveNames, containingFile, _redirectedReference) => typeDirectiveNames.map(directive => resolveTypeReferenceDirective(directive, containingFile, _redirectedReference).resolvedTypeReferenceDirective);
const resolveModuleName = makeResolveModuleName(compiler, compilerOptions, moduleResolutionHost, customResolveModuleName);
const resolveModuleNames = (moduleNames, containingFile, _reusedNames, _redirectedReference) => {
const resolvedModules = moduleNames.map(moduleName => resolveModule(resolveSync, resolveModuleName, appendTsTsxSuffixesIfRequired, scriptRegex, moduleName, containingFile));
populateDependencyGraphs(resolvedModules, instance, containingFile);
return resolvedModules;
};
return {
resolveTypeReferenceDirectives,
resolveModuleNames
};
}
function createWatchFactory() {
const watchedFiles = new Map();
const watchedDirectories = new Map();
const watchedDirectoriesRecursive = new Map();
return {
watchedFiles,
watchedDirectories,
watchedDirectoriesRecursive,
invokeFileWatcher,
invokeDirectoryWatcher,
watchFile,
watchDirectory
};
function invokeWatcherCallbacks(map, key, fileName, eventKind) {
const callbacks = map.get(key);
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);
}
}
}
function invokeFileWatcher(fileName, eventKind) {
fileName = path.normalize(fileName);
invokeWatcherCallbacks(watchedFiles, fileName, fileName, eventKind);
}
function invokeDirectoryWatcher(directory, fileAddedOrRemoved) {
directory = path.normalize(directory);
invokeWatcherCallbacks(watchedDirectories, directory, fileAddedOrRemoved);
invokeRecursiveDirectoryWatcher(directory, fileAddedOrRemoved);
}
function invokeRecursiveDirectoryWatcher(directory, fileAddedOrRemoved) {
directory = path.normalize(directory);
invokeWatcherCallbacks(watchedDirectoriesRecursive, directory, fileAddedOrRemoved);
const basePath = path.dirname(directory);
if (directory !== basePath) {
invokeRecursiveDirectoryWatcher(basePath, fileAddedOrRemoved);
}
}
function createWatcher(file, callbacks, callback) {
file = path.normalize(file);
const existing = callbacks.get(file);
if (existing === undefined) {
callbacks.set(file, [callback]);
}
else {
existing.push(callback);
}
return {
close: () => {
// tslint:disable-next-line:no-shadowed-variable
const existing = callbacks.get(file);
if (existing !== undefined) {
utils_1.unorderedRemoveItem(existing, callback);
if (!existing.length) {
callbacks.delete(file);
}
}
}
};
}
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, filePath, text) {
const nFilePath = path.normalize(filePath);
const file = instance.files.get(nFilePath) || instance.otherFiles.get(nFilePath);
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(nFilePath, file);
if (instance.watchHost !== undefined) {
instance.watchHost.invokeFileWatcher(nFilePath, instance.compiler.FileWatcherEventKind.Changed);
}
if (instance.solutionBuilderHost !== undefined) {
instance.solutionBuilderHost.invokeFileWatcher(nFilePath, instance.compiler.FileWatcherEventKind.Changed);
}
}
}
}
exports.updateFileWithText = updateFileWithText;
/**
* Create the TypeScript Watch host
*/
function makeWatchHost(scriptRegex, loader, instance, projectReferences) {
const { compiler, compilerOptions, appendTsTsxSuffixesIfRequired, files, otherFiles, loaderOptions: { resolveModuleName: customResolveModuleName, resolveTypeReferenceDirective: customResolveTypeReferenceDirective } } = instance;
const newLine = compilerOptions.newLine === constants.CarriageReturnLineFeedCode
? constants.CarriageReturnLineFeed
: compilerOptions.newLine === constants.LineFeedCode
? constants.LineFeed
: constants.EOL;
// make a (sync) resolver that follows webpack's rules
const resolveSync = resolver_1.makeResolver(loader._compiler.options);
const readFileWithFallback = (filePath, encoding) => readFileWithInstance(instance, filePath, encoding);
const moduleResolutionHost = {
fileExists,
readFile: readFileWithFallback,
realpath: compiler.sys.realpath
};
// 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;
const { watchFile, watchDirectory, invokeFileWatcher, invokeDirectoryWatcher } = createWatchFactory();
const resolvers = makeResolvers(compiler, compilerOptions, moduleResolutionHost, customResolveTypeReferenceDirective, customResolveModuleName, resolveSync, appendTsTsxSuffixesIfRequired, scriptRegex, instance);
const watchHost = {
rootFiles: getRootFileNames(),
options: compilerOptions,
useCaseSensitiveFileNames: () => compiler.sys.useCaseSensitiveFileNames,
getNewLine: () => newLine,
getCurrentDirectory,
getDefaultLibFileName: options => compiler.getDefaultLibFilePath(options),
fileExists,
readFile: readFileWithCachingText,
directoryExists: dirPath => compiler.sys.directoryExists(path.normalize(dirPath)),
getDirectories: dirPath => compiler.sys.getDirectories(path.normalize(dirPath)),
readDirectory: (dirPath, extensions, exclude, include, depth) => compiler.sys.readDirectory(path.normalize(dirPath), extensions, exclude, include, depth),
realpath: dirPath => compiler.sys.resolvePath(path.normalize(dirPath)),
trace: logData => instance.log.log(logData),
watchFile,
watchDirectory,
// used for (/// <reference types="...">) see https://github.com/Realytics/fork-ts-checker-webpack-plugin/pull/250#issuecomment-485061329
resolveTypeReferenceDirectives: resolvers.resolveTypeReferenceDirectives,
resolveModuleNames: resolvers.resolveModuleNames,
invokeFileWatcher,
invokeDirectoryWatcher,
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.keys()].filter(filePath => filePath.match(scriptRegex));
}
function readFileWithCachingText(fileName, encoding) {
fileName = path.normalize(fileName);
const file = files.get(fileName) || otherFiles.get(fileName);
if (file !== undefined) {
return file.text;
}
const text = readFileWithFallback(fileName, encoding);
if (text === undefined) {
return undefined;
}
otherFiles.set(fileName, { version: 0, text });
return text;
}
function fileExists(fileName) {
const filePath = path.normalize(fileName);
return files.has(filePath) || compiler.sys.fileExists(filePath);
}
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;
function normalizeSlashes(file) {
return file.replace(/\\/g, '/');
}
/**
* Create the TypeScript Watch host
*/
function makeSolutionBuilderHost(scriptRegex, loader, instance) {
const { compiler, compilerOptions, appendTsTsxSuffixesIfRequired, loaderOptions: { resolveModuleName: customResolveModuleName, resolveTypeReferenceDirective: customResolveTypeReferenceDirective, transpileOnly } } = instance;
// 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;
const formatDiagnosticHost = {
getCurrentDirectory: compiler.sys.getCurrentDirectory,
getCanonicalFileName: compiler.sys.useCaseSensitiveFileNames
? s => s
: s => s.toLowerCase(),
getNewLine: () => compiler.sys.newLine
};
const diagnostics = {
global: [],
perFile: new Map(),
transpileErrors: []
};
const reportDiagnostic = (d) => {
if (transpileOnly) {
const filePath = d.file ? path.resolve(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 = path.resolve(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 writtenFiles = [];
const outputAffectingInstanceVersion = new Map();
let timeoutId;
const configFileInfo = new Map();
const solutionBuilderHost = Object.assign(Object.assign(Object.assign(Object.assign({}, compiler.createSolutionBuilderWithWatchHost(compiler.sys, compiler.createEmitAndSemanticDiagnosticsBuilderProgram, reportDiagnostic, reportSolutionBuilderStatus, reportWatchStatus)), { diagnostics }), createWatchFactory()), {
// Overrides
getCurrentDirectory,
// behave as if there is no tsbuild info on disk since we want to generate all outputs in memory and only use those
readFile: (fileName, encoding) => {
const outputFile = ensureOutputFile(fileName);
return outputFile !== undefined
? outputFile
? outputFile.text
: undefined
: readInputFile(fileName, encoding).text;
}, writeFile: (name, text, writeByteOrderMark) => {
updateFileWithText(instance, name, () => text);
const resolvedFileName = path.resolve(name);
const existing = outputFiles.get(resolvedFileName);
const newOutputFile = {
name,
text,
writeByteOrderMark: !!writeByteOrderMark,
time: new Date(),
version: existing
? existing.text !== text
? existing.version + 1
: existing.version
: 0
};
outputFiles.set(resolvedFileName, newOutputFile);
writtenFiles.push(newOutputFile);
if (outputAffectingInstanceVersion.has(resolvedFileName) &&
(!existing || existing.text !== text)) {
instance.version++;
}
}, getModifiedTime: fileName => {
const outputFile = ensureOutputFile(fileName);
if (outputFile !== undefined) {
return outputFile ? outputFile.time : undefined;
}
const existing = instance.files.get(path.resolve(fileName)) ||
instance.otherFiles.get(path.resolve(fileName));
return existing
? existing.modifiedTime
: compiler.sys.getModifiedTime(fileName);
}, setModifiedTime: (fileName, time) => {
const outputFile = ensureOutputFile(fileName);
if (outputFile !== undefined) {
if (outputFile) {
outputFile.time = time;
}
}
compiler.sys.setModifiedTime(fileName, time);
const existing = instance.files.get(path.resolve(fileName)) ||
instance.otherFiles.get(path.resolve(fileName));
if (existing) {
existing.modifiedTime = time;
}
}, fileExists: fileName => {
const outputFile = ensureOutputFile(fileName);
if (outputFile !== undefined) {
return !!outputFile;
}
const existing = instance.files.get(path.resolve(fileName)) ||
instance.otherFiles.get(path.resolve(fileName));
return existing
? existing.text !== undefined
: compiler.sys.fileExists(fileName);
}, directoryExists: directory => {
if (compiler.sys.directoryExists(directory)) {
return true;
}
const resolvedDirectory = normalizeSlashes(path.resolve(directory)) + '/';
for (const outputFile of outputFiles.keys()) {
if (normalizeSlashes(outputFile).startsWith(resolvedDirectory)) {
return true;
}
}
return false;
}, afterProgramEmitAndDiagnostics: transpileOnly ? undefined : storeDtsFiles, setTimeout: (callback, _time, ...args) => {
timeoutId = [callback, args];
return timeoutId;
}, clearTimeout: _timeoutId => {
timeoutId = undefined;
}, writtenFiles,
configFileInfo,
outputAffectingInstanceVersion,
getOutputFileFromReferencedProject, getInputFileNameFromOutput: fileName => {
const result = getInputFileNameFromOutput(fileName);
return typeof result === 'string' ? result : undefined;
}, getOutputFilesFromReferencedProjectInput,
buildReferences });
solutionBuilderHost.trace = logData => instance.log.logInfo(logData);
solutionBuilderHost.getParsedCommandLine = file => {
const config = config_1.getParsedCommandLine(compiler, instance.loaderOptions, file);
configFileInfo.set(path.resolve(file), { config });
return config;
};
// make a (sync) resolver that follows webpack's rules
const resolveSync = resolver_1.makeResolver(loader._compiler.options);
const resolvers = makeResolvers(compiler, compilerOptions, solutionBuilderHost, customResolveTypeReferenceDirective, customResolveModuleName, resolveSync, appendTsTsxSuffixesIfRequired, scriptRegex, instance);
// used for (/// <reference types="...">) see https://github.com/Realytics/fork-ts-checker-webpack-plugin/pull/250#issuecomment-485061329
solutionBuilderHost.resolveTypeReferenceDirectives =
resolvers.resolveTypeReferenceDirectives;
solutionBuilderHost.resolveModuleNames = resolvers.resolveModuleNames;
return solutionBuilderHost;
function buildReferences() {
if (!timeoutId) {
return;
}
diagnostics.global.length = 0;
diagnostics.perFile.clear();
diagnostics.transpileErrors.length = 0;
while (timeoutId) {
const [callback, args] = timeoutId;
timeoutId = undefined;
callback(...args);
}
}
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 = path.resolve(outputFileName);
for (const configInfo of configFileInfo.values()) {
ensureInputOutputInfo(configInfo);
if (configInfo.outputFileNames) {
for (const [inputFileName, outputFilesOfInput] of configInfo.outputFileNames.entries()) {
if (outputFilesOfInput.indexOf(resolvedFileName) !== -1) {
return inputFileName;
}
}
}
if (configInfo.tsbuildInfoFile &&
path.resolve(configInfo.tsbuildInfoFile) === resolvedFileName) {
return true;
}
}
return undefined;
}
function ensureInputOutputInfo(configInfo) {
if (configInfo.outputFileNames || !configInfo.config) {
return;
}
configInfo.outputFileNames = new Map();
configInfo.config.fileNames.forEach(inputFile => configInfo.outputFileNames.set(path.resolve(inputFile), instances_1.getOutputFileNames(instance, configInfo.config, inputFile).map(output => path.resolve(output))));
configInfo.tsbuildInfoFile = instance.compiler
.getTsBuildInfoEmitOutputFilePath
? instance.compiler.getTsBuildInfoEmitOutputFilePath(configInfo.config.options)
: // before api
instance.compiler.getOutputPathForBuildInfo(configInfo.config.options);
}
function getOutputFileFromReferencedProject(outputFileName) {
const resolvedFileName = path.resolve(outputFileName);
return outputFiles.get(resolvedFileName);
}
function ensureOutputFile(outputFileName, encoding) {
const outputFile = getOutputFileFromReferencedProject(outputFileName);
if (outputFile !== undefined) {
return outputFile;
}
if (!getInputFileNameFromOutput(outputFileName)) {
return undefined;
}
const resolvedFileName = path.resolve(outputFileName);
const text = compiler.sys.readFile(outputFileName, encoding);
if (text === undefined) {
outputFiles.set(resolvedFileName, false);
return false;
}
const newOutputFile = {
name: outputFileName,
text,
writeByteOrderMark: false,
time: compiler.sys.getModifiedTime(outputFileName),
version: 0
};
outputFiles.set(resolvedFileName, newOutputFile);
return newOutputFile;
}
function getOutputFilesFromReferencedProjectInput(inputFileName) {
const resolvedFileName = path.resolve(inputFileName);
for (const configInfo of configFileInfo.values()) {
ensureInputOutputInfo(configInfo);
if (configInfo.outputFileNames) {
const result = configInfo.outputFileNames.get(resolvedFileName);
if (result) {
return result
.map(outputFile => outputFiles.get(outputFile))
.filter(output => !!output);
}
}
}
return [];
}
function readInputFile(inputFileName, encoding) {
const resolvedFileName = path.resolve(inputFileName);
const existing = instance.otherFiles.get(resolvedFileName);
if (existing) {
return existing;
}
const tsFile = {
version: 1,
text: compiler.sys.readFile(inputFileName, encoding),
modifiedTime: compiler.sys.getModifiedTime(inputFileName)
};
instance.otherFiles.set(resolvedFileName, tsFile);
return tsFile;
}
}
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(...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) {
if (customResolveTypeReferenceDirective === undefined) {
return (directive, containingFile, redirectedReference) => compiler.resolveTypeReferenceDirective(directive, containingFile, compilerOptions, moduleResolutionHost, redirectedReference);
}
return (directive, containingFile) => customResolveTypeReferenceDirective(directive, 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) {
let resolutionResult;
try {
const originalFileName = resolveSync(undefined, path.normalize(path.dirname(containingFile)), moduleName);
const resolvedFileName = appendTsTsxSuffixesIfRequired(originalFileName);
if (resolvedFileName.match(scriptRegex) !== null) {
resolutionResult = { resolvedFileName, originalFileName };
}
// tslint:disable-next-line:no-empty
}
catch (e) { }
const tsResolution = resolveModuleName(moduleName, containingFile);
if (tsResolution.resolvedModule !== undefined) {
const resolvedFileName = path.normalize(tsResolution.resolvedModule.resolvedFileName);
const tsResolutionResult = {
originalFileName: resolvedFileName,
resolvedFileName,
isExternalLibraryImport: tsResolution.resolvedModule.isExternalLibraryImport
};
return resolutionResult === undefined ||
resolutionResult.resolvedFileName ===
tsResolutionResult.resolvedFileName ||
isJsImplementationOfTypings(resolutionResult, tsResolutionResult)
? tsResolutionResult
: resolutionResult;
}
return resolutionResult;
}
function makeResolveModuleName(compiler, compilerOptions, moduleResolutionHost, customResolveModuleName) {
if (customResolveModuleName === undefined) {
return (moduleName, containingFile) => compiler.resolveModuleName(moduleName, containingFile, compilerOptions, moduleResolutionHost);
}
return (moduleName, containingFile) => customResolveModuleName(moduleName, containingFile, compilerOptions, moduleResolutionHost, compiler.resolveModuleName);
}
function populateDependencyGraphs(resolvedModules, instance, containingFile) {
resolvedModules = resolvedModules.filter(mod => mod !== null && mod !== undefined);
instance.dependencyGraph[path.normalize(containingFile)] = resolvedModules;
resolvedModules.forEach(resolvedModule => {
if (instance.reverseDependencyGraph[resolvedModule.resolvedFileName] ===
undefined) {
instance.reverseDependencyGraph[resolvedModule.resolvedFileName] = {};
}
instance.reverseDependencyGraph[resolvedModule.resolvedFileName][path.normalize(containingFile)] = true;
});
}
function addCache(servicesHost) {
const clearCacheFunctions = [];
return {
moduleResolutionHost: Object.assign(Object.assign({}, servicesHost), { fileExists: createCache(servicesHost.fileExists), directoryExists: servicesHost.directoryExists &&
createCache(servicesHost.directoryExists), realpath: servicesHost.realpath && createCache(servicesHost.realpath) }),
clearCache: () => clearCacheFunctions.forEach(clear => clear())
};
function createCache(originalFunction) {
const cache = new Map();
clearCacheFunctions.push(() => cache.clear());
return function getCached(arg) {
let res = cache.get(arg);
if (res !== undefined) {
return res;
}
res = originalFunction(arg);
cache.set(arg, res);
return res;
};
}
}
//# sourceMappingURL=servicesHost.js.map
+1
View File
@@ -0,0 +1 @@
//# sourceMappingURL=stringify-loader.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"stringify-loader.d.ts","sourceRoot":"","sources":["../src/stringify-loader.ts"],"names":[],"mappings":""}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
module.exports = (source) => JSON.stringify(source);
//# sourceMappingURL=stringify-loader.js.map
+51
View File
@@ -0,0 +1,51 @@
import { Chalk } from 'chalk';
import * as typescript from 'typescript';
import * as webpack from 'webpack';
import { DependencyGraph, LoaderOptions, ReverseDependencyGraph, TSInstance, WebpackError, WebpackModule } from './interfaces';
/**
* Take TypeScript errors, parse them and format to webpack errors
* Optionally adds a file name
*/
export declare function formatErrors(diagnostics: ReadonlyArray<typescript.Diagnostic> | undefined, loaderOptions: LoaderOptions, colors: Chalk, compiler: typeof typescript, merge: {
file?: string;
module?: WebpackModule;
}, context: string): WebpackError[];
export declare function readFile(fileName: string, encoding?: string | undefined): string | undefined;
export declare function makeError(message: string, file: string | undefined, location?: {
line: number;
character: number;
}): WebpackError;
export declare function appendSuffixIfMatch(patterns: RegExp[], filePath: string, suffix: string): string;
export declare function appendSuffixesIfMatch(suffixDict: {
[suffix: string]: RegExp[];
}, filePath: string): string;
export declare function unorderedRemoveItem<T>(array: T[], item: T): boolean;
/**
* Recursively collect all possible dependants of passed file
*/
export declare function collectAllDependants(reverseDependencyGraph: ReverseDependencyGraph, fileName: string, collected?: {
[file: string]: boolean;
}): string[];
/**
* Recursively collect all possible dependencies of passed file
*/
export declare function collectAllDependencies(dependencyGraph: DependencyGraph, filePath: string, collected?: {
[file: string]: boolean;
}): string[];
export declare function arrify<T>(val: T | T[]): T[];
export declare function ensureProgram(instance: TSInstance): typescript.Program | undefined;
export declare function supportsProjectReferences(instance: TSInstance): true | undefined;
export declare function isUsingProjectReferences(instance: TSInstance): boolean;
/**
* Gets the project reference for a file from the cache if it exists,
* or gets it from TypeScript and caches it otherwise.
*/
export declare function getAndCacheProjectReference(filePath: string, instance: TSInstance): typescript.ResolvedProjectReference | undefined;
export declare function validateSourceMapOncePerProject(instance: TSInstance, loader: webpack.loader.LoaderContext, jsFileName: string, project: typescript.ResolvedProjectReference): void;
export declare function supportsSolutionBuild(instance: TSInstance): boolean;
/**
* Gets the output JS file path for an input file governed by a composite project.
* Pulls from the cache if it exists; computes and caches the result otherwise.
*/
export declare function getAndCacheOutputJSFileName(inputFileName: string, projectReference: typescript.ResolvedProjectReference, instance: TSInstance): string;
//# sourceMappingURL=utils.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAI9B,OAAO,KAAK,UAAU,MAAM,YAAY,CAAC;AACzC,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAGnC,OAAO,EACL,eAAe,EAEf,aAAa,EACb,sBAAsB,EAEtB,UAAU,EACV,YAAY,EACZ,aAAa,EACd,MAAM,cAAc,CAAC;AAqBtB;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,SAAS,EAC7D,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,KAAK,EACb,QAAQ,EAAE,OAAO,UAAU,EAC3B,KAAK,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,aAAa,CAAA;CAAE,EAChD,OAAO,EAAE,MAAM,GACd,YAAY,EAAE,CA8DhB;AAED,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,MAAM,EAChB,QAAQ,GAAE,MAAM,GAAG,SAAkB,sBAQtC;AAED,wBAAgB,SAAS,CACvB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,QAAQ,CAAC,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC7C,YAAY,CAOd;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAAE,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,MAAM,CASR;AAED,wBAAgB,qBAAqB,CACnC,UAAU,EAAE;IAAE,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;CAAE,EAC1C,QAAQ,EAAE,MAAM,GACf,MAAM,CAMR;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,OAAO,CAUnE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,sBAAsB,EAAE,sBAAsB,EAC9C,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE;IAAE,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAAO,GAC1C,MAAM,EAAE,CAiBV;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,eAAe,EAAE,eAAe,EAChC,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE;IAAE,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAAO,GAC1C,MAAM,EAAE,CAiBV;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,OAMrC;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,UAAU,kCAkBjD;AAED,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,UAAU,oBAG7D;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,UAAU,WAS5D;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,UAAU,mDAkBrB;AAiCD,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,UAAU,EACpB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EACpC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,UAAU,CAAC,wBAAwB,QAsB7C;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,UAAU,WAQzD;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,aAAa,EAAE,MAAM,EACrB,gBAAgB,EAAE,UAAU,CAAC,wBAAwB,EACrD,QAAQ,EAAE,UAAU,UAoBrB"}
+293
View File
@@ -0,0 +1,293 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const fs = require("fs");
const micromatch = require("micromatch");
const path = require("path");
const typescript = require("typescript");
const constants = require("./constants");
/**
* The default error formatter.
*/
function defaultErrorFormatter(error, colors) {
const messageColor = error.severity === 'warning' ? colors.bold.yellow : colors.bold.red;
return (colors.grey('[tsl] ') +
messageColor(error.severity.toUpperCase()) +
(error.file === ''
? ''
: messageColor(' in ') +
colors.bold.cyan(`${error.file}(${error.line},${error.character})`)) +
constants.EOL +
messageColor(` TS${error.code}: ${error.content}`));
}
/**
* Take TypeScript errors, parse them and format to webpack errors
* Optionally adds a file name
*/
function formatErrors(diagnostics, loaderOptions, colors, compiler, merge, context) {
return diagnostics === undefined
? []
: diagnostics
.filter(diagnostic => {
if (loaderOptions.ignoreDiagnostics.indexOf(diagnostic.code) !== -1) {
return false;
}
if (loaderOptions.reportFiles.length > 0 &&
diagnostic.file !== undefined) {
const relativeFileName = path.relative(context, diagnostic.file.fileName);
const matchResult = micromatch([relativeFileName], loaderOptions.reportFiles);
if (matchResult.length === 0) {
return false;
}
}
return true;
})
.map(diagnostic => {
const file = diagnostic.file;
const position = file === undefined
? undefined
: file.getLineAndCharacterOfPosition(diagnostic.start);
const errorInfo = {
code: diagnostic.code,
severity: compiler.DiagnosticCategory[diagnostic.category].toLowerCase(),
content: compiler.flattenDiagnosticMessageText(diagnostic.messageText, constants.EOL),
file: file === undefined ? '' : path.normalize(file.fileName),
line: position === undefined ? 0 : position.line + 1,
character: position === undefined ? 0 : position.character + 1,
context
};
const message = loaderOptions.errorFormatter === undefined
? defaultErrorFormatter(errorInfo, colors)
: loaderOptions.errorFormatter(errorInfo, colors);
const error = makeError(message, merge.file === undefined ? errorInfo.file : merge.file, position === undefined
? undefined
: { line: errorInfo.line, character: errorInfo.character });
return Object.assign(error, merge);
});
}
exports.formatErrors = formatErrors;
function readFile(fileName, encoding = 'utf8') {
fileName = path.normalize(fileName);
try {
return fs.readFileSync(fileName, encoding);
}
catch (e) {
return undefined;
}
}
exports.readFile = readFile;
function makeError(message, file, location) {
return {
message,
location,
file,
loaderSource: 'ts-loader'
};
}
exports.makeError = makeError;
function appendSuffixIfMatch(patterns, filePath, suffix) {
if (patterns.length > 0) {
for (const regexp of patterns) {
if (filePath.match(regexp) !== null) {
return filePath + suffix;
}
}
}
return filePath;
}
exports.appendSuffixIfMatch = appendSuffixIfMatch;
function appendSuffixesIfMatch(suffixDict, filePath) {
let amendedPath = filePath;
for (const suffix in suffixDict) {
amendedPath = appendSuffixIfMatch(suffixDict[suffix], amendedPath, suffix);
}
return amendedPath;
}
exports.appendSuffixesIfMatch = appendSuffixesIfMatch;
function unorderedRemoveItem(array, item) {
for (let i = 0; i < array.length; i++) {
if (array[i] === item) {
// Fill in the "hole" left at `index`.
array[i] = array[array.length - 1];
array.pop();
return true;
}
}
return false;
}
exports.unorderedRemoveItem = unorderedRemoveItem;
/**
* Recursively collect all possible dependants of passed file
*/
function collectAllDependants(reverseDependencyGraph, fileName, collected = {}) {
const result = {};
result[fileName] = true;
collected[fileName] = true;
const dependants = reverseDependencyGraph[fileName];
if (dependants !== undefined) {
Object.keys(dependants).forEach(dependantFileName => {
if (!collected[dependantFileName]) {
collectAllDependants(reverseDependencyGraph, dependantFileName, collected).forEach(fName => (result[fName] = true));
}
});
}
return Object.keys(result);
}
exports.collectAllDependants = collectAllDependants;
/**
* Recursively collect all possible dependencies of passed file
*/
function collectAllDependencies(dependencyGraph, filePath, collected = {}) {
const result = {};
result[filePath] = true;
collected[filePath] = true;
const directDependencies = dependencyGraph[filePath];
if (directDependencies !== undefined) {
directDependencies.forEach(dependencyModule => {
if (!collected[dependencyModule.originalFileName]) {
collectAllDependencies(dependencyGraph, dependencyModule.resolvedFileName, collected).forEach(depFilePath => (result[depFilePath] = true));
}
});
}
return Object.keys(result);
}
exports.collectAllDependencies = collectAllDependencies;
function arrify(val) {
if (val === null || val === undefined) {
return [];
}
return Array.isArray(val) ? val : [val];
}
exports.arrify = arrify;
function ensureProgram(instance) {
if (instance && instance.watchHost) {
if (instance.hasUnaccountedModifiedFiles) {
if (instance.changedFilesList) {
instance.watchHost.updateRootFileNames();
}
if (instance.watchOfFilesAndCompilerOptions) {
instance.builderProgram = instance.watchOfFilesAndCompilerOptions.getProgram();
instance.program = instance.builderProgram.getProgram();
}
instance.hasUnaccountedModifiedFiles = false;
}
return instance.program;
}
if (instance.languageService) {
return instance.languageService.getProgram();
}
return instance.program;
}
exports.ensureProgram = ensureProgram;
function supportsProjectReferences(instance) {
const program = ensureProgram(instance);
return program && !!program.getProjectReferences;
}
exports.supportsProjectReferences = supportsProjectReferences;
function isUsingProjectReferences(instance) {
if (instance.loaderOptions.projectReferences &&
supportsProjectReferences(instance)) {
const program = ensureProgram(instance);
return Boolean(program && program.getProjectReferences());
}
return false;
}
exports.isUsingProjectReferences = isUsingProjectReferences;
/**
* Gets the project reference for a file from the cache if it exists,
* or gets it from TypeScript and caches it otherwise.
*/
function getAndCacheProjectReference(filePath, instance) {
// When using solution builder, dont do the project reference caching
if (instance.solutionBuilderHost) {
return undefined;
}
const file = instance.files.get(filePath);
if (file !== undefined && file.projectReference) {
return file.projectReference.project;
}
const projectReference = getProjectReferenceForFile(filePath, instance);
if (file !== undefined) {
file.projectReference = { project: projectReference };
}
return projectReference;
}
exports.getAndCacheProjectReference = getAndCacheProjectReference;
function getResolvedProjectReferences(program) {
const getProjectReferences = program.getResolvedProjectReferences ||
program.getProjectReferences;
if (getProjectReferences) {
return getProjectReferences();
}
return;
}
function getProjectReferenceForFile(filePath, instance) {
if (isUsingProjectReferences(instance)) {
const program = ensureProgram(instance);
return (program &&
getResolvedProjectReferences(program).find(ref => (ref &&
ref.commandLine.fileNames.some(file => path.normalize(file) === filePath)) ||
false));
}
return;
}
function validateSourceMapOncePerProject(instance, loader, jsFileName, project) {
const { projectsMissingSourceMaps = new Set() } = instance;
if (!projectsMissingSourceMaps.has(project.sourceFile.fileName)) {
instance.projectsMissingSourceMaps = projectsMissingSourceMaps;
projectsMissingSourceMaps.add(project.sourceFile.fileName);
const mapFileName = jsFileName + '.map';
if (!instance.compiler.sys.fileExists(mapFileName)) {
const [relativeJSPath, relativeProjectConfigPath] = [
path.relative(loader.rootContext, jsFileName),
path.relative(loader.rootContext, project.sourceFile.fileName)
];
loader.emitWarning(new Error('Could not find source map file for referenced project output ' +
`${relativeJSPath}. Ensure the 'sourceMap' compiler option ` +
`is enabled in ${relativeProjectConfigPath} to ensure Webpack ` +
'can map project references to the appropriate source files.'));
}
}
}
exports.validateSourceMapOncePerProject = validateSourceMapOncePerProject;
function supportsSolutionBuild(instance) {
return (!!instance.configFilePath &&
!!instance.loaderOptions.projectReferences &&
!!instance.compiler.InvalidatedProjectKind &&
!!instance.configParseResult.projectReferences &&
!!instance.configParseResult.projectReferences.length);
}
exports.supportsSolutionBuild = supportsSolutionBuild;
/**
* Gets the output JS file path for an input file governed by a composite project.
* Pulls from the cache if it exists; computes and caches the result otherwise.
*/
function getAndCacheOutputJSFileName(inputFileName, projectReference, instance) {
const file = instance.files.get(inputFileName);
if (file && file.projectReference && file.projectReference.outputFileName) {
return file.projectReference.outputFileName;
}
const outputFileName = getOutputJavaScriptFileName(inputFileName, projectReference);
if (file !== undefined) {
file.projectReference = file.projectReference || {
project: projectReference
};
file.projectReference.outputFileName = outputFileName;
}
return outputFileName;
}
exports.getAndCacheOutputJSFileName = getAndCacheOutputJSFileName;
// Adapted from https://github.com/Microsoft/TypeScript/blob/45101491c0b077c509b25830ef0ee5f85b293754/src/compiler/tsbuild.ts#L305
function getOutputJavaScriptFileName(inputFileName, projectReference) {
const { options } = projectReference.commandLine;
const projectDirectory = options.rootDir || path.dirname(projectReference.sourceFile.fileName);
const relativePath = path.relative(projectDirectory, inputFileName);
const outputPath = path.resolve(options.outDir || projectDirectory, relativePath);
const newExtension = constants.jsonRegex.test(inputFileName)
? '.json'
: constants.tsxRegex.test(inputFileName) &&
options.jsx === typescript.JsxEmit.Preserve
? '.jsx'
: '.js';
return outputPath.replace(constants.extensionRegex, newExtension);
}
//# sourceMappingURL=utils.js.map
+7
View File
@@ -0,0 +1,7 @@
import * as webpack from 'webpack';
import { TSInstance } from './interfaces';
/**
* Make function which will manually update changed files
*/
export declare function makeWatchRun(instance: TSInstance, loader: webpack.loader.LoaderContext): (compiler: webpack.Compiler, callback: (err?: Error | undefined) => void) => void;
//# sourceMappingURL=watch-run.d.ts.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"watch-run.d.ts","sourceRoot":"","sources":["../src/watch-run.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAGnC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAI1C;;GAEG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,UAAU,EACpB,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,qFAkDrC"}
+82
View File
@@ -0,0 +1,82 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const constants = require("./constants");
const servicesHost_1 = require("./servicesHost");
const utils_1 = require("./utils");
/**
* Make function which will manually update changed files
*/
function makeWatchRun(instance, loader) {
// Called Before starting compilation after watch
const lastTimes = new Map();
const startTime = 0;
// Save the loader index.
const loaderIndex = loader.loaderIndex;
return (compiler, callback) => {
const promises = [];
if (instance.loaderOptions.transpileOnly) {
instance.reportTranspileErrors = true;
}
else {
const times = compiler.fileTimestamps;
for (const [filePath, date] of times) {
const lastTime = lastTimes.get(filePath) || startTime;
if (date <= lastTime) {
continue;
}
lastTimes.set(filePath, date);
promises.push(updateFile(instance, filePath, loader, loaderIndex));
}
// On watch update add all known dts files expect the ones in node_modules
// (skip @types/* and modules with typings)
for (const filePath of instance.files.keys()) {
if (filePath.match(constants.dtsDtsxOrDtsDtsxMapRegex) !== null &&
filePath.match(constants.nodeModules) === null) {
promises.push(updateFile(instance, filePath, loader, loaderIndex));
}
}
}
// Update all the watched files from solution builder
if (instance.solutionBuilderHost) {
for (const filePath of instance.solutionBuilderHost.watchedFiles.keys()) {
promises.push(updateFile(instance, filePath, loader, loaderIndex));
}
}
Promise.all(promises)
.then(() => callback())
.catch(err => callback(err));
};
}
exports.makeWatchRun = makeWatchRun;
function updateFile(instance, filePath, loader, loaderIndex) {
return new Promise((resolve, reject) => {
// When other loaders are specified after ts-loader
// (e.g. `{ test: /\.ts$/, use: ['ts-loader', 'other-loader'] }`),
// manually apply them to TypeScript files.
// Otherwise, files not 'preprocessed' by them may cause complication errors (#1111).
if (loaderIndex + 1 < loader.loaders.length &&
instance.rootFileNames.has(path.normalize(filePath))) {
let request = `!!${path.resolve(__dirname, 'stringify-loader.js')}!`;
for (let i = loaderIndex + 1; i < loader.loaders.length; ++i) {
request += loader.loaders[i].request + '!';
}
request += filePath;
loader.loadModule(request, (err, source) => {
if (err) {
reject(err);
}
else {
const text = JSON.parse(source);
servicesHost_1.updateFileWithText(instance, filePath, () => text);
resolve();
}
});
}
else {
servicesHost_1.updateFileWithText(instance, filePath, nFilePath => utils_1.readFile(nFilePath) || '');
resolve();
}
});
}
//# sourceMappingURL=watch-run.js.map