ts-jest 29.0.1 → 29.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/.ts-jest-digest +1 -1
  2. package/CHANGELOG.md +34 -0
  3. package/dist/cli/config/init.d.ts +5 -0
  4. package/dist/cli/config/init.js +61 -20
  5. package/dist/cli/config/migrate.js +88 -15
  6. package/dist/cli/help.js +7 -1
  7. package/dist/cli/helpers/presets.js +12 -5
  8. package/dist/cli/index.js +9 -5
  9. package/dist/config/paths-to-module-name-mapper.d.ts +3 -2
  10. package/dist/config/paths-to-module-name-mapper.js +21 -11
  11. package/dist/constants.js +5 -0
  12. package/dist/legacy/compiler/compiler-utils.d.ts +6 -0
  13. package/dist/legacy/compiler/compiler-utils.js +10 -0
  14. package/dist/legacy/compiler/ts-compiler.d.ts +6 -0
  15. package/dist/legacy/compiler/ts-compiler.js +76 -7
  16. package/dist/legacy/compiler/ts-jest-compiler.js +2 -1
  17. package/dist/legacy/config/config-set.d.ts +7 -0
  18. package/dist/legacy/config/config-set.js +91 -12
  19. package/dist/legacy/ts-jest-transformer.d.ts +13 -0
  20. package/dist/legacy/ts-jest-transformer.js +61 -12
  21. package/dist/presets/create-jest-preset.js +3 -2
  22. package/dist/raw-compiler-options.d.ts +297 -0
  23. package/dist/transformers/hoist-jest.d.ts +4 -0
  24. package/dist/transformers/hoist-jest.js +24 -0
  25. package/dist/types.d.ts +103 -8
  26. package/dist/utils/backports.js +13 -4
  27. package/dist/utils/get-package-version.js +3 -0
  28. package/dist/utils/importer.js +31 -4
  29. package/dist/utils/json.js +9 -0
  30. package/dist/utils/jsonable-value.js +2 -1
  31. package/dist/utils/logger.js +1 -0
  32. package/dist/utils/memoize.js +20 -1
  33. package/dist/utils/messages.js +5 -0
  34. package/dist/utils/normalize-slashes.js +3 -0
  35. package/dist/utils/sha1.js +10 -0
  36. package/dist/utils/ts-error.js +12 -2
  37. package/dist/utils/version-checkers.js +9 -5
  38. package/package.json +5 -5
@@ -1,2 +1,8 @@
1
+ /**
2
+ * Rely on TypeScript compiled output generation which contains this prefix to point to sourcemap location.
3
+ */
1
4
  export declare const SOURCE_MAPPING_PREFIX = "sourceMappingURL=";
5
+ /**
6
+ * Update the output remapping the source map.
7
+ */
2
8
  export declare function updateOutput(outputText: string, normalizedFileName: string, sourceMap?: string): string;
@@ -2,17 +2,27 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.updateOutput = exports.SOURCE_MAPPING_PREFIX = void 0;
4
4
  var utils_1 = require("../../utils");
5
+ /**
6
+ * Rely on TypeScript compiled output generation which contains this prefix to point to sourcemap location.
7
+ */
5
8
  exports.SOURCE_MAPPING_PREFIX = 'sourceMappingURL=';
9
+ /**
10
+ * Update the output remapping the source map.
11
+ */
6
12
  function updateOutput(outputText, normalizedFileName, sourceMap) {
7
13
  if (sourceMap) {
8
14
  var base64Map = Buffer.from(updateSourceMap(sourceMap, normalizedFileName), 'utf8').toString('base64');
9
15
  var sourceMapContent = "data:application/json;charset=utf-8;base64,".concat(base64Map);
16
+ // sourceMappingURL= prefix is always at the end of compiledOutput, using lastIndexOf should be the safest way to substring
10
17
  return (outputText.slice(0, outputText.lastIndexOf(exports.SOURCE_MAPPING_PREFIX) + exports.SOURCE_MAPPING_PREFIX.length) +
11
18
  sourceMapContent);
12
19
  }
13
20
  return outputText;
14
21
  }
15
22
  exports.updateOutput = updateOutput;
