UNPKG

10.4 kBJavaScriptView Raw
1"use strict";
2var fs = require("fs");
3var path = require("path");
4var _ = require("lodash");
5var helpers_1 = require("./helpers");
6var checker_1 = require("./checker");
7var watch_mode_1 = require("./watch-mode");
8var colors = require('colors/safe');
9var pkg = require('../package.json');
10var mkdirp = require('mkdirp');
11function getRootCompiler(compiler) {
12 if (compiler.parentCompilation) {
13 return getRootCompiler(compiler.parentCompilation.compiler);
14 }
15 else {
16 return compiler;
17 }
18}
19exports.getRootCompiler = getRootCompiler;
20function resolveInstance(compiler, instanceName) {
21 if (!compiler._tsInstances) {
22 compiler._tsInstances = {};
23 }
24 return compiler._tsInstances[instanceName];
25}
26var COMPILER_ERROR = colors.red("\n\nTypescript compiler cannot be found, please add it to your package.json file:\n npm install --save-dev typescript\n");
27var BABEL_ERROR = colors.red("\n\nBabel compiler cannot be found, please add it to your package.json file:\n npm install --save-dev babel-core\n");
28var id = 0;
29function ensureInstance(webpack, query, options, instanceName, rootCompiler) {
30 var exInstance = resolveInstance(rootCompiler, instanceName);
31 if (exInstance) {
32 return exInstance;
33 }
34 var watching = isWatching(rootCompiler);
35 var context = process.cwd();
36 var compilerInfo = setupTs(query.compiler);
37 var tsImpl = compilerInfo.tsImpl;
38 var _a = readConfigFile(context, query, options, tsImpl), configFilePath = _a.configFilePath, compilerConfig = _a.compilerConfig, loaderConfig = _a.loaderConfig;
39 applyDefaults(configFilePath, compilerConfig, loaderConfig, context);
40 if (!loaderConfig.silent) {
41 var sync = watching === WatchMode.Enabled ? ' (in a forked process)' : '';
42 console.log("\n[" + instanceName + "] Using typescript@" + compilerInfo.compilerVersion + " from " + compilerInfo.compilerPath + " and "
43 + ("\"tsconfig.json\" from " + configFilePath + sync + ".\n"));
44 }
45 var babelImpl = setupBabel(loaderConfig, context);
46 var cacheIdentifier = setupCache(loaderConfig, tsImpl, webpack, babelImpl, context);
47 var compiler = webpack._compiler;
48 setupWatchRun(compiler, instanceName);
49 setupAfterCompile(compiler, instanceName);
50 var webpackOptions = _.pick(webpack._compiler.options, 'resolve');
51 var checker = new checker_1.Checker(compilerInfo, loaderConfig, compilerConfig, webpackOptions, context, watching === WatchMode.Enabled);
52 return rootCompiler._tsInstances[instanceName] = {
53 id: ++id,
54 babelImpl: babelImpl,
55 compiledFiles: {},
56 loaderConfig: loaderConfig,
57 configFilePath: configFilePath,
58 compilerConfig: compilerConfig,
59 checker: checker,
60 cacheIdentifier: cacheIdentifier,
61 context: context
62 };
63}
64exports.ensureInstance = ensureInstance;
65function findTsImplPackage(inputPath) {
66 var pkgDir = path.dirname(inputPath);
67 if (fs.readdirSync(pkgDir).find(function (value) { return value === 'package.json'; })) {
68 return path.join(pkgDir, 'package.json');
69 }
70 else {
71 return findTsImplPackage(pkgDir);
72 }
73}
74function setupTs(compiler) {
75 var compilerPath = compiler || 'typescript';
76 var tsImpl;
77 var tsImplPath;
78 try {
79 tsImplPath = require.resolve(compilerPath);
80 tsImpl = require(tsImplPath);
81 }
82 catch (e) {
83 console.error(e);
84 console.error(COMPILER_ERROR);
85 process.exit(1);
86 }
87 var pkgPath = findTsImplPackage(tsImplPath);
88 var compilerVersion = require(pkgPath).version;
89 var compilerInfo = {
90 compilerPath: compilerPath,
91 compilerVersion: compilerVersion,
92 tsImpl: tsImpl,
93 };
94 return compilerInfo;
95}
96exports.setupTs = setupTs;
97function setupCache(loaderConfig, tsImpl, webpack, babelImpl, context) {
98 var cacheIdentifier = null;
99 if (loaderConfig.useCache) {
100 if (!loaderConfig.cacheDirectory) {
101 loaderConfig.cacheDirectory = path.join(context, '.awcache');
102 }
103 if (!fs.existsSync(loaderConfig.cacheDirectory)) {
104 mkdirp.sync(loaderConfig.cacheDirectory);
105 }
106 cacheIdentifier = {
107 'typescript': tsImpl.version,
108 'awesome-typescript-loader': pkg.version,
109 'awesome-typescript-loader-query': webpack.query,
110 'babel-core': babelImpl
111 ? babelImpl.version
112 : null
113 };
114 }
115}
116function setupBabel(loaderConfig, context) {
117 var babelImpl;
118 if (loaderConfig.useBabel) {
119 try {
120 var babelPath = loaderConfig.babelCore || path.join(context, 'node_modules', 'babel-core');
121 babelImpl = require(babelPath);
122 }
123 catch (e) {
124 console.error(BABEL_ERROR);
125 process.exit(1);
126 }
127 }
128 return babelImpl;
129}
130function applyDefaults(configFilePath, compilerConfig, loaderConfig, context) {
131 _.defaults(compilerConfig.options, {
132 sourceMap: true,
133 verbose: false,
134 skipDefaultLibCheck: true,
135 suppressOutputPathCheck: true
136 });
137 if (loaderConfig.transpileOnly) {
138 compilerConfig.options.isolatedModules = true;
139 }
140 _.defaults(compilerConfig.options, {
141 sourceRoot: compilerConfig.options.sourceMap ? context : undefined
142 });
143 _.defaults(loaderConfig, {
144 sourceMap: true,
145 verbose: false,
146 });
147 delete compilerConfig.options.outDir;
148 delete compilerConfig.options.outFile;
149 delete compilerConfig.options.out;
150 delete compilerConfig.options.noEmit;
151}
152function absolutize(fileName, context) {
153 if (path.isAbsolute(fileName)) {
154 return fileName;
155 }
156 else {
157 return path.join(context, fileName);
158 }
159}
160function readConfigFile(context, query, options, tsImpl) {
161 var configFilePath;
162 if (query.configFileName && query.configFileName.match(/\.json$/)) {
163 configFilePath = absolutize(query.configFileName, context);
164 }
165 else {
166 configFilePath = tsImpl.findConfigFile(context, tsImpl.sys.fileExists);
167 }
168 var existingOptions = tsImpl.convertCompilerOptionsFromJson(query, context, 'atl.query');
169 if (!configFilePath || query.configFileContent) {
170 return {
171 configFilePath: configFilePath || path.join(context, 'tsconfig.json'),
172 compilerConfig: tsImpl.parseJsonConfigFileContent(query.configFileContent || {}, tsImpl.sys, context, _.extend({}, tsImpl.getDefaultCompilerOptions(), existingOptions.options), context),
173 loaderConfig: query
174 };
175 }
176 var jsonConfigFile = tsImpl.readConfigFile(configFilePath, tsImpl.sys.readFile);
177 var compilerConfig = tsImpl.parseJsonConfigFileContent(jsonConfigFile.config, tsImpl.sys, path.dirname(configFilePath), existingOptions.options, configFilePath);
178 return {
179 configFilePath: configFilePath,
180 compilerConfig: compilerConfig,
181 loaderConfig: _.defaults(query, jsonConfigFile.config.awesomeTypescriptLoaderOptions, options)
182 };
183}
184exports.readConfigFile = readConfigFile;
185var EXTENSIONS = /\.tsx?$|\.jsx?$/;
186function setupWatchRun(compiler, instanceName) {
187 compiler.plugin('watch-run', function (watching, callback) {
188 var instance = resolveInstance(watching.compiler, instanceName);
189 var checker = instance.checker;
190 var watcher = watching.compiler.watchFileSystem.watcher
191 || watching.compiler.watchFileSystem.wfs.watcher;
192 var mtimes = watcher.mtimes || {};
193 var changedFiles = Object.keys(mtimes).map(helpers_1.toUnix);
194 var updates = changedFiles
195 .filter(function (file) { return EXTENSIONS.test(file); })
196 .map(function (changedFile) {
197 if (fs.existsSync(changedFile)) {
198 checker.updateFile(changedFile, fs.readFileSync(changedFile).toString());
199 }
200 else {
201 checker.removeFile(changedFile);
202 }
203 });
204 Promise.all(updates)
205 .then(function () { return callback(); })
206 .catch(callback);
207 });
208}
209var WatchMode;
210(function (WatchMode) {
211 WatchMode[WatchMode["Enabled"] = 0] = "Enabled";
212 WatchMode[WatchMode["Disabled"] = 1] = "Disabled";
213 WatchMode[WatchMode["Unknown"] = 2] = "Unknown";
214})(WatchMode || (WatchMode = {}));
215function isWatching(compiler) {
216 var value = compiler && compiler[watch_mode_1.WatchModeSymbol];
217 if (value === true) {
218 return WatchMode.Enabled;
219 }
220 else if (value === false) {
221 return WatchMode.Disabled;
222 }
223 else {
224 return WatchMode.Unknown;
225 }
226}
227function setupAfterCompile(compiler, instanceName, forkChecker) {
228 if (forkChecker === void 0) { forkChecker = false; }
229 compiler.plugin('after-compile', function (compilation, callback) {
230 if (compilation.compiler.isChild()) {
231 callback();
232 return;
233 }
234 var watchMode = isWatching(compilation.compiler);
235 var instance = resolveInstance(compilation.compiler, instanceName);
236 var silent = instance.loaderConfig.silent;
237 var asyncErrors = watchMode === WatchMode.Enabled && !silent;
238 var emitError = function (msg) {
239 if (compilation.bail) {
240 console.error('Error in bail mode:', msg);
241 process.exit(1);
242 }
243 if (asyncErrors) {
244 console.log(msg, '\n');
245 }
246 else {
247 compilation.errors.push(new Error(msg));
248 }
249 };
250 instance.compiledFiles = {};
251 var files = instance.checker.getFiles()
252 .then(function (_a) {
253 var files = _a.files;
254 Array.prototype.push.apply(compilation.fileDependencies, files.map(path.normalize));
255 });
256 var diag = instance.loaderConfig.transpileOnly
257 ? Promise.resolve()
258 : instance.checker.getDiagnostics()
259 .then(function (diags) {
260 diags.forEach(function (diag) { return emitError(diag.pretty); });
261 });
262 files
263 .then(function () {
264 if (asyncErrors) {
265 return;
266 }
267 else {
268 return diag;
269 }
270 })
271 .then(function () { return callback(); })
272 .catch(callback);
273 });
274}
275//# sourceMappingURL=instance.js.map
\No newline at end of file