compiler.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. "use strict";
  2. var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
  3. if (k2 === undefined) k2 = k;
  4. Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
  5. }) : (function(o, m, k, k2) {
  6. if (k2 === undefined) k2 = k;
  7. o[k2] = m[k];
  8. }));
  9. var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
  10. Object.defineProperty(o, "default", { enumerable: true, value: v });
  11. }) : function(o, v) {
  12. o["default"] = v;
  13. });
  14. var __importStar = (this && this.__importStar) || function (mod) {
  15. if (mod && mod.__esModule) return mod;
  16. var result = {};
  17. if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
  18. __setModuleDefault(result, mod);
  19. return result;
  20. };
  21. var __importDefault = (this && this.__importDefault) || function (mod) {
  22. return (mod && mod.__esModule) ? mod : { "default": mod };
  23. };
  24. Object.defineProperty(exports, "__esModule", { value: true });
  25. exports.makeCompiler = void 0;
  26. var tsNode = __importStar(require("ts-node"));
  27. var fs_1 = __importDefault(require("fs"));
  28. var path_1 = __importDefault(require("path"));
  29. var os_1 = __importDefault(require("os"));
  30. var mkdirp_1 = __importDefault(require("mkdirp"));
  31. var rimraf_1 = __importDefault(require("rimraf"));
  32. var tsconfig_1 = require("tsconfig");
  33. var get_compiled_path_1 = require("./get-compiled-path");
  34. var get_cwd_1 = require("./get-cwd");
  35. var fixPath = function (p) { return p.replace(/\\/g, '/').replace(/\$/g, '$$$$'); };
  36. var sourceMapSupportPath = require.resolve('source-map-support');
  37. var compileExtensions = ['.ts', '.tsx'];
  38. var cwd = process.cwd();
  39. var compilationInstanceStamp = Math.random().toString().slice(2);
  40. var originalJsHandler = require.extensions['.js'];
  41. var parse = function (value) {
  42. return typeof value === 'string' ? JSON.parse(value) : undefined;
  43. };
  44. function split(value) {
  45. return typeof value === 'string'
  46. ? value.split(/ *, */g).filter(function (v) { return v !== ''; })
  47. : undefined;
  48. }
  49. exports.makeCompiler = function (options, _a) {
  50. var log = _a.log, restart = _a.restart;
  51. var _errorCompileTimeout;
  52. var allowJs = false;
  53. var project = options['project'];
  54. var tsConfigPath = tsconfig_1.resolveSync(cwd, typeof project === 'string' ? project : undefined) || '';
  55. var compiledPathsHash = {};
  56. var tmpDir = options['cache-directory']
  57. ? path_1.default.resolve(options['cache-directory'])
  58. : fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), '.ts-node'));
  59. var writeChildHookFile = function (options) {
  60. var compileTimeout = parseInt(options['compile-timeout']);
  61. var getIgnoreVal = function (ignore) {
  62. var ignoreVal = !ignore || ignore === 'false'
  63. ? 'false'
  64. : '[' +
  65. ignore
  66. .split(/,/)
  67. .map(function (i) { return i.trim(); })
  68. .map(function (ignore) { return 'new RegExp("' + ignore + '")'; })
  69. .join(', ') +
  70. ']';
  71. return ignoreVal;
  72. };
  73. var varDecl = function (name, value) { return "var " + name + " = '" + value + "'"; };
  74. var replacements = [
  75. compileTimeout ? ['10000', compileTimeout.toString()] : null,
  76. allowJs ? ['allowJs = false', 'allowJs = true'] : null,
  77. options['prefer-ts-exts']
  78. ? ['preferTs = false', 'preferTs = true']
  79. : null,
  80. options['exec-check'] ? ['execCheck = false', 'execCheck = true'] : null,
  81. options['exit-child'] ? ['exitChild = false', 'exitChild = true'] : null,
  82. options['ignore'] !== undefined
  83. ? [
  84. 'var ignore = [/node_modules/]',
  85. 'var ignore = ' + getIgnoreVal(options['ignore']),
  86. ]
  87. : null,
  88. [
  89. varDecl('compilationId', ''),
  90. varDecl('compilationId', getCompilationId()),
  91. ],
  92. [varDecl('compiledDir', ''), varDecl('compiledDir', getCompiledDir())],
  93. [
  94. './get-compiled-path',
  95. fixPath(path_1.default.join(__dirname, 'get-compiled-path')),
  96. ],
  97. [
  98. varDecl('readyFile', ''),
  99. varDecl('readyFile', getCompilerReadyFilePath()),
  100. ],
  101. [
  102. varDecl('sourceMapSupportPath', ''),
  103. varDecl('sourceMapSupportPath', fixPath(sourceMapSupportPath)),
  104. ],
  105. [
  106. varDecl('libPath', ''),
  107. varDecl('libPath', __dirname.replace(/\\/g, '\\\\')),
  108. ],
  109. ['__dirname', '"' + fixPath(__dirname) + '"'],
  110. ]
  111. .filter(function (_) { return !!_; })
  112. .map(function (_) { return _; });
  113. var fileText = fs_1.default.readFileSync(path_1.default.join(__dirname, 'child-require-hook.js'), 'utf-8');
  114. var fileData = replacements.reduce(function (text, _a) {
  115. var what = _a[0], to = _a[1];
  116. return text.replace(what, to);
  117. }, fileText);
  118. fs_1.default.writeFileSync(getChildHookPath(), fileData);
  119. };
  120. var init = function () {
  121. registerTsNode();
  122. /* clean up compiled on each new init*/
  123. rimraf_1.default.sync(getCompiledDir());
  124. createCompiledDir();
  125. // check if `allowJs` compiler option enable
  126. // (.js handler was changed while ts-node registration)
  127. allowJs = require.extensions['.js'] !== originalJsHandler;
  128. if (allowJs) {
  129. compileExtensions.push('.js', '.jsx');
  130. }
  131. writeChildHookFile(options);
  132. };
  133. var getCompilationId = function () {
  134. return compilationInstanceStamp;
  135. };
  136. var createCompiledDir = function () {
  137. var compiledDir = getCompiledDir();
  138. if (!fs_1.default.existsSync(compiledDir)) {
  139. mkdirp_1.default.sync(getCompiledDir());
  140. }
  141. };
  142. var getCompiledDir = function () {
  143. return path_1.default.join(tmpDir, 'compiled').replace(/\\/g, '/');
  144. };
  145. var getCompileReqFilePath = function () {
  146. return path_1.default.join(getCompiledDir(), getCompilationId() + '.req');
  147. };
  148. var getCompilerReadyFilePath = function () {
  149. return path_1.default
  150. .join(os_1.default.tmpdir(), 'ts-node-dev-ready-' + compilationInstanceStamp)
  151. .replace(/\\/g, '/');
  152. };
  153. var getChildHookPath = function () {
  154. return path_1.default
  155. .join(os_1.default.tmpdir(), 'ts-node-dev-hook-' + compilationInstanceStamp + '.js')
  156. .replace(/\\/g, '/');
  157. };
  158. var writeReadyFile = function () {
  159. fs_1.default.writeFileSync(getCompilerReadyFilePath(), '');
  160. };
  161. var clearErrorCompile = function () {
  162. clearTimeout(_errorCompileTimeout);
  163. };
  164. var registerTsNode = function () {
  165. Object.keys(compiledPathsHash).forEach(function (key) {
  166. delete compiledPathsHash[key];
  167. });
  168. ['.js', '.jsx', '.ts', '.tsx'].forEach(function (ext) {
  169. require.extensions[ext] = originalJsHandler;
  170. });
  171. var scriptPath = options._.length
  172. ? path_1.default.resolve(cwd, options._[0])
  173. : undefined;
  174. tsNode.register({
  175. // --dir does not work (it gives a boolean only) so we only check for script-mode
  176. dir: get_cwd_1.getCwd(options['dir'], options['script-mode'], scriptPath),
  177. scope: options['scope'],
  178. scopeDir: options['scopeDir'],
  179. emit: options['emit'],
  180. files: options['files'],
  181. pretty: options['pretty'],
  182. transpileOnly: options['transpile-only'],
  183. ignore: options['ignore'] ? split(options['ignore']) : undefined,
  184. preferTsExts: options['prefer-ts-exts'],
  185. logError: options['log-error'],
  186. project: options['project'],
  187. skipProject: options['skip-project'],
  188. transpiler: options['transpiler'],
  189. skipIgnore: options['skip-ignore'],
  190. compiler: options['compiler'],
  191. compilerHost: options['compiler-host'],
  192. ignoreDiagnostics: options['ignore-diagnostics']
  193. ? split(options['ignore-diagnostics'])
  194. : undefined,
  195. compilerOptions: parse(options['compiler-options']),
  196. });
  197. };
  198. var compiler = {
  199. tsConfigPath: tsConfigPath,
  200. init: init,
  201. getCompileReqFilePath: getCompileReqFilePath,
  202. getChildHookPath: getChildHookPath,
  203. writeReadyFile: writeReadyFile,
  204. clearErrorCompile: clearErrorCompile,
  205. compileChanged: function (fileName) {
  206. var ext = path_1.default.extname(fileName);
  207. if (compileExtensions.indexOf(ext) < 0)
  208. return;
  209. try {
  210. var code = fs_1.default.readFileSync(fileName, 'utf-8');
  211. compiler.compile({
  212. code: code,
  213. compile: fileName,
  214. compiledPath: get_compiled_path_1.getCompiledPath(code, fileName, getCompiledDir()),
  215. });
  216. }
  217. catch (e) {
  218. console.error(e);
  219. }
  220. },
  221. compile: function (params) {
  222. var fileName = params.compile;
  223. var code = fs_1.default.readFileSync(fileName, 'utf-8');
  224. var compiledPath = params.compiledPath;
  225. // Prevent occasional duplicate compilation requests
  226. if (compiledPathsHash[compiledPath]) {
  227. return;
  228. }
  229. compiledPathsHash[compiledPath] = true;
  230. function writeCompiled(code, fileName) {
  231. fs_1.default.writeFile(compiledPath, code, function (err) {
  232. err && log.error(err);
  233. fs_1.default.writeFile(compiledPath + '.done', '', function (err) {
  234. err && log.error(err);
  235. });
  236. });
  237. }
  238. if (fs_1.default.existsSync(compiledPath)) {
  239. return;
  240. }
  241. var starTime = new Date().getTime();
  242. var m = {
  243. _compile: writeCompiled,
  244. };
  245. var _compile = function () {
  246. var ext = path_1.default.extname(fileName);
  247. var extHandler = require.extensions[ext];
  248. extHandler(m, fileName);
  249. log.debug(fileName, 'compiled in', new Date().getTime() - starTime, 'ms');
  250. };
  251. try {
  252. _compile();
  253. }
  254. catch (e) {
  255. console.error('Compilation error in', fileName);
  256. var errorCode = 'throw ' +
  257. 'new Error(' +
  258. JSON.stringify(e.message) +
  259. ')' +
  260. ';';
  261. writeCompiled(errorCode);
  262. // reinitialize ts-node compilation to clean up state after error
  263. // without timeout in causes cases error not be printed out
  264. setTimeout(function () {
  265. registerTsNode();
  266. }, 0);
  267. if (!options['error-recompile']) {
  268. return;
  269. }
  270. var timeoutMs_1 = parseInt(process.env.TS_NODE_DEV_ERROR_RECOMPILE_TIMEOUT || '0') ||
  271. 5000;
  272. var errorHandler_1 = function () {
  273. clearTimeout(_errorCompileTimeout);
  274. _errorCompileTimeout = setTimeout(function () {
  275. try {
  276. _compile();
  277. restart(fileName);
  278. }
  279. catch (e) {
  280. registerTsNode();
  281. errorHandler_1();
  282. }
  283. }, timeoutMs_1);
  284. };
  285. errorHandler_1();
  286. }
  287. },
  288. };
  289. return compiler;
  290. };