23
+ /**
24
+ * Update the source map contents for improved output.
25
+ */
16
26
  var updateSourceMap = function (sourceMapText, normalizedFileName) {
17
27
  var sourceMap = JSON.parse(sourceMapText);
18
28
  sourceMap.file = normalizedFileName;
@@ -10,7 +10,13 @@ export declare class TsCompiler implements TsCompilerInstance {
10
10
  protected readonly _ts: TTypeScript;
11
11
  protected readonly _initialCompilerOptions: CompilerOptions;
12
12
  protected _compilerOptions: CompilerOptions;
13
+ /**
14
+ * @private
15
+ */
13
16
  private _runtimeCacheFS;
17
+ /**
18
+ * @private
19
+ */
14
20
  private _fileContentCache;
15
21
  program: Program | undefined;
16
22
  constructor(configSet: ConfigSet, runtimeCacheFS: StringMap);
@@ -58,12 +58,15 @@ var constants_1 = require("../../constants");
58
58
  var utils_1 = require("../../utils");
59
59
  var messages_1 = require("../../utils/messages");
60
60
  var compiler_utils_1 = require("./compiler-utils");
61
- var TsCompiler = (function () {
61
+ var TsCompiler = /** @class */ (function () {
62
62
  function TsCompiler(configSet, runtimeCacheFS) {
63
63
  var _a;
64
64
  var _this = this;
65
65
  this.configSet = configSet;
66
66
  this.runtimeCacheFS = runtimeCacheFS;
67
+ /**
68
+ * @internal
69
+ */
67
70
  this._projectVersion = 1;
68
71
  this._ts = configSet.compilerModule;
69
72
  this._logger = utils_1.rootLogger.child({ namespace: 'ts-compiler' });
@@ -80,6 +83,7 @@ var TsCompiler = (function () {
80
83
  },
81
84
  _a[bs_logger_1.LogContexts.logLevel] = bs_logger_1.LogLevels.trace,
82
85
  _a), 'readFile', (0, lodash_memoize_1.default)(this._ts.sys.readFile));
86
+ /* istanbul ignore next */
83
87
  this._moduleResolutionHost = {
84
88
  fileExists: (0, lodash_memoize_1.default)(this._ts.sys.fileExists),
85
89
  readFile: this._cachedReadFile,
@@ -95,6 +99,7 @@ var TsCompiler = (function () {
95
99
  }
96
100
  TsCompiler.prototype.getResolvedModules = function (fileContent, fileName, runtimeCacheFS) {
97
101
  var _this = this;
102
+ // In watch mode, it is possible that the initial cacheFS becomes empty
98
103
  if (!this.runtimeCacheFS.size) {
99
104
  this._runtimeCacheFS = runtimeCacheFS;
100
105
  }
@@ -122,6 +127,7 @@ var TsCompiler = (function () {
122
127
  ![this._ts.ModuleKind.ES2015, this._ts.ModuleKind.ES2020, this._ts.ModuleKind.ESNext].includes(moduleKind))
123
128
  ? this._ts.ModuleKind.ESNext
124
129
  : moduleKind;
130
+ // Make sure `esModuleInterop` and `allowSyntheticDefaultImports` true to support import CJS into ESM
125
131
  esModuleInterop = true;
126
132
  allowSyntheticDefaultImports = true;
127
133
  }
@@ -131,6 +137,7 @@ var TsCompiler = (function () {
131
137
  this._compilerOptions = __assign(__assign({}, this._compilerOptions), { allowSyntheticDefaultImports: allowSyntheticDefaultImports, esModuleInterop: esModuleInterop, module: moduleKind });
132
138
  if (this._languageService) {
133
139
  this._logger.debug({ fileName: fileName }, 'getCompiledOutput(): compiling using language service');
140
+ // Must set memory cache before attempting to compile
134
141
  this._updateMemoryCache(fileContent, fileName, currentModuleKind === moduleKind);
135
142
  var output = this._languageService.getEmitOutput(fileName);
136
143
  var diagnostics = this.getDiagnostics(fileName);
@@ -147,6 +154,7 @@ var TsCompiler = (function () {
147
154
  this._logger.debug({ fileToReTypeCheck: fileToReTypeCheck }, '_doTypeChecking(): computing diagnostics using language service');
148
155
  this._updateMemoryCache(this._getFileContentFromCache(fileToReTypeCheck), fileToReTypeCheck);
149
156
  var importedModulesDiagnostics = __spreadArray(__spreadArray([], __read(this._languageService.getSemanticDiagnostics(fileToReTypeCheck)), false), __read(this._languageService.getSyntacticDiagnostics(fileToReTypeCheck)), false);
157
+ // will raise or just warn diagnostics depending on config
150
158
  this.configSet.raiseDiagnostics(importedModulesDiagnostics, fileName, this._logger);
151
159
  }
152
160
  }
@@ -162,17 +170,18 @@ var TsCompiler = (function () {
162
170
  }
163
171
  if (output.emitSkipped) {
164
172
  if (constants_1.TS_TSX_REGEX.test(fileName)) {
165
- throw new Error((0, messages_1.interpolate)("Unable to process '{{file}}', please make sure that `outDir` in your tsconfig is neither `''` or `'.'`. You can also configure Jest config option `transformIgnorePatterns` to inform `ts-jest` to transform {{file}}", { file: fileName }));
173
+ throw new Error((0, messages_1.interpolate)("Unable to process '{{file}}', please make sure that `outDir` in your tsconfig is neither `''` or `'.'`. You can also configure Jest config option `transformIgnorePatterns` to inform `ts-jest` to transform {{file}}" /* Errors.CannotProcessFile */, { file: fileName }));
166
174
  }
167
175
  else {
168
- this._logger.warn((0, messages_1.interpolate)("Unable to process '{{file}}', falling back to original file content. You can also configure Jest config option `transformIgnorePatterns` to ignore {{file}} from transformation or make sure that `outDir` in your tsconfig is neither `''` or `'.'`", { file: fileName }));
176
+ this._logger.warn((0, messages_1.interpolate)("Unable to process '{{file}}', falling back to original file content. You can also configure Jest config option `transformIgnorePatterns` to ignore {{file}} from transformation or make sure that `outDir` in your tsconfig is neither `''` or `'.'`" /* Errors.CannotProcessFileReturnOriginal */, { file: fileName }));
169
177
  return {
170
178
  code: fileContent,
171
179
  };
172
180
  }
173
181
  }
182
+ // Throw an error when requiring `.d.ts` files.
174
183
  if (!output.outputFiles.length) {
175
- throw new TypeError((0, messages_1.interpolate)("Unable to require `.d.ts` file for file: {{file}}.\nThis is usually the result of a faulty configuration or import. Make sure there is a `.js`, `.json` or another executable extension available alongside `{{file}}`.", {
184
+ throw new TypeError((0, messages_1.interpolate)("Unable to require `.d.ts` file for file: {{file}}.\nThis is usually the result of a faulty configuration or import. Make sure there is a `.js`, `.json` or another executable extension available alongside `{{file}}`." /* Errors.UnableToRequireDefinitionFile */, {
176
185
  file: (0, path_1.basename)(fileName),
177
186
  }));
178
187
  }
@@ -220,19 +229,33 @@ var TsCompiler = (function () {
220
229
  }),
221
230
  };
222
231
  };
232
+ /**
233
+ * @internal
234
+ */
223
235
  TsCompiler.prototype._createLanguageService = function () {
224
236
  var _this = this;
225
237
  var _a;
238
+ // Initialize memory cache for typescript compiler
226
239
  this._parsedTsConfig.fileNames
227
240
  .filter(function (fileName) { return constants_1.TS_TSX_REGEX.test(fileName) && !_this.configSet.isTestFile(fileName); })
241
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
228
242
  .forEach(function (fileName) { return _this._fileVersionCache.set(fileName, 0); });
243
+ /* istanbul ignore next */
229
244
  var serviceHost = {
230
245
  useCaseSensitiveFileNames: function () { return _this._ts.sys.useCaseSensitiveFileNames; },
231
246
  getProjectVersion: function () { return String(_this._projectVersion); },
247
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
232
248
  getScriptFileNames: function () { return __spreadArray([], __read(_this._fileVersionCache.keys()), false); },
233
249
  getScriptVersion: function (fileName) {
234
250
  var normalizedFileName = (0, path_1.normalize)(fileName);
251
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
235
252
  var version = _this._fileVersionCache.get(normalizedFileName);
253
+ // We need to return `undefined` and not a string here because TypeScript will use
254
+ // `getScriptVersion` and compare against their own version - which can be `undefined`.
255
+ // If we don't return `undefined` it results in `undefined === "undefined"` and run
256
+ // `createProgram` again (which is very slow). Using a `string` assertion here to avoid
257
+ // TypeScript errors from the function signature (expects `(x: string) => string`).
258
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
236
259
  return version === undefined ? undefined : String(version);
237
260
  },
238
261
  getScriptSnapshot: function (fileName) {
@@ -240,13 +263,19 @@ var TsCompiler = (function () {
240
263
  var normalizedFileName = (0, path_1.normalize)(fileName);
241
264
  var hit = _this._isFileInCache(normalizedFileName);
242
265
  _this._logger.trace({ normalizedFileName: normalizedFileName, cacheHit: hit }, 'getScriptSnapshot():', 'cache', hit ? 'hit' : 'miss');
266
+ // Read file content from either memory cache or Jest runtime cache or fallback to file system read
243
267
  if (!hit) {
244
- var fileContent = (_d = (_b = (_a = _this._fileContentCache.get(normalizedFileName)) !== null && _a !== void 0 ? _a : _this._runtimeCacheFS.get(normalizedFileName)) !== null && _b !== void 0 ? _b : (_c = _this._cachedReadFile) === null || _c === void 0 ? void 0 : _c.call(_this, normalizedFileName)) !== null && _d !== void 0 ? _d : undefined;
268
+ var fileContent =
269
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
270
+ (_d = (_b = (_a = _this._fileContentCache.get(normalizedFileName)) !== null && _a !== void 0 ? _a : _this._runtimeCacheFS.get(normalizedFileName)) !== null && _b !== void 0 ? _b : (_c = _this._cachedReadFile) === null || _c === void 0 ? void 0 : _c.call(_this, normalizedFileName)) !== null && _d !== void 0 ? _d : undefined;
245
271
  if (fileContent !== undefined) {
272
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
246
273
  _this._fileContentCache.set(normalizedFileName, fileContent);
274
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
247
275
  _this._fileVersionCache.set(normalizedFileName, 1);
248
276
  }
249
277
  }
278
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
250
279
  var contents = _this._fileContentCache.get(normalizedFileName);
251
280
  if (contents === undefined)
252
281
  return;
@@ -271,51 +300,87 @@ var TsCompiler = (function () {
271
300
  this._languageService = this._ts.createLanguageService(serviceHost, this._ts.createDocumentRegistry(this._ts.sys.useCaseSensitiveFileNames, this.configSet.cwd));
272
301
  this.program = this._languageService.getProgram();
273
302
  };
303
+ /**
304
+ * @internal
305
+ */
274
306
  TsCompiler.prototype._getFileContentFromCache = function (filePath) {
275
307
  var normalizedFilePath = (0, path_1.normalize)(filePath);
276
308
  var resolvedFileContent = this._runtimeCacheFS.get(normalizedFilePath);
277
309
  if (!resolvedFileContent) {
310
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
278
311
  resolvedFileContent = this._moduleResolutionHost.readFile(normalizedFilePath);
279
312
  this._runtimeCacheFS.set(normalizedFilePath, resolvedFileContent);
280
313
  }
281
314
  return resolvedFileContent;
282
315
  };
316
+ /**
317
+ * @internal
318
+ */
283
319
  TsCompiler.prototype._getImportedModulePaths = function (resolvedFileContent, containingFile) {
284
320
  var _this = this;
285
321
  return this._ts
286
322
  .preProcessFile(resolvedFileContent, true, true)
287
323
  .importedFiles.map(function (importedFile) {
288
324
  var resolvedModule = _this._resolveModuleName(importedFile.fileName, containingFile).resolvedModule;
325
+ /* istanbul ignore next already covered */
289
326
  var resolvedFileName = resolvedModule === null || resolvedModule === void 0 ? void 0 : resolvedModule.resolvedFileName;
327
+ /* istanbul ignore next already covered */
290
328
  return resolvedFileName && !(resolvedModule === null || resolvedModule === void 0 ? void 0 : resolvedModule.isExternalLibraryImport) ? resolvedFileName : '';
291
329
  })
292
330
  .filter(function (resolveFileName) { return !!resolveFileName; });
293
331
  };
332
+ /**
333
+ * @internal
334
+ */
294
335
  TsCompiler.prototype._resolveModuleName = function (moduleNameToResolve, containingFile) {
295
- return this._ts.resolveModuleName(moduleNameToResolve, containingFile, this._compilerOptions, this._moduleResolutionHost, this._moduleResolutionCache);
336
+ return this._ts.resolveModuleName(moduleNameToResolve, containingFile, this._compilerOptions,
337
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
338
+ this._moduleResolutionHost,
339
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
340
+ this._moduleResolutionCache);
296
341
  };
342
+ /**
343
+ * @internal
344
+ */
297
345
  TsCompiler.prototype._isFileInCache = function (fileName) {
298
- return (this._fileContentCache.has(fileName) &&
346
+ return (
347
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
348
+ this._fileContentCache.has(fileName) &&
349
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
299
350
  this._fileVersionCache.has(fileName) &&
351
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
300
352
  this._fileVersionCache.get(fileName) !== 0);
301
353
  };
354
+ /**
355
+ * @internal
356
+ */
302
357
  TsCompiler.prototype._updateMemoryCache = function (contents, fileName, isModuleKindTheSame) {
303
358
  if (isModuleKindTheSame === void 0) { isModuleKindTheSame = true; }
304
359
  this._logger.debug({ fileName: fileName }, 'updateMemoryCache: update memory cache for language service');
305
360
  var shouldIncrementProjectVersion = false;
306
361
  var hit = this._isFileInCache(fileName);
307
362
  if (!hit) {
363
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
308
364
  this._fileVersionCache.set(fileName, 1);
309
365
  shouldIncrementProjectVersion = true;
310
366
  }
311
367
  else {
368
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
312
369
  var prevVersion = this._fileVersionCache.get(fileName);
370
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
313
371
  var previousContents = this._fileContentCache.get(fileName);
372
+ // Avoid incrementing cache when nothing has changed.
314
373
  if (previousContents !== contents) {
374
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
315
375
  this._fileVersionCache.set(fileName, prevVersion + 1);
376
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
316
377
  this._fileContentCache.set(fileName, contents);
317
378
  shouldIncrementProjectVersion = true;
318
379
  }
380
+ /**
381
+ * When a file is from node_modules or referenced to a referenced project and jest wants to transform it, we need
382
+ * to make sure that the Program is updated with this information
383
+ */
319
384
  if (!this._parsedTsConfig.fileNames.includes(fileName) || !isModuleKindTheSame) {
320
385
  shouldIncrementProjectVersion = true;
321
386
  }
@@ -323,10 +388,14 @@ var TsCompiler = (function () {
323
388
  if (shouldIncrementProjectVersion)
324
389
  this._projectVersion++;
325
390
  };
391
+ /**
392
+ * @internal
393
+ */
326
394
  TsCompiler.prototype.getDiagnostics = function (fileName) {
327
395
  var diagnostics = [];
328
396
  if (this.configSet.shouldReportDiagnostics(fileName)) {
329
397
  this._logger.debug({ fileName: fileName }, '_doTypeChecking(): computing diagnostics using language service');
398
+ // Get the relevant diagnostics - this is 3x faster than `getPreEmitDiagnostics`.
330
399
  diagnostics.push.apply(diagnostics, __spreadArray(__spreadArray([], __read(this._languageService.getSemanticDiagnostics(fileName)), false), __read(this._languageService.getSyntacticDiagnostics(fileName)), false));
331
400
  }
332
401
  return diagnostics;
@@ -2,8 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TsJestCompiler = void 0;
4
4
  var ts_compiler_1 = require("./ts-compiler");
5
- var TsJestCompiler = (function () {
5
+ var TsJestCompiler = /** @class */ (function () {
6
6
  function TsJestCompiler(configSet, runtimeCacheFS) {
7
+ // Later we can add swc/esbuild or other typescript compiler instance here
7
8
  this._compilerInstance = new ts_compiler_1.TsCompiler(configSet, runtimeCacheFS);
8
9
  }
9
10
  TsJestCompiler.prototype.getResolvedModules = function (fileContent, fileName, runtimeCacheFS) {
@@ -4,6 +4,9 @@ import type { RawCompilerOptions } from '../../raw-compiler-options';
4
4
  import type { ProjectConfigTsJest, TsJestAstTransformer, TTypeScript } from '../../types';
5
5
  export declare class ConfigSet {
6
6
  readonly parentLogger?: Logger | undefined;
7
+ /**
8
+ * Use by e2e, don't mark as internal
9
+ */
7
10
  readonly tsJestDigest: string;
8
11
  readonly logger: Logger;
9
12
  readonly compilerModule: TTypeScript;
@@ -16,6 +19,10 @@ export declare class ConfigSet {
16
19
  resolvedTransformers: TsJestAstTransformer;
17
20
  useESM: boolean;
18
21
  constructor(jestConfig: ProjectConfigTsJest | undefined, parentLogger?: Logger | undefined);
22
+ /**
23
+ * Load TypeScript configuration. Returns the parsed TypeScript config and any `tsconfig` options specified in ts-jest
24
+ * Subclasses which extend `ConfigSet` can override the default behavior
25
+ */
19
26
  protected _resolveTsConfig(compilerOptions?: RawCompilerOptions, resolvedConfigFile?: string): Record<string, any>;
20
27
  isTestFile(fileName: string): boolean;
21
28
  shouldStringifyContent(filePath: string): boolean;