diff --git a/package.json b/package.json index 537497c333..08ed8d0f6a 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,7 @@ "@babel/core": "^7.0.0-beta.54", "@babel/preset-env": "^7.0.0-beta.54", "@types/babel-core": "^6.25.5", + "@types/babel__core": "^7.0.1", "@types/es6-shim": "0.31.37", "@types/fs-extra": "5.0.4", "@types/jest": "^23.3.0", @@ -88,9 +89,9 @@ "@types/node": "10.5.5", "@types/react": "16.4.7", "@types/yargs": "^11.0.0", + "babel-core": "^7.0.0-0", "babel-jest": "^23.4.0", "babel-preset-jest": "^23.2.0", - "babel-core": "^7.0.0-0", "cpx": "^1.5.0", "cross-spawn": "latest", "cross-spawn-with-kill": "latest", diff --git a/src/postprocess.ts b/src/postprocess.ts index 4ead6c3195..346b2ad4b6 100644 --- a/src/postprocess.ts +++ b/src/postprocess.ts @@ -2,27 +2,32 @@ * Postprocess step. Based on babel-jest: https://github.com/facebook/jest/blob/master/packages/babel-jest/src/index.js * https://github.com/facebook/jest/blob/9b157c3a7c325c3971b2aabbe4c8ab4ce0b0c56d/packages/babel-jest/src/index.js */ -import * as __types__babel from 'babel-core'; -import __types__istanbulPlugin from 'babel-plugin-istanbul'; -import * as __types__jestPreset from 'babel-preset-jest'; import { BabelTransformOptions, PostProcessHook, - JestCacheKeyOptions, + TBabel, + TBabelPluginIstanbul, + TBabelPresetJest, } from './types'; import { logOnce } from './utils/logger'; import getTSJestConfig from './utils/get-ts-jest-config'; +import { + importBabelCore, + importBabelPluginIstanbul, + importBabelPresetJest, +} from './utils/imports'; +import { TransformOptions } from '@babel/core'; -let babel: typeof __types__babel; -let istanbulPlugin: typeof __types__istanbulPlugin; -let jestPreset: typeof __types__jestPreset; +let babel: TBabel; +let istanbulPlugin: TBabelPluginIstanbul; +let jestPreset: TBabelPresetJest; function importBabelDeps() { if (babel) return; // tslint:disable-line // we must use babel until we handle hoisting of jest.mock() internally - babel = require('@babel/core'); - istanbulPlugin = require('babel-plugin-istanbul').default; - jestPreset = require('babel-preset-jest'); + babel = importBabelCore(); + istanbulPlugin = importBabelPluginIstanbul(); + jestPreset = importBabelPresetJest(); } // Function that takes the transpiled typescript and runs it through babel/whatever. @@ -62,13 +67,17 @@ function createBabelTransformer( codeSourcemapPair: jest.TransformedSource, filename: string, config: jest.ProjectConfig, - transformOptions: JestCacheKeyOptions, + transformOptions: jest.TransformOptions, ): jest.TransformedSource => { const inputSourceMap = typeof codeSourcemapPair.map === 'string' ? JSON.parse(codeSourcemapPair.map) : codeSourcemapPair.map; - const theseOptions = { ...optionsBase, filename, inputSourceMap }; + const theseOptions = { + ...optionsBase, + filename, + inputSourceMap, + } as TransformOptions; if (transformOptions && transformOptions.instrument) { theseOptions.auxiliaryCommentBefore = ' istanbul ignore next '; // Copied from jest-runtime transform.js diff --git a/src/types.ts b/src/types.ts index 5e65556867..0445e8b172 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,5 +1,15 @@ import { TransformOptions as BabelTransformOpts } from 'babel-core'; +import * as _babel from '@babel/core'; +import * as _babelEnv from '@babel/preset-env'; +import * as _babelJest from 'babel-preset-jest'; +import _babelIstanbul from 'babel-plugin-istanbul'; + +export type TBabel = typeof _babel; +export type TBabelPluginIstanbul = typeof _babelIstanbul; +export type TBabelPresetEnv = typeof _babelEnv; +export type TBabelPresetJest = typeof _babelJest; + export interface JestCacheKeyOptions { rootDir: string; instrument: boolean; diff --git a/src/utils/imports.ts b/src/utils/imports.ts new file mode 100644 index 0000000000..6856a35923 --- /dev/null +++ b/src/utils/imports.ts @@ -0,0 +1,57 @@ +import { + TBabel, + TBabelPresetEnv, + TBabelPluginIstanbul, + TBabelPresetJest, +} from '../types'; + +export function importBabelCore(): TBabel { + const mod = tryRequire('@babel/core') || tryRequire('babel-core'); + if (!mod) { + throw new Error( + `[ts-jest] You must install the '@babel/core' or 'babel-core'` + + ` package (depending on the version you want to use).`, + ); + } + return mod; +} + +export function importBabelPresetEnv(): TBabelPresetEnv { + const mod = tryRequire('@babel/preset-env') || tryRequire('babel-preset-env'); + if (!mod) { + throw new Error( // babel-jest has the env preset as a dep + `[ts-jest] You must install the 'babel-jest' package if you're using babel.`, + ); + } + return mod; +} + +export function importBabelPresetJest(): TBabelPresetJest { + const mod = tryRequire('babel-preset-jest'); + if (!mod) { + throw new Error( // babel-jest has the jest preset as a dep + `[ts-jest] You must install the 'babel-jest' package if you're using babel.`, + ); + } + return mod; +} + +export function importBabelPluginIstanbul(): TBabelPluginIstanbul { + const mod = tryRequire('babel-plugin-istanbul'); + if (!mod) { + throw new Error( // babel-jest has the istanbul plugin as a dep + `[ts-jest] You must install the 'babel-jest' package if you're using babel.`, + ); + } + return mod.default; +} + +function tryRequire(packageName: string): T | void { + let mod: T; + try { + mod = require(packageName); + } catch (err) { + if (err.code !== 'ENOENT') throw err; // tslint:disable-line + } + return mod; +} diff --git a/yarn.lock b/yarn.lock index 5c45a2fba7..eee432f5c1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -515,6 +515,14 @@ lodash "^4.17.5" to-fast-properties "^2.0.0" +"@babel/types@^7.0.0-beta.54": + version "7.0.0-beta.55" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.55.tgz#7755c9d2e58315a64f05d8cf3322379be16d9199" + dependencies: + esutils "^2.0.2" + lodash "^4.17.10" + to-fast-properties "^2.0.0" + "@samverschueren/stream-to-observable@^0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" @@ -554,6 +562,12 @@ version "7.0.4" resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-7.0.4.tgz#bfd5b0d0d1ba13e351dff65b6e52783b816826c8" +"@types/babel__core@^7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.0.1.tgz#8b608a1c55cb4c752352cc6c78f7beb61a3fd51f" + dependencies: + "@babel/types" "^7.0.0-beta.54" + "@types/babylon@*": version "6.16.3" resolved "https://registry.yarnpkg.com/@types/babylon/-/babylon-6.16.3.tgz#c2937813a89fcb5e79a00062fc4a8b143e7237bb" @@ -3979,22 +3993,22 @@ rc@^1.1.7: minimist "^1.2.0" strip-json-comments "~2.0.1" -react-is@^16.4.1: - version "16.4.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.4.1.tgz#d624c4650d2c65dbd52c72622bbf389435d9776e" +react-is@^16.4.2: + version "16.4.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.4.2.tgz#84891b56c2b6d9efdee577cc83501dfc5ecead88" -react-test-renderer@16.4.1: - version "16.4.1" - resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.4.1.tgz#f2fb30c2c7b517db6e5b10ed20bb6b0a7ccd8d70" +react-test-renderer@16.4.2: + version "16.4.2" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.4.2.tgz#4e03eca9359bb3210d4373f7547d1364218ef74e" dependencies: fbjs "^0.8.16" object-assign "^4.1.1" prop-types "^15.6.0" - react-is "^16.4.1" + react-is "^16.4.2" -react@16.4.1: - version "16.4.1" - resolved "https://registry.yarnpkg.com/react/-/react-16.4.1.tgz#de51ba5764b5dbcd1f9079037b862bd26b82fe32" +react@16.4.2: + version "16.4.2" + resolved "https://registry.yarnpkg.com/react/-/react-16.4.2.tgz#2cd90154e3a9d9dd8da2991149fdca3c260e129f" dependencies: fbjs "^0.8.16" loose-envify "^1.1.0"