1. 'use strict';
    
  2. 
    
  3. const fs = require('fs');
    
  4. const path = require('path');
    
  5. const ts = require('typescript');
    
  6. 
    
  7. const tsOptions = {
    
  8.   module: ts.ModuleKind.CommonJS,
    
  9.   jsx: ts.JsxEmit.React,
    
  10. };
    
  11. 
    
  12. function formatErrorMessage(error) {
    
  13.   if (error.file) {
    
  14.     const message = ts.flattenDiagnosticMessageText(error.messageText, '\n');
    
  15.     return (
    
  16.       error.file.fileName +
    
  17.       '(' +
    
  18.       error.file.getLineAndCharacterOfPosition(error.start).line +
    
  19.       '): ' +
    
  20.       message
    
  21.     );
    
  22.   } else {
    
  23.     return ts.flattenDiagnosticMessageText(error.messageText, '\n');
    
  24.   }
    
  25. }
    
  26. 
    
  27. function compile(content, contentFilename) {
    
  28.   let output = null;
    
  29.   const compilerHost = {
    
  30.     fileExists(filename) {
    
  31.       return ts.sys.fileExists(filename);
    
  32.     },
    
  33.     getCanonicalFileName(filename) {
    
  34.       return filename;
    
  35.     },
    
  36.     getCurrentDirectory() {
    
  37.       return '';
    
  38.     },
    
  39.     getDefaultLibFileName: () => 'lib.d.ts',
    
  40.     getNewLine: () => ts.sys.newLine,
    
  41.     getSourceFile(filename, languageVersion) {
    
  42.       let source;
    
  43.       const libRegex = /lib\.(.+\.)?d\.ts$/;
    
  44.       const jestRegex = /jest\.d\.ts/;
    
  45.       const reactRegex =
    
  46.         /(?:React|ReactDOM|ReactDOMClient|ReactInternalAct|PropTypes)(?:\.d)?\.ts$/;
    
  47. 
    
  48.       // `path.normalize` is used to turn forward slashes in
    
  49.       // the file path into backslashes on Windows.
    
  50.       filename = path.normalize(filename);
    
  51.       if (filename.match(libRegex)) {
    
  52.         source = fs
    
  53.           .readFileSync(require.resolve('typescript/lib/' + filename))
    
  54.           .toString();
    
  55.       } else if (filename.match(jestRegex)) {
    
  56.         source = fs.readFileSync(path.join(__dirname, 'jest.d.ts')).toString();
    
  57.       } else if (filename === contentFilename) {
    
  58.         source = content;
    
  59.       } else if (reactRegex.test(filename)) {
    
  60.         // TypeScript will look for the .d.ts files in each ancestor directory,
    
  61.         // so there may not be a file at the referenced path as it climbs the
    
  62.         // hierarchy.
    
  63.         try {
    
  64.           source = fs.readFileSync(filename).toString();
    
  65.         } catch (e) {
    
  66.           if (e.code === 'ENOENT') {
    
  67.             return undefined;
    
  68.           }
    
  69.           throw e;
    
  70.         }
    
  71.       } else {
    
  72.         throw new Error('Unexpected filename ' + filename);
    
  73.       }
    
  74.       return ts.createSourceFile(filename, source, 'ES5', '0');
    
  75.     },
    
  76.     readFile(filename) {
    
  77.       return ts.sys.readFile(filename);
    
  78.     },
    
  79.     useCaseSensitiveFileNames() {
    
  80.       return ts.sys.useCaseSensitiveFileNames;
    
  81.     },
    
  82.     writeFile(name, text, writeByteOrderMark) {
    
  83.       if (output === null) {
    
  84.         output = text;
    
  85.       } else {
    
  86.         throw new Error('Expected only one dependency.');
    
  87.       }
    
  88.     },
    
  89.   };
    
  90.   const program = ts.createProgram(
    
  91.     ['lib.d.ts', 'jest.d.ts', contentFilename],
    
  92.     tsOptions,
    
  93.     compilerHost
    
  94.   );
    
  95.   const emitResult = program.emit();
    
  96.   const errors = ts
    
  97.     .getPreEmitDiagnostics(program)
    
  98.     .concat(emitResult.diagnostics);
    
  99.   if (errors.length) {
    
  100.     throw new Error(errors.map(formatErrorMessage).join('\n'));
    
  101.   }
    
  102.   return output;
    
  103. }
    
  104. 
    
  105. module.exports = {
    
  106.   compile: compile,
    
  107. };