Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

674 rindas
29KB

  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. const path_1 = require("path");
  4. const sourceMapSupport = require("source-map-support");
  5. const ynModule = require("yn");
  6. const make_error_1 = require("make-error");
  7. const util = require("util");
  8. /**
  9. * Registered `ts-node` instance information.
  10. */
  11. exports.REGISTER_INSTANCE = Symbol.for('ts-node.register.instance');
  12. /**
  13. * @internal
  14. */
  15. exports.INSPECT_CUSTOM = util.inspect.custom || 'inspect';
  16. /**
  17. * Wrapper around yn module that returns `undefined` instead of `null`.
  18. * This is implemented by yn v4, but we're staying on v3 to avoid v4's node 10 requirement.
  19. */
  20. function yn(value) {
  21. var _a;
  22. return _a = ynModule(value), (_a !== null && _a !== void 0 ? _a : undefined);
  23. }
  24. /**
  25. * Debugging `ts-node`.
  26. */
  27. const shouldDebug = yn(process.env.TS_NODE_DEBUG);
  28. /** @internal */
  29. exports.debug = shouldDebug ?
  30. (...args) => console.log(`[ts-node ${new Date().toISOString()}]`, ...args)
  31. : () => undefined;
  32. const debugFn = shouldDebug ?
  33. (key, fn) => {
  34. let i = 0;
  35. return (x) => {
  36. exports.debug(key, x, ++i);
  37. return fn(x);
  38. };
  39. } :
  40. (_, fn) => fn;
  41. /**
  42. * Export the current version.
  43. */
  44. exports.VERSION = require('../package.json').version;
  45. /**
  46. * Like `Object.assign`, but ignores `undefined` properties.
  47. */
  48. function assign(initialValue, ...sources) {
  49. for (const source of sources) {
  50. for (const key of Object.keys(source)) {
  51. const value = source[key];
  52. if (value !== undefined)
  53. initialValue[key] = value;
  54. }
  55. }
  56. return initialValue;
  57. }
  58. /**
  59. * Default register options, including values specified via environment
  60. * variables.
  61. */
  62. exports.DEFAULTS = {
  63. dir: process.env.TS_NODE_DIR,
  64. emit: yn(process.env.TS_NODE_EMIT),
  65. scope: yn(process.env.TS_NODE_SCOPE),
  66. files: yn(process.env.TS_NODE_FILES),
  67. pretty: yn(process.env.TS_NODE_PRETTY),
  68. compiler: process.env.TS_NODE_COMPILER,
  69. compilerOptions: parse(process.env.TS_NODE_COMPILER_OPTIONS),
  70. ignore: split(process.env.TS_NODE_IGNORE),
  71. project: process.env.TS_NODE_PROJECT,
  72. skipProject: yn(process.env.TS_NODE_SKIP_PROJECT),
  73. skipIgnore: yn(process.env.TS_NODE_SKIP_IGNORE),
  74. preferTsExts: yn(process.env.TS_NODE_PREFER_TS_EXTS),
  75. ignoreDiagnostics: split(process.env.TS_NODE_IGNORE_DIAGNOSTICS),
  76. transpileOnly: yn(process.env.TS_NODE_TRANSPILE_ONLY),
  77. typeCheck: yn(process.env.TS_NODE_TYPE_CHECK),
  78. compilerHost: yn(process.env.TS_NODE_COMPILER_HOST),
  79. logError: yn(process.env.TS_NODE_LOG_ERROR)
  80. };
  81. /**
  82. * Default TypeScript compiler options required by `ts-node`.
  83. */
  84. const TS_NODE_COMPILER_OPTIONS = {
  85. sourceMap: true,
  86. inlineSourceMap: false,
  87. inlineSources: true,
  88. declaration: false,
  89. noEmit: false,
  90. outDir: '.ts-node'
  91. };
  92. /**
  93. * Split a string array of values.
  94. */
  95. function split(value) {
  96. return typeof value === 'string' ? value.split(/ *, */g) : undefined;
  97. }
  98. exports.split = split;
  99. /**
  100. * Parse a string as JSON.
  101. */
  102. function parse(value) {
  103. return typeof value === 'string' ? JSON.parse(value) : undefined;
  104. }
  105. exports.parse = parse;
  106. /**
  107. * Replace backslashes with forward slashes.
  108. */
  109. function normalizeSlashes(value) {
  110. return value.replace(/\\/g, '/');
  111. }
  112. exports.normalizeSlashes = normalizeSlashes;
  113. /**
  114. * TypeScript diagnostics error.
  115. */
  116. class TSError extends make_error_1.BaseError {
  117. constructor(diagnosticText, diagnosticCodes) {
  118. super(`⨯ Unable to compile TypeScript:\n${diagnosticText}`);
  119. this.diagnosticText = diagnosticText;
  120. this.diagnosticCodes = diagnosticCodes;
  121. this.name = 'TSError';
  122. }
  123. /**
  124. * @internal
  125. */
  126. [exports.INSPECT_CUSTOM]() {
  127. return this.diagnosticText;
  128. }
  129. }
  130. exports.TSError = TSError;
  131. /**
  132. * Cached fs operation wrapper.
  133. */
  134. function cachedLookup(fn) {
  135. const cache = new Map();
  136. return (arg) => {
  137. if (!cache.has(arg)) {
  138. cache.set(arg, fn(arg));
  139. }
  140. return cache.get(arg);
  141. };
  142. }
  143. /** @internal */
  144. function getExtensions(config) {
  145. const tsExtensions = ['.ts'];
  146. const jsExtensions = [];
  147. // Enable additional extensions when JSX or `allowJs` is enabled.
  148. if (config.options.jsx)
  149. tsExtensions.push('.tsx');
  150. if (config.options.allowJs)
  151. jsExtensions.push('.js');
  152. if (config.options.jsx && config.options.allowJs)
  153. jsExtensions.push('.jsx');
  154. return { tsExtensions, jsExtensions };
  155. }
  156. exports.getExtensions = getExtensions;
  157. /**
  158. * Register TypeScript compiler instance onto node.js
  159. */
  160. function register(opts = {}) {
  161. const originalJsHandler = require.extensions['.js']; // tslint:disable-line
  162. const service = create(opts);
  163. const { tsExtensions, jsExtensions } = getExtensions(service.config);
  164. const extensions = [...tsExtensions, ...jsExtensions];
  165. // Expose registered instance globally.
  166. process[exports.REGISTER_INSTANCE] = service;
  167. // Register the extensions.
  168. registerExtensions(service.options.preferTsExts, extensions, service, originalJsHandler);
  169. return service;
  170. }
  171. exports.register = register;
  172. /**
  173. * Create TypeScript compiler instance.
  174. */
  175. function create(rawOptions = {}) {
  176. var _a, _b;
  177. const dir = (_a = rawOptions.dir, (_a !== null && _a !== void 0 ? _a : exports.DEFAULTS.dir));
  178. const compilerName = (_b = rawOptions.compiler, (_b !== null && _b !== void 0 ? _b : exports.DEFAULTS.compiler));
  179. const cwd = dir ? path_1.resolve(dir) : process.cwd();
  180. /**
  181. * Load the typescript compiler. It is required to load the tsconfig but might
  182. * be changed by the tsconfig, so we sometimes have to do this twice.
  183. */
  184. function loadCompiler(name) {
  185. const compiler = require.resolve(name || 'typescript', { paths: [cwd, __dirname] });
  186. const ts = require(compiler);
  187. return { compiler, ts };
  188. }
  189. // Compute minimum options to read the config file.
  190. let { compiler, ts } = loadCompiler(compilerName);
  191. // Read config file and merge new options between env and CLI options.
  192. const { config, options: tsconfigOptions } = readConfig(cwd, ts, rawOptions);
  193. const options = assign({}, exports.DEFAULTS, tsconfigOptions || {}, rawOptions);
  194. // If `compiler` option changed based on tsconfig, re-load the compiler.
  195. if (options.compiler !== compilerName) {
  196. ({ compiler, ts } = loadCompiler(options.compiler));
  197. }
  198. const readFile = options.readFile || ts.sys.readFile;
  199. const fileExists = options.fileExists || ts.sys.fileExists;
  200. const transpileOnly = options.transpileOnly === true || options.typeCheck === false;
  201. const transformers = options.transformers || undefined;
  202. const ignoreDiagnostics = [
  203. 6059,
  204. 18002,
  205. 18003,
  206. ...(options.ignoreDiagnostics || [])
  207. ].map(Number);
  208. const configDiagnosticList = filterDiagnostics(config.errors, ignoreDiagnostics);
  209. const outputCache = new Map();
  210. const isScoped = options.scope ? (relname) => relname.charAt(0) !== '.' : () => true;
  211. const shouldIgnore = createIgnore(options.skipIgnore ? [] : (options.ignore || ['(?:^|/)node_modules/']).map(str => new RegExp(str)));
  212. const diagnosticHost = {
  213. getNewLine: () => ts.sys.newLine,
  214. getCurrentDirectory: () => cwd,
  215. getCanonicalFileName: ts.sys.useCaseSensitiveFileNames ? x => x : x => x.toLowerCase()
  216. };
  217. // Install source map support and read from memory cache.
  218. sourceMapSupport.install({
  219. environment: 'node',
  220. retrieveFile(path) {
  221. var _a;
  222. return ((_a = outputCache.get(path)) === null || _a === void 0 ? void 0 : _a.content) || '';
  223. }
  224. });
  225. const formatDiagnostics = process.stdout.isTTY || options.pretty
  226. ? (ts.formatDiagnosticsWithColorAndContext || ts.formatDiagnostics)
  227. : ts.formatDiagnostics;
  228. function createTSError(diagnostics) {
  229. const diagnosticText = formatDiagnostics(diagnostics, diagnosticHost);
  230. const diagnosticCodes = diagnostics.map(x => x.code);
  231. return new TSError(diagnosticText, diagnosticCodes);
  232. }
  233. function reportTSError(configDiagnosticList) {
  234. const error = createTSError(configDiagnosticList);
  235. if (options.logError) {
  236. // Print error in red color and continue execution.
  237. console.error('\x1b[31m%s\x1b[0m', error);
  238. }
  239. else {
  240. // Throw error and exit the script.
  241. throw error;
  242. }
  243. }
  244. // Render the configuration errors.
  245. if (configDiagnosticList.length)
  246. reportTSError(configDiagnosticList);
  247. /**
  248. * Get the extension for a transpiled file.
  249. */
  250. const getExtension = config.options.jsx === ts.JsxEmit.Preserve ?
  251. ((path) => /\.[tj]sx$/.test(path) ? '.jsx' : '.js') :
  252. ((_) => '.js');
  253. /**
  254. * Create the basic required function using transpile mode.
  255. */
  256. let getOutput;
  257. let getTypeInfo;
  258. const getOutputTranspileOnly = (code, fileName, overrideCompilerOptions) => {
  259. const result = ts.transpileModule(code, {
  260. fileName,
  261. compilerOptions: overrideCompilerOptions ? Object.assign(Object.assign({}, config.options), overrideCompilerOptions) : config.options,
  262. reportDiagnostics: true
  263. });
  264. const diagnosticList = filterDiagnostics(result.diagnostics || [], ignoreDiagnostics);
  265. if (diagnosticList.length)
  266. reportTSError(diagnosticList);
  267. return [result.outputText, result.sourceMapText];
  268. };
  269. // Use full language services when the fast option is disabled.
  270. if (!transpileOnly) {
  271. const fileContents = new Map();
  272. const rootFileNames = config.fileNames.slice();
  273. const cachedReadFile = cachedLookup(debugFn('readFile', readFile));
  274. // Use language services by default (TODO: invert next major version).
  275. if (!options.compilerHost) {
  276. let projectVersion = 1;
  277. const fileVersions = new Map(rootFileNames.map(fileName => [fileName, 0]));
  278. const getCustomTransformers = () => {
  279. if (typeof transformers === 'function') {
  280. const program = service.getProgram();
  281. return program ? transformers(program) : undefined;
  282. }
  283. return transformers;
  284. };
  285. // Create the compiler host for type checking.
  286. const serviceHost = {
  287. getProjectVersion: () => String(projectVersion),
  288. getScriptFileNames: () => Array.from(fileVersions.keys()),
  289. getScriptVersion: (fileName) => {
  290. const version = fileVersions.get(fileName);
  291. return version ? version.toString() : '';
  292. },
  293. getScriptSnapshot(fileName) {
  294. let contents = fileContents.get(fileName);
  295. // Read contents into TypeScript memory cache.
  296. if (contents === undefined) {
  297. contents = cachedReadFile(fileName);
  298. if (contents === undefined)
  299. return;
  300. fileVersions.set(fileName, 1);
  301. fileContents.set(fileName, contents);
  302. }
  303. return ts.ScriptSnapshot.fromString(contents);
  304. },
  305. readFile: cachedReadFile,
  306. readDirectory: ts.sys.readDirectory,
  307. getDirectories: cachedLookup(debugFn('getDirectories', ts.sys.getDirectories)),
  308. fileExists: cachedLookup(debugFn('fileExists', fileExists)),
  309. directoryExists: cachedLookup(debugFn('directoryExists', ts.sys.directoryExists)),
  310. getNewLine: () => ts.sys.newLine,
  311. useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,
  312. getCurrentDirectory: () => cwd,
  313. getCompilationSettings: () => config.options,
  314. getDefaultLibFileName: () => ts.getDefaultLibFilePath(config.options),
  315. getCustomTransformers: getCustomTransformers
  316. };
  317. const registry = ts.createDocumentRegistry(ts.sys.useCaseSensitiveFileNames, cwd);
  318. const service = ts.createLanguageService(serviceHost, registry);
  319. const updateMemoryCache = (contents, fileName) => {
  320. // Add to `rootFiles` when discovered for the first time.
  321. if (!fileVersions.has(fileName)) {
  322. rootFileNames.push(fileName);
  323. }
  324. const previousVersion = fileVersions.get(fileName) || 0;
  325. const previousContents = fileContents.get(fileName);
  326. // Avoid incrementing cache when nothing has changed.
  327. if (contents !== previousContents) {
  328. fileVersions.set(fileName, previousVersion + 1);
  329. fileContents.set(fileName, contents);
  330. // Increment project version for every file change.
  331. projectVersion++;
  332. }
  333. };
  334. let previousProgram = undefined;
  335. getOutput = (code, fileName) => {
  336. updateMemoryCache(code, fileName);
  337. const programBefore = service.getProgram();
  338. if (programBefore !== previousProgram) {
  339. exports.debug(`compiler rebuilt Program instance when getting output for ${fileName}`);
  340. }
  341. const output = service.getEmitOutput(fileName);
  342. // Get the relevant diagnostics - this is 3x faster than `getPreEmitDiagnostics`.
  343. const diagnostics = service.getSemanticDiagnostics(fileName)
  344. .concat(service.getSyntacticDiagnostics(fileName));
  345. const programAfter = service.getProgram();
  346. exports.debug('invariant: Is service.getProject() identical before and after getting emit output and diagnostics? (should always be true) ', programBefore === programAfter);
  347. previousProgram = programAfter;
  348. const diagnosticList = filterDiagnostics(diagnostics, ignoreDiagnostics);
  349. if (diagnosticList.length)
  350. reportTSError(diagnosticList);
  351. if (output.emitSkipped) {
  352. throw new TypeError(`${path_1.relative(cwd, fileName)}: Emit skipped`);
  353. }
  354. // Throw an error when requiring `.d.ts` files.
  355. if (output.outputFiles.length === 0) {
  356. throw new TypeError(`Unable to require file: ${path_1.relative(cwd, fileName)}\n` +
  357. 'This is usually the result of a faulty configuration or import. ' +
  358. 'Make sure there is a `.js`, `.json` or other executable extension with ' +
  359. 'loader attached before `ts-node` available.');
  360. }
  361. return [output.outputFiles[1].text, output.outputFiles[0].text];
  362. };
  363. getTypeInfo = (code, fileName, position) => {
  364. updateMemoryCache(code, fileName);
  365. const info = service.getQuickInfoAtPosition(fileName, position);
  366. const name = ts.displayPartsToString(info ? info.displayParts : []);
  367. const comment = ts.displayPartsToString(info ? info.documentation : []);
  368. return { name, comment };
  369. };
  370. }
  371. else {
  372. const sys = Object.assign(Object.assign(Object.assign({}, ts.sys), diagnosticHost), { readFile: (fileName) => {
  373. const cacheContents = fileContents.get(fileName);
  374. if (cacheContents !== undefined)
  375. return cacheContents;
  376. return cachedReadFile(fileName);
  377. }, readDirectory: ts.sys.readDirectory, getDirectories: cachedLookup(debugFn('getDirectories', ts.sys.getDirectories)), fileExists: cachedLookup(debugFn('fileExists', fileExists)), directoryExists: cachedLookup(debugFn('directoryExists', ts.sys.directoryExists)), resolvePath: cachedLookup(debugFn('resolvePath', ts.sys.resolvePath)), realpath: ts.sys.realpath ? cachedLookup(debugFn('realpath', ts.sys.realpath)) : undefined });
  378. const host = ts.createIncrementalCompilerHost
  379. ? ts.createIncrementalCompilerHost(config.options, sys)
  380. : Object.assign(Object.assign({}, sys), { getSourceFile: (fileName, languageVersion) => {
  381. const contents = sys.readFile(fileName);
  382. if (contents === undefined)
  383. return;
  384. return ts.createSourceFile(fileName, contents, languageVersion);
  385. }, getDefaultLibLocation: () => normalizeSlashes(path_1.dirname(compiler)), getDefaultLibFileName: () => normalizeSlashes(path_1.join(path_1.dirname(compiler), ts.getDefaultLibFileName(config.options))), useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames });
  386. // Fallback for older TypeScript releases without incremental API.
  387. let builderProgram = ts.createIncrementalProgram
  388. ? ts.createIncrementalProgram({
  389. rootNames: rootFileNames.slice(),
  390. options: config.options,
  391. host: host,
  392. configFileParsingDiagnostics: config.errors,
  393. projectReferences: config.projectReferences
  394. })
  395. : ts.createEmitAndSemanticDiagnosticsBuilderProgram(rootFileNames.slice(), config.options, host, undefined, config.errors, config.projectReferences);
  396. // Read and cache custom transformers.
  397. const customTransformers = typeof transformers === 'function'
  398. ? transformers(builderProgram.getProgram())
  399. : transformers;
  400. // Set the file contents into cache manually.
  401. const updateMemoryCache = (contents, fileName) => {
  402. const sourceFile = builderProgram.getSourceFile(fileName);
  403. fileContents.set(fileName, contents);
  404. // Add to `rootFiles` when discovered by compiler for the first time.
  405. if (sourceFile === undefined) {
  406. rootFileNames.push(fileName);
  407. }
  408. // Update program when file changes.
  409. if (sourceFile === undefined || sourceFile.text !== contents) {
  410. builderProgram = ts.createEmitAndSemanticDiagnosticsBuilderProgram(rootFileNames.slice(), config.options, host, builderProgram, config.errors, config.projectReferences);
  411. }
  412. };
  413. getOutput = (code, fileName) => {
  414. const output = ['', ''];
  415. updateMemoryCache(code, fileName);
  416. const sourceFile = builderProgram.getSourceFile(fileName);
  417. if (!sourceFile)
  418. throw new TypeError(`Unable to read file: ${fileName}`);
  419. const program = builderProgram.getProgram();
  420. const diagnostics = ts.getPreEmitDiagnostics(program, sourceFile);
  421. const diagnosticList = filterDiagnostics(diagnostics, ignoreDiagnostics);
  422. if (diagnosticList.length)
  423. reportTSError(diagnosticList);
  424. const result = builderProgram.emit(sourceFile, (path, file, writeByteOrderMark) => {
  425. if (path.endsWith('.map')) {
  426. output[1] = file;
  427. }
  428. else {
  429. output[0] = file;
  430. }
  431. if (options.emit)
  432. sys.writeFile(path, file, writeByteOrderMark);
  433. }, undefined, undefined, customTransformers);
  434. if (result.emitSkipped) {
  435. throw new TypeError(`${path_1.relative(cwd, fileName)}: Emit skipped`);
  436. }
  437. // Throw an error when requiring files that cannot be compiled.
  438. if (output[0] === '') {
  439. if (program.isSourceFileFromExternalLibrary(sourceFile)) {
  440. throw new TypeError(`Unable to compile file from external library: ${path_1.relative(cwd, fileName)}`);
  441. }
  442. throw new TypeError(`Unable to require file: ${path_1.relative(cwd, fileName)}\n` +
  443. 'This is usually the result of a faulty configuration or import. ' +
  444. 'Make sure there is a `.js`, `.json` or other executable extension with ' +
  445. 'loader attached before `ts-node` available.');
  446. }
  447. return output;
  448. };
  449. getTypeInfo = (code, fileName, position) => {
  450. updateMemoryCache(code, fileName);
  451. const sourceFile = builderProgram.getSourceFile(fileName);
  452. if (!sourceFile)
  453. throw new TypeError(`Unable to read file: ${fileName}`);
  454. const node = getTokenAtPosition(ts, sourceFile, position);
  455. const checker = builderProgram.getProgram().getTypeChecker();
  456. const symbol = checker.getSymbolAtLocation(node);
  457. if (!symbol)
  458. return { name: '', comment: '' };
  459. const type = checker.getTypeOfSymbolAtLocation(symbol, node);
  460. const signatures = [...type.getConstructSignatures(), ...type.getCallSignatures()];
  461. return {
  462. name: signatures.length ? signatures.map(x => checker.signatureToString(x)).join('\n') : checker.typeToString(type),
  463. comment: ts.displayPartsToString(symbol ? symbol.getDocumentationComment(checker) : [])
  464. };
  465. };
  466. // Write `.tsbuildinfo` when `--build` is enabled.
  467. if (options.emit && config.options.incremental) {
  468. process.on('exit', () => {
  469. // Emits `.tsbuildinfo` to filesystem.
  470. builderProgram.getProgram().emitBuildInfo();
  471. });
  472. }
  473. }
  474. }
  475. else {
  476. if (typeof transformers === 'function') {
  477. throw new TypeError('Transformers function is unavailable in "--transpile-only"');
  478. }
  479. getOutput = getOutputTranspileOnly;
  480. getTypeInfo = () => {
  481. throw new TypeError('Type information is unavailable in "--transpile-only"');
  482. };
  483. }
  484. const cannotCompileViaBothCodepathsErrorMessage = 'Cannot compile the same file via both `require()` and ESM hooks codepaths. ' +
  485. 'This breaks source-map-support, which cannot tell the difference between the two sourcemaps. ' +
  486. 'To avoid this problem, load each .ts file as only ESM or only CommonJS.';
  487. // Create a simple TypeScript compiler proxy.
  488. function compile(code, fileName, lineOffset = 0) {
  489. const normalizedFileName = normalizeSlashes(fileName);
  490. const [value, sourceMap] = getOutput(code, normalizedFileName);
  491. const output = updateOutput(value, normalizedFileName, sourceMap, getExtension);
  492. outputCache.set(normalizedFileName, { content: output });
  493. return output;
  494. }
  495. let active = true;
  496. const enabled = (enabled) => enabled === undefined ? active : (active = !!enabled);
  497. const ignored = (fileName) => {
  498. if (!active)
  499. return true;
  500. const relname = path_1.relative(cwd, fileName);
  501. if (!config.options.allowJs) {
  502. const ext = path_1.extname(fileName);
  503. if (ext === '.js' || ext === '.jsx')
  504. return true;
  505. }
  506. return !isScoped(relname) || shouldIgnore(relname);
  507. };
  508. return { ts, config, compile, getTypeInfo, ignored, enabled, options };
  509. }
  510. exports.create = create;
  511. /**
  512. * Check if the filename should be ignored.
  513. */
  514. function createIgnore(ignore) {
  515. return (relname) => {
  516. const path = normalizeSlashes(relname);
  517. return ignore.some(x => x.test(path));
  518. };
  519. }
  520. /**
  521. * "Refreshes" an extension on `require.extensions`.
  522. *
  523. * @param {string} ext
  524. */
  525. function reorderRequireExtension(ext) {
  526. const old = require.extensions[ext]; // tslint:disable-line
  527. delete require.extensions[ext]; // tslint:disable-line
  528. require.extensions[ext] = old; // tslint:disable-line
  529. }
  530. /**
  531. * Register the extensions to support when importing files.
  532. */
  533. function registerExtensions(preferTsExts, extensions, register, originalJsHandler) {
  534. // Register new extensions.
  535. for (const ext of extensions) {
  536. registerExtension(ext, register, originalJsHandler);
  537. }
  538. if (preferTsExts) {
  539. // tslint:disable-next-line
  540. const preferredExtensions = new Set([...extensions, ...Object.keys(require.extensions)]);
  541. for (const ext of preferredExtensions)
  542. reorderRequireExtension(ext);
  543. }
  544. }
  545. /**
  546. * Register the extension for node.
  547. */
  548. function registerExtension(ext, register, originalHandler) {
  549. const old = require.extensions[ext] || originalHandler; // tslint:disable-line
  550. require.extensions[ext] = function (m, filename) {
  551. if (register.ignored(filename))
  552. return old(m, filename);
  553. const _compile = m._compile;
  554. m._compile = function (code, fileName) {
  555. exports.debug('module._compile', fileName);
  556. return _compile.call(this, register.compile(code, fileName), fileName);
  557. };
  558. return old(m, filename);
  559. };
  560. }
  561. /**
  562. * Do post-processing on config options to support `ts-node`.
  563. */
  564. function fixConfig(ts, config) {
  565. // Delete options that *should not* be passed through.
  566. delete config.options.out;
  567. delete config.options.outFile;
  568. delete config.options.composite;
  569. delete config.options.declarationDir;
  570. delete config.options.declarationMap;
  571. delete config.options.emitDeclarationOnly;
  572. // Target ES5 output by default (instead of ES3).
  573. if (config.options.target === undefined) {
  574. config.options.target = ts.ScriptTarget.ES5;
  575. }
  576. // Target CommonJS modules by default (instead of magically switching to ES6 when the target is ES6).
  577. if (config.options.module === undefined) {
  578. config.options.module = ts.ModuleKind.CommonJS;
  579. }
  580. return config;
  581. }
  582. /**
  583. * Load TypeScript configuration. Returns the parsed TypeScript config and
  584. * any `ts-node` options specified in the config file.
  585. */
  586. function readConfig(cwd, ts, rawOptions) {
  587. var _a, _b;
  588. let config = { compilerOptions: {} };
  589. let basePath = cwd;
  590. let configFileName = undefined;
  591. const { fileExists = ts.sys.fileExists, readFile = ts.sys.readFile, skipProject = exports.DEFAULTS.skipProject, project = exports.DEFAULTS.project } = rawOptions;
  592. // Read project configuration when available.
  593. if (!skipProject) {
  594. configFileName = project
  595. ? path_1.resolve(cwd, project)
  596. : ts.findConfigFile(cwd, fileExists);
  597. if (configFileName) {
  598. const result = ts.readConfigFile(configFileName, readFile);
  599. // Return diagnostics.
  600. if (result.error) {
  601. return {
  602. config: { errors: [result.error], fileNames: [], options: {} },
  603. options: {}
  604. };
  605. }
  606. config = result.config;
  607. basePath = path_1.dirname(configFileName);
  608. }
  609. }
  610. // Fix ts-node options that come from tsconfig.json
  611. const tsconfigOptions = Object.assign({}, config['ts-node']);
  612. // Remove resolution of "files".
  613. const files = (_b = (_a = rawOptions.files, (_a !== null && _a !== void 0 ? _a : tsconfigOptions.files)), (_b !== null && _b !== void 0 ? _b : exports.DEFAULTS.files));
  614. if (!files) {
  615. config.files = [];
  616. config.include = [];
  617. }
  618. // Override default configuration options `ts-node` requires.
  619. config.compilerOptions = Object.assign({}, config.compilerOptions, exports.DEFAULTS.compilerOptions, tsconfigOptions.compilerOptions, rawOptions.compilerOptions, TS_NODE_COMPILER_OPTIONS);
  620. const fixedConfig = fixConfig(ts, ts.parseJsonConfigFileContent(config, {
  621. fileExists,
  622. readFile,
  623. readDirectory: ts.sys.readDirectory,
  624. useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames
  625. }, basePath, undefined, configFileName));
  626. return { config: fixedConfig, options: tsconfigOptions };
  627. }
  628. /**
  629. * Update the output remapping the source map.
  630. */
  631. function updateOutput(outputText, fileName, sourceMap, getExtension) {
  632. const base64Map = Buffer.from(updateSourceMap(sourceMap, fileName), 'utf8').toString('base64');
  633. const sourceMapContent = `data:application/json;charset=utf-8;base64,${base64Map}`;
  634. const sourceMapLength = `${path_1.basename(fileName)}.map`.length + (getExtension(fileName).length - path_1.extname(fileName).length);
  635. return outputText.slice(0, -sourceMapLength) + sourceMapContent;
  636. }
  637. /**
  638. * Update the source map contents for improved output.
  639. */
  640. function updateSourceMap(sourceMapText, fileName) {
  641. const sourceMap = JSON.parse(sourceMapText);
  642. sourceMap.file = fileName;
  643. sourceMap.sources = [fileName];
  644. delete sourceMap.sourceRoot;
  645. return JSON.stringify(sourceMap);
  646. }
  647. /**
  648. * Filter diagnostics.
  649. */
  650. function filterDiagnostics(diagnostics, ignore) {
  651. return diagnostics.filter(x => ignore.indexOf(x.code) === -1);
  652. }
  653. /**
  654. * Get token at file position.
  655. *
  656. * Reference: https://github.com/microsoft/TypeScript/blob/fcd9334f57d85b73dd66ad2d21c02e84822f4841/src/services/utilities.ts#L705-L731
  657. */
  658. function getTokenAtPosition(ts, sourceFile, position) {
  659. let current = sourceFile;
  660. outer: while (true) {
  661. for (const child of current.getChildren(sourceFile)) {
  662. const start = child.getFullStart();
  663. if (start > position)
  664. break;
  665. const end = child.getEnd();
  666. if (position <= end) {
  667. current = child;
  668. continue outer;
  669. }
  670. }
  671. return current;
  672. }
  673. }
  674. //# sourceMappingURL=index.js.map